@usebruno/js 0.13.0 → 0.14.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.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
"package.json"
|
|
9
9
|
],
|
|
10
10
|
"peerDependencies": {
|
|
11
|
-
"@
|
|
11
|
+
"@usebruno/vm2": "^3.9.13"
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"test": "jest --testPathIgnorePatterns test.js"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
+
"@usebruno/common": "0.2.0",
|
|
17
18
|
"@usebruno/query": "0.1.0",
|
|
18
19
|
"ajv": "^8.12.0",
|
|
19
20
|
"ajv-formats": "^2.1.1",
|
|
@@ -23,7 +24,6 @@
|
|
|
23
24
|
"chai": "^4.3.7",
|
|
24
25
|
"chai-string": "^1.5.0",
|
|
25
26
|
"crypto-js": "^4.1.1",
|
|
26
|
-
"handlebars": "^4.7.8",
|
|
27
27
|
"json-query": "^2.2.2",
|
|
28
28
|
"lodash": "^4.17.21",
|
|
29
29
|
"moment": "^2.29.4",
|
package/src/bru.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
const Handlebars = require('handlebars');
|
|
2
1
|
const { cloneDeep } = require('lodash');
|
|
3
2
|
const { uuid } = require('./utils');
|
|
3
|
+
const { interpolate } = require('@usebruno/common');
|
|
4
4
|
|
|
5
5
|
const variableNameRegex = /^[\w-.]*$/;
|
|
6
6
|
|
|
@@ -12,31 +12,36 @@ class Bru {
|
|
|
12
12
|
collectionPath,
|
|
13
13
|
historyLogger,
|
|
14
14
|
setHtmlVisualizationString,
|
|
15
|
-
secretVariables
|
|
15
|
+
secretVariables,
|
|
16
|
+
requestVariables
|
|
16
17
|
) {
|
|
17
|
-
this.envVariables = envVariables;
|
|
18
|
-
this.collectionVariables = collectionVariables;
|
|
18
|
+
this.envVariables = envVariables || {};
|
|
19
|
+
this.collectionVariables = collectionVariables || {};
|
|
19
20
|
this.processEnvVars = cloneDeep(processEnvVars || {});
|
|
20
21
|
this.secretVariables = cloneDeep(secretVariables || {});
|
|
22
|
+
this.requestVariables = requestVariables || {};
|
|
21
23
|
this.collectionPath = collectionPath;
|
|
22
24
|
this.historyLogger = historyLogger;
|
|
23
25
|
this.setHtmlVisualizationString = setHtmlVisualizationString;
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
|
|
28
|
+
_interpolate = (str) => {
|
|
27
29
|
if (!str || !str.length || typeof str !== 'string') {
|
|
28
30
|
return str;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
const combinedVars = {
|
|
34
|
+
...this.envVariables,
|
|
35
|
+
...this.requestVariables,
|
|
36
|
+
...this.collectionVariables,
|
|
34
37
|
process: {
|
|
35
38
|
env: {
|
|
36
39
|
...this.processEnvVars
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
|
-
}
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
return interpolate(str, combinedVars);
|
|
40
45
|
};
|
|
41
46
|
|
|
42
47
|
cwd() {
|
|
@@ -51,8 +56,12 @@ class Bru {
|
|
|
51
56
|
return this.processEnvVars[key];
|
|
52
57
|
}
|
|
53
58
|
|
|
59
|
+
hasEnvVar(key) {
|
|
60
|
+
return Object.hasOwn(this.envVariables, key);
|
|
61
|
+
}
|
|
62
|
+
|
|
54
63
|
getEnvVar(key) {
|
|
55
|
-
return this.
|
|
64
|
+
return this._interpolate(this.envVariables[key]);
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
setEnvVar(key, value) {
|
|
@@ -72,6 +81,10 @@ class Bru {
|
|
|
72
81
|
this.envVariables[key] = value;
|
|
73
82
|
}
|
|
74
83
|
|
|
84
|
+
hasVar(key) {
|
|
85
|
+
return Object.hasOwn(this.collectionVariables, key);
|
|
86
|
+
}
|
|
87
|
+
|
|
75
88
|
setVar(key, value) {
|
|
76
89
|
if (!key) {
|
|
77
90
|
throw new Error('Creating a variable without specifying a name is not allowed.');
|
|
@@ -104,7 +117,15 @@ class Bru {
|
|
|
104
117
|
);
|
|
105
118
|
}
|
|
106
119
|
|
|
107
|
-
return this.collectionVariables[key];
|
|
120
|
+
return this._interpolate(this.collectionVariables[key]);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
deleteVar(key) {
|
|
124
|
+
delete this.collectionVariables[key];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getRequestVar(key) {
|
|
128
|
+
return this._interpolate(this.requestVariables[key]);
|
|
108
129
|
}
|
|
109
130
|
|
|
110
131
|
setNextRequest(nextRequest) {
|
|
@@ -1,44 +1,16 @@
|
|
|
1
|
-
const
|
|
2
|
-
const { forOwn, cloneDeep } = require('lodash');
|
|
1
|
+
const { interpolate } = require('@usebruno/common');
|
|
3
2
|
|
|
4
|
-
const
|
|
3
|
+
const interpolateString = (
|
|
4
|
+
str,
|
|
5
|
+
{ envVariables = {}, collectionVariables = {}, processEnvVars = {}, requestVariables = {} }
|
|
6
|
+
) => {
|
|
5
7
|
if (!str || !str.length || typeof str !== 'string') {
|
|
6
8
|
return str;
|
|
7
9
|
}
|
|
8
10
|
|
|
9
|
-
const template = Handlebars.compile(str, { noEscape: true });
|
|
10
|
-
|
|
11
|
-
return template({
|
|
12
|
-
process: {
|
|
13
|
-
env: {
|
|
14
|
-
...processEnvVars
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const interpolateString = (str, { envVariables, collectionVariables, processEnvVars }) => {
|
|
21
|
-
if (!str || !str.length || typeof str !== 'string') {
|
|
22
|
-
return str;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
processEnvVars = processEnvVars || {};
|
|
26
|
-
collectionVariables = collectionVariables || {};
|
|
27
|
-
|
|
28
|
-
// we clone envVariables because we don't want to modify the original object
|
|
29
|
-
envVariables = envVariables ? cloneDeep(envVariables) : {};
|
|
30
|
-
|
|
31
|
-
// envVariables can inturn have values as {{process.env.VAR_NAME}}
|
|
32
|
-
// so we need to interpolate envVariables first with processEnvVars
|
|
33
|
-
forOwn(envVariables, (value, key) => {
|
|
34
|
-
envVariables[key] = interpolateEnvVars(value, processEnvVars);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const template = Handlebars.compile(str, { noEscape: true });
|
|
38
|
-
|
|
39
|
-
// collectionVariables take precedence over envVariables
|
|
40
11
|
const combinedVars = {
|
|
41
12
|
...envVariables,
|
|
13
|
+
...requestVariables,
|
|
42
14
|
...collectionVariables,
|
|
43
15
|
process: {
|
|
44
16
|
env: {
|
|
@@ -47,7 +19,7 @@ const interpolateString = (str, { envVariables, collectionVariables, processEnvV
|
|
|
47
19
|
}
|
|
48
20
|
};
|
|
49
21
|
|
|
50
|
-
return
|
|
22
|
+
return interpolate(str, combinedVars);
|
|
51
23
|
};
|
|
52
24
|
|
|
53
25
|
module.exports = {
|
|
@@ -66,6 +66,7 @@ chai.use(function (chai, utils) {
|
|
|
66
66
|
* isNumber : is number
|
|
67
67
|
* isString : is string
|
|
68
68
|
* isBoolean : is boolean
|
|
69
|
+
* isArray : is array
|
|
69
70
|
*/
|
|
70
71
|
const parseAssertionOperator = (str = '') => {
|
|
71
72
|
if (!str || typeof str !== 'string' || !str.length) {
|
|
@@ -101,7 +102,8 @@ const parseAssertionOperator = (str = '') => {
|
|
|
101
102
|
'isJson',
|
|
102
103
|
'isNumber',
|
|
103
104
|
'isString',
|
|
104
|
-
'isBoolean'
|
|
105
|
+
'isBoolean',
|
|
106
|
+
'isArray'
|
|
105
107
|
];
|
|
106
108
|
|
|
107
109
|
const unaryOperators = [
|
|
@@ -114,7 +116,8 @@ const parseAssertionOperator = (str = '') => {
|
|
|
114
116
|
'isJson',
|
|
115
117
|
'isNumber',
|
|
116
118
|
'isString',
|
|
117
|
-
'isBoolean'
|
|
119
|
+
'isBoolean',
|
|
120
|
+
'isArray'
|
|
118
121
|
];
|
|
119
122
|
|
|
120
123
|
const [operator, ...rest] = str.trim().split(' ');
|
|
@@ -151,7 +154,8 @@ const isUnaryOperator = (operator) => {
|
|
|
151
154
|
'isJson',
|
|
152
155
|
'isNumber',
|
|
153
156
|
'isString',
|
|
154
|
-
'isBoolean'
|
|
157
|
+
'isBoolean',
|
|
158
|
+
'isArray'
|
|
155
159
|
];
|
|
156
160
|
|
|
157
161
|
return unaryOperators.includes(operator);
|
|
@@ -163,6 +167,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
|
163
167
|
}
|
|
164
168
|
|
|
165
169
|
const interpolationContext = {
|
|
170
|
+
requestVariables: context.bru.requestVariables,
|
|
166
171
|
collectionVariables: context.bru.collectionVariables,
|
|
167
172
|
envVariables: context.bru.envVariables,
|
|
168
173
|
processEnvVars: context.bru.processEnvVars
|
|
@@ -205,10 +210,11 @@ class AssertRuntime {
|
|
|
205
210
|
response,
|
|
206
211
|
envVariables,
|
|
207
212
|
collectionVariables,
|
|
208
|
-
|
|
213
|
+
processEnvVars,
|
|
209
214
|
historyLogger,
|
|
210
215
|
secretVariables
|
|
211
216
|
) {
|
|
217
|
+
const requestVariables = request?.requestVariables || {};
|
|
212
218
|
const enabledAssertions = _.filter(assertions, (a) => a.enabled);
|
|
213
219
|
if (!enabledAssertions.length) {
|
|
214
220
|
return [];
|
|
@@ -217,11 +223,12 @@ class AssertRuntime {
|
|
|
217
223
|
const bru = new Bru(
|
|
218
224
|
envVariables,
|
|
219
225
|
collectionVariables,
|
|
220
|
-
|
|
226
|
+
processEnvVars,
|
|
221
227
|
undefined, // collectionPath,
|
|
222
228
|
undefined, // historyLogger,
|
|
223
229
|
undefined, // setHtmlVisualizationString,
|
|
224
|
-
secretVariables
|
|
230
|
+
secretVariables,
|
|
231
|
+
requestVariables
|
|
225
232
|
);
|
|
226
233
|
const req = new BrunoRequest(request, historyLogger);
|
|
227
234
|
const res = createResponseParser(response);
|
|
@@ -234,7 +241,9 @@ class AssertRuntime {
|
|
|
234
241
|
|
|
235
242
|
const context = {
|
|
236
243
|
...envVariables,
|
|
244
|
+
...requestVariables,
|
|
237
245
|
...collectionVariables,
|
|
246
|
+
...processEnvVars,
|
|
238
247
|
...bruContext
|
|
239
248
|
};
|
|
240
249
|
|
|
@@ -330,6 +339,9 @@ class AssertRuntime {
|
|
|
330
339
|
case 'isBoolean':
|
|
331
340
|
expect(lhs).to.be.a('boolean');
|
|
332
341
|
break;
|
|
342
|
+
case 'isArray':
|
|
343
|
+
expect(lhs).to.be.a('array');
|
|
344
|
+
break;
|
|
333
345
|
default:
|
|
334
346
|
expect(lhs).to.equal(rhs);
|
|
335
347
|
break;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { NodeVM } = require('vm2');
|
|
1
|
+
const { NodeVM } = require('@usebruno/vm2');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const http = require('http');
|
|
4
4
|
const https = require('https');
|
|
@@ -50,6 +50,7 @@ class ScriptRuntime {
|
|
|
50
50
|
let setHtmlVisualizationString = (htmlString) => {
|
|
51
51
|
htmlVisualizationString = htmlString;
|
|
52
52
|
};
|
|
53
|
+
const requestVariables = request?.requestVariables || {};
|
|
53
54
|
const bru = new Bru(
|
|
54
55
|
envVariables,
|
|
55
56
|
collectionVariables,
|
|
@@ -57,7 +58,8 @@ class ScriptRuntime {
|
|
|
57
58
|
collectionPath,
|
|
58
59
|
historyLogger,
|
|
59
60
|
setHtmlVisualizationString,
|
|
60
|
-
secretVariables
|
|
61
|
+
secretVariables,
|
|
62
|
+
requestVariables
|
|
61
63
|
);
|
|
62
64
|
const req = new BrunoRequest(request, historyLogger);
|
|
63
65
|
const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
|
|
@@ -162,6 +164,7 @@ class ScriptRuntime {
|
|
|
162
164
|
let setHtmlVisualizationString = (htmlString) => {
|
|
163
165
|
htmlVisualizationString = htmlString;
|
|
164
166
|
};
|
|
167
|
+
const requestVariables = request?.requestVariables || {};
|
|
165
168
|
const bru = new Bru(
|
|
166
169
|
envVariables,
|
|
167
170
|
collectionVariables,
|
|
@@ -169,7 +172,8 @@ class ScriptRuntime {
|
|
|
169
172
|
collectionPath,
|
|
170
173
|
historyLogger,
|
|
171
174
|
setHtmlVisualizationString,
|
|
172
|
-
secretVariables
|
|
175
|
+
secretVariables,
|
|
176
|
+
requestVariables
|
|
173
177
|
);
|
|
174
178
|
const req = new BrunoRequest(request, historyLogger);
|
|
175
179
|
const res = new BrunoResponse(response);
|
|
@@ -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');
|
|
@@ -47,6 +47,7 @@ class TestRuntime {
|
|
|
47
47
|
historyLogger,
|
|
48
48
|
secretVariables
|
|
49
49
|
) {
|
|
50
|
+
const requestVariables = request?.requestVariables || {};
|
|
50
51
|
const bru = new Bru(
|
|
51
52
|
envVariables,
|
|
52
53
|
collectionVariables,
|
|
@@ -54,7 +55,8 @@ class TestRuntime {
|
|
|
54
55
|
collectionPath,
|
|
55
56
|
historyLogger,
|
|
56
57
|
undefined, // setHtmlVisualizationString
|
|
57
|
-
secretVariables
|
|
58
|
+
secretVariables,
|
|
59
|
+
requestVariables
|
|
58
60
|
);
|
|
59
61
|
const req = new BrunoRequest(request, historyLogger);
|
|
60
62
|
const res = new BrunoResponse(response);
|
|
@@ -14,6 +14,9 @@ class VarsRuntime {
|
|
|
14
14
|
historyLogger,
|
|
15
15
|
secretVars = {}
|
|
16
16
|
) {
|
|
17
|
+
if (!request?.requestVariables) {
|
|
18
|
+
request.requestVariables = {};
|
|
19
|
+
}
|
|
17
20
|
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
18
21
|
if (!enabledVars.length) {
|
|
19
22
|
return;
|
|
@@ -44,12 +47,8 @@ class VarsRuntime {
|
|
|
44
47
|
|
|
45
48
|
_.each(enabledVars, (v) => {
|
|
46
49
|
const value = evaluateJsTemplateLiteral(v.value, context);
|
|
47
|
-
|
|
50
|
+
request?.requestVariables && (request.requestVariables[v.name] = value);
|
|
48
51
|
});
|
|
49
|
-
|
|
50
|
-
return {
|
|
51
|
-
collectionVariables
|
|
52
|
-
};
|
|
53
52
|
}
|
|
54
53
|
|
|
55
54
|
runPostResponseVars(
|
|
@@ -63,6 +62,7 @@ class VarsRuntime {
|
|
|
63
62
|
historyLogger,
|
|
64
63
|
secretVars = {}
|
|
65
64
|
) {
|
|
65
|
+
const requestVariables = request?.requestVariables || {};
|
|
66
66
|
const enabledVars = _.filter(vars, (v) => v.enabled);
|
|
67
67
|
if (!enabledVars.length) {
|
|
68
68
|
return;
|
|
@@ -75,7 +75,8 @@ class VarsRuntime {
|
|
|
75
75
|
null,
|
|
76
76
|
historyLogger,
|
|
77
77
|
undefined, // setHtmlVisualizationString
|
|
78
|
-
secretVars
|
|
78
|
+
secretVars,
|
|
79
|
+
requestVariables
|
|
79
80
|
);
|
|
80
81
|
const req = new BrunoRequest(request, historyLogger);
|
|
81
82
|
const res = createResponseParser(response);
|
|
@@ -93,14 +94,27 @@ class VarsRuntime {
|
|
|
93
94
|
...bruContext
|
|
94
95
|
};
|
|
95
96
|
|
|
97
|
+
const errors = new Map();
|
|
96
98
|
_.each(enabledVars, (v) => {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
try {
|
|
100
|
+
const value = evaluateJsExpression(v.value, context);
|
|
101
|
+
bru.setVar(v.name, value);
|
|
102
|
+
} catch (error) {
|
|
103
|
+
errors.set(v.name, error);
|
|
104
|
+
}
|
|
99
105
|
});
|
|
100
106
|
|
|
107
|
+
let error = null;
|
|
108
|
+
if (errors.size > 0) {
|
|
109
|
+
// Format all errors as a single string to be displayed in a toast
|
|
110
|
+
const errorMessage = [...errors.entries()].map(([name, err]) => `${name}: ${err.message ?? err}`).join('\n');
|
|
111
|
+
error = `${errors.size} error${errors.size === 1 ? '' : 's'} in post response variables: \n${errorMessage}`;
|
|
112
|
+
}
|
|
113
|
+
|
|
101
114
|
return {
|
|
102
115
|
envVariables,
|
|
103
|
-
collectionVariables
|
|
116
|
+
collectionVariables,
|
|
117
|
+
error
|
|
104
118
|
};
|
|
105
119
|
}
|
|
106
120
|
}
|