Source: simplePass.js

/**
* simplePass - A JavaScript password generator.
* Copyright (C) 2023  Jordan Vezina(staticBanter)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <https://www.gnu.org/licenses/>.
*/
'use strict';
import whitespaceAttributes from "./data/lists/whitespaceAttributes.js";
import characterCodeConstraints from "./data/objects/characterCodeConstraints.js";
import errors from "./data/objects/errors.js";
import passwordPreConfigs from "./data/objects/passwordPreConfigs.js";
import cleanModifier from "./functions/cleanModifier.js";
import ensureRepeatingCharacters from "./functions/ensureRepeatingCharacters.js";
import generateCharCode from "./functions/generateCharCode.js";
import initializer from "./functions/initializer.js";
import messageHandler from "./functions/messageHandler.js";
import shuffle from "./functions/shuffle.js";
import strengthChecker from "./functions/strengthChecker.js";
import validateModifier from "./functions/validateModifier.js";
import config from "./simplePass.config.js";
/**
 *
 * @file This file contains the main 'simplePass' function. This file also is used to export any other function methods that are attached to the main function.
 * Other programs that wish to use simplePass should import this file into there program and call various functions/methods found inside of this file.
 * @module simplePass
 */
/**
 * Main program function.
 * Returns either a random strin or a [strength check password object]{@link module:strengthCheckedPassword} that contains the a random string with additional information.
 * If compression is configured, simplePass will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) containing your [strength check password object]{@link module:strengthCheckedPassword}.
 *
 * @function simplePass
 * @param {passwordModifier | FormData} [modifier] The available [password modifiers]{@link module:passwordModifier} that can be used to create the password. Defaults to *[config.defaultPasswordModifier]{@link module:config}*.
 * @param {module:config} [cFig] The configuration settings for the program.
 * @requires errors
 * @requires cleanModifier
 * @requires validateModifier
 * @requires whitespaceAttributes
 * @requires generateCharCode
 * @requires ensureRepeatingCharacters
 * @requires shuffle
 * @requires strengthChecker
 * @requires passwordPreConfigs
 * @requires messageHandler
 * @requires characterCodeConstraints
 * @throws {errors} Will throw an Error if the [modifier]{@link passwordModifier} is ```null```, ```undefined``` or not a JavaScript Object.
 * @returns {string | strengthCheckedPassword | Promise<strengthCheckedPassword>} The generated password or strength checked password object.
 */
