@usebruno/js 0.32.0 → 0.34.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 +4 -3
- package/src/bru.js +2 -0
- package/src/bruno-request.js +8 -0
- package/src/runtime/test-runtime.js +61 -47
- package/src/sandbox/quickjs/index.js +1 -1
- package/src/sandbox/quickjs/shims/bru.js +45 -3
- package/src/utils.js +28 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usebruno/js",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"files": [
|
|
@@ -12,10 +12,11 @@
|
|
|
12
12
|
},
|
|
13
13
|
"scripts": {
|
|
14
14
|
"test": "node --experimental-vm-modules $(npx which jest) --testPathIgnorePatterns test.js",
|
|
15
|
-
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js"
|
|
15
|
+
"sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js",
|
|
16
|
+
"prepack": "npm run test"
|
|
16
17
|
},
|
|
17
18
|
"dependencies": {
|
|
18
|
-
"@usebruno/common": "0.
|
|
19
|
+
"@usebruno/common": "0.8.0",
|
|
19
20
|
"@usebruno/crypto-js": "^3.1.9",
|
|
20
21
|
"@usebruno/query": "0.1.0",
|
|
21
22
|
"ajv": "^8.12.0",
|
package/src/bru.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const { cloneDeep } = require('lodash');
|
|
2
2
|
const { uuid } = require('./utils');
|
|
3
3
|
const { interpolate: _interpolate } = require('@usebruno/common');
|
|
4
|
+
const { sendRequest } = require('@usebruno/requests').scripting;
|
|
4
5
|
|
|
5
6
|
const variableNameRegex = /^[\w-.]*$/;
|
|
6
7
|
|
|
@@ -19,6 +20,7 @@ class Bru {
|
|
|
19
20
|
this.historyLogger = historyLogger;
|
|
20
21
|
this.setVisualizations = setVisualizations;
|
|
21
22
|
this.collectionName = collectionName;
|
|
23
|
+
this.sendRequest = sendRequest;
|
|
22
24
|
this.runner = {
|
|
23
25
|
skipRequest: () => {
|
|
24
26
|
this.skipRequest = true;
|
package/src/bruno-request.js
CHANGED
|
@@ -169,6 +169,14 @@ class BrunoRequest {
|
|
|
169
169
|
this.timeout = timeout;
|
|
170
170
|
this.req.timeout = timeout;
|
|
171
171
|
}
|
|
172
|
+
|
|
173
|
+
onFail(callback) {
|
|
174
|
+
if (typeof callback === 'function') {
|
|
175
|
+
this.req.onFailHandler = callback;
|
|
176
|
+
} else if (callback) {
|
|
177
|
+
throw new Error(`${callback} is not a function`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
172
180
|
|
|
173
181
|
__safeParseJSON(str) {
|
|
174
182
|
try {
|
|
@@ -128,53 +128,60 @@ class TestRuntime {
|
|
|
128
128
|
context.bru.runRequest = runRequestByItemPathname;
|
|
129
129
|
}
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
131
|
+
let scriptError = null;
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
if (this.runtime === 'quickjs') {
|
|
135
|
+
await executeQuickJsVmAsync({
|
|
136
|
+
script: testsFile,
|
|
137
|
+
context: context
|
|
138
|
+
});
|
|
139
|
+
} else {
|
|
140
|
+
// default runtime is vm2
|
|
141
|
+
const vm = new NodeVM({
|
|
142
|
+
sandbox: context,
|
|
143
|
+
require: {
|
|
144
|
+
context: 'sandbox',
|
|
145
|
+
external: true,
|
|
146
|
+
root: [collectionPath, ...additionalContextRootsAbsolute],
|
|
147
|
+
mock: {
|
|
148
|
+
// node libs
|
|
149
|
+
path,
|
|
150
|
+
stream,
|
|
151
|
+
util,
|
|
152
|
+
url,
|
|
153
|
+
http,
|
|
154
|
+
https,
|
|
155
|
+
punycode,
|
|
156
|
+
zlib,
|
|
157
|
+
// 3rd party libs
|
|
158
|
+
ajv,
|
|
159
|
+
'ajv-formats': addFormats,
|
|
160
|
+
btoa,
|
|
161
|
+
atob,
|
|
162
|
+
lodash,
|
|
163
|
+
moment,
|
|
164
|
+
uuid,
|
|
165
|
+
nanoid,
|
|
166
|
+
axios,
|
|
167
|
+
chai,
|
|
168
|
+
'node-fetch': fetch,
|
|
169
|
+
'crypto-js': CryptoJS,
|
|
170
|
+
'xml2js': xml2js,
|
|
171
|
+
cheerio,
|
|
172
|
+
tv4,
|
|
173
|
+
...whitelistedModules,
|
|
174
|
+
fs: allowScriptFilesystemAccess ? fs : undefined,
|
|
175
|
+
'node-vault': NodeVault
|
|
176
|
+
}
|
|
173
177
|
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
+
});
|
|
179
|
+
const asyncVM = vm.run(`module.exports = async () => { ${testsFile}}`, path.join(collectionPath, 'vm.js'));
|
|
180
|
+
await asyncVM();
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
scriptError = error;
|
|
184
|
+
console.error('Test script execution error:', error);
|
|
178
185
|
}
|
|
179
186
|
|
|
180
187
|
if (historyLogger) {
|
|
@@ -186,7 +193,7 @@ class TestRuntime {
|
|
|
186
193
|
});
|
|
187
194
|
}
|
|
188
195
|
|
|
189
|
-
|
|
196
|
+
const result = {
|
|
190
197
|
request,
|
|
191
198
|
envVariables: cleanJson(envVariables),
|
|
192
199
|
runtimeVariables: cleanJson(runtimeVariables),
|
|
@@ -194,6 +201,13 @@ class TestRuntime {
|
|
|
194
201
|
results: cleanJson(__brunoTestResults.getResults()),
|
|
195
202
|
nextRequestName: bru.nextRequest
|
|
196
203
|
};
|
|
204
|
+
|
|
205
|
+
if (scriptError) {
|
|
206
|
+
scriptError.partialResults = result;
|
|
207
|
+
throw scriptError;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return result;
|
|
197
211
|
}
|
|
198
212
|
}
|
|
199
213
|
|
|
@@ -142,10 +142,10 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
|
|
|
142
142
|
|
|
143
143
|
const { bru, req, res, test, __brunoTestResults, console: consoleFn } = externalContext;
|
|
144
144
|
|
|
145
|
+
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
|
145
146
|
bru && addBruShimToContext(vm, bru);
|
|
146
147
|
req && addBrunoRequestShimToContext(vm, req);
|
|
147
148
|
res && addBrunoResponseShimToContext(vm, res);
|
|
148
|
-
consoleFn && addConsoleShimToContext(vm, consoleFn);
|
|
149
149
|
addLocalModuleLoaderShimToContext(vm, collectionPath);
|
|
150
150
|
addPathShimToContext(vm);
|
|
151
151
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { cleanJson } = require('../../../utils');
|
|
1
|
+
const { cleanJson, cleanCircularJson } = require('../../../utils');
|
|
2
2
|
const { marshallToVm } = require('../utils');
|
|
3
3
|
|
|
4
4
|
const addBruShimToContext = (vm, bru) => {
|
|
@@ -252,8 +252,7 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
252
252
|
bru
|
|
253
253
|
.runRequest(vm.dump(args))
|
|
254
254
|
.then((response) => {
|
|
255
|
-
|
|
256
|
-
promise.resolve(marshallToVm(cleanJson({ status, statusText, headers, data, dataBuffer, size }), vm));
|
|
255
|
+
promise.resolve(marshallToVm(cleanCircularJson(response), vm));
|
|
257
256
|
})
|
|
258
257
|
.catch((err) => {
|
|
259
258
|
promise.resolve(
|
|
@@ -270,6 +269,26 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
270
269
|
});
|
|
271
270
|
runRequestHandle.consume((handle) => vm.setProp(bruObject, 'runRequest', handle));
|
|
272
271
|
|
|
272
|
+
let sendRequestHandle = vm.newFunction('_sendRequest', (args) => {
|
|
273
|
+
const promise = vm.newPromise();
|
|
274
|
+
bru
|
|
275
|
+
.sendRequest(vm.dump(args))
|
|
276
|
+
.then((response) => {
|
|
277
|
+
promise.resolve(marshallToVm(cleanCircularJson(response), vm));
|
|
278
|
+
})
|
|
279
|
+
.catch((err) => {
|
|
280
|
+
promise.reject(
|
|
281
|
+
marshallToVm(
|
|
282
|
+
cleanJson(err),
|
|
283
|
+
vm
|
|
284
|
+
)
|
|
285
|
+
);
|
|
286
|
+
});
|
|
287
|
+
promise.settled.then(vm.runtime.executePendingJobs);
|
|
288
|
+
return promise.handle;
|
|
289
|
+
});
|
|
290
|
+
sendRequestHandle.consume((handle) => vm.setProp(bruObject, '_sendRequest', handle));
|
|
291
|
+
|
|
273
292
|
const sleep = vm.newFunction('sleep', (timer) => {
|
|
274
293
|
const t = vm.getString(timer);
|
|
275
294
|
const promise = vm.newPromise();
|
|
@@ -285,6 +304,29 @@ const addBruShimToContext = (vm, bru) => {
|
|
|
285
304
|
vm.setProp(bruObject, 'runner', bruRunnerObject);
|
|
286
305
|
vm.setProp(vm.global, 'bru', bruObject);
|
|
287
306
|
bruObject.dispose();
|
|
307
|
+
|
|
308
|
+
vm.evalCode(`
|
|
309
|
+
globalThis.bru.sendRequest = async (requestConfig, callback) => {
|
|
310
|
+
if (!callback) return await globalThis.bru._sendRequest(requestConfig);
|
|
311
|
+
try {
|
|
312
|
+
const response = await globalThis.bru._sendRequest(requestConfig);
|
|
313
|
+
try {
|
|
314
|
+
await callback(null, response);
|
|
315
|
+
}
|
|
316
|
+
catch(error) {
|
|
317
|
+
return Promise.reject(error);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
catch(error) {
|
|
321
|
+
try {
|
|
322
|
+
await callback(JSON.parse(JSON.stringify(error)), null);
|
|
323
|
+
}
|
|
324
|
+
catch(err) {
|
|
325
|
+
return Promise.reject(err);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
`);
|
|
288
330
|
};
|
|
289
331
|
|
|
290
332
|
module.exports = addBruShimToContext;
|
package/src/utils.js
CHANGED
|
@@ -158,6 +158,32 @@ const appendAwaitToTestFunc = (str) => {
|
|
|
158
158
|
return str.replace(/(?<!\.\s*)(?<!await\s)(test\()/g, 'await $1');
|
|
159
159
|
};
|
|
160
160
|
|
|
161
|
+
const cleanCircularJson = (data) => {
|
|
162
|
+
try {
|
|
163
|
+
// Handle circular references by keeping track of seen objects
|
|
164
|
+
const seen = new WeakSet();
|
|
165
|
+
|
|
166
|
+
const replacer = (key, value) => {
|
|
167
|
+
// Skip non-objects and null
|
|
168
|
+
if (typeof value !== 'object' || value === null) {
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Detect circular reference
|
|
173
|
+
if (seen.has(value)) {
|
|
174
|
+
return '[Circular Reference]';
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
seen.add(value);
|
|
178
|
+
return value;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
return JSON.parse(JSON.stringify(data, replacer));
|
|
182
|
+
} catch (e) {
|
|
183
|
+
return data;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
|
|
161
187
|
module.exports = {
|
|
162
188
|
evaluateJsExpression,
|
|
163
189
|
evaluateJsTemplateLiteral,
|
|
@@ -165,5 +191,6 @@ module.exports = {
|
|
|
165
191
|
internalExpressionCache,
|
|
166
192
|
cleanJson,
|
|
167
193
|
uuid,
|
|
168
|
-
appendAwaitToTestFunc
|
|
194
|
+
appendAwaitToTestFunc,
|
|
195
|
+
cleanCircularJson
|
|
169
196
|
};
|