UNPKG

camote-utils

Version:

A comprehensive TypeScript utility library featuring advanced string and number formatting, data structures, and algorithms

331 lines (330 loc) 14.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateRandom = exports.generateUUIDv4 = exports.generateUUID = exports.generateRandomColor = exports.generateColorPalette = exports.generateRandomHSL = exports.generateRandomRGB = exports.generateRandomHexColor = exports.generateStrongPassword = exports.generateRandomPassword = exports.generateRandomString = exports.generateRandomIntegerExcluding = exports.generateRandomIntegerArray = exports.generateRandomIntegerInRange = exports.generateRandomInteger = void 0; /** * Generates a random integer between min (inclusive) and max (inclusive) * @param min - The minimum value (inclusive) * @param max - The maximum value (inclusive) * @returns A random integer between min and max * @throws {Error} If min is greater than max * @throws {Error} If min or max is not a finite number * @example * generateRandomInteger(1, 10); // Returns a number between 1 and 10 * generateRandomInteger(0, 1); // Returns either 0 or 1 * generateRandomInteger(-5, 5); // Returns a number between -5 and 5 */ const generateRandomInteger = (min, max) => { // Validate input types if (!Number.isFinite(min) || !Number.isFinite(max)) { throw new Error('Both min and max must be finite numbers'); } // Convert to integers min = Math.floor(min); max = Math.floor(max); // Validate range if (min > max) { throw new Error('Min cannot be greater than max'); } // Calculate range and add 1 to make max inclusive const range = max - min + 1; // Generate random number return Math.floor(Math.random() * range) + min; }; exports.generateRandomInteger = generateRandomInteger; /** * Generates a random integer between min (inclusive) and max (inclusive) * @param min - The minimum value (inclusive) * @param max - The maximum value (inclusive) * @returns A random integer between min and max * @throws {Error} If min is greater than max * @throws {Error} If min or max is not a finite number * @example * generateRandomIntegerInRange(5, 10); // Returns a number between 5 and 10 * generateRandomIntegerInRange(-10, 10); // Returns a number between -10 and 10 */ const generateRandomIntegerInRange = (min, max) => { // Validate input types if (!Number.isFinite(min) || !Number.isFinite(max)) { throw new Error('Both min and max must be finite numbers'); } // Convert to integers min = Math.floor(min); max = Math.floor(max); // Validate range if (min > max) { throw new Error('Min cannot be greater than max'); } // Calculate range and add 1 to make max inclusive const range = max - min + 1; // Generate random number return Math.floor(Math.random() * range) + min; }; exports.generateRandomIntegerInRange = generateRandomIntegerInRange; /** * Generates an array of random integers * @param length - The length of the array to generate * @param min - The minimum value (inclusive) * @param max - The maximum value (inclusive) * @returns An array of random integers * @throws {Error} If length is less than 0 * @example * generateRandomIntegerArray(3, 1, 10); // Returns e.g. [4, 7, 2] * generateRandomIntegerArray(5, 0, 1); // Returns e.g. [1, 0, 1, 0, 1] */ const generateRandomIntegerArray = (length, min, max) => { if (length < 0) { throw new Error('Length cannot be negative'); } return Array.from({ length }, () => (0, exports.generateRandomInteger)(min, max)); }; exports.generateRandomIntegerArray = generateRandomIntegerArray; /** * Generates a random integer excluding certain values * @param min - The minimum value (inclusive) * @param max - The maximum value (inclusive) * @param exclude - Array of numbers to exclude * @returns A random integer between min and max, excluding specified values * @throws {Error} If no valid numbers are available in the range * @example * generateRandomIntegerExcluding(1, 10, [5, 6]); // Returns a number between 1-4 or 7-10 * generateRandomIntegerExcluding(1, 3, [2]); // Returns either 1 or 3 */ const generateRandomIntegerExcluding = (min, max, exclude) => { // Convert to integers and create a set of excluded numbers min = Math.floor(min); max = Math.floor(max); const excludeSet = new Set(exclude.map(Math.floor)); // Calculate available numbers const range = max - min + 1; const availableNumbers = Array.from({ length: range }, (_, i) => min + i).filter(num => !excludeSet.has(num)); const availableCount = availableNumbers.length; if (availableCount <= 0) { throw new Error('No valid numbers available in the range after exclusions. Please check your min, max, and exclude values.'); } // Generate random number until we get one that's not excluded let result; do { result = (0, exports.generateRandomInteger)(min, max); } while (excludeSet.has(result)); return result; }; exports.generateRandomIntegerExcluding = generateRandomIntegerExcluding; const CHARS = { lowercase: 'abcdefghijklmnopqrstuvwxyz', uppercase: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', numbers: '0123456789', special: '!@#$%^&*()_+-=[]{}|;:,.<>?' }; /** * Generates a random string based on specified options. * * @param length - The length of the string to generate. * @param options - Configuration options for string generation, which may include: * - custom: A string of custom characters to use for generation. * - lowercase: A boolean indicating whether to include lowercase letters. * - uppercase: A boolean indicating whether to include uppercase letters. * - numbers: A boolean indicating whether to include numeric characters. * - special: A boolean indicating whether to include special characters. * - exclude: A string of characters to exclude from the generated string. * * @returns A random string that matches the specified criteria. * * @throws {Error} If length is less than 0. * @throws {Error} If no character set is selected (i.e., all options are false or empty). * * @example * generateRandomString(8); // Might return "aB3$kL9p" * generateRandomString(10, { lowercase: true, numbers: true }); // Might return "a7b2n9k4m5" * generateRandomString(5, { custom: "ABC123" }); // Might return "B1CA3" */ const generateRandomString = (length, options) => { // Check for negative length if (length < 0) { throw new Error('Length cannot be negative'); } const { custom, lowercase, uppercase, numbers, special, exclude } = options || {}; let characters = ''; // Build the character set using the CHARS object if (custom) { characters += custom; } if (lowercase) { characters += CHARS.lowercase; } if (uppercase) { characters += CHARS.uppercase; } if (numbers) { characters += CHARS.numbers; } if (special) { characters += CHARS.special; } // Exclude specified characters if (exclude) { characters = characters.split('').filter(char => !exclude.includes(char)).join(''); } // Throw an error if no characters are available if (characters.length === 0) { throw new Error('No characters available for string generation. Please specify at least one character type.'); } // Generate the random string let result = ''; for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * characters.length); result += characters[randomIndex]; } return result; }; exports.generateRandomString = generateRandomString; const generateRandomPassword = (length, options = {}) => { if (length < 8) { throw new Error('Password length must be at least 8 characters'); } // Ensure password has at least one of each required character type const password = (0, exports.generateRandomString)(length, { ...options, lowercase: true, uppercase: true, numbers: true, special: true }); return password; }; exports.generateRandomPassword = generateRandomPassword; const generateStrongPassword = (length = 12) => { if (length < 8) { throw new Error('Password length must be at least 8 characters'); } const lowercaseChars = 'abcdefghijklmnopqrstuvwxyz'; const uppercaseChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const numberChars = '0123456789'; const specialChars = '!@#$%^&*()_+[]{}|;:,.<>?'; // Ensure at least one character from each set is included const passwordChars = [ lowercaseChars.charAt(Math.floor(Math.random() * lowercaseChars.length)), uppercaseChars.charAt(Math.floor(Math.random() * uppercaseChars.length)), numberChars.charAt(Math.floor(Math.random() * numberChars.length)), specialChars.charAt(Math.floor(Math.random() * specialChars.length)) ]; // Fill the rest of the password length with random characters for (let i = 4; i < length; i++) { const allChars = lowercaseChars + uppercaseChars + numberChars + specialChars; passwordChars.push(allChars.charAt(Math.floor(Math.random() * allChars.length))); } // Shuffle the password characters for (let i = passwordChars.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [passwordChars[i], passwordChars[j]] = [passwordChars[j], passwordChars[i]]; } return passwordChars.join(''); }; exports.generateStrongPassword = generateStrongPassword; const generateRandomHexColor = (includeHash = true) => { const hex = (0, exports.generateRandomInteger)(0, 0xFFFFFF).toString(16).padStart(6, '0').toUpperCase(); return includeHash ? `#${hex}` : hex; }; exports.generateRandomHexColor = generateRandomHexColor; const generateRandomRGB = (includeArray = false) => { const r = Math.floor(Math.random() * 256); const g = Math.floor(Math.random() * 256); const b = Math.floor(Math.random() * 256); return includeArray ? [r, g, b] : `rgb(${r}, ${g}, ${b})`; }; exports.generateRandomRGB = generateRandomRGB; const generateRandomHSL = (includeArray = false) => { const h = Math.floor(Math.random() * 361); // Hue: 0-360 const s = Math.floor(Math.random() * 101); // Saturation: 0-100% const l = Math.floor(Math.random() * 101); // Lightness: 0-100% return includeArray ? [h, s, l] : `hsl(${h}, ${s}%, ${l}%)`; }; exports.generateRandomHSL = generateRandomHSL; const generateColorPalette = (numColors, format = 'hex') => { const palette = []; for (let i = 0; i < numColors; i++) { palette.push((0, exports.generateRandomColor)(format)); } return palette; }; exports.generateColorPalette = generateColorPalette; const generateRandomColor = (format = 'hex') => { switch (format) { case 'rgb': const rgbArray = (0, exports.generateRandomRGB)(true); return Array.isArray(rgbArray) ? `rgb(${rgbArray.join(', ')})` : rgbArray; case 'hsl': const hslArray = (0, exports.generateRandomHSL)(true); return Array.isArray(hslArray) ? `hsl(${hslArray.join(', ')})` : hslArray; default: return (0, exports.generateRandomHexColor)(); } }; exports.generateRandomColor = generateRandomColor; const generateUUID = () => { // Generate 16 random bytes const bytes = new Uint8Array(16); for (let i = 0; i < 16; i++) { bytes[i] = (0, exports.generateRandomInteger)(0, 255); } // Set version (4) and variant (RFC4122) bytes[6] = (bytes[6] & 0x0f) | 0x40; bytes[8] = (bytes[8] & 0x3f) | 0x80; // Convert to hex string const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join(''); // Format as UUID return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; }; exports.generateUUID = generateUUID; const generateUUIDv4 = () => { const bytes = new Uint8Array(16); for (let i = 0; i < 16; i++) { bytes[i] = (0, exports.generateRandomInteger)(0, 255); } bytes[6] = (bytes[6] & 0x0f) | 0x40; // Set version to 4 bytes[8] = (bytes[8] & 0x3f) | 0x80; // Set variant to RFC4122 const hex = Array.from(bytes, byte => byte.toString(16).padStart(2, '0')).join(''); return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`; }; exports.generateUUIDv4 = generateUUIDv4; const generateRandom = (options) => { switch (options.type) { case 'integer': if (typeof options.min !== 'number' || typeof options.max !== 'number') { throw new Error('Min and max must be provided for integer type'); } return (0, exports.generateRandomInteger)(options.min, options.max); case 'float': if (typeof options.min !== 'number' || typeof options.max !== 'number') { throw new Error('Min and max must be provided for float type'); } return options.min + Math.random() * (options.max - options.min); case 'boolean': return Math.random() < 0.5; case 'string': if (typeof options.length !== 'number') { throw new Error('Length must be provided for string type'); } return (0, exports.generateRandomString)(options.length, options.stringOptions); case 'hexColor': return (0, exports.generateRandomHexColor)(options.includeHash); case 'rgbColor': const rgb = (0, exports.generateRandomRGB)(); return Array.isArray(rgb) ? rgb.map(num => num.toString()) : rgb; case 'hslColor': const hsl = (0, exports.generateRandomHSL)(); return Array.isArray(hsl) ? hsl.map(num => num.toString()) : hsl; case 'colorPalette': if (typeof options.numColors !== 'number') { throw new Error('Number of colors must be provided for colorPalette type'); } if (typeof options.format !== 'string') { throw new Error('Format must be provided for colorPalette type'); } return (0, exports.generateColorPalette)(options.numColors, options.format); case 'uuid': return (0, exports.generateUUID)(); default: throw new Error(`Invalid random type: ${options.type}`); } }; exports.generateRandom = generateRandom;