export default function simplePass(modifier = config.defaultPasswordModifier, cFig = config) {
    let messageBoard = null;
    if (cFig.messages
        && cFig.messages.messageBoard) {
        messageBoard = document.body.querySelector(cFig.messages.messageBoard);
    }
    messageHandler('CLEAR', {
        htmlMessage: (messageBoard ? {
            messageBoard: messageBoard,
            clear: true,
        } : undefined),
        consoleMessage: {
            clear: cFig.messages?.clearConsole,
        },
        level: "CLEAR"
    }, cFig);
    /**
     * If the modifier is not an object
     * throw an error.
     */
    if (!modifier
        || typeof modifier !== 'object') {
        messageHandler({
            messageKey: 'invalidModifier',
            templateMessages: {
                replacements: [
                    'M',
                    '1'
                ],
                templates: errors
            }
        }, {
            htmlMessage: (messageBoard ? {
                messageBoard: messageBoard,
            } :
                undefined),
            consoleMessage: true,
            level: "ERROR",
        }, cFig);
    }
    // Remove unneeded object attributes and normalize formData objects.
    modifier = cleanModifier(modifier);
    // Ensure certain values are set and set properly.
    try {
        validateModifier(modifier);
    }
    catch (caught) {
        if (caught.message) {
            messageHandler({
                messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
            }, {
                htmlMessage: (messageBoard ? {
                    messageBoard: messageBoard,
                } :
                    undefined),
                consoleMessage: true,
                level: "ERROR",
            }, cFig);
        }
        else {
            messageHandler({
                messageKey: caught.errorKey,
                templateMessages: {
                    replacements: caught.replacements,
                    templates: errors,
                }
            }, {
                htmlMessage: (messageBoard ? {
                    messageBoard: messageBoard
                } :
                    undefined),
                consoleMessage: true,
                level: "ERROR",
            }, cFig);
        }
    }
    // Initialize the password.
    let password = '';
    let middleCharacters = '';
    // Initialize preserve beginning and end character flags.
    let preserveBeginning = false;
    let preserveEnd = false;
    if (!cFig.defaultPasswordModifier) {
        cFig.defaultPasswordModifier = Object.assign(config.defaultPasswordModifier, cFig.defaultPasswordModifier);
    }
    if (!cFig.passwordConstraints) {
        cFig.passwordConstraints = Object.assign(config.passwordConstraints, cFig.defaultPasswordModifier);
    }
    if (modifier.preConfig) {
        const preConfig = passwordPreConfigs[modifier.preConfig];
        modifier = {
            length: modifier.length
        };
        if (preConfig) {
            Object.assign(modifier, preConfig);
        }
    }
    // Get the attributes that can affect the character type
    const characterAttributes = Object.keys(modifier).filter((item) => {
        return Object.keys(characterCodeConstraints).includes(item);
    });
    // Get the attributes that can set whitespace
    const setWhitespaceAttributes = Object.keys(modifier).filter((item) => {
        return whitespaceAttributes.includes(item);
    });
    /**
     * Because we manually add the first and last character
     * we need to changed the password length limit.
     */
    let passwordLimit = (modifier.length - 2);
    /**
     * Prevent ```uniqueCharacters``` begin set
     * with modifiers that conflict with it.
     */
    if (modifier.uniqueCharacters
        && (modifier.repeatingCharacter
            || modifier.whitespaceBeginning
            || modifier.whitespaceEnd
            || modifier.whitespaceEnd
            || modifier.required_whitespaceEnd
            || modifier.required_whitespaceBeginning
            || modifier.whitespaceBetween
            || modifier.max_whitespaceBetween
            || modifier.preConfig)) {
        messageHandler(`ERROR.simplePass-M_E.2: Unique modifier was set with clashing modifiers.`);
    }
    /**
     * If the repeating characters attribute is set we need to generate less characters.
     */
    if (modifier.repeatingCharacter) {
        if (modifier.customRepeatingCharacters) {
            if (typeof (modifier.customRepeatingCharacters) !== 'string') {
                modifier.customRepeatingCharacters.forEach((set) => {
                    passwordLimit -= parseInt(set[1]);
                });
            }
            else {
                passwordLimit -= (modifier.customRepeatingCharacters.length * 2);
            }
            if (modifier.max_repeatingCharacter) {
                passwordLimit -= modifier.max_repeatingCharacter;
            }
        }
        else if (modifier.max_repeatingCharacter) {
            passwordLimit -= modifier.max_repeatingCharacter;
        }
        else {
            passwordLimit--;
        }
    }
    /**
     * If the whitespace between attribute is set,
     * we need to lower the password limit
     * to make room for the whitespace.
     */
    if (modifier.whitespaceBetween) {
        const max_whitespaceBetween = modifier.max_whitespaceBetween ?? 1;
        if ((modifier.length - max_whitespaceBetween) < characterAttributes.length) {
            messageHandler({
                messageKey: 'ERROR: The password length can not contain the selected amount of characters',
            }, {
                htmlMessage: (messageBoard ? {
                    messageBoard: messageBoard,
                } :
                    undefined),
                consoleMessage: true,
                level: "ERROR",
            }, cFig);
        }
        passwordLimit = passwordLimit - max_whitespaceBetween;
    }
    /**
     * If the password limit drops below zero the password will not be able to contain all the characters.
     */
    if (passwordLimit <= -1) {
        messageHandler({
            messageKey: 'ERROR: The password length can not contain the selected amount of characters',
        }, {
            htmlMessage: (messageBoard ? {
                messageBoard: messageBoard,
            } :
                undefined),
            consoleMessage: true,
            level: "ERROR",
        }, cFig);
    }
    /**
     * If our character attributes list is greater than one,
     * we need to use `.pop()` and therefore need to do more work,
     * like ensuring the attribute list is replenished.
     * Where if there is only one item we can just reference that.
     */
    if (characterAttributes.length > 1) {
        /**
         * Because we may need through the attributes a few times
         * we don't want to modify the original list.
         * Therefore we create a new list.
         * Because we don't want this list to just be a pointer
         * to the old list we need to initialize it and contact
         * the old list to it.
         */
        let deck = [];
        deck = deck.concat(shuffle(characterAttributes));
        /**
         * Set the first character of the password.
         * Check if it's required to be a whitespace.
         */
        if (modifier.whitespaceBeginning
            && modifier.required_whitespaceBeginning) {
            password += ' ';
            preserveBeginning = true;
        }
        else {
            try {
                password += String.fromCharCode(generateCharCode({
                    charType: deck[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, {
                    beginning: true
                }, cFig.cryptoModule));
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
            deck.shift();
        }
        /**
         * Set the middle characters for the password.
         */
        while (middleCharacters.length < passwordLimit) {
            /**
             * If the current character type is undefined,
             * and the deck length is 0,
             * replenish the deck.
             */
            if (!deck.length) {
                deck = deck.concat(shuffle(characterAttributes));
            }
            try {
                const generatedCharacter = String.fromCharCode(generateCharCode({
                    charType: deck[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, undefined, cFig.cryptoModule));
                if (modifier.uniqueCharacters) {
                    if (password.includes(generatedCharacter)
                        || middleCharacters.includes(generatedCharacter)) {
                        continue;
                    }
                }
                ;
                middleCharacters += generatedCharacter;
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
            deck.shift();
        }
        // Add any needed whitespace characters.
        if (modifier.whitespaceBetween) {
            if (modifier.max_whitespaceBetween
                && modifier.max_whitespaceBetween > 1) {
                while (modifier.max_whitespaceBetween--) {
                    middleCharacters += " ";
                }
            }
            else {
                middleCharacters += " ";
            }
        }
        // Add the middle characters
        password += shuffle(middleCharacters.split('')).join('');
        /**
         * Set the last character of the password.
         * Check if it's required to be a whitespace.
         */
        if (modifier.whitespaceEnd
            && modifier.required_whitespaceEnd) {
            password += ' ';
            preserveEnd = true;
        }
        else {
            /**
             * If the current character type is undefined,
             * and the deck length is 0,
             * replenish the deck.
             * We need to do this here because the loop
             * could have ended it on empty.
             */
            if (!deck.length) {
                deck = deck.concat(shuffle(characterAttributes));
            }
            try {
                let generatedCharacter = String.fromCharCode(generateCharCode({
                    charType: deck[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, {
                    end: true
                }, cFig.cryptoModule));
                if (modifier.uniqueCharacters) {
                    if (password.includes(generatedCharacter)) {
                        while (password.includes(generatedCharacter)) {
                            generatedCharacter = String.fromCharCode(generateCharCode({
                                charType: deck[0],
                                charCodeOptions: {
                                    whitespaceOptions: setWhitespaceAttributes,
                                    excludeCharacters: modifier.excludeCharacters
                                }
                            }, {
                                end: true
                            }, cFig.cryptoModule));
                        }
                    }
                }
                password += generatedCharacter;
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
        }
        // Check if we need to repeat any characters.
        if (modifier.repeatingCharacter) {
            // Recreate the password
            password = ensureRepeatingCharacters(password, {
                repeatingSetCount: modifier.max_repeatingCharacter,
                customCharacterSet: modifier.customRepeatingCharacters,
                preservations: {
                    beginning: preserveBeginning,
                    end: preserveEnd
                }
            });
            /**
             * The *ensureRepeatingCharacters* function may remove some characters from
             * the original password.
             * We will check if the password length is less than our requested length
             * and add new characters if it is.
             *
             * Because *ensureRepeatingCharacters* function only removes repeating
             * characters from the original password, we should be OK to add any
             * new characters from the request as we like.
             */
            if (password.length < modifier.length) {
                // Split the sting into pieces
                let stringBeginning = password.slice(0, 1);
                let stringMiddle = password.slice(1, password.length - 1);
                let stringEnd = password.slice(password.length - 1, password.length);
                // Add new characters to the middle of the string  the way we usually do.
                while (stringMiddle.length < (modifier.length - 2)) {
                    /**
                     * Check and reinitialize deck.
                     */
                    if (!deck.length) {
                        deck = deck.concat(shuffle(characterAttributes));
                    }
                    /**
                     * Add current character to string middle.
                     * If we can repeat this character we will.
                     */
                    try {
                        const currentCharacter = String.fromCharCode(generateCharCode({
                            charType: deck[0],
                            charCodeOptions: {
                                whitespaceOptions: setWhitespaceAttributes,
                                excludeCharacters: modifier.excludeCharacters
                            }
                        }, undefined, cFig.cryptoModule));
                        stringMiddle += currentCharacter;
                        // Repeat character if possible.
                        if ((stringMiddle.length + 1) <= (modifier.length - 2)) {
                            stringMiddle += currentCharacter;
                        }
                    }
                    catch (caught) {
                        if (caught.message) {
                            messageHandler({
                                messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                            }, {
                                htmlMessage: (messageBoard ? {
                                    messageBoard: messageBoard,
                                } :
                                    undefined),
                                consoleMessage: true,
                                level: "ERROR",
                            }, cFig);
                        }
                        else {
                            messageHandler({
                                messageKey: caught.errorKey,
                                templateMessages: {
                                    replacements: caught.replacements,
                                    templates: errors,
                                }
                            }, {
                                htmlMessage: (messageBoard ? {
                                    messageBoard: messageBoard
                                } :
                                    undefined),
                                consoleMessage: true,
                                level: "ERROR",
                            }, cFig);
                        }
                    }
                }
                // Recreate our password.
                password = stringBeginning + shuffle(stringMiddle.split('')).join('') + stringEnd;
            }
        }
    }
    else {
        // ^ Our character attributes list only contained one item.
        /**
         * Set the first character of the password.
         * Check if it's required to be a whitespace.
         */
        if (modifier.whitespaceBeginning
            && modifier.required_whitespaceBeginning) {
            password += ' ';
            preserveBeginning = true;
        }
        else {
            try {
                password += String.fromCharCode(generateCharCode({
                    charType: characterAttributes[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, {
                    beginning: true
                }, cFig.cryptoModule));
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
        }
        /**
         * Set the middle characters for the password.
         */
        while (middleCharacters.length < passwordLimit) {
            try {
                const generatedCharacter = String.fromCharCode(generateCharCode({
                    charType: characterAttributes[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, undefined, cFig.cryptoModule));
                if (modifier.uniqueCharacters) {
                    if (password.includes(generatedCharacter)
                        || middleCharacters.includes(generatedCharacter)) {
                        continue;
                    }
                }
                middleCharacters += generatedCharacter;
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
        }
        // Add any needed whitespace characters.
        if (modifier.whitespaceBetween) {
            if (modifier.max_whitespaceBetween
                && modifier.max_whitespaceBetween > 1) {
                while (modifier.max_whitespaceBetween--) {
                    middleCharacters += " ";
                }
            }
            else {
                middleCharacters += " ";
            }
        }
        // Add middle characters to password
        password += shuffle(middleCharacters.split('')).join('');
        /**
         * Set the last character of the password.
         * Check if it's required to be a whitespace.
         */
        if (modifier.whitespaceEnd
            && modifier.required_whitespaceEnd) {
            password += ' ';
            preserveEnd = true;
        }
        else {
            try {
                let generatedCharacter = String.fromCharCode(generateCharCode({
                    charType: characterAttributes[0],
                    charCodeOptions: {
                        whitespaceOptions: setWhitespaceAttributes,
                        excludeCharacters: modifier.excludeCharacters
                    }
                }, {
                    end: true
                }, cFig.cryptoModule));
                if (modifier.uniqueCharacters) {
                    if (password.includes(generatedCharacter)) {
                        while (password.includes(generatedCharacter)) {
                            generatedCharacter = String.fromCharCode(generateCharCode({
                                charType: characterAttributes[0],
                                charCodeOptions: {
                                    whitespaceOptions: setWhitespaceAttributes,
                                    excludeCharacters: modifier.excludeCharacters
                                }
                            }, {
                                end: true
                            }, cFig.cryptoModule));
                        }
                    }
                }
                password += generatedCharacter;
            }
            catch (caught) {
                if (caught.message) {
                    messageHandler({
                        messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard,
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
                else {
                    messageHandler({
                        messageKey: caught.errorKey,
                        templateMessages: {
                            replacements: caught.replacements,
                            templates: errors,
                        }
                    }, {
                        htmlMessage: (messageBoard ? {
                            messageBoard: messageBoard
                        } :
                            undefined),
                        consoleMessage: true,
                        level: "ERROR",
                    }, cFig);
                }
            }
        }
        // Check if we need to repeat any characters.
        if (modifier.repeatingCharacter) {
            // Recreate the password
            password = ensureRepeatingCharacters(password, {
                repeatingSetCount: modifier.max_repeatingCharacter,
                customCharacterSet: modifier.customRepeatingCharacters,
                preservations: {
                    beginning: preserveBeginning,
                    end: preserveEnd
                }
            });
            /**
             * The *ensureRepeatingCharacters* function may remove some characters from
             * the original password.
             * We will check if the password length is less than our requested length
             * and add new characters if it is.
             *
             * Because *ensureRepeatingCharacters* function only removes repeating
             * characters from the original password, we should be OK to add any
             * new characters from the request as we like.
             */
            if (password.length < modifier.length) {
                // Split the sting into pieces
                let stringBeginning = password.slice(0, 1);
                let stringMiddle = password.slice(1, password.length - 1);
                let stringEnd = password.slice(password.length - 1, password.length);
                // Add new characters to the middle of the string  the way we usually do.
                while (stringMiddle.length < (modifier.length - 2)) {
                    try {
                        const currentCharacter = String.fromCharCode(generateCharCode({
                            charType: characterAttributes[0],
                            charCodeOptions: {
                                whitespaceOptions: setWhitespaceAttributes,
                                excludeCharacters: modifier.excludeCharacters
                            }
                        }, undefined, cFig.cryptoModule));
                        stringMiddle += currentCharacter;
                        // If we can repeat this character we shall.
                        if ((stringMiddle.length + 1) <= (modifier.length - 2)) {
                            stringMiddle += currentCharacter;
                        }
                    }
                    catch (caught) {
                        if (caught.message) {
                            messageHandler({
                                messageKey: `${caught.name ?? 'Internal Error'}: ${caught.message}`,
                            }, {
                                htmlMessage: (messageBoard ? {
                                    messageBoard: messageBoard,
                                } :
                                    undefined),
                                consoleMessage: true,
                                level: "ERROR",
                            }, cFig);
                        }
                        else {
                            messageHandler({
                                messageKey: caught.errorKey,
                                templateMessages: {
                                    replacements: caught.replacements,
                                    templates: errors,
                                }
                            }, {
                                htmlMessage: (messageBoard ? {
                                    messageBoard: messageBoard,
                                } :
                                    undefined),
                                consoleMessage: true,
                                level: "ERROR",
                            }, cFig);
                        }
                    }
                }
                // Recreate our password.
                password = stringBeginning + shuffle(stringMiddle.split('')).join('') + stringEnd;
            }
        }
    }
    if (cFig.strengthCheck) {
        if (typeof (cFig.strengthCheck) === 'object'
            && cFig.strengthCheck.compression) {
            const compressions = Object.keys(cFig.strengthCheck.compression)
                .map((key) => {
                return key.replace('Target', '');
            })
                .filter((key) => {
                return [
                    'gzip',
                    'deflate',
                    'deflate-raw'
                ].includes(key);
            });
            return strengthChecker(password, {
                characterSets: {
                    used: Object.keys(modifier),
                    available: Object.keys(characterCodeConstraints)
                },
                excludeCharacters: modifier.excludeCharacters,
                min_length: cFig.passwordConstraints.min_length,
                max_length: cFig.passwordConstraints.max_length
            }, compressions);
        }
        return strengthChecker(password, {
            characterSets: {
                used: Object.keys(modifier),
                available: Object.keys(characterCodeConstraints)
            },
            excludeCharacters: modifier.excludeCharacters,
            min_length: cFig.passwordConstraints.min_length,
            max_length: cFig.passwordConstraints.max_length
        });
    }
    // Return the password.
    return password;
}
simplePass.init = initializer;