"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MaskingParser = void 0; /** * MaskingParser class for handling the masking and rehydrating of messages. */ class MaskingParser { constructor(config = {}) { Object.defineProperty(this, "transformers", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "state", { enumerable: true, configurable: true, writable: true, value: void 0 }); Object.defineProperty(this, "config", { enumerable: true, configurable: true, writable: true, value: void 0 }); this.transformers = config.transformers ?? []; this.state = new Map(); this.config = config; } /** * Adds a transformer to the parser. * @param transformer - An instance of a class extending MaskingTransformer. */ addTransformer(transformer) { this.transformers.push(transformer); } /** * Getter method for retrieving the current state. * @returns The current state map. */ getState() { return this.state; } /** * Masks the provided message using the added transformers. * This method sequentially applies each transformer's masking logic to the message. * It utilizes a state map to track original values corresponding to their masked versions. * * @param message - The message to be masked. * @returns A masked version of the message. * @throws {TypeError} If the message is not a string. * @throws {Error} If no transformers are added. */ async mask(message) { // If onMaskingStart is a function, handle it accordingly if (this.config.onMaskingStart) { await this.config.onMaskingStart(message); } // Check if there are any transformers added to the parser. If not, throw an error // as masking requires at least one transformer to apply its logic. if (this.transformers.length === 0) { throw new Error("MaskingParser.mask Error: No transformers have been added. Please add at least one transformer before parsing."); } if (typeof message !== "string") { throw new TypeError("MaskingParser.mask Error: The 'message' argument must be a string."); } // Initialize the variable to hold the progressively masked message. // It starts as the original message and gets transformed by each transformer. let processedMessage = message; // Iterate through each transformer and apply their transform method. for (const transformer of this.transformers) { // Transform the message and get the transformer's state changes, ensuring no direct mutation of the shared state. const [transformedMessage, transformerState] = await transformer.transform(processedMessage, new Map(this.state)); // Update the processed message for subsequent transformers. processedMessage = transformedMessage; // Merge state changes from the transformer into the parser's state. // This accumulates all transformations' effects on the state. transformerState.forEach((value, key) => this.state.set(key, value)); } // Handle onMaskingEnd callback if (this.config.onMaskingEnd) { await this.config.onMaskingEnd(processedMessage); } // Return the fully masked message after all transformers have been applied. return processedMessage; } /** * Rehydrates a masked message back to its original form. * This method sequentially applies the rehydration logic of each added transformer in reverse order. * It relies on the state map to correctly map the masked values back to their original values. * * The rehydration process is essential for restoring the original content of a message * that has been transformed (masked) by the transformers. This process is the inverse of the masking process. * * @param message - The masked message to be rehydrated. * @returns The original (rehydrated) version of the message. */ async rehydrate(message, state) { // Handle onRehydratingStart callback if (this.config.onRehydratingStart) { await this.config.onRehydratingStart(message); } if (typeof message !== "string") { throw new TypeError("MaskingParser.rehydrate Error: The 'message' argument must be a string."); } // Check if any transformers have been added to the parser. // If no transformers are present, throw an error as rehydration requires at least one transformer. if (this.transformers.length === 0) { throw new Error("MaskingParser.rehydrate Error: No transformers have been added. Please add at least one transformer before rehydrating."); } // eslint-disable-next-line no-instanceof/no-instanceof if (state && !(state instanceof Map)) { throw new TypeError("MaskingParser.rehydrate Error: The 'state' argument, if provided, must be an instance of Map."); } const rehydrationState = state || this.state; // Use provided state or fallback to internal state // Initialize the rehydratedMessage with the input masked message. // This variable will undergo rehydration by each transformer in reverse order. let rehydratedMessage = message; // Use a reverse for...of loop to accommodate asynchronous rehydrate methods const reversedTransformers = this.transformers.slice().reverse(); for (const transformer of reversedTransformers) { // Check if the result is a Promise and use await, otherwise use it directly rehydratedMessage = await transformer.rehydrate(rehydratedMessage, rehydrationState); } // Handle onRehydratingEnd callback if (this.config.onRehydratingEnd) { await this.config.onRehydratingEnd(rehydratedMessage); } // Return the fully rehydrated message after all transformers have been applied. return rehydratedMessage; } } exports.MaskingParser = MaskingParser;