UNPKG

langchain

Version:
146 lines (145 loc) 7.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.RegexMaskingTransformer = void 0; const transformer_js_1 = require("./transformer.cjs"); /** * RegexMaskingTransformer class for masking and rehydrating messages with Regex. */ class RegexMaskingTransformer extends transformer_js_1.MaskingTransformer { /** * Constructs a RegexMaskingTransformer with given patterns and an optional hash function. * Validates the provided patterns to ensure they conform to the expected structure. * * @param patterns - An object containing masking patterns. Each pattern should include * a regular expression (`regex`) and optionally a `replacement` string * or a `mask` function. * @param hashFunction - An optional custom hash function to be used for masking. */ constructor(patterns, hashFunction) { super(); Object.defineProperty(this, "patterns", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "hashFunction", { enumerable: true, configurable: true, writable: true, value: void 0 }); // Validates the provided masking patterns before initializing the transformer. // This ensures that each pattern has a valid regular expression. this.validatePatterns(patterns); // Assigns the validated patterns and the hash function to the transformer. // If no custom hash function is provided, the default hash function is used. this.patterns = patterns; this.hashFunction = hashFunction || this.defaultHashFunction; } /** * Validates the given masking patterns to ensure each pattern has a valid regular expression. * Throws an error if any pattern is found to be invalid. * * @param patterns - The patterns object to validate. */ validatePatterns(patterns) { for (const key of Object.keys(patterns)) { const pattern = patterns[key]; // Checks that each pattern is an object and has a regex property that is an instance of RegExp. // Throws an error if these conditions are not met, indicating an invalid pattern configuration. if (!pattern || typeof pattern !== "object" || // eslint-disable-next-line no-instanceof/no-instanceof !(pattern.regex instanceof RegExp)) { throw new Error("Invalid pattern configuration."); } } } /** * Masks content in a message based on the defined patterns. * @param message - The message to be masked. * @param state - The current state containing original values. * @returns A tuple of the masked message and the updated state. */ async transform(message, state) { if (typeof message !== "string") { throw new TypeError("RegexMaskingTransformer.transform Error: The 'message' argument must be a string."); } // eslint-disable-next-line no-instanceof/no-instanceof if (!(state instanceof Map)) { throw new TypeError("RegexMaskingTransformer.transform Error: The 'state' argument must be an instance of Map."); } // Holds the progressively masked message let processedMessage = message; // Initialize original values map with the current state or a new map const originalValues = state || new Map(); // Iterate over each pattern defined in the transformer for (const key of Object.keys(this.patterns)) { const pattern = this.patterns[key]; // Apply the current pattern's regex to the message processedMessage = processedMessage.replace(pattern.regex, (match) => { // Determine the masked value: use the mask function if provided, else use the replacement string, // else use the hash function. const maskedValue = pattern.mask ? pattern.mask(match) : pattern.replacement ?? this.hashFunction(match); // Store the mapping of the masked value to the original value (match) originalValues.set(maskedValue, match); // Return the masked value to replace the original value in the message return maskedValue; }); } // Return the fully masked message and the state map with all original values // Wrap the synchronous return values in Promise.resolve() to maintain compatibility // with the MaskingParser's expectation of a Promise return type. return [processedMessage, originalValues]; } /** * Rehydrates a masked message back to its original form using the provided state. * @param message - The masked message to be rehydrated. * @param state - The state map containing mappings of masked values to their original values. * @returns The rehydrated (original) message. */ async rehydrate(message, state) { if (typeof message !== "string") { throw new TypeError("RegexMaskingTransformer.rehydrate Error: The 'message' argument must be a string."); } // eslint-disable-next-line no-instanceof/no-instanceof if (!(state instanceof Map)) { throw new TypeError("RegexMaskingTransformer.rehydrate Error: The 'state' argument must be an instance of Map."); } // Convert the state map to an array and use reduce to sequentially replace masked values with original values. const rehydratedMessage = Array.from(state).reduce((msg, [masked, original]) => { // Escape special characters in the masked string to ensure it can be used in a regular expression safely. // This is necessary because masked values might contain characters that have special meanings in regex. const escapedMasked = masked.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // Replace all instances of the escaped masked value in the message with the original value. // The 'g' flag in the RegExp ensures that all occurrences of the masked value are replaced. return msg.replace(new RegExp(escapedMasked, "g"), original); }, message); return rehydratedMessage; } /** * Default hash function for creating unique hash values. * @param input - The input string to hash. * @returns The resulting hash as a string. */ defaultHashFunction(input) { let hash = 0; // Iterate over each character in the input string for (let i = 0; i < input.length; i += 1) { // Get ASCII value of the character const char = input.charCodeAt(i); // Combine the current hash with the new character and ensure it remains a 32-bit integer hash = (hash << 5) - hash + char; // Bitwise OR operation to convert to a 32-bit integer. // This is a common technique to ensure the final hash value stays within the 32-bit limit, // effectively wrapping the value when it becomes too large. hash |= 0; } // Convert the numerical hash value to a string and return return hash.toString(); } } exports.RegexMaskingTransformer = RegexMaskingTransformer;