const require_logger = require('./logger-DXu5t4bD.cjs');
const require_esm = require('./esm-C8GQ-4k9.cjs');
const require_pythonUtils = require('./pythonUtils-CJADVBl_.cjs');
const require_fileExtensions = require('./fileExtensions-Da2HykPA.cjs');

//#region src/util/processShim.ts
/**
* Browser-safe process shim module.
*
* This module provides a shimmed process object that works in both Node.js and browser
* environments. In Node.js, it provides full functionality including process.mainModule.require.
* In browsers, it returns a minimal shim that throws helpful errors when Node.js-specific
* features are accessed.
*
* This separation is necessary because:
* 1. The promptfoo webui imports httpTransforms.ts which needs getProcessShim()
* 2. httpTransforms.ts is designed to be frontend-importable for testing transforms in the UI
* 3. The Node.js implementation uses createRequire from 'node:module' which doesn't exist in browsers
*
* By using runtime environment detection and dynamic imports, we can:
* - Avoid top-level imports of Node.js-only modules that would break browser bundling
* - Provide appropriate functionality for each environment
*/
/**
* Detects if the current environment is a browser or web worker.
* Handles test environments (jsdom/happy-dom) that define window in Node.js.
*/
function isBrowserEnvironment() {
	if (typeof process !== "undefined" && typeof process.versions?.node === "string") return false;
	return typeof window !== "undefined" || typeof self !== "undefined" && typeof self.importScripts === "function";
}
/**
* Creates a minimal process shim for browser environments.
* This shim provides helpful error messages when Node.js-specific features are accessed.
*/
function createBrowserProcessShim() {
	return {
		env: {},
		mainModule: {
			require: () => {
				throw new Error("require() is not available in browser transforms. Use standard JavaScript instead.");
			},
			exports: {},
			id: ".",
			filename: "",
			loaded: true,
			children: [],
			paths: []
		}
	};
}
let cachedNodeProcessShim = null;
/**
* Returns a shimmed process object that works in both Node.js and browser environments.
*
* In Node.js:
* - Returns a proxy with process.mainModule.require shimmed for ESM compatibility
* - Allows inline transforms to use require() even in ESM context
*
* In browsers:
* - Returns a minimal shim with helpful error messages
* - Allows simple transforms that don't use require() to work
*
* @example
* // In Node.js - can use require
* const fn = new Function('data', 'process', `return process.mainModule.require('fs')`);
* fn(data, getProcessShim());
*
* @example
* // In browser - simple transforms work
* const fn = new Function('data', 'process', `return data.toUpperCase()`);
* fn(data, getProcessShim());
*/
function getProcessShim() {
	if (isBrowserEnvironment()) return createBrowserProcessShim();
	if (!cachedNodeProcessShim) try {
		const esmRequire = require("node:module").createRequire(require("url").pathToFileURL(__filename).href);
		cachedNodeProcessShim = new Proxy(process, { get(target, prop) {
			if (prop === "mainModule") return {
				require: esmRequire,
				exports: {},
				id: ".",
				filename: "",
				loaded: true,
				children: [],
				paths: []
			};
			return Reflect.get(target, prop);
		} });
	} catch {
		return createBrowserProcessShim();
	}
	return cachedNodeProcessShim;
}

