@usebruno/js 0.13.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 +23 -5
- package/src/bru.js +62 -18
- package/src/interpolate-string.js +8 -36
- package/src/runtime/assert-runtime.js +61 -25
- package/src/runtime/script-runtime.js +69 -26
- package/src/runtime/test-runtime.js +67 -49
- package/src/runtime/vars-runtime.js +65 -28
- 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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { NodeVM } = require('vm2');
|
|
1
|
+
const { NodeVM } = require('@usebruno/vm2');
|
|
2
2
|
const chai = require('chai');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const http = require('http');
|
|
@@ -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,
|
|
@@ -47,14 +50,16 @@ class TestRuntime {
|
|
|
47
50
|
historyLogger,
|
|
48
51
|
secretVariables
|
|
49
52
|
) {
|
|
53
|
+
const requestVariables = request?.requestVariables || {};
|
|
50
54
|
const bru = new Bru(
|
|
51
55
|
envVariables,
|
|
52
|
-
|
|
56
|
+
runtimeVariables,
|
|
53
57
|
processEnvVars,
|
|
54
58
|
collectionPath,
|
|
55
59
|
historyLogger,
|
|
56
|
-
undefined, //
|
|
57
|
-
secretVariables
|
|
60
|
+
undefined, // setVisualizations
|
|
61
|
+
secretVariables,
|
|
62
|
+
requestVariables
|
|
58
63
|
);
|
|
59
64
|
const req = new BrunoRequest(request, historyLogger);
|
|
60
65
|
const res = new BrunoResponse(response);
|
|
@@ -84,11 +89,15 @@ class TestRuntime {
|
|
|
84
89
|
return {
|
|
85
90
|
request,
|
|
86
91
|
envVariables,
|
|
87
|
-
|
|
88
|
-
results: __brunoTestResults.getResults()
|
|
92
|
+
runtimeVariables,
|
|
93
|
+
results: __brunoTestResults.getResults(),
|
|
94
|
+
nextRequestName: bru.nextRequest
|
|
89
95
|
};
|
|
90
96
|
}
|
|
91
97
|
|
|
98
|
+
// add 'await' prefix to the test function calls
|
|
99
|
+
testsFile = appendAwaitToTestFunc(testsFile);
|
|
100
|
+
|
|
92
101
|
const context = {
|
|
93
102
|
test,
|
|
94
103
|
bru,
|
|
@@ -109,48 +118,56 @@ class TestRuntime {
|
|
|
109
118
|
log: customLogger('log'),
|
|
110
119
|
info: customLogger('info'),
|
|
111
120
|
warn: customLogger('warn'),
|
|
121
|
+
debug: customLogger('debug'),
|
|
112
122
|
error: customLogger('error')
|
|
113
123
|
};
|
|
114
124
|
}
|
|
115
125
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
context:
|
|
120
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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
|
+
}
|
|
148
166
|
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
await asyncVM();
|
|
167
|
+
});
|
|
168
|
+
const asyncVM = vm.run(`module.exports = async () => { ${testsFile}}`, path.join(collectionPath, 'vm.js'));
|
|
169
|
+
await asyncVM();
|
|
170
|
+
}
|
|
154
171
|
|
|
155
172
|
if (historyLogger) {
|
|
156
173
|
historyLogger({
|
|
@@ -164,8 +181,9 @@ class TestRuntime {
|
|
|
164
181
|
return {
|
|
165
182
|
request,
|
|
166
183
|
envVariables: cleanJson(envVariables),
|
|
167
|
-
|
|
168
|
-
results: cleanJson(__brunoTestResults.getResults())
|
|
184
|
+
runtimeVariables: cleanJson(runtimeVariables),
|
|
185
|
+
results: cleanJson(__brunoTestResults.getResults()),
|
|
186
|
+
nextRequestName: bru.nextRequest
|
|
169
187
|
};
|
|
170
188
|
}
|
|
171
189
|
}
|
|
@@ -3,17 +3,42 @@ const Bru = require('../bru');
|
|
|
3
3
|
const BrunoRequest = require('../bruno-request');
|
|
4
4
|
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
|
|
5
5
|
|
|
6
|
+
const { executeQuickJsVm } = require('../sandbox/quickjs');
|
|
7
|
+
|
|
8
|
+
const evaluateJsTemplateLiteralBasedOnRuntime = (literal, context, runtime) => {
|
|
9
|
+
if (runtime === 'quickjs') {
|
|
10
|
+
return executeQuickJsVm({
|
|
11
|
+
script: literal,
|
|
12
|
+
context,
|
|
13
|
+
scriptType: 'template-literal'
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return evaluateJsTemplateLiteral(literal, context);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const evaluateJsExpressionBasedOnRuntime = (expr, context, runtime, mode) => {
|
|
21
|
+
if (runtime === 'quickjs') {
|
|
22
|
+
return executeQuickJsVm({
|
|
23
|
+
script: expr,
|
|
24
|
+
context,
|
|
25
|
+
scriptType: 'expression'
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return evaluateJsExpression(expr, context);
|
|
30
|
+
};
|
|
31
|
+
|
|
6
32
|
class VarsRuntime {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
) {
|
|
33
|
+
constructor(props) {
|
|
34
|
+
this.runtime = props?.runtime || 'vm2';
|
|
35
|
+
this.mode = props?.mode || 'developer';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
runPreRequestVars(vars, request, envVariables, runtimeVariables, collectionPath, processEnvVars, historyLogger, secretVars = {}) {
|
|
39
|
+
if (!request?.requestVariables) {
|
|
40
|
+
request.requestVariables = {};
|
|
41
|
+
}
|
|
17
42
|
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
18
43
|
if (!enabledVars.length) {
|
|
19
44
|
return;
|
|
@@ -21,12 +46,13 @@ class VarsRuntime {
|
|
|
21
46
|
|
|
22
47
|
const bru = new Bru(
|
|
23
48
|
envVariables,
|
|
24
|
-
|
|
49
|
+
runtimeVariables,
|
|
25
50
|
processEnvVars,
|
|
26
51
|
null,
|
|
27
52
|
historyLogger,
|
|
28
|
-
undefined, //
|
|
29
|
-
secretVars
|
|
53
|
+
undefined, // setVisualizations
|
|
54
|
+
secretVars,
|
|
55
|
+
undefined, // requestVariables
|
|
30
56
|
);
|
|
31
57
|
const req = new BrunoRequest(request, historyLogger);
|
|
32
58
|
|
|
@@ -37,19 +63,15 @@ class VarsRuntime {
|
|
|
37
63
|
|
|
38
64
|
const context = {
|
|
39
65
|
...envVariables,
|
|
40
|
-
...
|
|
66
|
+
...runtimeVariables,
|
|
41
67
|
...secretVars,
|
|
42
68
|
...bruContext
|
|
43
69
|
};
|
|
44
70
|
|
|
45
71
|
_.each(enabledVars, (v) => {
|
|
46
|
-
const value =
|
|
47
|
-
|
|
72
|
+
const value = evaluateJsTemplateLiteralBasedOnRuntime(v.value, context, this.runtime);
|
|
73
|
+
request?.requestVariables && (request.requestVariables[v.name] = value);
|
|
48
74
|
});
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
collectionVariables
|
|
52
|
-
};
|
|
53
75
|
}
|
|
54
76
|
|
|
55
77
|
runPostResponseVars(
|
|
@@ -57,12 +79,13 @@ class VarsRuntime {
|
|
|
57
79
|
request,
|
|
58
80
|
response,
|
|
59
81
|
envVariables,
|
|
60
|
-
|
|
82
|
+
runtimeVariables,
|
|
61
83
|
collectionPath,
|
|
62
84
|
processEnvVars,
|
|
63
85
|
historyLogger,
|
|
64
86
|
secretVars = {}
|
|
65
87
|
) {
|
|
88
|
+
const requestVariables = request?.requestVariables || {};
|
|
66
89
|
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
67
90
|
if (!enabledVars.length) {
|
|
68
91
|
return;
|
|
@@ -70,12 +93,13 @@ class VarsRuntime {
|
|
|
70
93
|
|
|
71
94
|
const bru = new Bru(
|
|
72
95
|
envVariables,
|
|
73
|
-
|
|
96
|
+
runtimeVariables,
|
|
74
97
|
processEnvVars,
|
|
75
98
|
null,
|
|
76
99
|
historyLogger,
|
|
77
|
-
undefined, //
|
|
78
|
-
secretVars
|
|
100
|
+
undefined, // setVisualizations
|
|
101
|
+
secretVars,
|
|
102
|
+
requestVariables
|
|
79
103
|
);
|
|
80
104
|
const req = new BrunoRequest(request, historyLogger);
|
|
81
105
|
const res = createResponseParser(response);
|
|
@@ -88,19 +112,32 @@ class VarsRuntime {
|
|
|
88
112
|
|
|
89
113
|
const context = {
|
|
90
114
|
...envVariables,
|
|
91
|
-
...
|
|
115
|
+
...runtimeVariables,
|
|
92
116
|
...secretVars,
|
|
93
117
|
...bruContext
|
|
94
118
|
};
|
|
95
119
|
|
|
120
|
+
const errors = new Map();
|
|
96
121
|
_.each(enabledVars, (v) => {
|
|
97
|
-
|
|
98
|
-
|
|
122
|
+
try {
|
|
123
|
+
const value = evaluateJsExpressionBasedOnRuntime(v.value, context, this.runtime);
|
|
124
|
+
bru.setVar(v.name, value);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
errors.set(v.name, error);
|
|
127
|
+
}
|
|
99
128
|
});
|
|
100
129
|
|
|
130
|
+
let error = null;
|
|
131
|
+
if (errors.size > 0) {
|
|
132
|
+
// Format all errors as a single string to be displayed in a toast
|
|
133
|
+
const errorMessage = [...errors.entries()].map(([name, err]) => `${name}: ${err.message ?? err}`).join('\n');
|
|
134
|
+
error = `${errors.size} error${errors.size === 1 ? '' : 's'} in post response variables: \n${errorMessage}`;
|
|
135
|
+
}
|
|
136
|
+
|
|
101
137
|
return {
|
|
102
138
|
envVariables,
|
|
103
|
-
|
|
139
|
+
runtimeVariables,
|
|
140
|
+
error
|
|
104
141
|
};
|
|
105
142
|
}
|
|
106
143
|
}
|