houser-js-utils
Version:
A comprehensive collection of TypeScript utility functions for common development tasks including array manipulation, string processing, date handling, random number generation, validation, and much more.
1 lines • 21.5 kB
Source Map (JSON)
{"version":3,"file":"ValidationUtils.mjs","sources":["../src/ValidationUtils.ts"],"sourcesContent":["/**\n * @module ValidationUtils\n * @description A comprehensive collection of validation functions for common data types and formats.\n * @example\n * ```typescript\n * import { ValidationUtils } from 'houser-js-utils';\n *\n * // Validate email address\n * const isValid = ValidationUtils.isEmail('user@example.com'); // true\n *\n * // Validate credit card number\n * const isValidCard = ValidationUtils.isCreditCard('4111111111111111'); // true\n *\n * // Validate password strength\n * const isStrongPassword = ValidationUtils.isPassword('MyP@ssw0rd123'); // true\n * ```\n */\n\n/**\n * Validation utility functions for common data types and formats\n */\nexport const ValidationUtils = {\n /**\n * Checks if a value is a valid base64 encoded string.\n * @param base64 - The base64 string to validate\n * @returns True if the string is valid base64, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isBase64('SGVsbG8gV29ybGQ='); // Returns true\n * ValidationUtils.isBase64('invalid-base64'); // Returns false\n * ```\n */\n isBase64(base64: string): boolean {\n try {\n return btoa(atob(base64)) === base64;\n } catch {\n return false;\n }\n },\n\n /**\n * Validates a credit card number using the Luhn algorithm.\n * @param number - The credit card number to validate (can include spaces, dashes, etc.)\n * @returns True if the credit card number is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isCreditCard('4111111111111111'); // Returns true (Visa test number)\n * ValidationUtils.isCreditCard('4111-1111-1111-1111'); // Returns true (with dashes)\n * ValidationUtils.isCreditCard('1234567890123456'); // Returns false (invalid)\n * ```\n */\n isCreditCard(number: string): boolean {\n const cleanNumber = number.replace(/\\D/g, \"\");\n if (cleanNumber.length < 13 || cleanNumber.length > 19) return false;\n\n let sum = 0;\n let isEven = false;\n\n for (let i = cleanNumber.length - 1; i >= 0; i--) {\n let digit = parseInt(cleanNumber.charAt(i));\n\n if (isEven) {\n digit *= 2;\n if (digit > 9) {\n digit -= 9;\n }\n }\n\n sum += digit;\n isEven = !isEven;\n }\n\n return sum % 10 === 0;\n },\n\n /**\n * Validates a credit card CVV (Card Verification Value).\n * @param cvv - The CVV to validate (3 or 4 digits)\n * @returns True if the CVV format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isCreditCardCvv('123'); // Returns true\n * ValidationUtils.isCreditCardCvv('1234'); // Returns true (Amex)\n * ValidationUtils.isCreditCardCvv('12'); // Returns false (too short)\n * ```\n */\n isCreditCardCvv(cvv: string): boolean {\n return /^\\d{3,4}$/.test(cvv);\n },\n\n /**\n * Validates a credit card expiry date in MM/YY format.\n * @param expiry - The expiry date to validate in MM/YY format\n * @returns True if the expiry date is valid and not in the past, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isCreditCardExpiry('12/25'); // Returns true (if current date is before Dec 2025)\n * ValidationUtils.isCreditCardExpiry('01/20'); // Returns false (expired)\n * ValidationUtils.isCreditCardExpiry('13/25'); // Returns false (invalid month)\n * ```\n */\n isCreditCardExpiry(expiry: string): boolean {\n const expiryRegex = /^(0[1-9]|1[0-2])\\/([0-9]{2})$/;\n if (!expiryRegex.test(expiry)) return false;\n\n const [month, year] = expiry.split(\"/\");\n const currentDate = new Date();\n const currentYear = currentDate.getFullYear() % 100;\n const currentMonth = currentDate.getMonth() + 1;\n\n const expiryYear = parseInt(year);\n const expiryMonth = parseInt(month);\n\n if (expiryYear < currentYear) return false;\n if (expiryYear === currentYear && expiryMonth < currentMonth) return false;\n\n return true;\n },\n\n /**\n * Validates a domain name format.\n * @param domain - The domain name to validate\n * @returns True if the domain name format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isDomain('example.com'); // Returns true\n * ValidationUtils.isDomain('sub.example.org'); // Returns true\n * ValidationUtils.isDomain('invalid..domain'); // Returns false\n * ```\n */\n isDomain(domain: string): boolean {\n const domainRegex =\n /^(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$/;\n return domainRegex.test(domain);\n },\n\n /**\n * Validates an email address format.\n * @param email - The email address to validate\n * @returns True if the email format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isEmail('user@example.com'); // Returns true\n * ValidationUtils.isEmail('test.email+tag@domain.co.uk'); // Returns true\n * ValidationUtils.isEmail('invalid-email'); // Returns false\n * ```\n */\n isEmail(email: string): boolean {\n const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/;\n return emailRegex.test(email);\n },\n\n /**\n * Validates a hostname format.\n * @param hostname - The hostname to validate\n * @returns True if the hostname format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isHostname('localhost'); // Returns true\n * ValidationUtils.isHostname('web-server-01'); // Returns true\n * ValidationUtils.isHostname('invalid_hostname'); // Returns false\n * ```\n */\n isHostname(hostname: string): boolean {\n const hostnameRegex = /^[a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/;\n return hostnameRegex.test(hostname);\n },\n\n /**\n * Checks if a value is empty (null, undefined, empty string, empty array, or empty object).\n * @param value - The value to check for emptiness\n * @returns True if the value is considered empty, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isEmpty(null); // Returns true\n * ValidationUtils.isEmpty(''); // Returns true\n * ValidationUtils.isEmpty([]); // Returns true\n * ValidationUtils.isEmpty({}); // Returns true\n * ValidationUtils.isEmpty('hello'); // Returns false\n * ```\n */\n isEmpty(value: unknown): boolean {\n if (value === null || value === undefined) return true;\n if (typeof value === \"string\") return value.trim().length === 0;\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") return Object.keys(value).length === 0;\n return false;\n },\n\n /**\n * Validates an IP address (IPv4 or IPv6).\n * @param ip - The IP address to validate\n * @returns True if the IP address format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isIpAddress('192.168.1.1'); // Returns true (IPv4)\n * ValidationUtils.isIpAddress('2001:0db8:85a3:0000:0000:8a2e:0370:7334'); // Returns true (IPv6)\n * ValidationUtils.isIpAddress('256.1.1.1'); // Returns false (invalid IPv4)\n * ```\n */\n isIpAddress(ip: string): boolean {\n const ipv4Regex =\n /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;\n const ipv6Regex = /^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/;\n return ipv4Regex.test(ip) || ipv6Regex.test(ip);\n },\n\n /**\n * Validates if a string is valid JSON.\n * @param json - The JSON string to validate\n * @returns True if the string is valid JSON, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isJson('{\"name\": \"John\", \"age\": 30}'); // Returns true\n * ValidationUtils.isJson('[1, 2, 3]'); // Returns true\n * ValidationUtils.isJson('invalid json'); // Returns false\n * ```\n */\n isJson(json: string): boolean {\n try {\n JSON.parse(json);\n return true;\n } catch {\n return false;\n }\n },\n\n /**\n * Validates a MIME type format.\n * @param mimeType - The MIME type to validate\n * @returns True if the MIME type format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isMimeType('text/html'); // Returns true\n * ValidationUtils.isMimeType('application/json'); // Returns true\n * ValidationUtils.isMimeType('invalid-mime'); // Returns false\n * ```\n */\n isMimeType(mimeType: string): boolean {\n const mimeTypeRegex = /^[a-z]+\\/[a-z0-9-+.]+$/;\n return mimeTypeRegex.test(mimeType);\n },\n\n /**\n * Validates password strength based on configurable criteria.\n * @param password - The password to validate\n * @param options - Password validation options\n * @param options.minLength - Minimum password length (default: 8)\n * @param options.requireUppercase - Require uppercase letters (default: true)\n * @param options.requireLowercase - Require lowercase letters (default: true)\n * @param options.requireNumbers - Require numbers (default: true)\n * @param options.requireSpecialChars - Require special characters (default: true)\n * @returns True if the password meets all criteria, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isPassword('MyP@ssw0rd123'); // Returns true\n * ValidationUtils.isPassword('weak', { minLength: 4, requireSpecialChars: false }); // Returns false\n * ValidationUtils.isPassword('StrongPass123!'); // Returns true\n * ```\n */\n isPassword(\n password: string,\n options: {\n minLength?: number;\n requireUppercase?: boolean;\n requireLowercase?: boolean;\n requireNumbers?: boolean;\n requireSpecialChars?: boolean;\n } = {}\n ): boolean {\n const {\n minLength = 8,\n requireUppercase = true,\n requireLowercase = true,\n requireNumbers = true,\n requireSpecialChars = true,\n } = options;\n\n if (password.length < minLength) return false;\n if (requireUppercase && !/[A-Z]/.test(password)) return false;\n if (requireLowercase && !/[a-z]/.test(password)) return false;\n if (requireNumbers && !/\\d/.test(password)) return false;\n if (requireSpecialChars && !/[!@#$%^&*(),.?\":{}|<>]/.test(password))\n return false;\n\n return true;\n },\n\n /**\n * Validates a phone number format.\n * @param phone - The phone number to validate\n * @returns True if the phone number format is valid, false otherwise\n * @example\n * ```typescript\n * ValidationUtils.isPhoneNumber('+1 (555) 123-4567'); // Returns true\n * ValidationUtils.isPhoneNumber('555-123-4567'); // Returns true\n * ValidationUtils.isPhoneNumber('123'); // Returns false (too short)\n * ```\n */\n isPhoneNumber(phone: string): boolean {\n const phoneRegex = /^\\+?[\\d\\s-()]{10,}$/;\n return phoneRegex.test(phone);\n },\n\n /**\n * Checks if a value is a valid port number\n * @param port - Port number to validate\n * @returns True if valid, false otherwise\n */\n isPort(port: number): boolean {\n return Number.isInteger(port) && port >= 0 && port <= 65535;\n },\n\n /**\n * Checks if a value is a valid postal code\n * @param postalCode - Postal code to validate\n * @param country - Country code (ISO 3166-1 alpha-2)\n * @returns True if valid, false otherwise\n */\n isPostalCode(postalCode: string, country: string): boolean {\n const patterns: Record<string, RegExp> = {\n US: /^\\d{5}(-\\d{4})?$/,\n CA: /^[A-Z]\\d[A-Z] \\d[A-Z]\\d$/,\n GB: /^[A-Z]{1,2}\\d[A-Z\\d]? ?\\d[A-Z]{2}$/,\n DE: /^\\d{5}$/,\n FR: /^\\d{5}$/,\n IT: /^\\d{5}$/,\n ES: /^\\d{5}$/,\n NL: /^\\d{4} ?[A-Z]{2}$/,\n BE: /^\\d{4}$/,\n CH: /^\\d{4}$/,\n AT: /^\\d{4}$/,\n SE: /^\\d{3} ?\\d{2}$/,\n NO: /^\\d{4}$/,\n DK: /^\\d{4}$/,\n FI: /^\\d{5}$/,\n PL: /^\\d{2}-\\d{3}$/,\n PT: /^\\d{4}-\\d{3}$/,\n GR: /^\\d{3} ?\\d{2}$/,\n CZ: /^\\d{3} ?\\d{2}$/,\n HU: /^\\d{4}$/,\n SK: /^\\d{3} ?\\d{2}$/,\n RO: /^\\d{6}$/,\n BG: /^\\d{4}$/,\n HR: /^\\d{5}$/,\n RS: /^\\d{5}$/,\n KZ: /^\\d{6}$/,\n TR: /^\\d{5}$/,\n IL: /^\\d{5}$/,\n AE: /^\\d{5}$/,\n SA: /^\\d{5}$/,\n IN: /^\\d{6}$/,\n CN: /^\\d{6}$/,\n JP: /^\\d{3}-\\d{4}$/,\n KR: /^\\d{5}$/,\n SG: /^\\d{6}$/,\n MY: /^\\d{5}$/,\n ID: /^\\d{5}$/,\n PH: /^\\d{4}$/,\n VN: /^\\d{6}$/,\n AU: /^\\d{4}$/,\n NZ: /^\\d{4}$/,\n ZA: /^\\d{4}$/,\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return false;\n\n return pattern.test(postalCode);\n },\n\n /**\n * Checks if a value is a valid semver version\n * @param version - Version string to validate\n * @returns True if valid, false otherwise\n */\n isSemver(version: string): boolean {\n const semverRegex =\n /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$/;\n return semverRegex.test(version);\n },\n\n /**\n * Checks if a value is a valid social security number\n * @param ssn - Social security number to validate\n * @param country - Country code (ISO 3166-1 alpha-2)\n * @returns True if valid, false otherwise\n */\n isSocialSecurityNumber(ssn: string, country: string): boolean {\n const patterns: Record<string, RegExp> = {\n US: /^(?!000|666)[0-8][0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}$/,\n GB: /^[A-Z]{2}\\d{6}[A-Z]{1}$/,\n DE: /^\\d{11}$/,\n FR: /^\\d{15}$/,\n IT: /^[A-Z]{6}\\d{2}[A-Z]\\d{2}[A-Z]\\d{3}[A-Z]$/,\n ES: /^\\d{8}[A-Z]$/,\n NL: /^\\d{9}$/,\n BE: /^\\d{11}$/,\n CH: /^\\d{13}$/,\n AT: /^\\d{10}$/,\n SE: /^\\d{12}$/,\n NO: /^\\d{11}$/,\n DK: /^\\d{10}$/,\n FI: /^\\d{11}$/,\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return false;\n\n return pattern.test(ssn);\n },\n\n /**\n * Checks if a value is a valid tax identification number\n * @param tin - Tax identification number to validate\n * @param country - Country code (ISO 3166-1 alpha-2)\n * @returns True if valid, false otherwise\n */\n isTaxIdentificationNumber(tin: string, country: string): boolean {\n const patterns: Record<string, RegExp> = {\n US: /^\\d{2}-\\d{7}$/, // EIN\n GB: /^\\d{10}$/, // VAT\n DE: /^DE\\d{9}$/, // VAT\n FR: /^FR\\d{11}$/, // VAT\n IT: /^IT\\d{11}$/, // VAT\n ES: /^ES[A-Z0-9]{9}$/, // VAT\n NL: /^NL\\d{9}B\\d{2}$/, // VAT\n BE: /^BE\\d{10}$/, // VAT\n CH: /^CHE-\\d{3}\\.\\d{3}\\.\\d{3}$/, // VAT\n AT: /^ATU\\d{8}$/, // VAT\n SE: /^SE\\d{12}$/, // VAT\n NO: /^\\d{9}MVA$/, // VAT\n DK: /^DK\\d{8}$/, // VAT\n FI: /^FI\\d{8}$/, // VAT\n };\n\n const pattern = patterns[country.toUpperCase()];\n if (!pattern) return false;\n\n return pattern.test(tin);\n },\n\n /**\n * Checks if a value is a valid URL\n * @param url - URL to validate\n * @returns True if valid, false otherwise\n */\n isUrl(url: string): boolean {\n try {\n new URL(url);\n return true;\n } catch {\n return false;\n }\n },\n\n /**\n * Checks if a value is a valid username\n * @param username - Username to validate\n * @param options - Username validation options\n * @returns True if valid, false otherwise\n */\n isUsername(\n username: string,\n options: {\n minLength?: number;\n maxLength?: number;\n allowSpecialChars?: boolean;\n } = {}\n ): boolean {\n const {\n minLength = 3,\n maxLength = 20,\n allowSpecialChars = false,\n } = options;\n\n if (username.length < minLength || username.length > maxLength)\n return false;\n\n const pattern = allowSpecialChars\n ? /^[a-zA-Z0-9_\\-\\.]+$/\n : /^[a-zA-Z0-9_]+$/;\n\n return pattern.test(username);\n },\n\n /**\n * Checks if a value is a valid UUID\n * @param uuid - UUID to validate\n * @returns True if valid, false otherwise\n */\n isUuid(uuid: string): boolean {\n return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(\n uuid\n );\n },\n};\n"],"names":[],"mappings":"AAqBO,MAAM,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW7B,SAAS,QAAyB;AAChC,QAAI;AACF,aAAO,KAAK,KAAK,MAAM,CAAC,MAAM;AAAA,IAChC,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,aAAa,QAAyB;AACpC,UAAM,cAAc,OAAO,QAAQ,OAAO,EAAE;AAC5C,QAAI,YAAY,SAAS,MAAM,YAAY,SAAS,GAAI,QAAO;AAE/D,QAAI,MAAM;AACV,QAAI,SAAS;AAEb,aAAS,IAAI,YAAY,SAAS,GAAG,KAAK,GAAG,KAAK;AAChD,UAAI,QAAQ,SAAS,YAAY,OAAO,CAAC,CAAC;AAE1C,UAAI,QAAQ;AACV,iBAAS;AACT,YAAI,QAAQ,GAAG;AACb,mBAAS;AAAA,QACX;AAAA,MACF;AAEA,aAAO;AACP,eAAS,CAAC;AAAA,IACZ;AAEA,WAAO,MAAM,OAAO;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,gBAAgB,KAAsB;AACpC,WAAO,YAAY,KAAK,GAAG;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,mBAAmB,QAAyB;AAC1C,UAAM,cAAc;AACpB,QAAI,CAAC,YAAY,KAAK,MAAM,EAAG,QAAO;AAEtC,UAAM,CAAC,OAAO,IAAI,IAAI,OAAO,MAAM,GAAG;AACtC,UAAM,kCAAkB,KAAA;AACxB,UAAM,cAAc,YAAY,YAAA,IAAgB;AAChD,UAAM,eAAe,YAAY,SAAA,IAAa;AAE9C,UAAM,aAAa,SAAS,IAAI;AAChC,UAAM,cAAc,SAAS,KAAK;AAElC,QAAI,aAAa,YAAa,QAAO;AACrC,QAAI,eAAe,eAAe,cAAc,aAAc,QAAO;AAErE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,SAAS,QAAyB;AAChC,UAAM,cACJ;AACF,WAAO,YAAY,KAAK,MAAM;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,QAAQ,OAAwB;AAC9B,UAAM,aAAa;AACnB,WAAO,WAAW,KAAK,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,UAA2B;AACpC,UAAM,gBAAgB;AACtB,WAAO,cAAc,KAAK,QAAQ;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,QAAQ,OAAyB;AAC/B,QAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,QAAI,OAAO,UAAU,iBAAiB,MAAM,KAAA,EAAO,WAAW;AAC9D,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,WAAW;AAClD,QAAI,OAAO,UAAU,SAAU,QAAO,OAAO,KAAK,KAAK,EAAE,WAAW;AACpE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,YAAY,IAAqB;AAC/B,UAAM,YACJ;AACF,UAAM,YAAY;AAClB,WAAO,UAAU,KAAK,EAAE,KAAK,UAAU,KAAK,EAAE;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,MAAuB;AAC5B,QAAI;AACF,WAAK,MAAM,IAAI;AACf,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,WAAW,UAA2B;AACpC,UAAM,gBAAgB;AACtB,WAAO,cAAc,KAAK,QAAQ;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,WACE,UACA,UAMI,IACK;AACT,UAAM;AAAA,MACJ,YAAY;AAAA,MACZ,mBAAmB;AAAA,MACnB,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,MACjB,sBAAsB;AAAA,IAAA,IACpB;AAEJ,QAAI,SAAS,SAAS,UAAW,QAAO;AACxC,QAAI,oBAAoB,CAAC,QAAQ,KAAK,QAAQ,EAAG,QAAO;AACxD,QAAI,oBAAoB,CAAC,QAAQ,KAAK,QAAQ,EAAG,QAAO;AACxD,QAAI,kBAAkB,CAAC,KAAK,KAAK,QAAQ,EAAG,QAAO;AACnD,QAAI,uBAAuB,CAAC,yBAAyB,KAAK,QAAQ;AAChE,aAAO;AAET,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,cAAc,OAAwB;AACpC,UAAM,aAAa;AACnB,WAAO,WAAW,KAAK,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAuB;AAC5B,WAAO,OAAO,UAAU,IAAI,KAAK,QAAQ,KAAK,QAAQ;AAAA,EACxD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,aAAa,YAAoB,SAA0B;AACzD,UAAM,WAAmC;AAAA,MACvC,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAGN,UAAM,UAAU,SAAS,QAAQ,YAAA,CAAa;AAC9C,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO,QAAQ,KAAK,UAAU;AAAA,EAChC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,SAAS,SAA0B;AACjC,UAAM,cACJ;AACF,WAAO,YAAY,KAAK,OAAO;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,uBAAuB,KAAa,SAA0B;AAC5D,UAAM,WAAmC;AAAA,MACvC,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IAAA;AAGN,UAAM,UAAU,SAAS,QAAQ,YAAA,CAAa;AAC9C,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,0BAA0B,KAAa,SAA0B;AAC/D,UAAM,WAAmC;AAAA,MACvC,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,MACJ,IAAI;AAAA;AAAA,IAAA;AAGN,UAAM,UAAU,SAAS,QAAQ,YAAA,CAAa;AAC9C,QAAI,CAAC,QAAS,QAAO;AAErB,WAAO,QAAQ,KAAK,GAAG;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,KAAsB;AAC1B,QAAI;AACF,UAAI,IAAI,GAAG;AACX,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,WACE,UACA,UAII,IACK;AACT,UAAM;AAAA,MACJ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,oBAAoB;AAAA,IAAA,IAClB;AAEJ,QAAI,SAAS,SAAS,aAAa,SAAS,SAAS;AACnD,aAAO;AAET,UAAM,UAAU,oBACZ,wBACA;AAEJ,WAAO,QAAQ,KAAK,QAAQ;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,MAAuB;AAC5B,WAAO,6EAA6E;AAAA,MAClF;AAAA,IAAA;AAAA,EAEJ;AACF;"}