//#endregion
//#region src/util/transform.ts
const TransformInputType = {
	OUTPUT: "output",
	VARS: "vars"
};
/**
* Parses a file path string to extract the file path and function name.
* Handles Windows drive letters (e.g., C:\path\to\file.js:functionName).
* @param filePath - The file path string, potentially including a function name.
* @returns A tuple containing the file path and function name (if present).
*/
function parseFilePathAndFunctionName(filePath) {
	const lastColonIndex = filePath.lastIndexOf(":");
	if (lastColonIndex > 1) return [filePath.slice(0, lastColonIndex), filePath.slice(lastColonIndex + 1)];
	return [filePath, void 0];
}
/**
* Retrieves a JavaScript transform function from a file.
* @param filePath - The path to the JavaScript file.
* @param functionName - Optional name of the function to retrieve.
* @returns A Promise resolving to the requested function.
* @throws Error if the file doesn't export a valid function.
*/
async function getJavascriptTransformFunction(filePath, functionName) {
	const requiredModule = await require_esm.importModule(filePath);
	if (functionName && Object.prototype.hasOwnProperty.call(requiredModule, functionName) && typeof requiredModule[functionName] === "function") return requiredModule[functionName];
	else if (typeof requiredModule === "function") return requiredModule;
	else if (requiredModule.default && typeof requiredModule.default === "function") return requiredModule.default;
	throw new Error(`Transform ${filePath} must export a function, have a default export as a function, or export the specified function "${functionName}"`);
}
/**
* Creates a function that runs a Python transform function.
* @param filePath - The path to the Python file.
* @param functionName - The name of the function to run (defaults to 'get_transform').
* @returns A function that executes the Python transform.
*/
function getPythonTransformFunction(filePath, functionName = "get_transform") {
	return async (output, context) => {
		return require_pythonUtils.runPython(filePath, functionName, [output, context]);
	};
}
/**
* Retrieves a transform function from a file, supporting both JavaScript and Python.
* @param filePath - The path to the file, including the 'file://' prefix.
* @returns A Promise resolving to the requested function.
* @throws Error if the file format is unsupported.
*/
async function getFileTransformFunction(filePath) {
	const [actualFilePath, functionName] = parseFilePathAndFunctionName(filePath.slice(7));
	const fullPath = require_esm.safeJoin(require_logger.cliState_default.basePath || "", actualFilePath);
	if (require_fileExtensions.isJavascriptFile(fullPath)) return getJavascriptTransformFunction(fullPath, functionName);
	else if (fullPath.endsWith(".py")) return getPythonTransformFunction(fullPath, functionName);
	throw new Error(`Unsupported transform file format: file://${actualFilePath}`);
}
/**
* Creates a function from inline JavaScript code.
* @param code - The JavaScript code to convert into a function.
* @returns A Function created from the provided code.
*
* The function receives three parameters:
* - The input (output or vars depending on inputType)
* - A context object
* - A process object with mainModule.require shimmed for backwards compatibility
*
* To use require in inline transforms, use: process.mainModule.require('module-name')
* Or assign it to a variable: const require = process.mainModule.require;
*/
function getInlineTransformFunction(code, inputType) {
	return new Function(inputType, "context", "process", code.includes("\n") ? code : `return ${code}`);
}
/**
* Determines and retrieves the appropriate transform function based on the input.
* @param codeOrFilepath - Either inline code or a file path starting with 'file://'.
* @returns A Promise resolving to the appropriate transform function.
*/
async function getTransformFunction(codeOrFilepath, inputType) {
	let transformFn = null;
	if (codeOrFilepath.startsWith("file://")) try {
		transformFn = await getFileTransformFunction(codeOrFilepath);
	} catch (error) {
		require_logger.logger_default.error(`Error loading transform function from file: ${error instanceof Error ? error.message : String(error)}`);
		throw error;
	}
	else try {
		transformFn = getInlineTransformFunction(codeOrFilepath, inputType);
	} catch (error) {
		require_logger.logger_default.error(`Error creating inline transform function: ${error instanceof Error ? error.message : String(error)}`);
		throw error;
	}
	return transformFn;
}
/**
* Transforms the output using a specified function or file.
*
* @param codeOrFilepath - The transformation function code or file path.
* If it starts with 'file://', it's treated as a file path. The file path can
* optionally include a function name (e.g., 'file://transform.js:myFunction').
* If no function name is provided for Python files, it defaults to 'get_transform'.
* For inline code, it's treated as JavaScript.
* @param transformInput - The output to be transformed. Can be a string or an object.
* @param context - A context object that will be passed to the transform function.
* @param validateReturn - Optional. If true, throws an error if the transform function doesn't return a value.
* @returns A promise that resolves to the transformed output.
* @throws Error if the file format is unsupported or if the transform function
* doesn't return a value (unless validateReturn is false).
*/
async function transform(codeOrFilepath, transformInput, context, validateReturn = true, inputType = TransformInputType.OUTPUT) {
	const postprocessFn = await getTransformFunction(codeOrFilepath, inputType);
	if (!postprocessFn) throw new Error(`Invalid transform function for ${codeOrFilepath}`);
	const ret = await Promise.resolve(postprocessFn(transformInput, context, getProcessShim()));
	if (validateReturn && (ret === null || ret === void 0)) throw new Error(`Transform function did not return a value\n\n${codeOrFilepath}`);
	return ret;
}

//#endregion
Object.defineProperty(exports, 'TransformInputType', {
  enumerable: true,
  get: function () {
    return TransformInputType;
  }
});
Object.defineProperty(exports, 'getProcessShim', {
  enumerable: true,
  get: function () {
    return getProcessShim;
  }
});
Object.defineProperty(exports, 'transform', {
  enumerable: true,
  get: function () {
    return transform;
  }
});
//# sourceMappingURL=transform-BaDtC1ge.cjs.map