@usebruno/js 0.42.2 → 0.44.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,23 +1,20 @@
1
1
  {
2
2
  "name": "@usebruno/js",
3
- "version": "0.42.2",
3
+ "version": "0.44.0",
4
4
  "license": "MIT",
5
5
  "main": "src/index.js",
6
6
  "files": [
7
7
  "src",
8
8
  "package.json"
9
9
  ],
10
- "peerDependencies": {
11
- "@usebruno/vm2": "^3.9.13"
12
- },
13
10
  "scripts": {
14
11
  "test": "node --experimental-vm-modules $(npx which jest) --testPathIgnorePatterns test.js",
15
12
  "sandbox:bundle-libraries": "node ./src/sandbox/bundle-libraries.js",
16
13
  "prepack": "npm run test"
17
14
  },
18
15
  "dependencies": {
19
- "@usebruno/common": "0.15.0",
20
- "@usebruno/query": "0.1.0",
16
+ "@usebruno/common": "0.17.0",
17
+ "@usebruno/query": "0.2.0",
21
18
  "ajv": "^8.12.0",
22
19
  "ajv-formats": "^2.1.1",
23
20
  "atob": "^2.1.2",
@@ -28,7 +25,7 @@
28
25
  "cheerio": "^1.0.0",
29
26
  "crypto-js": "^4.2.0",
30
27
  "json-query": "^2.2.2",
31
- "jsonwebtoken": "^9.0.2",
28
+ "jsonwebtoken": "^9.0.3",
32
29
  "lodash": "^4.17.21",
33
30
  "moment": "^2.29.4",
34
31
  "nanoid": "3.3.8",
package/src/bru.js CHANGED
@@ -8,9 +8,10 @@ const { jar: createCookieJar } = require('@usebruno/requests').cookies;
8
8
  const variableNameRegex = /^[\w-.]*$/;
9
9
 
10
10
  class Bru {
11
- constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName) {
11
+ constructor(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables) {
12
12
  this.envVariables = envVariables || {};
13
13
  this.runtimeVariables = runtimeVariables || {};
14
+ this.promptVariables = promptVariables || {};
14
15
  this.processEnvVars = cloneDeep(processEnvVars || {});
15
16
  this.secretVariables = cloneDeep(secretVariables || {});
16
17
  this.collectionVariables = collectionVariables || {};
@@ -26,7 +27,7 @@ class Bru {
26
27
  this.cookies = {
27
28
  jar: () => {
28
29
  const cookieJar = createCookieJar();
29
-
30
+
30
31
  return {
31
32
  getCookie: (url, cookieName, callback) => {
32
33
  const interpolatedUrl = this.interpolate(url);
@@ -81,7 +82,7 @@ class Bru {
81
82
  iterationData: new IterationDataManager(iterationDetails?.iterationData),
82
83
  iterationIndex: iterationDetails?.iterationIndex,
83
84
  totalIterations: iterationDetails?.totalIterations
84
- };
85
+ };
85
86
 
86
87
  this.utils = {
87
88
  minifyJson: (json) => {
@@ -127,7 +128,6 @@ class Bru {
127
128
  }
128
129
  };
129
130
  }
130
-
131
131
 
132
132
  interpolate = (strOrObj) => {
133
133
  if (!strOrObj) return strOrObj;
@@ -142,6 +142,7 @@ class Bru {
142
142
  ...this.requestVariables,
143
143
  ...this.oauth2CredentialVariables,
144
144
  ...this.runtimeVariables,
145
+ ...this.promptVariables,
145
146
  process: {
146
147
  env: {
147
148
  ...this.processEnvVars
@@ -177,7 +178,7 @@ class Bru {
177
178
  if (!key) {
178
179
  throw new Error('Creating a env variable without specifying a name is not allowed.');
179
180
  }
180
-
181
+
181
182
  if (variableNameRegex.test(key) === false) {
182
183
  throw new Error(
183
184
  `Variable name: "${key}" contains invalid characters! Names must only contain alpha-numeric characters, "-", "_", "."`
@@ -240,8 +241,8 @@ class Bru {
240
241
 
241
242
  if (variableNameRegex.test(key) === false) {
242
243
  throw new Error(
243
- `Variable name: "${key}" contains invalid characters!` +
244
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
244
+ `Variable name: "${key}" contains invalid characters!`
245
+ + ' Names must only contain alpha-numeric characters, "-", "_", "."'
245
246
  );
246
247
  }
247
248
 
@@ -260,8 +261,8 @@ class Bru {
260
261
  getVar(key) {
261
262
  if (variableNameRegex.test(key) === false) {
262
263
  throw new Error(
263
- `Variable name: "${key}" contains invalid characters!` +
264
- ' Names must only contain alpha-numeric characters, "-", "_", "."'
264
+ `Variable name: "${key}" contains invalid characters!`
265
+ + ' Names must only contain alpha-numeric characters, "-", "_", "."'
265
266
  );
266
267
  }
267
268
 
@@ -296,12 +297,10 @@ class Bru {
296
297
  this.nextRequest = nextRequest;
297
298
  }
298
299
 
299
-
300
300
  getSecretVar(key) {
301
301
  return this.secretVariables?.[`$secrets.${key}`];
302
302
  }
303
303
 
304
-
305
304
  visualize(type, data) {
306
305
  if (type == 'table') {
307
306
  if (data?.provider == 'ag-grid') {
@@ -8,7 +8,7 @@ class BrunoRequest {
8
8
  * - req.headers
9
9
  * - req.timeout
10
10
  * - req.body
11
- *
11
+ *
12
12
  * Above shorthands are useful for accessing the request properties directly in the scripts
13
13
  * It must be noted that the user cannot set these properties directly.
14
14
  * They should use the respective setter methods to set these properties.
@@ -26,9 +26,9 @@ class BrunoRequest {
26
26
  /**
27
27
  * We automatically parse the JSON body if the content type is JSON
28
28
  * This is to make it easier for the user to access the body directly
29
- *
29
+ *
30
30
  * It must be noted that the request data is always a string and is what gets sent over the network
31
- * If the user wants to access the raw data, they can use getBody({raw: true}) method
31
+ * If the user wants to access the raw data, they can use getBody({raw: true}) method
32
32
  */
33
33
  const isJson = this.hasJSONContentType(this.req.headers);
34
34
  if (isJson) {
@@ -48,6 +48,7 @@ class BrunoRequest {
48
48
  getMethod() {
49
49
  return this.req.method;
50
50
  }
51
+
51
52
  getAuthMode() {
52
53
  if (this.req?.oauth2) {
53
54
  return 'oauth2';
@@ -104,7 +105,7 @@ class BrunoRequest {
104
105
 
105
106
  /**
106
107
  * Get the body of the request
107
- *
108
+ *
108
109
  * We automatically parse and return the JSON body if the content type is JSON
109
110
  * If the user wants the raw body, they can pass the raw option as true
110
111
  */
@@ -128,7 +129,7 @@ class BrunoRequest {
128
129
  * Otherwise
129
130
  * - We set the request data as the data itself
130
131
  * - We set the body property as the data itself
131
- *
132
+ *
132
133
  * If the user wants to override this behavior, they can pass the raw option as true
133
134
  */
134
135
  setBody(data, options = {}) {
@@ -140,7 +141,7 @@ class BrunoRequest {
140
141
  createdAt: new Date().toISOString()
141
142
  });
142
143
  }
143
-
144
+
144
145
  if (options.raw) {
145
146
  this.req.data = data;
146
147
  this.body = data;
@@ -170,7 +171,7 @@ class BrunoRequest {
170
171
  this.timeout = timeout;
171
172
  this.req.timeout = timeout;
172
173
  }
173
-
174
+
174
175
  onFail(callback) {
175
176
  if (typeof callback === 'function') {
176
177
  this.req.onFailHandler = callback;
@@ -198,7 +199,6 @@ class BrunoRequest {
198
199
  __isObject(obj) {
199
200
  return obj !== null && typeof obj === 'object';
200
201
  }
201
-
202
202
 
203
203
  disableParsingResponseJson() {
204
204
  this.req.__brunoDisableParsingResponseJson = true;
@@ -65,7 +65,7 @@ class BrunoResponse {
65
65
 
66
66
  const { data, dataBuffer, headers } = this.res;
67
67
  let bodySize = 0;
68
-
68
+
69
69
  // Use raw received bytes
70
70
  if (Buffer.isBuffer(dataBuffer)) {
71
71
  bodySize = dataBuffer.length;
@@ -94,7 +94,6 @@ class BrunoResponse {
94
94
  const headerSize = Buffer.byteLength(headerLines.join('\r\n'));
95
95
 
96
96
  return { header: headerSize, body: bodySize, total: headerSize + bodySize };
97
-
98
97
  }
99
98
 
100
99
  getDataBuffer() {
@@ -241,7 +241,7 @@ const evaluateRhsOperand = (rhsOperand, operator, context, runtime) => {
241
241
 
242
242
  class AssertRuntime {
243
243
  constructor(props) {
244
- this.runtime = props?.runtime || 'vm2';
244
+ this.runtime = props?.runtime || 'quickjs';
245
245
  }
246
246
 
247
247
  runAssertions(assertions, request, response, envVariables, runtimeVariables, processEnvVars, historyLogger, secretVariables) {
@@ -250,6 +250,7 @@ class AssertRuntime {
250
250
  const collectionVariables = request?.collectionVariables || {};
251
251
  const folderVariables = request?.folderVariables || {};
252
252
  const requestVariables = request?.requestVariables || {};
253
+ const promptVariables = request?.promptVariables || {};
253
254
  const iterationDetails = request?.runnerIterationDetails || {};
254
255
  const enabledAssertions = _.filter(assertions, (a) => a.enabled);
255
256
  if (!enabledAssertions.length) {
@@ -269,7 +270,9 @@ class AssertRuntime {
269
270
  requestVariables,
270
271
  globalEnvironmentVariables,
271
272
  oauth2CredentialVariables,
272
- iterationDetails
273
+ iterationDetails,
274
+ undefined,
275
+ promptVariables
273
276
  );
274
277
  const req = new BrunoRequest(request, historyLogger);
275
278
  const res = createResponseParser(response);
@@ -1,45 +1,15 @@
1
- const { NodeVM } = require('@usebruno/vm2');
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');
10
- const fs = require('fs');
11
- const { get } = require('lodash');
1
+ const chai = require('chai');
12
2
  const Bru = require('../bru');
13
3
  const BrunoRequest = require('../bruno-request');
14
4
  const BrunoResponse = require('../bruno-response');
15
5
  const { cleanJson } = require('../utils');
16
6
  const { createBruTestResultMethods } = require('../utils/results');
17
7
  const { runScriptInNodeVm } = require('../sandbox/node-vm');
18
-
19
- // Inbuilt Library Support
20
- const ajv = require('ajv');
21
- const addFormats = require('ajv-formats');
22
- const atob = require('atob');
23
- const btoa = require('btoa');
24
- const lodash = require('lodash');
25
- const moment = require('moment');
26
- const uuid = require('uuid');
27
- const nanoid = require('nanoid');
28
- const axios = require('axios');
29
- const fetch = require('node-fetch');
30
- const chai = require('chai');
31
- const CryptoJS = require('crypto-js');
32
- const NodeVault = require('node-vault');
33
- const xml2js = require('xml2js');
34
- const cheerio = require('cheerio');
35
- const tv4 = require('tv4');
36
- const jsonwebtoken = require('jsonwebtoken');
37
8
  const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
38
- const { mixinTypedArrays } = require('../sandbox/mixins/typed-arrays');
39
9
 
40
10
  class ScriptRuntime {
41
11
  constructor(props) {
42
- this.runtime = props?.runtime || 'vm2';
12
+ this.runtime = props?.runtime || 'quickjs';
43
13
  }
44
14
 
45
15
  // This approach is getting out of hand
@@ -61,35 +31,18 @@ class ScriptRuntime {
61
31
  let visualizations = [];
62
32
  let setVisualizations = (data) => {
63
33
  visualizations.push(data);
64
- }
34
+ };
65
35
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
66
36
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
67
37
  const collectionVariables = request?.collectionVariables || {};
68
38
  const folderVariables = request?.folderVariables || {};
69
39
  const requestVariables = request?.requestVariables || {};
40
+ const promptVariables = request?.promptVariables || {};
70
41
  const iterationDetails = request?.runnerIterationDetails || {};
71
42
  const assertionResults = request?.assertionResults || [];
72
43
  // TODO please clean this up
73
- const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
44
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables);
74
45
  const req = new BrunoRequest(request);
75
- const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
76
- const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
77
- const additionalContextRoots = get(scriptingConfig, 'additionalContextRoots', []);
78
- const additionalContextRootsAbsolute = lodash
79
- .chain(additionalContextRoots)
80
- .map((acr) => (acr.startsWith('/') ? acr : path.join(collectionPath, acr)))
81
- .value();
82
-
83
- const whitelistedModules = {};
84
-
85
- for (let module of moduleWhitelist) {
86
- try {
87
- whitelistedModules[module] = require(module);
88
- } catch (e) {
89
- // Ignore
90
- console.warn(e);
91
- }
92
- }
93
46
 
94
47
  // extend bru with result getter methods
95
48
  const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
@@ -103,10 +56,6 @@ class ScriptRuntime {
103
56
  __brunoTestResults: __brunoTestResults
104
57
  };
105
58
 
106
- if (this.runtime === 'vm2') {
107
- mixinTypedArrays(context);
108
- }
109
-
110
59
  if (onConsoleLog && typeof onConsoleLog === 'function') {
111
60
  const customLogger = (type) => {
112
61
  return (...args) => {
@@ -148,70 +97,12 @@ class ScriptRuntime {
148
97
  };
149
98
  }
150
99
 
151
- if (this.runtime === 'quickjs') {
152
- await executeQuickJsVmAsync({
153
- script: script,
154
- context: context,
155
- collectionPath
156
- });
157
-
158
- return {
159
- request,
160
- envVariables: cleanJson(envVariables),
161
- runtimeVariables: cleanJson(runtimeVariables),
162
- visualizations,
163
- persistentEnvVariables: bru.persistentEnvVariables,
164
- globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
165
- results: cleanJson(__brunoTestResults.getResults()),
166
- nextRequestName: bru.nextRequest,
167
- skipRequest: bru.skipRequest,
168
- stopExecution: bru.stopExecution
169
- };
170
- }
171
-
172
- // default runtime is vm2
173
- const vm = new NodeVM({
174
- sandbox: context,
175
- require: {
176
- context: 'sandbox',
177
- builtin: [ "*" ],
178
- external: true,
179
- root: [collectionPath, ...additionalContextRootsAbsolute],
180
- mock: {
181
- // node libs
182
- path,
183
- stream,
184
- util,
185
- url,
186
- http,
187
- https,
188
- punycode,
189
- zlib,
190
- // 3rd party libs
191
- ajv,
192
- 'ajv-formats': addFormats,
193
- atob,
194
- btoa,
195
- lodash,
196
- moment,
197
- uuid,
198
- nanoid,
199
- axios,
200
- chai,
201
- 'node-fetch': fetch,
202
- 'crypto-js': CryptoJS,
203
- xml2js: xml2js,
204
- jsonwebtoken,
205
- cheerio,
206
- tv4,
207
- ...whitelistedModules,
208
- fs: allowScriptFilesystemAccess ? fs : undefined,
209
- 'node-vault': NodeVault
210
- }
211
- }
100
+ // default runtime is `quickjs`
101
+ await executeQuickJsVmAsync({
102
+ script: script,
103
+ context: context,
104
+ collectionPath
212
105
  });
213
- const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
214
- await asyncVM();
215
106
 
216
107
  return {
217
108
  request,
@@ -245,35 +136,18 @@ class ScriptRuntime {
245
136
  let visualizations = [];
246
137
  let setVisualizations = (data) => {
247
138
  visualizations.push(data);
248
- }
139
+ };
249
140
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
250
141
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
251
142
  const collectionVariables = request?.collectionVariables || {};
252
143
  const folderVariables = request?.folderVariables || {};
253
144
  const requestVariables = request?.requestVariables || {};
145
+ const promptVariables = request?.promptVariables || {};
254
146
  const iterationDetails = request?.runnerIterationDetails || {};
255
147
  const assertionResults = request?.assertionResults || [];
256
- const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName);
148
+ const bru = new Bru(envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables);
257
149
  const req = new BrunoRequest(request);
258
150
  const res = new BrunoResponse(response);
259
- const allowScriptFilesystemAccess = get(scriptingConfig, 'filesystemAccess.allow', false);
260
- const moduleWhitelist = get(scriptingConfig, 'moduleWhitelist', []);
261
- const additionalContextRoots = get(scriptingConfig, 'additionalContextRoots', []);
262
- const additionalContextRootsAbsolute = lodash
263
- .chain(additionalContextRoots)
264
- .map((acr) => (acr.startsWith('/') ? acr : path.join(collectionPath, acr)))
265
- .value();
266
-
267
- const whitelistedModules = {};
268
-
269
- for (let module of moduleWhitelist) {
270
- try {
271
- whitelistedModules[module] = require(module);
272
- } catch (e) {
273
- // Ignore
274
- console.warn(e);
275
- }
276
- }
277
151
 
278
152
  // extend bru with result getter methods
279
153
  const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
@@ -288,10 +162,6 @@ class ScriptRuntime {
288
162
  __brunoTestResults: __brunoTestResults
289
163
  };
290
164
 
291
- if (this.runtime === 'vm2') {
292
- mixinTypedArrays(context);
293
- }
294
-
295
165
  if (onConsoleLog && typeof onConsoleLog === 'function') {
296
166
  const customLogger = (type) => {
297
167
  return (...args) => {
@@ -333,71 +203,13 @@ class ScriptRuntime {
333
203
  };
334
204
  }
335
205
 
336
- if (this.runtime === 'quickjs') {
337
- await executeQuickJsVmAsync({
338
- script: script,
339
- context: context,
340
- collectionPath
341
- });
342
-
343
- return {
344
- response,
345
- envVariables: cleanJson(envVariables),
346
- persistentEnvVariables: cleanJson(bru.persistentEnvVariables),
347
- runtimeVariables: cleanJson(runtimeVariables),
348
- visualizations,
349
- globalEnvironmentVariables: cleanJson(globalEnvironmentVariables),
350
- results: cleanJson(__brunoTestResults.getResults()),
351
- nextRequestName: bru.nextRequest,
352
- skipRequest: bru.skipRequest,
353
- stopExecution: bru.stopExecution
354
- };
355
- }
356
-
357
- // default runtime is vm2
358
- const vm = new NodeVM({
359
- sandbox: context,
360
- require: {
361
- context: 'sandbox',
362
- builtin: [ "*" ],
363
- external: true,
364
- root: [collectionPath, ...additionalContextRootsAbsolute],
365
- mock: {
366
- // node libs
367
- path,
368
- stream,
369
- util,
370
- url,
371
- http,
372
- https,
373
- punycode,
374
- zlib,
375
- // 3rd party libs
376
- ajv,
377
- 'ajv-formats': addFormats,
378
- atob,
379
- btoa,
380
- lodash,
381
- moment,
382
- uuid,
383
- nanoid,
384
- axios,
385
- 'node-fetch': fetch,
386
- 'crypto-js': CryptoJS,
387
- 'xml2js': xml2js,
388
- jsonwebtoken,
389
- cheerio,
390
- tv4,
391
- ...whitelistedModules,
392
- fs: allowScriptFilesystemAccess ? fs : undefined,
393
- 'node-vault': NodeVault
394
- }
395
- }
206
+ // default runtime is `quickjs`
207
+ await executeQuickJsVmAsync({
208
+ script: script,
209
+ context: context,
210
+ collectionPath
396
211
  });
397
212
 
398
- const asyncVM = vm.run(`module.exports = async () => { ${script} }`, path.join(collectionPath, 'vm.js'));
399
- await asyncVM();
400
-
401
213
  return {
402
214
  response,
403
215
  envVariables: cleanJson(envVariables),