mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-25 05:35:41 +00:00
refactor: centralize BrunoRequest and BrunoResponse creation in HooksRuntime
This commit is contained in:
@@ -7,9 +7,6 @@ const prepareRequest = require('./prepare-request');
|
||||
const interpolateVars = require('./interpolate-vars');
|
||||
const { interpolateString, interpolateObject } = require('./interpolate-string');
|
||||
const { ScriptRuntime, TestRuntime, VarsRuntime, AssertRuntime, HooksRuntime, HooksExecutor } = require('@usebruno/js');
|
||||
const HookManager = require('@usebruno/js/src/hook-manager');
|
||||
const BrunoRequest = require('@usebruno/js/src/bruno-request');
|
||||
const BrunoResponse = require('@usebruno/js/src/bruno-response');
|
||||
const { stripExtension } = require('../utils/filesystem');
|
||||
const { getOptions } = require('../utils/bru');
|
||||
const { extractHooks, getTreePathFromCollectionToItem, HOOK_EVENTS } = require('../utils/collection');
|
||||
@@ -238,7 +235,8 @@ const runSingleRequest = async function (
|
||||
|
||||
// Call beforeRequest hooks before running pre-request scripts
|
||||
// Hooks are called in registration order: collection -> folder(s) -> request
|
||||
const beforeRequestEventData = { request, req: new BrunoRequest(request), collection };
|
||||
// Note: BrunoRequest is now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const beforeRequestEventData = { request, collection };
|
||||
|
||||
const beforeRequestHooksResult = await executeAllHooksConsolidated(
|
||||
{ collectionHooks, folderHooks, requestHooks },
|
||||
@@ -717,13 +715,8 @@ const runSingleRequest = async function (
|
||||
// Call afterResponse hooks after response is received but before post-response scripts
|
||||
// Hooks are called in registration order: collection -> folder(s) -> request
|
||||
// Uses consolidated execution when multiple levels have hooks (more efficient)
|
||||
const afterResponseEventData = {
|
||||
request,
|
||||
response,
|
||||
req: new BrunoRequest(request),
|
||||
res: new BrunoResponse(response),
|
||||
collection
|
||||
};
|
||||
// Note: BrunoRequest and BrunoResponse are now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const afterResponseEventData = { request, response, collection };
|
||||
|
||||
const afterResponseHooksResult = await executeAllHooksConsolidated(
|
||||
{ collectionHooks, folderHooks, requestHooks },
|
||||
|
||||
@@ -9,9 +9,6 @@ const { ipcMain } = require('electron');
|
||||
const { each, get, extend, cloneDeep, merge } = require('lodash');
|
||||
const { NtlmClient } = require('axios-ntlm');
|
||||
const { VarsRuntime, AssertRuntime, ScriptRuntime, TestRuntime, HooksRuntime, HooksExecutor } = require('@usebruno/js');
|
||||
// BrunoRequest and BrunoResponse are not exported from main index, require directly
|
||||
const BrunoRequest = require('@usebruno/js/src/bruno-request');
|
||||
const BrunoResponse = require('@usebruno/js/src/bruno-response');
|
||||
const { encodeUrl } = require('@usebruno/common').utils;
|
||||
const { extractPromptVariables } = require('@usebruno/common').utils;
|
||||
const { interpolateString } = require('./interpolate-string');
|
||||
@@ -750,7 +747,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
|
||||
// Call beforeRequest hooks before running pre-request scripts
|
||||
// Hooks are called in registration order: collection -> folder(s) -> request
|
||||
const beforeRequestEventData = { request, req: new BrunoRequest(request), collection, collectionUid };
|
||||
// Note: BrunoRequest is now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const beforeRequestEventData = { request, collection, collectionUid };
|
||||
const hookOptions = {
|
||||
request,
|
||||
envVars,
|
||||
@@ -943,14 +941,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
|
||||
// Call afterResponse hooks after response is received but before post-response scripts
|
||||
// Hooks are called in registration order: collection -> folder(s) -> request
|
||||
const afterResponseEventData = {
|
||||
request,
|
||||
response,
|
||||
req: new BrunoRequest(request),
|
||||
res: new BrunoResponse(response),
|
||||
collection,
|
||||
collectionUid
|
||||
};
|
||||
// Note: BrunoRequest and BrunoResponse are now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const afterResponseEventData = { request, response, collection, collectionUid };
|
||||
|
||||
// Call afterResponse hooks using consolidated approach when multiple levels have hooks
|
||||
await executeAllHooksConsolidated(
|
||||
@@ -1476,7 +1468,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
|
||||
try {
|
||||
// Call beforeRequest hooks using consolidated approach when multiple levels have hooks
|
||||
const beforeRequestEventData = { request, req: new BrunoRequest(request), collection, collectionUid };
|
||||
// Note: BrunoRequest is now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const beforeRequestEventData = { request, collection, collectionUid };
|
||||
|
||||
const beforeRequestHooksResult = await executeAllHooksConsolidated(
|
||||
{ collectionHooks, folderHooks, requestHooks },
|
||||
@@ -1731,14 +1724,8 @@ const registerNetworkIpc = (mainWindow) => {
|
||||
}
|
||||
|
||||
// Call afterResponse hooks using consolidated approach when multiple levels have hooks
|
||||
const afterResponseEventData = {
|
||||
request,
|
||||
response,
|
||||
req: new BrunoRequest(request),
|
||||
res: new BrunoResponse(response),
|
||||
collection,
|
||||
collectionUid
|
||||
};
|
||||
// Note: BrunoRequest and BrunoResponse are now created inside HooksRuntime for consistency with ScriptRuntime
|
||||
const afterResponseEventData = { request, response, collection, collectionUid };
|
||||
|
||||
const afterResponseHooksResult = await executeAllHooksConsolidated(
|
||||
{ collectionHooks, folderHooks, requestHooks },
|
||||
|
||||
@@ -80,11 +80,15 @@ const executeHooksForLevel = async (hooksFile, hookEvent, eventData, options) =>
|
||||
collectionName
|
||||
} = options;
|
||||
|
||||
// Extract response from eventData if available (for afterResponse hooks)
|
||||
const response = eventData?.response;
|
||||
|
||||
try {
|
||||
const hooksRuntime = new HooksRuntime({ runtime: scriptingConfig?.runtime });
|
||||
const result = await hooksRuntime.runHooks({
|
||||
hooksFile: decomment(hooksFile),
|
||||
request,
|
||||
response,
|
||||
envVariables,
|
||||
runtimeVariables,
|
||||
collectionPath,
|
||||
@@ -96,7 +100,13 @@ const executeHooksForLevel = async (hooksFile, hookEvent, eventData, options) =>
|
||||
});
|
||||
|
||||
if (result?.hookManager) {
|
||||
await result.hookManager.call(hookEvent, eventData);
|
||||
// Enrich eventData with runtime-created req/res wrappers
|
||||
const enrichedEventData = {
|
||||
...eventData,
|
||||
req: result.req || eventData.req,
|
||||
res: result.res || eventData.res
|
||||
};
|
||||
await result.hookManager.call(hookEvent, enrichedEventData);
|
||||
// Dispose HookManager to free VM resources
|
||||
if (typeof result.hookManager.dispose === 'function') {
|
||||
result.hookManager.dispose();
|
||||
@@ -139,12 +149,16 @@ const executeConsolidatedHooks = async (extractedHooks, hookEvent, eventData, op
|
||||
collectionName
|
||||
} = options;
|
||||
|
||||
// Extract response from eventData if available (for afterResponse hooks)
|
||||
const response = eventData?.response;
|
||||
|
||||
try {
|
||||
const hooksRuntime = new HooksRuntime({ runtime: scriptingConfig?.runtime });
|
||||
const result = await hooksRuntime.runHooks({
|
||||
consolidated: true,
|
||||
consolidatedHooks: extractedHooks,
|
||||
request,
|
||||
response,
|
||||
envVariables,
|
||||
runtimeVariables,
|
||||
collectionPath,
|
||||
@@ -156,7 +170,13 @@ const executeConsolidatedHooks = async (extractedHooks, hookEvent, eventData, op
|
||||
});
|
||||
|
||||
if (result?.hookManager) {
|
||||
await result.hookManager.call(hookEvent, eventData);
|
||||
// Enrich eventData with runtime-created req/res wrappers
|
||||
const enrichedEventData = {
|
||||
...eventData,
|
||||
req: result.req || eventData.req,
|
||||
res: result.res || eventData.res
|
||||
};
|
||||
await result.hookManager.call(hookEvent, enrichedEventData);
|
||||
|
||||
// IMPORTANT: Re-capture runner control values AFTER hooks have been called
|
||||
// The hooks may have called bru.runner.setNextRequest(), bru.runner.skipRequest(), etc.
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { runScriptInNodeVm } = require('../sandbox/node-vm');
|
||||
const Bru = require('../bru');
|
||||
const BrunoRequest = require('../bruno-request');
|
||||
const BrunoResponse = require('../bruno-response');
|
||||
const HookManager = require('../hook-manager');
|
||||
const { cleanJson } = require('../utils');
|
||||
const { executeQuickJsVmAsync } = require('../sandbox/quickjs');
|
||||
@@ -54,7 +56,8 @@ class HooksRuntime {
|
||||
* Run hooks script to register event handlers
|
||||
* @param {object} options - Configuration options
|
||||
* @param {string} [options.hooksFile] - The hooks script content (for single-level execution)
|
||||
* @param {object} options.request - The request object (used for variable extraction only)
|
||||
* @param {object} options.request - The request object (used for variable extraction and BrunoRequest creation)
|
||||
* @param {object} [options.response] - The response object (used for BrunoResponse creation, only for afterResponse hooks)
|
||||
* @param {object} options.envVariables - Environment variables
|
||||
* @param {object} options.runtimeVariables - Runtime variables
|
||||
* @param {string} options.collectionPath - Collection path
|
||||
@@ -69,12 +72,13 @@ class HooksRuntime {
|
||||
* @param {string} [options.consolidatedHooks.collectionHooks] - Collection-level hooks script
|
||||
* @param {Array<object>} [options.consolidatedHooks.folderHooks] - Array of folder hooks
|
||||
* @param {string} [options.consolidatedHooks.requestHooks] - Request-level hooks script
|
||||
* @returns {object} Result containing the hookManager instance
|
||||
* @returns {object} Result containing the hookManager instance, and req/res wrapper objects
|
||||
*/
|
||||
async runHooks(options) {
|
||||
const {
|
||||
hooksFile,
|
||||
request,
|
||||
response,
|
||||
envVariables,
|
||||
runtimeVariables,
|
||||
collectionPath,
|
||||
@@ -100,6 +104,7 @@ class HooksRuntime {
|
||||
return this._runConsolidatedHooks({
|
||||
consolidatedHooks,
|
||||
request,
|
||||
response,
|
||||
envVariables,
|
||||
runtimeVariables,
|
||||
collectionPath,
|
||||
@@ -122,8 +127,14 @@ class HooksRuntime {
|
||||
// Pass activeHookManager to Bru so it uses the same instance (whether provided or newly created)
|
||||
const bru = new Bru(this.runtime, envVariables, runtimeVariables, processEnvVars, collectionPath, collectionVariables, folderVariables, requestVariables, globalEnvironmentVariables, oauth2CredentialVariables, collectionName, promptVariables, activeHookManager);
|
||||
|
||||
// Create BrunoRequest and BrunoResponse wrappers (similar to ScriptRuntime)
|
||||
const req = request ? new BrunoRequest(request) : null;
|
||||
const res = response ? new BrunoResponse(response) : null;
|
||||
|
||||
const context = {
|
||||
bru
|
||||
bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
|
||||
if (onConsoleLog && typeof onConsoleLog === 'function') {
|
||||
@@ -157,7 +168,9 @@ class HooksRuntime {
|
||||
nextRequestName: bru.nextRequest,
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
|
||||
@@ -184,7 +197,9 @@ class HooksRuntime {
|
||||
nextRequestName: bru.nextRequest,
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,7 +226,9 @@ class HooksRuntime {
|
||||
nextRequestName: bru.nextRequest,
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
|
||||
@@ -225,6 +242,8 @@ class HooksRuntime {
|
||||
async _runConsolidatedHooks(options) {
|
||||
const {
|
||||
consolidatedHooks,
|
||||
request,
|
||||
response,
|
||||
envVariables,
|
||||
runtimeVariables,
|
||||
collectionPath,
|
||||
@@ -264,6 +283,9 @@ class HooksRuntime {
|
||||
promptVariables,
|
||||
activeHookManager
|
||||
);
|
||||
// Create BrunoRequest and BrunoResponse wrappers
|
||||
const req = request ? new BrunoRequest(request) : null;
|
||||
const res = response ? new BrunoResponse(response) : null;
|
||||
return {
|
||||
hookManager: activeHookManager,
|
||||
envVariables: cleanJson(envVariables),
|
||||
@@ -273,7 +295,9 @@ class HooksRuntime {
|
||||
nextRequestName: bru.nextRequest,
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
|
||||
@@ -298,9 +322,15 @@ class HooksRuntime {
|
||||
activeHookManager
|
||||
);
|
||||
|
||||
// Create BrunoRequest and BrunoResponse wrappers (similar to ScriptRuntime)
|
||||
const req = request ? new BrunoRequest(request) : null;
|
||||
const res = response ? new BrunoResponse(response) : null;
|
||||
|
||||
// Prepare context with error handling callback
|
||||
const context = {
|
||||
bru,
|
||||
req,
|
||||
res,
|
||||
__hookResult: null,
|
||||
__onHookError: (level, error) => {
|
||||
if (onConsoleLog) {
|
||||
@@ -348,7 +378,9 @@ class HooksRuntime {
|
||||
nextRequestName: bru.nextRequest,
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
|
||||
@@ -375,7 +407,9 @@ class HooksRuntime {
|
||||
skipRequest: bru.skipRequest,
|
||||
stopExecution: bru.stopExecution,
|
||||
// Include bru reference so callers can read updated values after hook execution
|
||||
__bru: bru
|
||||
__bru: bru,
|
||||
req,
|
||||
res
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user