import { M as state, o as logger } from "./logger-CtGm8dC_.js";
import { i as isJavascriptFile } from "./fileExtensions-Cked_yPQ.js";
import { a as safeJoin, r as importModule } from "./esm-CxsIm9IU.js";
import { r as runPython } from "./pythonUtils-D75i-07l.js";
import { t as getProcessShim } from "./processShim-DwdcSYEj.js";
//#region src/util/transform.ts
const INLINE_FUNCTION_LABEL = "[inline function]";
const INLINE_STRING_LABEL = "[inline transform]";
const FILE_TRANSFORM_LABEL = "[file transform]";
/** Error labels truncate inline string transforms past this length so they stay readable in logs. */
const INLINE_STRING_LABEL_MAX_LENGTH = 80;
/**
* Every config field that accepts a `StringOrFunctionSchema`. Shared between the
* runtime sanitizer in `src/node/evaluate.ts` (which replaces function values with
* markers before persistence) and `scripts/generateJsonSchema.ts` (which rewrites
* these fields to string-only in the generated JSON schema).
*/
const TRANSFORM_KEYS = [
	"transform",
	"transformVars",
	"contextTransform",
	"postprocess"
];
/**
* Unwraps `transform()`'s `Transform failed (label): ...` wrapper and returns
* the underlying message. Callers that add their own label wrapper (e.g.
* `contextUtils.resolveContext`, SageMaker's error response) use this to avoid
* stuttering two labels in the user-facing message.
*/
function getTransformErrorMessage(error) {
	const cause = error?.cause;
	const raw = error instanceof Error && cause instanceof Error ? cause : error;
	return raw instanceof Error ? raw.message : String(raw);
}
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 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 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 = safeJoin(state.basePath || "", actualFilePath);
	if (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) {
	if (codeOrFilepath.startsWith("file://")) try {
		return await getFileTransformFunction(codeOrFilepath);
	} catch (error) {
		logger.error("Error loading transform function from file", {
			error,
			message: error instanceof Error ? error.message : String(error),
			transform: getTransformLabel(codeOrFilepath)
		});
		throw error;
	}
	else try {
		return getInlineTransformFunction(codeOrFilepath, inputType);
	} catch (error) {
		logger.error("Error creating inline transform function", {
			error,
			message: error instanceof Error ? error.message : String(error),
			transform: getTransformLabel(codeOrFilepath)
		});
		throw error;
	}
}
/**
* Returns a human-readable label for a transform value, suitable for error messages.
*
* Inline string transforms are shown verbatim (single-line, truncated to
* {@link INLINE_STRING_LABEL_MAX_LENGTH}) so users can see which expression failed.
* Inline functions are shown by name only — their source is never rendered, to avoid
* leaking implementation details via `Function.toString()` into logs and persisted errors.
*/
function getTransformLabel(t) {
	if (t == null) return INLINE_STRING_LABEL;
	if (typeof t === "function") return t.name ? `${INLINE_FUNCTION_LABEL}: ${t.name}` : INLINE_FUNCTION_LABEL;
	if (t.startsWith("file://")) return FILE_TRANSFORM_LABEL;
	const singleLine = t.replace(/\s+/g, " ").trim();
	return `${INLINE_STRING_LABEL}: ${singleLine.length > INLINE_STRING_LABEL_MAX_LENGTH ? `${singleLine.slice(0, INLINE_STRING_LABEL_MAX_LENGTH - 1)}…` : singleLine}`;
}
/**
* Transforms the output using a specified function, inline code, or file reference.
*
* @param codeOrFilepathOrFn - A TransformFunction, inline JavaScript code, or a file path
* starting with 'file://'. File paths can include a function name
* (e.g., 'file://transform.js:myFunction'). Python files default to 'get_transform'.
* @param transformInput - The input to transform. Can be a string, object, or undefined.
* @param context - Context object passed to the transform function (vars, prompt, metadata).
* @param validateReturn - If true (default), throws when the transform returns null/undefined.
* @param inputType - Whether the first parameter is named 'output' or 'vars' in inline code.
* @returns A promise that resolves to the transformed output.
* @throws When the transform is unloadable, throws, or (with `validateReturn`) returns null/undefined.
*/
async function transform(codeOrFilepathOrFn, transformInput, context, validateReturn = true, inputType = TransformInputType.OUTPUT) {
	const isDirectFunction = typeof codeOrFilepathOrFn === "function";
	const transformFn = isDirectFunction ? codeOrFilepathOrFn : await getTransformFunction(codeOrFilepathOrFn, inputType);
	let ret;
	try {
		ret = isDirectFunction ? await Promise.resolve(transformFn(transformInput, context)) : await Promise.resolve(transformFn(transformInput, context, getProcessShim()));
	} catch (error) {
		const message = error instanceof Error ? error.message : String(error);
		const label = getTransformLabel(codeOrFilepathOrFn);
		logger.error("Error in transform function", {
			error,
			message,
			transform: label
		});
		if (error instanceof Error) {
			const wrapped = /* @__PURE__ */ new Error(`Transform failed (${label}): ${message}`);
			wrapped.cause = error;
			throw wrapped;
		}
		throw error;
	}
	if (validateReturn && (ret === null || ret === void 0)) throw new Error(`Transform function did not return a value\n\n${getTransformLabel(codeOrFilepathOrFn)}`);
	return ret;
}
//#endregion
export { getTransformLabel as a, getTransformErrorMessage as i, TRANSFORM_KEYS as n, transform as o, TransformInputType as r, INLINE_FUNCTION_LABEL as t };

//# sourceMappingURL=transform-BI9NfX1T.js.map