@usebruno/js 0.46.0 → 0.47.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.
@@ -0,0 +1,184 @@
1
+ const ReadOnlyPropertyList = require('./readonly-property-list');
2
+
3
+ /**
4
+ * PropertyList - A mutable collection data structure.
5
+ *
6
+ * Extends ReadOnlyPropertyList with mutation methods that operate on the
7
+ * internal _items array in static mode. In dynamic mode, all mutations
8
+ * throw — subclasses (e.g. CookieList) override with async implementations.
9
+ *
10
+ * Class hierarchy:
11
+ * ReadOnlyPropertyList (read-only, both modes)
12
+ * └── PropertyList (sync mutations in static mode; throws in dynamic mode)
13
+ * └── CookieList (overrides add/upsert/remove/clear/delete with async jar ops)
14
+ */
15
+ class PropertyList extends ReadOnlyPropertyList {
16
+ /**
17
+ * Guard that throws in dynamic mode. Called by all mutation methods.
18
+ * @param {string} method - Name of the calling method (for error message)
19
+ */
20
+ #ensureStaticMode(method) {
21
+ if (this._dynamic) {
22
+ throw new Error(`${method}() is not supported in dynamic mode. Override in subclass.`);
23
+ }
24
+ }
25
+
26
+ // ── Mutation methods ──────────────────────────────────────────────────
27
+
28
+ /**
29
+ * Append an item to the end of the list.
30
+ * @param {object} item
31
+ */
32
+ add(item) {
33
+ this.#ensureStaticMode('add');
34
+ this._items.push(item);
35
+ }
36
+
37
+ /**
38
+ * Alias for add().
39
+ * @param {object} item
40
+ */
41
+ append(item) {
42
+ return this.add(item);
43
+ }
44
+
45
+ /**
46
+ * Insert an item at the beginning of the list.
47
+ * @param {object} item
48
+ */
49
+ prepend(item) {
50
+ this.#ensureStaticMode('prepend');
51
+ this._items.unshift(item);
52
+ }
53
+
54
+ /**
55
+ * Insert an item before a reference item.
56
+ * @param {object} item - The item to insert
57
+ * @param {string|object} before - Key string or item object to insert before
58
+ */
59
+ insert(item, before) {
60
+ this.#ensureStaticMode('insert');
61
+ const idx = this.#findIndex(before);
62
+ if (idx === -1) {
63
+ this._items.push(item);
64
+ } else {
65
+ this._items.splice(idx, 0, item);
66
+ }
67
+ }
68
+
69
+ /**
70
+ * Insert an item after a reference item.
71
+ * @param {object} item - The item to insert
72
+ * @param {string|object} after - Key string or item object to insert after
73
+ */
74
+ insertAfter(item, after) {
75
+ this.#ensureStaticMode('insertAfter');
76
+ const idx = this.#findIndex(after);
77
+ if (idx === -1) {
78
+ this._items.push(item);
79
+ } else {
80
+ this._items.splice(idx + 1, 0, item);
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Remove items matching a predicate, key string, or item reference.
86
+ * @param {Function|string|object} predicate
87
+ */
88
+ remove(predicate) {
89
+ this.#ensureStaticMode('remove');
90
+ if (typeof predicate === 'function') {
91
+ this._items = this._items.filter((item) => !predicate(item));
92
+ } else if (typeof predicate === 'string') {
93
+ this._items = this._items.filter((item) => item[this._keyProperty] !== predicate);
94
+ } else if (predicate && typeof predicate === 'object') {
95
+ const idx = this.indexOf(predicate);
96
+ if (idx !== -1) {
97
+ this._items.splice(idx, 1);
98
+ }
99
+ }
100
+ }
101
+
102
+ /**
103
+ * Remove all items from the list.
104
+ */
105
+ clear() {
106
+ this.#ensureStaticMode('clear');
107
+ this._items = [];
108
+ }
109
+
110
+ /**
111
+ * Update an existing item by key, or append if not found.
112
+ * @param {object} item
113
+ */
114
+ upsert(item) {
115
+ this.#ensureStaticMode('upsert');
116
+ const key = item[this._keyProperty];
117
+ const idx = this._items.findIndex((i) => i[this._keyProperty] === key);
118
+ if (idx !== -1) {
119
+ this._items[idx] = item;
120
+ } else {
121
+ this._items.push(item);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Replace all items with a new array.
127
+ * @param {Array} items
128
+ */
129
+ populate(items) {
130
+ this.#ensureStaticMode('populate');
131
+ this._items = Array.isArray(items) ? [...items] : [];
132
+ }
133
+
134
+ /**
135
+ * Clear and repopulate with new items.
136
+ * @param {Array} items
137
+ */
138
+ repopulate(items) {
139
+ this.#ensureStaticMode('repopulate');
140
+ this.populate(items);
141
+ }
142
+
143
+ /**
144
+ * Merge items from another PropertyList or array.
145
+ * @param {PropertyList|Array} source - Source of items to merge
146
+ * @param {boolean} [prune=false] - If true, clear existing items first
147
+ */
148
+ assimilate(source, prune) {
149
+ this.#ensureStaticMode('assimilate');
150
+ if (prune) {
151
+ this._items = [];
152
+ }
153
+ let items;
154
+ if (ReadOnlyPropertyList.isPropertyList(source)) {
155
+ items = source.all();
156
+ } else if (Array.isArray(source)) {
157
+ items = source;
158
+ } else {
159
+ items = [];
160
+ }
161
+ for (const item of items) {
162
+ this._items.push(item);
163
+ }
164
+ }
165
+
166
+ // ── Internal helpers ──────────────────────────────────────────────────
167
+
168
+ /**
169
+ * Find the index of a reference (key string or item object).
170
+ * @param {string|object} ref
171
+ * @returns {number}
172
+ */
173
+ #findIndex(ref) {
174
+ if (typeof ref === 'string') {
175
+ return this._items.findIndex((i) => i[this._keyProperty] === ref);
176
+ }
177
+ if (ref && typeof ref === 'object') {
178
+ return this.indexOf(ref);
179
+ }
180
+ return -1;
181
+ }
182
+ }
183
+
184
+ module.exports = PropertyList;
@@ -0,0 +1,227 @@
1
+ /**
2
+ * ReadOnlyPropertyList - A read-only collection data structure.
3
+ *
4
+ * Two modes:
5
+ * - Static mode: items stored internally in an array (for headers, query params, etc.)
6
+ * - Dynamic mode: a dataSource function returns fresh items on every read (for cookies)
7
+ *
8
+ * Items are plain objects with a configurable key property (keyProperty) and value property (valueProperty).
9
+ *
10
+ * This base class provides only read/search/iteration/transform methods.
11
+ * See PropertyList for static-mode mutation methods.
12
+ * See CookieList for async cookie-jar write methods.
13
+ *
14
+ * Convention:
15
+ * #field / #method – truly private, inaccessible to subclasses
16
+ * _field / _method – protected, intended for subclass access only
17
+ */
18
+ class ReadOnlyPropertyList {
19
+ // ── Private fields (not accessible by subclasses) ────────────────────
20
+ #valueProperty;
21
+ #dataSource;
22
+
23
+ /**
24
+ * @param {object} options
25
+ * @param {string} [options.keyProperty='key'] - The property name used as the unique key
26
+ * @param {string} [options.valueProperty='value'] - The property name used as the value
27
+ * @param {Function} [options.dataSource] - Dynamic data source function (returns array of items)
28
+ * @param {Array} [options.items] - Initial items for static mode
29
+ */
30
+ // Items are stored in an array (not a Map) to support positional access (idx, indexOf),
31
+ // ordered insertion (insert, insertAfter, prepend in PropertyList), and duplicate keys.
32
+ // At typical list sizes (cookies, headers) the O(n) key lookup is negligible.
33
+ constructor({ keyProperty = 'key', valueProperty = 'value', dataSource, items } = {}) {
34
+ this._keyProperty = keyProperty;
35
+ this.#valueProperty = valueProperty;
36
+ this._dynamic = typeof dataSource === 'function';
37
+ if (this._dynamic) {
38
+ this.#dataSource = dataSource;
39
+ } else {
40
+ this._items = Array.isArray(items) ? [...items] : [];
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Returns the current list of items.
46
+ * In dynamic mode, calls the dataSource function.
47
+ * In static mode, returns the internal array.
48
+ */
49
+ #getItems() {
50
+ return this._dynamic ? this.#dataSource() : this._items;
51
+ }
52
+
53
+ // ── Retrieval ──────────────────────────────────────────────────────────
54
+
55
+ /**
56
+ * Get the value of an item by its key.
57
+ * @param {string} name
58
+ * @returns {*} The value property of the matching item, or undefined
59
+ */
60
+ get(name) {
61
+ const items = this.#getItems();
62
+ // Use findLast so that duplicate keys resolve to the last entry,
63
+ // consistent with toObject() which also gives last-wins semantics.
64
+ const item = items.findLast((i) => i[this._keyProperty] === name);
65
+ return item ? item[this.#valueProperty] : undefined;
66
+ }
67
+
68
+ /**
69
+ * Get the full item object by its key.
70
+ * @param {string} name
71
+ * @returns {object|undefined}
72
+ */
73
+ one(name) {
74
+ const items = this.#getItems();
75
+ // Use findLast so that duplicate keys resolve to the last entry,
76
+ // consistent with get() and toObject() which also give last-wins semantics.
77
+ return items.findLast((i) => i[this._keyProperty] === name);
78
+ }
79
+
80
+ /**
81
+ * Get a cloned array of all items.
82
+ * @returns {Array}
83
+ */
84
+ all() {
85
+ return [...this.#getItems()];
86
+ }
87
+
88
+ /**
89
+ * Get an item by its positional index.
90
+ * @param {number} index
91
+ * @returns {object|undefined}
92
+ */
93
+ idx(index) {
94
+ return this.#getItems()[index];
95
+ }
96
+
97
+ /**
98
+ * Get the number of items.
99
+ * @returns {number}
100
+ */
101
+ count() {
102
+ return this.#getItems().length;
103
+ }
104
+
105
+ /**
106
+ * Get the index of an item.
107
+ * Uses structural equality (matching by key and value) so it works
108
+ * even when the item is a copy rather than the same reference.
109
+ * @param {object} item
110
+ * @returns {number} -1 if not found
111
+ */
112
+ indexOf(item) {
113
+ if (!item || typeof item !== 'object') return -1;
114
+ const items = this.#getItems();
115
+ const keyProp = this._keyProperty;
116
+ return items.findIndex(
117
+ (i) => i[keyProp] === item[keyProp] && i[this.#valueProperty] === item[this.#valueProperty]
118
+ );
119
+ }
120
+
121
+ // ── Search ─────────────────────────────────────────────────────────────
122
+
123
+ /**
124
+ * Check if an item with the given key exists.
125
+ * If value is provided, also checks that the item's value matches.
126
+ * @param {string} name
127
+ * @param {*} [value]
128
+ * @returns {boolean}
129
+ */
130
+ has(name, value) {
131
+ const items = this.#getItems();
132
+ if (value !== undefined) {
133
+ return items.some((i) => i[this._keyProperty] === name && i[this.#valueProperty] === value);
134
+ }
135
+ return items.some((i) => i[this._keyProperty] === name);
136
+ }
137
+
138
+ /**
139
+ * Find the first item matching a predicate.
140
+ * @param {Function} predicate
141
+ * @returns {object|undefined}
142
+ */
143
+ find(predicate) {
144
+ return this.#getItems().find(predicate);
145
+ }
146
+
147
+ /**
148
+ * Filter items by a predicate.
149
+ * @param {Function} predicate
150
+ * @returns {Array}
151
+ */
152
+ filter(predicate) {
153
+ return this.#getItems().filter(predicate);
154
+ }
155
+
156
+ // ── Iteration ──────────────────────────────────────────────────────────
157
+
158
+ /**
159
+ * Iterate over each item.
160
+ * @param {Function} fn - Called with (item, index)
161
+ */
162
+ each(fn) {
163
+ this.#getItems().forEach(fn);
164
+ }
165
+
166
+ /**
167
+ * Map over items.
168
+ * @param {Function} fn
169
+ * @returns {Array}
170
+ */
171
+ map(fn) {
172
+ return this.#getItems().map(fn);
173
+ }
174
+
175
+ /**
176
+ * Reduce items.
177
+ * @param {Function} fn
178
+ * @param {*} [initialValue] - Optional initial accumulator value
179
+ * @returns {*}
180
+ */
181
+ reduce(fn, ...rest) {
182
+ return rest.length ? this.#getItems().reduce(fn, rest[0]) : this.#getItems().reduce(fn);
183
+ }
184
+
185
+ // ── Transformation ─────────────────────────────────────────────────────
186
+
187
+ /**
188
+ * Convert to a plain object { key: value }.
189
+ * @returns {object}
190
+ */
191
+ toObject() {
192
+ const result = {};
193
+ for (const item of this.#getItems()) {
194
+ result[item[this._keyProperty]] = item[this.#valueProperty];
195
+ }
196
+ return result;
197
+ }
198
+
199
+ /**
200
+ * Convert to a string "key=value; key2=value2".
201
+ * @returns {string}
202
+ */
203
+ toString() {
204
+ return this.#getItems()
205
+ .map((i) => `${i[this._keyProperty]}=${i[this.#valueProperty]}`)
206
+ .join('; ');
207
+ }
208
+
209
+ /**
210
+ * Convert to JSON (returns the same as all()).
211
+ * @returns {Array}
212
+ */
213
+ toJSON() {
214
+ return this.all();
215
+ }
216
+
217
+ /**
218
+ * Check if an object is an instance of ReadOnlyPropertyList.
219
+ * @param {*} obj
220
+ * @returns {boolean}
221
+ */
222
+ static isPropertyList(obj) {
223
+ return obj instanceof ReadOnlyPropertyList;
224
+ }
225
+ }
226
+
227
+ module.exports = ReadOnlyPropertyList;
@@ -17,8 +17,8 @@ chai.use(function (chai, utils) {
17
17
  // Objects created inside Node's vm.createContext() have a different Object constructor,
18
18
  // so obj.constructor === Object fails for objects passed via res.setBody() from scripts.
19
19
  // Note: toString check is more permissive than constructor check — custom class instances
20
- const isJson = typeof obj === 'object' && obj !== null && !Array.isArray(obj)
21
- && Object.prototype.toString.call(obj) === '[object Object]';
20
+ const isJson = typeof obj === 'object' && obj !== null
21
+ && (Array.isArray(obj) || Object.prototype.toString.call(obj) === '[object Object]');
22
22
 
23
23
  this.assert(isJson, `expected ${utils.inspect(obj)} to be JSON`, `expected ${utils.inspect(obj)} not to be JSON`);
24
24
  });
@@ -263,14 +263,12 @@ class AssertRuntime {
263
263
  }
264
264
 
265
265
  const certsAndProxyConfig = request?.certsAndProxyConfig;
266
- const bru = new Bru(
267
- this.runtime,
266
+ const bru = new Bru({
267
+ runtime: this.runtime,
268
268
  envVariables,
269
269
  runtimeVariables,
270
270
  processEnvVars,
271
- undefined, // collectionPath,
272
- undefined, // historyLogger,
273
- undefined, // setVisualizations,
271
+ historyLogger,
274
272
  secretVariables,
275
273
  collectionVariables,
276
274
  folderVariables,
@@ -278,10 +276,10 @@ class AssertRuntime {
278
276
  globalEnvironmentVariables,
279
277
  oauth2CredentialVariables,
280
278
  iterationDetails,
281
- undefined,
282
279
  promptVariables,
283
- certsAndProxyConfig
284
- );
280
+ certsAndProxyConfig,
281
+ requestUrl: request?.url
282
+ });
285
283
  const req = new BrunoRequest(request, historyLogger);
286
284
  const res = createResponseParser(response);
287
285
 
@@ -1,5 +1,6 @@
1
1
  const chai = require('chai');
2
2
  const Bru = require('../bru');
3
+ const { VISUALIZATION_CLEAR } = require('../bru');
3
4
  const BrunoRequest = require('../bruno-request');
4
5
  const BrunoResponse = require('../bruno-response');
5
6
  const { cleanJson } = require('../utils');
@@ -31,7 +32,11 @@ class ScriptRuntime {
31
32
  ) {
32
33
  let visualizations = [];
33
34
  let setVisualizations = (data) => {
34
- visualizations.push(data);
35
+ if (data.type === VISUALIZATION_CLEAR) {
36
+ visualizations = [];
37
+ } else {
38
+ visualizations.push(data);
39
+ }
35
40
  };
36
41
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
37
42
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
@@ -43,8 +48,28 @@ class ScriptRuntime {
43
48
  const assertionResults = request?.assertionResults || [];
44
49
  const certsAndProxyConfig = request?.certsAndProxyConfig;
45
50
  const scriptPath = request?.pathname;
46
- const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables, certsAndProxyConfig);
47
- const req = new BrunoRequest(request);
51
+ const bru = new Bru({
52
+ runtime: this.runtime,
53
+ envVariables,
54
+ runtimeVariables,
55
+ processEnvVars,
56
+ collectionPath,
57
+ historyLogger,
58
+ setVisualizations,
59
+ secretVariables,
60
+ collectionVariables,
61
+ folderVariables,
62
+ requestVariables,
63
+ globalEnvironmentVariables,
64
+ oauth2CredentialVariables,
65
+ iterationDetails,
66
+ collectionName,
67
+ promptVariables,
68
+ certsAndProxyConfig,
69
+ requestUrl: request?.url,
70
+ onConsoleLog
71
+ });
72
+ const req = new BrunoRequest(request, historyLogger);
48
73
 
49
74
  // extend bru with result getter methods
50
75
  const { __brunoTestResults, test } = createBruTestResultMethods(bru, assertionResults, chai);
@@ -158,7 +183,11 @@ class ScriptRuntime {
158
183
  ) {
159
184
  let visualizations = [];
160
185
  let setVisualizations = (data) => {
161
- visualizations.push(data);
186
+ if (data.type === VISUALIZATION_CLEAR) {
187
+ visualizations = [];
188
+ } else {
189
+ visualizations.push(data);
190
+ }
162
191
  };
163
192
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
164
193
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
@@ -170,8 +199,28 @@ class ScriptRuntime {
170
199
  const assertionResults = request?.assertionResults || [];
171
200
  const certsAndProxyConfig = request?.certsAndProxyConfig;
172
201
  const scriptPath = request?.pathname;
173
- const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, setVisualizations, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables, certsAndProxyConfig);
174
- const req = new BrunoRequest(request);
202
+ const bru = new Bru({
203
+ runtime: this.runtime,
204
+ envVariables,
205
+ runtimeVariables,
206
+ processEnvVars,
207
+ collectionPath,
208
+ historyLogger,
209
+ setVisualizations,
210
+ secretVariables,
211
+ collectionVariables,
212
+ folderVariables,
213
+ requestVariables,
214
+ globalEnvironmentVariables,
215
+ oauth2CredentialVariables,
216
+ iterationDetails,
217
+ collectionName,
218
+ promptVariables,
219
+ certsAndProxyConfig,
220
+ requestUrl: request?.url,
221
+ onConsoleLog
222
+ });
223
+ const req = new BrunoRequest(request, historyLogger);
175
224
  const res = new BrunoResponse(response);
176
225
 
177
226
  // extend bru with result getter methods
@@ -40,7 +40,25 @@ class TestRuntime {
40
40
  const assertionResults = request?.assertionResults || [];
41
41
  const certsAndProxyConfig = request?.certsAndProxyConfig;
42
42
  const scriptPath = request?.pathname;
43
- const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, undefined, secretVariables, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, collectionName, promptVariables, certsAndProxyConfig);
43
+ const bru = new Bru({
44
+ runtime: this.runtime,
45
+ envVariables,
46
+ runtimeVariables,
47
+ processEnvVars,
48
+ collectionPath,
49
+ historyLogger,
50
+ secretVariables,
51
+ collectionVariables,
52
+ folderVariables,
53
+ requestVariables,
54
+ globalEnvironmentVariables,
55
+ oauth2CredentialVariables,
56
+ iterationDetails,
57
+ collectionName,
58
+ promptVariables,
59
+ certsAndProxyConfig,
60
+ requestUrl: request?.url
61
+ });
44
62
  const req = new BrunoRequest(request, historyLogger);
45
63
  const res = new BrunoResponse(response);
46
64
 
@@ -24,7 +24,7 @@ class VarsRuntime {
24
24
  this.mode = props?.mode || 'developer';
25
25
  }
26
26
 
27
- runPostResponseVars(vars, request, response, envVariables, runtimeVariables, collectionPath, processEnvVars, historyLogger, secretVars = {}) {
27
+ runPostResponseVars(vars, request, response, envVariables, runtimeVariables, collectionPath, processEnvVars, historyLogger, secretVariables = {}) {
28
28
  const requestVariables = request?.requestVariables || {};
29
29
  const globalEnvironmentVariables = request?.globalEnvironmentVariables || {};
30
30
  const oauth2CredentialVariables = request?.oauth2CredentialVariables || {};
@@ -38,7 +38,24 @@ class VarsRuntime {
38
38
 
39
39
  const promptVariables = request?.promptVariables || {};
40
40
  const certsAndProxyConfig = request?.certsAndProxyConfig;
41
- const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, historyLogger, undefined, secretVars, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, iterationDetails, undefined, promptVariables, certsAndProxyConfig);
41
+ const bru = new Bru({
42
+ runtime: this.runtime,
43
+ envVariables,
44
+ runtimeVariables,
45
+ processEnvVars,
46
+ collectionPath,
47
+ historyLogger,
48
+ secretVariables,
49
+ collectionVariables,
50
+ folderVariables,
51
+ requestVariables,
52
+ globalEnvironmentVariables,
53
+ oauth2CredentialVariables,
54
+ iterationDetails,
55
+ promptVariables,
56
+ certsAndProxyConfig,
57
+ requestUrl: request?.url
58
+ });
42
59
  const req = new BrunoRequest(request, historyLogger);
43
60
  const res = createResponseParser(response);
44
61
 
@@ -51,7 +68,7 @@ class VarsRuntime {
51
68
  const context = {
52
69
  ...envVariables,
53
70
  ...runtimeVariables,
54
- ...secretVars,
71
+ ...secretVariables,
55
72
  ...bruContext
56
73
  };
57
74
 
@@ -2,7 +2,7 @@ const rollup = require('rollup');
2
2
  const { nodeResolve } = require('@rollup/plugin-node-resolve');
3
3
  const commonjs = require('@rollup/plugin-commonjs');
4
4
  const fs = require('fs');
5
- const { terser } = require('rollup-plugin-terser');
5
+ const terser = require('@rollup/plugin-terser').default;
6
6
 
7
7
  const bundleLibraries = async () => {
8
8
  const codeScript = `
@@ -5,6 +5,7 @@ const addBrunoResponseShimToContext = require('./shims/bruno-response');
5
5
  const addTestShimToContext = require('./shims/test');
6
6
  const addLibraryShimsToContext = require('./shims/lib');
7
7
  const addLocalModuleLoaderShimToContext = require('./shims/local-module');
8
+ const { getRequireCode } = require('./shims/require');
8
9
  const { newQuickJSWASMModule, memoizePromiseFactory } = require('quickjs-emscripten');
9
10
 
10
11
  // execute `npm run sandbox:bundle-libraries` if the below file doesn't exist
@@ -104,44 +105,11 @@ const executeQuickJsVmAsync = async ({ script: externalScript, context: external
104
105
  await addCryptoUtilsShimToContext(vm);
105
106
 
106
107
  const bundledCode = getBundledCode?.toString() || '';
107
- const moduleLoaderCode = function () {
108
- return `
109
- globalThis.require = (mod) => {
110
- let lib = globalThis.requireObject[mod];
111
- let isModuleAPath = (module) => (module?.startsWith('.') || module?.startsWith?.(bru.cwd()))
112
- if (lib) {
113
- return lib;
114
- }
115
- else if (isModuleAPath(mod)) {
116
- // fetch local module
117
- let localModuleCode = globalThis.__brunoLoadLocalModule(mod);
118
-
119
- // compile local module as iife
120
- (function (){
121
- const initModuleExportsCode = "const module = { exports: {} };"
122
- const copyModuleExportsCode = "\\n;globalThis.requireObject[mod] = module.exports;";
123
- const patchedRequire = ${`
124
- "\\n;" +
125
- "let require = (subModule) => isModuleAPath(subModule) ? globalThis.require(path.resolve(bru.cwd(), mod, '..', subModule)) : globalThis.require(subModule)" +
126
- "\\n;"
127
- `}
128
- eval(initModuleExportsCode + patchedRequire + localModuleCode + copyModuleExportsCode);
129
- })();
130
-
131
- // resolve module
132
- return globalThis.requireObject[mod];
133
- }
134
- else {
135
- throw new Error("Cannot find module " + mod);
136
- }
137
- }
138
- `;
139
- };
140
108
 
141
109
  vm.evalCode(
142
110
  `
143
111
  (${bundledCode})()
144
- ${moduleLoaderCode()}
112
+ ${getRequireCode()}
145
113
  `
146
114
  );
147
115