@usebruno/js 0.14.0 → 0.15.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 +22 -4
- package/src/bru.js +35 -12
- package/src/interpolate-string.js +2 -2
- package/src/runtime/assert-runtime.js +44 -20
- package/src/runtime/script-runtime.js +62 -23
- package/src/runtime/test-runtime.js +63 -47
- package/src/runtime/vars-runtime.js +44 -21
- package/src/sandbox/bundle-browser-rollup.js +502 -0
- package/src/sandbox/bundle-libraries.js +88 -0
- package/src/sandbox/quickjs/index.js +193 -0
- package/src/sandbox/quickjs/shims/bru.js +87 -0
- package/src/sandbox/quickjs/shims/bruno-request.js +112 -0
- package/src/sandbox/quickjs/shims/bruno-response.js +55 -0
- package/src/sandbox/quickjs/shims/console.js +46 -0
- package/src/sandbox/quickjs/shims/lib/axios.js +72 -0
- package/src/sandbox/quickjs/shims/lib/index.js +13 -0
- package/src/sandbox/quickjs/shims/lib/nanoid.js +24 -0
- package/src/sandbox/quickjs/shims/lib/path.js +28 -0
- package/src/sandbox/quickjs/shims/lib/uuid.js +30 -0
- package/src/sandbox/quickjs/shims/local-module.js +35 -0
- package/src/sandbox/quickjs/shims/test.js +63 -0
- package/src/sandbox/quickjs/utils/index.js +33 -0
- package/src/utils.js +6 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebruno/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.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.
|
|
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
|
@@ -7,22 +7,22 @@ const variableNameRegex = /^[\w-.]*$/;
|
|
|
7
7
|
class Bru {
|
|
8
8
|
constructor(
|
|
9
9
|
envVariables,
|
|
10
|
-
|
|
10
|
+
runtimeVariables,
|
|
11
11
|
processEnvVars,
|
|
12
12
|
collectionPath,
|
|
13
13
|
historyLogger,
|
|
14
|
-
|
|
14
|
+
setVisualizations,
|
|
15
15
|
secretVariables,
|
|
16
16
|
requestVariables
|
|
17
17
|
) {
|
|
18
18
|
this.envVariables = envVariables || {};
|
|
19
|
-
this.
|
|
19
|
+
this.runtimeVariables = runtimeVariables || {};
|
|
20
20
|
this.processEnvVars = cloneDeep(processEnvVars || {});
|
|
21
21
|
this.secretVariables = cloneDeep(secretVariables || {});
|
|
22
22
|
this.requestVariables = requestVariables || {};
|
|
23
23
|
this.collectionPath = collectionPath;
|
|
24
24
|
this.historyLogger = historyLogger;
|
|
25
|
-
this.
|
|
25
|
+
this.setVisualizations = setVisualizations;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
_interpolate = (str) => {
|
|
@@ -33,7 +33,7 @@ class Bru {
|
|
|
33
33
|
const combinedVars = {
|
|
34
34
|
...this.envVariables,
|
|
35
35
|
...this.requestVariables,
|
|
36
|
-
...this.
|
|
36
|
+
...this.runtimeVariables,
|
|
37
37
|
process: {
|
|
38
38
|
env: {
|
|
39
39
|
...this.processEnvVars
|
|
@@ -82,7 +82,7 @@ class Bru {
|
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
hasVar(key) {
|
|
85
|
-
return Object.hasOwn(this.
|
|
85
|
+
return Object.hasOwn(this.runtimeVariables, key);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
setVar(key, value) {
|
|
@@ -106,7 +106,7 @@ class Bru {
|
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
this.
|
|
109
|
+
this.runtimeVariables[key] = value;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
getVar(key) {
|
|
@@ -117,11 +117,11 @@ class Bru {
|
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
return this._interpolate(this.
|
|
120
|
+
return this._interpolate(this.runtimeVariables[key]);
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
deleteVar(key) {
|
|
124
|
-
delete this.
|
|
124
|
+
delete this.runtimeVariables[key];
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
getRequestVar(key) {
|
|
@@ -132,13 +132,36 @@ class Bru {
|
|
|
132
132
|
this.nextRequest = nextRequest;
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
-
visualize(htmlString) {
|
|
136
|
-
this.setHtmlVisualizationString(htmlString);
|
|
137
|
-
}
|
|
138
135
|
|
|
139
136
|
getSecretVar(key) {
|
|
140
137
|
return this.secretVariables?.[`$secrets.${key}`];
|
|
141
138
|
}
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
visualize(type, data) {
|
|
142
|
+
if (type == 'table') {
|
|
143
|
+
if (data?.provider == 'ag-grid') {
|
|
144
|
+
if (!data?.props?.columnDefinitions) {
|
|
145
|
+
throw new Error(`columns definitions are required`);
|
|
146
|
+
}
|
|
147
|
+
if (!data?.props?.rowData) {
|
|
148
|
+
throw new Error(`row data is required`);
|
|
149
|
+
}
|
|
150
|
+
this.setVisualizations({ uid: uuid(), type, data });
|
|
151
|
+
} else if (data?.provider == 'react-table') {
|
|
152
|
+
this.setVisualizations({ uid: uuid(), type, data });
|
|
153
|
+
}
|
|
154
|
+
} else if (type == 'html') {
|
|
155
|
+
if (!data?.content) {
|
|
156
|
+
throw new Error(`html content is required`);
|
|
157
|
+
}
|
|
158
|
+
this.setVisualizations({ uid: uuid(), type, data });
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
sleep(ms) {
|
|
163
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
164
|
+
}
|
|
142
165
|
}
|
|
143
166
|
|
|
144
167
|
module.exports = Bru;
|
|
@@ -2,7 +2,7 @@ const { interpolate } = require('@usebruno/common');
|
|
|
2
2
|
|
|
3
3
|
const interpolateString = (
|
|
4
4
|
str,
|
|
5
|
-
{ envVariables = {},
|
|
5
|
+
{ envVariables = {}, runtimeVariables = {}, processEnvVars = {}, requestVariables = {} }
|
|
6
6
|
) => {
|
|
7
7
|
if (!str || !str.length || typeof str !== 'string') {
|
|
8
8
|
return str;
|
|
@@ -11,7 +11,7 @@ const interpolateString = (
|
|
|
11
11
|
const combinedVars = {
|
|
12
12
|
...envVariables,
|
|
13
13
|
...requestVariables,
|
|
14
|
-
...
|
|
14
|
+
...runtimeVariables,
|
|
15
15
|
process: {
|
|
16
16
|
env: {
|
|
17
17
|
...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,38 @@ const isUnaryOperator = (operator) => {
|
|
|
161
162
|
return unaryOperators.includes(operator);
|
|
162
163
|
};
|
|
163
164
|
|
|
164
|
-
const
|
|
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
195
|
requestVariables: context.bru.requestVariables,
|
|
171
|
-
|
|
196
|
+
runtimeVariables: context.bru.runtimeVariables,
|
|
172
197
|
envVariables: context.bru.envVariables,
|
|
173
198
|
processEnvVars: context.bru.processEnvVars
|
|
174
199
|
};
|
|
@@ -181,13 +206,17 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
|
181
206
|
|
|
182
207
|
return rhsOperand
|
|
183
208
|
.split(',')
|
|
184
|
-
.map((v) =>
|
|
209
|
+
.map((v) =>
|
|
210
|
+
evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
|
|
211
|
+
);
|
|
185
212
|
}
|
|
186
213
|
|
|
187
214
|
if (operator === 'between') {
|
|
188
215
|
const [lhs, rhs] = rhsOperand
|
|
189
216
|
.split(',')
|
|
190
|
-
.map((v) =>
|
|
217
|
+
.map((v) =>
|
|
218
|
+
evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(v.trim(), interpolationContext), context, runtime)
|
|
219
|
+
);
|
|
191
220
|
return [lhs, rhs];
|
|
192
221
|
}
|
|
193
222
|
|
|
@@ -200,20 +229,15 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
|
200
229
|
return interpolateString(rhsOperand, interpolationContext);
|
|
201
230
|
}
|
|
202
231
|
|
|
203
|
-
return
|
|
232
|
+
return evaluateJsTemplateLiteralBasedOnRuntime(interpolateString(rhsOperand, interpolationContext), context, runtime);
|
|
204
233
|
};
|
|
205
234
|
|
|
206
235
|
class AssertRuntime {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
collectionVariables,
|
|
213
|
-
processEnvVars,
|
|
214
|
-
historyLogger,
|
|
215
|
-
secretVariables
|
|
216
|
-
) {
|
|
236
|
+
constructor(props) {
|
|
237
|
+
this.runtime = props?.runtime || 'vm2';
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
runAssertions(assertions, request, response, envVariables, runtimeVariables, processEnvVars, historyLogger, secretVariables) {
|
|
217
241
|
const requestVariables = request?.requestVariables || {};
|
|
218
242
|
const enabledAssertions = _.filter(assertions, (a) => a.enabled);
|
|
219
243
|
if (!enabledAssertions.length) {
|
|
@@ -222,11 +246,11 @@ class AssertRuntime {
|
|
|
222
246
|
|
|
223
247
|
const bru = new Bru(
|
|
224
248
|
envVariables,
|
|
225
|
-
|
|
249
|
+
runtimeVariables,
|
|
226
250
|
processEnvVars,
|
|
227
251
|
undefined, // collectionPath,
|
|
228
252
|
undefined, // historyLogger,
|
|
229
|
-
undefined, //
|
|
253
|
+
undefined, // setVisualizations,
|
|
230
254
|
secretVariables,
|
|
231
255
|
requestVariables
|
|
232
256
|
);
|
|
@@ -242,7 +266,7 @@ class AssertRuntime {
|
|
|
242
266
|
const context = {
|
|
243
267
|
...envVariables,
|
|
244
268
|
...requestVariables,
|
|
245
|
-
...
|
|
269
|
+
...runtimeVariables,
|
|
246
270
|
...processEnvVars,
|
|
247
271
|
...bruContext
|
|
248
272
|
};
|
|
@@ -256,8 +280,8 @@ class AssertRuntime {
|
|
|
256
280
|
const { operator, value: rhsOperand } = parseAssertionOperator(rhsExpr);
|
|
257
281
|
|
|
258
282
|
try {
|
|
259
|
-
const lhs =
|
|
260
|
-
const rhs = evaluateRhsOperand(rhsOperand, operator, context);
|
|
283
|
+
const lhs = evaluateJsExpressionBasedOnRuntime(lhsExpr, context, this.runtime);
|
|
284
|
+
const rhs = evaluateRhsOperand(rhsOperand, operator, context, this.runtime);
|
|
261
285
|
|
|
262
286
|
switch (operator) {
|
|
263
287
|
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
|
|
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
|
-
|
|
44
|
+
runtimeVariables,
|
|
42
45
|
collectionPath,
|
|
43
46
|
onConsoleLog,
|
|
44
47
|
processEnvVars,
|
|
@@ -46,18 +49,18 @@ class ScriptRuntime {
|
|
|
46
49
|
historyLogger,
|
|
47
50
|
secretVariables
|
|
48
51
|
) {
|
|
49
|
-
let
|
|
50
|
-
let
|
|
51
|
-
|
|
52
|
-
}
|
|
52
|
+
let visualizations = [];
|
|
53
|
+
let setVisualizations = (data) => {
|
|
54
|
+
visualizations.push(data);
|
|
55
|
+
}
|
|
53
56
|
const requestVariables = request?.requestVariables || {};
|
|
54
57
|
const bru = new Bru(
|
|
55
58
|
envVariables,
|
|
56
|
-
|
|
59
|
+
runtimeVariables,
|
|
57
60
|
processEnvVars,
|
|
58
61
|
collectionPath,
|
|
59
62
|
historyLogger,
|
|
60
|
-
|
|
63
|
+
setVisualizations,
|
|
61
64
|
secretVariables,
|
|
62
65
|
requestVariables
|
|
63
66
|
);
|
|
@@ -101,6 +104,23 @@ class ScriptRuntime {
|
|
|
101
104
|
};
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
if (this.runtime === 'quickjs') {
|
|
108
|
+
await executeQuickJsVmAsync({
|
|
109
|
+
script: script,
|
|
110
|
+
context: context,
|
|
111
|
+
collectionPath
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
request,
|
|
116
|
+
envVariables: cleanJson(envVariables),
|
|
117
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
118
|
+
visualizations,
|
|
119
|
+
nextRequestName: bru.nextRequest
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// default runtime is vm2
|
|
104
124
|
const vm = new NodeVM({
|
|
105
125
|
sandbox: context,
|
|
106
126
|
require: {
|
|
@@ -132,17 +152,18 @@ class ScriptRuntime {
|
|
|
132
152
|
'crypto-js': CryptoJS,
|
|
133
153
|
...whitelistedModules,
|
|
134
154
|
fs: allowScriptFilesystemAccess ? fs : undefined,
|
|
135
|
-
'node-vault':
|
|
155
|
+
'node-vault': NodeVault
|
|
136
156
|
}
|
|
137
157
|
}
|
|
138
158
|
});
|
|
139
159
|
const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
|
|
140
160
|
await asyncVM();
|
|
161
|
+
|
|
141
162
|
return {
|
|
142
163
|
request,
|
|
143
164
|
envVariables: cleanJson(envVariables),
|
|
144
|
-
|
|
145
|
-
|
|
165
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
166
|
+
visualizations,
|
|
146
167
|
nextRequestName: bru.nextRequest
|
|
147
168
|
};
|
|
148
169
|
}
|
|
@@ -152,7 +173,7 @@ class ScriptRuntime {
|
|
|
152
173
|
request,
|
|
153
174
|
response,
|
|
154
175
|
envVariables,
|
|
155
|
-
|
|
176
|
+
runtimeVariables,
|
|
156
177
|
collectionPath,
|
|
157
178
|
onConsoleLog,
|
|
158
179
|
processEnvVars,
|
|
@@ -160,18 +181,18 @@ class ScriptRuntime {
|
|
|
160
181
|
historyLogger,
|
|
161
182
|
secretVariables
|
|
162
183
|
) {
|
|
163
|
-
let
|
|
164
|
-
let
|
|
165
|
-
|
|
166
|
-
}
|
|
184
|
+
let visualizations = [];
|
|
185
|
+
let setVisualizations = (data) => {
|
|
186
|
+
visualizations.push(data);
|
|
187
|
+
}
|
|
167
188
|
const requestVariables = request?.requestVariables || {};
|
|
168
189
|
const bru = new Bru(
|
|
169
190
|
envVariables,
|
|
170
|
-
|
|
191
|
+
runtimeVariables,
|
|
171
192
|
processEnvVars,
|
|
172
193
|
collectionPath,
|
|
173
194
|
historyLogger,
|
|
174
|
-
|
|
195
|
+
setVisualizations,
|
|
175
196
|
secretVariables,
|
|
176
197
|
requestVariables
|
|
177
198
|
);
|
|
@@ -207,10 +228,28 @@ class ScriptRuntime {
|
|
|
207
228
|
log: customLogger('log'),
|
|
208
229
|
info: customLogger('info'),
|
|
209
230
|
warn: customLogger('warn'),
|
|
210
|
-
error: customLogger('error')
|
|
231
|
+
error: customLogger('error'),
|
|
232
|
+
debug: customLogger('debug')
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (this.runtime === 'quickjs') {
|
|
237
|
+
await executeQuickJsVmAsync({
|
|
238
|
+
script: script,
|
|
239
|
+
context: context,
|
|
240
|
+
collectionPath
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return {
|
|
244
|
+
response,
|
|
245
|
+
envVariables: cleanJson(envVariables),
|
|
246
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
247
|
+
visualizations,
|
|
248
|
+
nextRequestName: bru.nextRequest
|
|
211
249
|
};
|
|
212
250
|
}
|
|
213
251
|
|
|
252
|
+
// default runtime is vm2
|
|
214
253
|
const vm = new NodeVM({
|
|
215
254
|
sandbox: context,
|
|
216
255
|
require: {
|
|
@@ -241,7 +280,7 @@ class ScriptRuntime {
|
|
|
241
280
|
'crypto-js': CryptoJS,
|
|
242
281
|
...whitelistedModules,
|
|
243
282
|
fs: allowScriptFilesystemAccess ? fs : undefined,
|
|
244
|
-
'node-vault':
|
|
283
|
+
'node-vault': NodeVault
|
|
245
284
|
}
|
|
246
285
|
}
|
|
247
286
|
});
|
|
@@ -252,8 +291,8 @@ class ScriptRuntime {
|
|
|
252
291
|
return {
|
|
253
292
|
response,
|
|
254
293
|
envVariables: cleanJson(envVariables),
|
|
255
|
-
|
|
256
|
-
|
|
294
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
295
|
+
visualizations,
|
|
257
296
|
nextRequestName: bru.nextRequest
|
|
258
297
|
};
|
|
259
298
|
}
|
|
@@ -15,7 +15,7 @@ const BrunoRequest = require('../bruno-request');
|
|
|
15
15
|
const BrunoResponse = require('../bruno-response');
|
|
16
16
|
const Test = require('../test');
|
|
17
17
|
const TestResults = require('../test-results');
|
|
18
|
-
const { cleanJson } = require('../utils');
|
|
18
|
+
const { cleanJson, appendAwaitToTestFunc } = require('../utils');
|
|
19
19
|
|
|
20
20
|
// Inbuilt Library Support
|
|
21
21
|
const ajv = require('ajv');
|
|
@@ -29,17 +29,20 @@ const nanoid = require('nanoid');
|
|
|
29
29
|
const axios = require('axios');
|
|
30
30
|
const fetch = require('node-fetch');
|
|
31
31
|
const CryptoJS = require('crypto-js');
|
|
32
|
-
const
|
|
32
|
+
const NodeVault = require('node-vault');
|
|
33
|
+
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
|
|
33
34
|
|
|
34
35
|
class TestRuntime {
|
|
35
|
-
constructor() {
|
|
36
|
+
constructor(props) {
|
|
37
|
+
this.runtime = props?.runtime || 'vm2';
|
|
38
|
+
}
|
|
36
39
|
|
|
37
40
|
async runTests(
|
|
38
41
|
testsFile,
|
|
39
42
|
request,
|
|
40
43
|
response,
|
|
41
44
|
envVariables,
|
|
42
|
-
|
|
45
|
+
runtimeVariables,
|
|
43
46
|
collectionPath,
|
|
44
47
|
onConsoleLog,
|
|
45
48
|
processEnvVars,
|
|
@@ -50,11 +53,11 @@ class TestRuntime {
|
|
|
50
53
|
const requestVariables = request?.requestVariables || {};
|
|
51
54
|
const bru = new Bru(
|
|
52
55
|
envVariables,
|
|
53
|
-
|
|
56
|
+
runtimeVariables,
|
|
54
57
|
processEnvVars,
|
|
55
58
|
collectionPath,
|
|
56
59
|
historyLogger,
|
|
57
|
-
undefined, //
|
|
60
|
+
undefined, // setVisualizations
|
|
58
61
|
secretVariables,
|
|
59
62
|
requestVariables
|
|
60
63
|
);
|
|
@@ -86,11 +89,15 @@ class TestRuntime {
|
|
|
86
89
|
return {
|
|
87
90
|
request,
|
|
88
91
|
envVariables,
|
|
89
|
-
|
|
90
|
-
results: __brunoTestResults.getResults()
|
|
92
|
+
runtimeVariables,
|
|
93
|
+
results: __brunoTestResults.getResults(),
|
|
94
|
+
nextRequestName: bru.nextRequest
|
|
91
95
|
};
|
|
92
96
|
}
|
|
93
97
|
|
|
98
|
+
// add 'await' prefix to the test function calls
|
|
99
|
+
testsFile = appendAwaitToTestFunc(testsFile);
|
|
100
|
+
|
|
94
101
|
const context = {
|
|
95
102
|
test,
|
|
96
103
|
bru,
|
|
@@ -111,48 +118,56 @@ class TestRuntime {
|
|
|
111
118
|
log: customLogger('log'),
|
|
112
119
|
info: customLogger('info'),
|
|
113
120
|
warn: customLogger('warn'),
|
|
121
|
+
debug: customLogger('debug'),
|
|
114
122
|
error: customLogger('error')
|
|
115
123
|
};
|
|
116
124
|
}
|
|
117
125
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
context:
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
126
|
+
if (this.runtime === 'quickjs') {
|
|
127
|
+
await executeQuickJsVmAsync({
|
|
128
|
+
script: testsFile,
|
|
129
|
+
context: context
|
|
130
|
+
});
|
|
131
|
+
} else {
|
|
132
|
+
// default runtime is vm2
|
|
133
|
+
const vm = new NodeVM({
|
|
134
|
+
sandbox: context,
|
|
135
|
+
require: {
|
|
136
|
+
context: 'sandbox',
|
|
137
|
+
external: true,
|
|
138
|
+
root: [collectionPath, ...additionalContextRootsAbsolute],
|
|
139
|
+
mock: {
|
|
140
|
+
// node libs
|
|
141
|
+
path,
|
|
142
|
+
stream,
|
|
143
|
+
util,
|
|
144
|
+
url,
|
|
145
|
+
http,
|
|
146
|
+
https,
|
|
147
|
+
punycode,
|
|
148
|
+
zlib,
|
|
149
|
+
// 3rd party libs
|
|
150
|
+
ajv,
|
|
151
|
+
'ajv-formats': addFormats,
|
|
152
|
+
btoa,
|
|
153
|
+
atob,
|
|
154
|
+
lodash,
|
|
155
|
+
moment,
|
|
156
|
+
uuid,
|
|
157
|
+
nanoid,
|
|
158
|
+
axios,
|
|
159
|
+
chai,
|
|
160
|
+
'node-fetch': fetch,
|
|
161
|
+
'crypto-js': CryptoJS,
|
|
162
|
+
...whitelistedModules,
|
|
163
|
+
fs: allowScriptFilesystemAccess ? fs : undefined,
|
|
164
|
+
'node-vault': NodeVault
|
|
165
|
+
}
|
|
150
166
|
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
await asyncVM();
|
|
167
|
+
});
|
|
168
|
+
const asyncVM = vm.run(`module.exports = async () => { ${testsFile}}`, path.join(collectionPath, 'vm.js'));
|
|
169
|
+
await asyncVM();
|
|
170
|
+
}
|
|
156
171
|
|
|
157
172
|
if (historyLogger) {
|
|
158
173
|
historyLogger({
|
|
@@ -166,8 +181,9 @@ class TestRuntime {
|
|
|
166
181
|
return {
|
|
167
182
|
request,
|
|
168
183
|
envVariables: cleanJson(envVariables),
|
|
169
|
-
|
|
170
|
-
results: cleanJson(__brunoTestResults.getResults())
|
|
184
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
185
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
186
|
+
nextRequestName: bru.nextRequest
|
|
171
187
|
};
|
|
172
188
|
}
|
|
173
189
|
}
|