@usebruno/js 0.2.0 → 0.4.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 +5 -3
- package/src/bru.js +6 -2
- package/src/bruno-response.js +8 -8
- package/src/runtime/assert-runtime.js +92 -15
- package/src/runtime/script-runtime.js +33 -11
- package/src/runtime/test-runtime.js +12 -3
- package/src/runtime/vars-runtime.js +11 -2
- package/src/utils.js +41 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebruno/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"main": "src/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"src",
|
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
16
|
"@usebruno/query": "0.1.0",
|
|
17
|
-
"atob": "^2.1.2",
|
|
18
17
|
"ajv": "^8.12.0",
|
|
18
|
+
"atob": "^2.1.2",
|
|
19
|
+
"axios": "^0.26.0",
|
|
19
20
|
"btoa": "^1.2.1",
|
|
20
21
|
"crypto-js": "^4.1.1",
|
|
21
22
|
"json-query": "^2.2.2",
|
|
22
23
|
"lodash": "^4.17.21",
|
|
23
24
|
"moment": "^2.29.4",
|
|
24
25
|
"nanoid": "3.3.4",
|
|
26
|
+
"node-fetch": "2.*",
|
|
25
27
|
"uuid": "^9.0.0"
|
|
26
28
|
}
|
|
27
|
-
}
|
|
29
|
+
}
|
package/src/bru.js
CHANGED
|
@@ -5,6 +5,10 @@ class Bru {
|
|
|
5
5
|
this._collectionVariables = collectionVariables;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
getProcessEnv(key) {
|
|
9
|
+
return process.env[key];
|
|
10
|
+
}
|
|
11
|
+
|
|
8
12
|
getEnvVar(key) {
|
|
9
13
|
return this._envVariables[key];
|
|
10
14
|
}
|
|
@@ -16,7 +20,7 @@ class Bru {
|
|
|
16
20
|
|
|
17
21
|
// gracefully ignore if key is not present in environment
|
|
18
22
|
if(!this._envVariables.hasOwnProperty(key)) {
|
|
19
|
-
|
|
23
|
+
return;
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
this._envVariables[key] = value;
|
|
@@ -35,4 +39,4 @@ class Bru {
|
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
|
|
38
|
-
module.exports = Bru;
|
|
42
|
+
module.exports = Bru;
|
package/src/bruno-response.js
CHANGED
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
class BrunoResponse {
|
|
2
2
|
constructor(res) {
|
|
3
3
|
this.res = res;
|
|
4
|
-
this.status = res.status;
|
|
5
|
-
this.statusText = res.statusText;
|
|
6
|
-
this.headers = res.headers;
|
|
7
|
-
this.body = res.data;
|
|
4
|
+
this.status = res ? res.status : null;
|
|
5
|
+
this.statusText = res ? res.statusText : null;
|
|
6
|
+
this.headers = res ? res.headers : null;
|
|
7
|
+
this.body = res ? res.data : null;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
getStatus() {
|
|
11
|
-
return this.res.status;
|
|
11
|
+
return this.res ? this.res.status : null;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
getHeader(name) {
|
|
15
|
-
return this.res.
|
|
15
|
+
return (this.res && this.res.headers) ? this.res.headers[name] : null;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
getHeaders() {
|
|
19
|
-
return this.res.headers;
|
|
19
|
+
return this.res ? this.res.headers : null;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
getBody() {
|
|
23
|
-
return this.res.data;
|
|
23
|
+
return this.res ? this.res.data : null;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -1,17 +1,49 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
|
-
const chai = require('chai');
|
|
2
|
+
const chai = require('chai');
|
|
3
|
+
const { nanoid } = require('nanoid');
|
|
3
4
|
const Bru = require('../bru');
|
|
4
5
|
const BrunoRequest = require('../bruno-request');
|
|
5
|
-
const { evaluateJsExpression, createResponseParser } = require('../utils');
|
|
6
|
+
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
|
|
6
7
|
|
|
7
8
|
const { expect } = chai;
|
|
9
|
+
chai.use(function (chai, utils) {
|
|
10
|
+
// Custom assertion for checking if a variable is JSON
|
|
11
|
+
chai.Assertion.addProperty('json', function () {
|
|
12
|
+
const obj = this._obj;
|
|
13
|
+
const isJson = typeof obj === 'object' && obj !== null && !Array.isArray(obj) && obj.constructor === Object;
|
|
14
|
+
|
|
15
|
+
this.assert(
|
|
16
|
+
isJson,
|
|
17
|
+
`expected ${utils.inspect(obj)} to be JSON`,
|
|
18
|
+
`expected ${utils.inspect(obj)} not to be JSON`
|
|
19
|
+
);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// Custom assertion for matching regex
|
|
24
|
+
chai.use(function (chai, utils) {
|
|
25
|
+
chai.Assertion.addMethod('match', function (regex) {
|
|
26
|
+
const obj = this._obj;
|
|
27
|
+
let match = false;
|
|
28
|
+
if(obj === undefined) {
|
|
29
|
+
match = false;
|
|
30
|
+
} else {
|
|
31
|
+
match = regex.test(obj);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
this.assert(
|
|
35
|
+
match,
|
|
36
|
+
`expected ${utils.inspect(obj)} to match ${regex}`,
|
|
37
|
+
`expected ${utils.inspect(obj)} not to match ${regex}`
|
|
38
|
+
);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
8
41
|
|
|
9
42
|
/**
|
|
10
43
|
* Assertion operators
|
|
11
44
|
*
|
|
12
45
|
* eq : equal to
|
|
13
46
|
* neq : not equal to
|
|
14
|
-
* like : like
|
|
15
47
|
* gt : greater than
|
|
16
48
|
* gte : greater than or equal to
|
|
17
49
|
* lt : less than
|
|
@@ -20,7 +52,6 @@ const { expect } = chai;
|
|
|
20
52
|
* notIn : not in
|
|
21
53
|
* contains : contains
|
|
22
54
|
* notContains : not contains
|
|
23
|
-
* count : count
|
|
24
55
|
* length : length
|
|
25
56
|
* matches : matches
|
|
26
57
|
* notMatches : not matches
|
|
@@ -47,15 +78,26 @@ const parseAssertionOperator = (str = '') => {
|
|
|
47
78
|
}
|
|
48
79
|
|
|
49
80
|
const operators = [
|
|
50
|
-
'eq', 'neq', '
|
|
51
|
-
'contains', 'notContains', '
|
|
81
|
+
'eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'in', 'notIn',
|
|
82
|
+
'contains', 'notContains', 'length', 'matches', 'notMatches',
|
|
52
83
|
'startsWith', 'endsWith', 'between', 'isEmpty', 'isNull', 'isUndefined',
|
|
53
84
|
'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean'
|
|
54
85
|
];
|
|
55
86
|
|
|
87
|
+
const unaryOperators = [
|
|
88
|
+
'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean'
|
|
89
|
+
];
|
|
90
|
+
|
|
56
91
|
const [operator, ...rest] = str.trim().split(' ');
|
|
57
92
|
const value = rest.join(' ');
|
|
58
93
|
|
|
94
|
+
if(unaryOperators.includes(operator)) {
|
|
95
|
+
return {
|
|
96
|
+
operator,
|
|
97
|
+
value: ''
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
59
101
|
if(operators.includes(operator)) {
|
|
60
102
|
return {
|
|
61
103
|
operator,
|
|
@@ -69,6 +111,45 @@ const parseAssertionOperator = (str = '') => {
|
|
|
69
111
|
};
|
|
70
112
|
};
|
|
71
113
|
|
|
114
|
+
const isUnaryOperator = (operator) => {
|
|
115
|
+
const unaryOperators = [
|
|
116
|
+
'isEmpty', 'isNull', 'isUndefined', 'isDefined', 'isTruthy', 'isFalsy', 'isJson', 'isNumber', 'isString', 'isBoolean'
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
return unaryOperators.includes(operator);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const evaluateRhsOperand = (rhsOperand, operator, context) => {
|
|
123
|
+
if(isUnaryOperator(operator)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// gracefully allow both a,b as well as [a, b]
|
|
128
|
+
if(operator === 'in' || operator === 'notIn') {
|
|
129
|
+
if(rhsOperand.startsWith('[') && rhsOperand.endsWith(']')) {
|
|
130
|
+
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context));
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if(operator === 'between') {
|
|
137
|
+
const [lhs, rhs] = rhsOperand.split(',').map((v) => evaluateJsTemplateLiteral(v.trim(), context));
|
|
138
|
+
return [lhs, rhs];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// gracefully allow both ^[a-Z] as well as /^[a-Z]/
|
|
142
|
+
if(operator === 'matches' || operator === 'notMatches') {
|
|
143
|
+
if(rhsOperand.startsWith('/') && rhsOperand.endsWith('/')) {
|
|
144
|
+
rhsOperand = rhsOperand.substring(1, rhsOperand.length - 1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return rhsOperand;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return evaluateJsTemplateLiteral(rhsOperand, context);
|
|
151
|
+
};
|
|
152
|
+
|
|
72
153
|
class AssertRuntime {
|
|
73
154
|
runAssertions(assertions, request, response, envVariables, collectionVariables, collectionPath) {
|
|
74
155
|
const enabledAssertions = _.filter(assertions, (a) => a.enabled);
|
|
@@ -105,7 +186,7 @@ class AssertRuntime {
|
|
|
105
186
|
|
|
106
187
|
try {
|
|
107
188
|
const lhs = evaluateJsExpression(lhsExpr, context);
|
|
108
|
-
const rhs =
|
|
189
|
+
const rhs = evaluateRhsOperand(rhsOperand, operator, context);
|
|
109
190
|
|
|
110
191
|
switch(operator) {
|
|
111
192
|
case 'eq':
|
|
@@ -114,9 +195,6 @@ class AssertRuntime {
|
|
|
114
195
|
case 'neq':
|
|
115
196
|
expect(lhs).to.not.equal(rhs);
|
|
116
197
|
break;
|
|
117
|
-
case 'like':
|
|
118
|
-
expect(lhs).to.match(new RegExp(rhs));
|
|
119
|
-
break;
|
|
120
198
|
case 'gt':
|
|
121
199
|
expect(lhs).to.be.greaterThan(rhs);
|
|
122
200
|
break;
|
|
@@ -141,9 +219,6 @@ class AssertRuntime {
|
|
|
141
219
|
case 'notContains':
|
|
142
220
|
expect(lhs).to.not.include(rhs);
|
|
143
221
|
break;
|
|
144
|
-
case 'count':
|
|
145
|
-
expect(lhs).to.have.lengthOf(rhs);
|
|
146
|
-
break;
|
|
147
222
|
case 'length':
|
|
148
223
|
expect(lhs).to.have.lengthOf(rhs);
|
|
149
224
|
break;
|
|
@@ -160,7 +235,7 @@ class AssertRuntime {
|
|
|
160
235
|
expect(lhs).to.endWith(rhs);
|
|
161
236
|
break;
|
|
162
237
|
case 'between':
|
|
163
|
-
const [min, max] = value.split('
|
|
238
|
+
const [min, max] = value.split(',');
|
|
164
239
|
expect(lhs).to.be.within(min, max);
|
|
165
240
|
break;
|
|
166
241
|
case 'isEmpty':
|
|
@@ -199,6 +274,7 @@ class AssertRuntime {
|
|
|
199
274
|
}
|
|
200
275
|
|
|
201
276
|
assertionResults.push({
|
|
277
|
+
uid: nanoid(),
|
|
202
278
|
lhsExpr,
|
|
203
279
|
rhsExpr,
|
|
204
280
|
rhsOperand,
|
|
@@ -208,6 +284,7 @@ class AssertRuntime {
|
|
|
208
284
|
}
|
|
209
285
|
catch (err) {
|
|
210
286
|
assertionResults.push({
|
|
287
|
+
uid: nanoid(),
|
|
211
288
|
lhsExpr,
|
|
212
289
|
rhsExpr,
|
|
213
290
|
rhsOperand,
|
|
@@ -222,4 +299,4 @@ class AssertRuntime {
|
|
|
222
299
|
}
|
|
223
300
|
}
|
|
224
301
|
|
|
225
|
-
module.exports = AssertRuntime;
|
|
302
|
+
module.exports = AssertRuntime;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
const { NodeVM } = require('vm2');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const http = require('http');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const stream = require('stream');
|
|
6
|
+
const util = require('util');
|
|
7
|
+
const zlib = require('zlib');
|
|
8
|
+
const url = require('url');
|
|
9
|
+
const punycode = require('punycode');
|
|
3
10
|
const Bru = require('../bru');
|
|
4
11
|
const BrunoRequest = require('../bruno-request');
|
|
5
12
|
const BrunoResponse = require('../bruno-response');
|
|
@@ -11,16 +18,17 @@ const lodash = require('lodash');
|
|
|
11
18
|
const moment = require('moment');
|
|
12
19
|
const uuid = require('uuid');
|
|
13
20
|
const nanoid = require('nanoid');
|
|
21
|
+
const axios = require('axios');
|
|
22
|
+
const fetch = require('node-fetch');
|
|
14
23
|
const CryptoJS = require('crypto-js');
|
|
15
24
|
|
|
16
25
|
class ScriptRuntime {
|
|
17
26
|
constructor() {
|
|
18
27
|
}
|
|
19
28
|
|
|
20
|
-
runRequestScript(script, request,
|
|
21
|
-
const bru = new Bru(
|
|
29
|
+
async runRequestScript(script, request, envVariables, collectionVariables, collectionPath){
|
|
30
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
22
31
|
const req = new BrunoRequest(request);
|
|
23
|
-
|
|
24
32
|
const context = {
|
|
25
33
|
bru,
|
|
26
34
|
req
|
|
@@ -32,28 +40,39 @@ class ScriptRuntime {
|
|
|
32
40
|
external: true,
|
|
33
41
|
root: [collectionPath],
|
|
34
42
|
mock: {
|
|
43
|
+
// node libs
|
|
44
|
+
path,
|
|
45
|
+
stream,
|
|
46
|
+
util,
|
|
47
|
+
url,
|
|
48
|
+
http,
|
|
49
|
+
https,
|
|
50
|
+
punycode,
|
|
51
|
+
zlib,
|
|
52
|
+
// 3rd party libs
|
|
35
53
|
atob,
|
|
36
54
|
btoa,
|
|
37
55
|
lodash,
|
|
38
56
|
moment,
|
|
39
57
|
uuid,
|
|
40
58
|
nanoid,
|
|
59
|
+
axios,
|
|
60
|
+
'node-fetch': fetch,
|
|
41
61
|
'crypto-js': CryptoJS
|
|
42
62
|
}
|
|
43
63
|
}
|
|
44
64
|
});
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
65
|
+
const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
|
|
66
|
+
await asyncVM();
|
|
48
67
|
return {
|
|
49
68
|
request,
|
|
50
|
-
|
|
69
|
+
envVariables,
|
|
51
70
|
collectionVariables
|
|
52
71
|
};
|
|
53
72
|
}
|
|
54
73
|
|
|
55
|
-
runResponseScript(script, request, response,
|
|
56
|
-
const bru = new Bru(
|
|
74
|
+
async runResponseScript(script, request, response, envVariables, collectionVariables, collectionPath) {
|
|
75
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
57
76
|
const req = new BrunoRequest(request);
|
|
58
77
|
const res = new BrunoResponse(response);
|
|
59
78
|
|
|
@@ -75,16 +94,19 @@ class ScriptRuntime {
|
|
|
75
94
|
moment,
|
|
76
95
|
uuid,
|
|
77
96
|
nanoid,
|
|
97
|
+
axios,
|
|
98
|
+
'node-fetch': fetch,
|
|
78
99
|
'crypto-js': CryptoJS
|
|
79
100
|
}
|
|
80
101
|
}
|
|
81
102
|
});
|
|
82
103
|
|
|
83
|
-
vm.run(script
|
|
104
|
+
const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
|
|
105
|
+
await asyncVM();
|
|
84
106
|
|
|
85
107
|
return {
|
|
86
108
|
response,
|
|
87
|
-
|
|
109
|
+
envVariables,
|
|
88
110
|
collectionVariables
|
|
89
111
|
};
|
|
90
112
|
}
|
|
@@ -20,14 +20,23 @@ class TestRuntime {
|
|
|
20
20
|
constructor() {
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
runTests(testsFile, request, response,
|
|
24
|
-
const bru = new Bru(
|
|
23
|
+
runTests(testsFile, request, response, envVariables, collectionVariables, collectionPath) {
|
|
24
|
+
const bru = new Bru(envVariables, collectionVariables);
|
|
25
25
|
const req = new BrunoRequest(request);
|
|
26
26
|
const res = new BrunoResponse(response);
|
|
27
27
|
|
|
28
28
|
const __brunoTestResults = new TestResults();
|
|
29
29
|
const test = Test(__brunoTestResults, chai);
|
|
30
30
|
|
|
31
|
+
if(!testsFile || !testsFile.length) {
|
|
32
|
+
return {
|
|
33
|
+
request,
|
|
34
|
+
envVariables,
|
|
35
|
+
collectionVariables,
|
|
36
|
+
results: __brunoTestResults.getResults()
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
31
40
|
const context = {
|
|
32
41
|
test,
|
|
33
42
|
bru,
|
|
@@ -60,7 +69,7 @@ class TestRuntime {
|
|
|
60
69
|
|
|
61
70
|
return {
|
|
62
71
|
request,
|
|
63
|
-
|
|
72
|
+
envVariables,
|
|
64
73
|
collectionVariables,
|
|
65
74
|
results: __brunoTestResults.getResults()
|
|
66
75
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const _ = require('lodash');
|
|
2
2
|
const Bru = require('../bru');
|
|
3
3
|
const BrunoRequest = require('../bruno-request');
|
|
4
|
-
const { evaluateJsExpression, createResponseParser } = require('../utils');
|
|
4
|
+
const { evaluateJsTemplateLiteral, evaluateJsExpression, createResponseParser } = require('../utils');
|
|
5
5
|
|
|
6
6
|
class VarsRuntime {
|
|
7
7
|
runPreRequestVars(vars, request, envVariables, collectionVariables, collectionPath) {
|
|
@@ -25,9 +25,13 @@ class VarsRuntime {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
_.each(enabledVars, (v) => {
|
|
28
|
-
const value =
|
|
28
|
+
const value = evaluateJsTemplateLiteral(v.value, context);
|
|
29
29
|
bru.setVar(v.name, value);
|
|
30
30
|
});
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
collectionVariables
|
|
34
|
+
};
|
|
31
35
|
}
|
|
32
36
|
|
|
33
37
|
runPostResponseVars(vars, request, response, envVariables, collectionVariables, collectionPath) {
|
|
@@ -56,6 +60,11 @@ class VarsRuntime {
|
|
|
56
60
|
const value = evaluateJsExpression(v.value, context);
|
|
57
61
|
bru.setVar(v.name, value);
|
|
58
62
|
});
|
|
63
|
+
|
|
64
|
+
return {
|
|
65
|
+
envVariables,
|
|
66
|
+
collectionVariables
|
|
67
|
+
};
|
|
59
68
|
}
|
|
60
69
|
}
|
|
61
70
|
|
package/src/utils.js
CHANGED
|
@@ -60,6 +60,46 @@ const evaluateJsExpression = (expression, context) => {
|
|
|
60
60
|
return fn(context);
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
+
const evaluateJsTemplateLiteral = (templateLiteral, context) => {
|
|
64
|
+
if(!templateLiteral || !templateLiteral.length || typeof templateLiteral !== 'string') {
|
|
65
|
+
return templateLiteral;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
templateLiteral = templateLiteral.trim();
|
|
69
|
+
|
|
70
|
+
if(templateLiteral === 'true') {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if(templateLiteral === 'false') {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if(templateLiteral === 'null') {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if(templateLiteral === 'undefined') {
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if(templateLiteral.startsWith('"') && templateLiteral.endsWith('"')) {
|
|
87
|
+
return templateLiteral.slice(1, -1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if(templateLiteral.startsWith("'") && templateLiteral.endsWith("'")) {
|
|
91
|
+
return templateLiteral.slice(1, -1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if(!isNaN(templateLiteral)) {
|
|
95
|
+
return Number(templateLiteral);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
templateLiteral = "`" + templateLiteral + "`";
|
|
99
|
+
|
|
100
|
+
return evaluateJsExpression(templateLiteral, context);
|
|
101
|
+
};
|
|
102
|
+
|
|
63
103
|
const createResponseParser = (response = {}) => {
|
|
64
104
|
const res = (expr, ...fns) => {
|
|
65
105
|
return get(response.data, expr, ...fns);
|
|
@@ -80,6 +120,7 @@ const createResponseParser = (response = {}) => {
|
|
|
80
120
|
|
|
81
121
|
module.exports = {
|
|
82
122
|
evaluateJsExpression,
|
|
123
|
+
evaluateJsTemplateLiteral,
|
|
83
124
|
createResponseParser,
|
|
84
125
|
internalExpressionCache
|
|
85
126
|
};
|