UNPKG

@rzl-zone/utils-js

Version:

A modern, lightweight set of JavaScript utility functions with TypeScript support for everyday development, crafted to enhance code readability and maintainability.

1,598 lines (1,560 loc) 51.1 kB
/*! * ==================================================== * Rzl Utils-JS. * ---------------------------------------------------- * Version: 3.11.0. * Author: Rizalvin Dwiky. * Repository: https://github.com/rzl-zone/utils-js. * ==================================================== */ 'use strict'; var isBoolean = (value) => { return typeof value === "boolean"; }; var isFunction = (value) => { return typeof value === "function"; }; function isNil(value) { return value == null; } function isArray(value) { return Array.isArray(value); } function isObject(value) { return typeof value === "object" && !isNil(value) && !isArray(value); } function isPlainObject(value) { if (!isObject(value)) return false; const proto = Object.getPrototypeOf(value); return proto === Object.prototype || proto === null; } var isString = (value) => { return typeof value === "string"; }; function isNumberObject(value) { return isObject(value) && Object.prototype.toString.call(value) === "[object Number]"; } function isNaN(value) { return typeof value === "number" ? Number.isNaN(value) : isNumberObject(value) && Number.isNaN(value.valueOf()); } var isNull = (val) => val === null; var assertIsBoolean = (value, options = {}) => { if (isBoolean(value)) return; resolveErrorMessageAssertions({ value, options, requiredValidType: "boolean" }); }; var isNumber = (value, options = {}) => { assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const includeNaN = isPlainObject(options) && isBoolean(options.includeNaN) ? options.includeNaN : false; assertIsBoolean(includeNaN, { message: ({ currentType, validType }) => `Parameter \`includeNaN\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const aNumber = typeof value === "number"; return includeNaN ? aNumber : aNumber && !Number.isNaN(value); }; var isSymbol = (value) => { return typeof value === "symbol"; }; var isUndefined = (value) => { return typeof value === "undefined"; }; function isObjectOrArray(value) { return isArray(value) || isObject(value); } function hasOwnProp(obj, key, options = {}) { if (!isString(obj) && !isObjectOrArray(obj) && !isFunction(obj)) return false; assertIsPlainObject(options, { message: ({ currentType, validType }) => `Third parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const discardUndefined = options.discardUndefined === void 0 ? true : options.discardUndefined; const discardNull = options.discardNull === void 0 ? false : options.discardNull; assertIsBoolean(discardUndefined, { message: ({ currentType, validType }) => `Parameter \`discardUndefined\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); assertIsBoolean(discardNull, { message: ({ currentType, validType }) => `Parameter \`discardNull\` property of the \`options\` (third parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const path = []; if (isString(key) && key.trim().length > 0 || isNumber(key, { includeNaN: true })) { const strKey = isNumber(key, { includeNaN: true }) ? String(key) : key; strKey.split(".").forEach((k) => { const bracketMatch = k.match(/^\[(\d+)\]$/); const symbolMatch = k.match(/^Symbol\((.+)\)$/); if (bracketMatch) path.push(Number(bracketMatch[1])); else if (symbolMatch) path.push(Symbol.for(symbolMatch[1])); else if (!isNaN(Number(k))) path.push(Number(k)); else path.push(k); }); } else if (isSymbol(key)) { path.push(key); } else { return false; } let current = isString(obj) && obj.trim().length > 0 ? Object(obj) : obj; for (const k of path) { if (isString(k) && k.trim().length > 0 || isNumber(k, { includeNaN: true })) { if (isNull(current) || !Object.prototype.hasOwnProperty.call(current, k)) { return false; } current = current[k]; } else if (isSymbol(k)) { if (isNull(current) || typeof current !== "object" && !isFunction(current)) { return false; } const symbols = Object.getOwnPropertySymbols(current); const matched = symbols.find((s) => s === k || s.description === k.description); if (!matched) return false; current = current[matched]; } else { return false; } } if (discardUndefined && isUndefined(current)) return false; if (discardNull && isNull(current)) return false; return true; } var isNonEmptyString = (value, options = {}) => { if (!isString(value)) return false; assertIsPlainObject(options, { message: ({ currentType, validType }) => `Second parameter (\`options\`) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const trim = hasOwnProp(options, "trim") ? options.trim : true; assertIsBoolean(trim, { message: ({ currentType, validType }) => `Parameter \`trim\` property of the \`options\` (second parameter) must be of type \`${validType}\`, but received: \`${currentType}\`.` }); const str = trim ? value.trim() : value; return str.length > 0; }; var isError = (error) => { return Object.prototype.toString.call(error) === "[object Error]" || error instanceof Error; }; var isBuffer = (value) => { return typeof Buffer !== "undefined" && typeof Buffer.isBuffer === "function" && Buffer.isBuffer(value); }; function isStringObject(value) { return isObject(value) && Object.prototype.toString.call(value) === "[object String]"; } function isBooleanObject(value) { return isObject(value) && Object.prototype.toString.call(value) === "[object Boolean]"; } function isInfinityNumber(value) { if (typeof value === "number" || isNumberObject(value)) { const num = Number(value); return num === Infinity || num === -Infinity; } return false; } function isNonEmptyArray(value) { return Array.isArray(value) && value.length > 0; } function isSet(value) { return Object.prototype.toString.call(value) === "[object Set]" || value instanceof Set; } var validateCaseInputWordsCase = (input) => { let result = ""; if (isArray(input)) { result = input.map((x) => isNonEmptyString(x) ? x.trim() : "").filter((x) => x.length).join("-"); } else if (isNonEmptyString(input)) { result = input.trim(); } return result.split(/[^\p{L}\p{N}]+/u).filter(Boolean); }; var validateCaseIgnoreWordsCase = (ignoreWord) => { const result = /* @__PURE__ */ new Set([]); const normalizeWord = (word) => word.trim().split(/[^\p{L}\p{N}]+/u).filter(Boolean).join(""); if (isNonEmptyString(ignoreWord)) { const clean = normalizeWord(ignoreWord); if (clean) result.add(clean); } if (isNonEmptyArray(ignoreWord)) { ignoreWord.forEach((w) => { if (isNonEmptyString(w)) { const clean = normalizeWord(w); if (clean) result.add(clean); } }); } if (isSet(ignoreWord)) { ignoreWord.forEach((w) => { if (isNonEmptyString(w)) { const clean = normalizeWord(w); if (clean) result.add(clean); } }); } return result; }; var slugify = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); const slug = wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.toLowerCase(); }).join("-"); return slug.replace(/^-+|-+$/g, ""); }; var toDotCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.toLowerCase(); }).join("."); }; var toCamelCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word, index) => { if (ignoreWordsValidated.has(word)) return word; return index === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(""); }; var toKebabCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.toLowerCase(); }).join("-"); }; var toSnakeCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.toLowerCase(); }).join("_"); }; var toLowerCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.toLowerCase(); }).join(" "); }; var toPascalCase = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(""); }; var toPascalCaseSpace = (input, ignoreWord) => { if (!isNonEmptyArray(input) && !isNonEmptyString(input)) return ""; const wordsValidated = validateCaseInputWordsCase(input); const ignoreWordsValidated = validateCaseIgnoreWordsCase(ignoreWord); return wordsValidated.map((word) => { if (ignoreWordsValidated.has(word)) return word; return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(); }).join(" "); }; var PreciseType = class _PreciseType { /** ---------------------------------------------------------- * * ***Mapping table of JavaScript built-in and environment-specific types.*** * ---------------------------------------------------------- * - **Behavior:** * - Maps internal or native type identifiers to **human-readable names** (usually PascalCase). * - Keys are normalized to lowercase and stripped of spaces, dashes, or underscores. * - Extend or modify entries to match your environment or platform. * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`}. * - Not intended for direct use in application code. * * @internal */ static FIXES_RAW = Object.freeze({ // primitives string: "String", number: "Number", boolean: "Boolean", bigint: "Bigint", symbol: "Symbol", undefined: "Undefined", null: "Null", regexp: "Reg Exp", // reflect / proxy / atomics reflect: "Reflect", proxy: "Proxy", atomics: "Atomics", // core / objects array: "Array", object: "Object", function: "Function", arguments: "Arguments", // functions asyncfunction: "Async Function", generatorfunction: "Generator Function", asyncgeneratorfunction: "Async Generator Function", generator: "Generator", promise: "Promise", // errors evalerror: "Eval Error", rangeerror: "Range Error", referenceerror: "Reference Error", syntaxerror: "Syntax Error", typeerror: "Type Error", urierror: "URI Error", aggregateerror: "Aggregate Error", error: "Error", // typed arrays & binary int8array: "Int 8 Array", uint8array: "Uint 8 Array", uint8clampedarray: "Uint 8 Clamped Array", int16array: "Int 16 Array", uint16array: "Uint 16 Array", int32array: "Int 32 Array", uint32array: "Uint 32 Array", float32array: "Float 32 Array", float64array: "Float 64 Array", bigint64array: "Big Int 64 Array", biguint64array: "Big Uint 64 Array", arraybuffer: "Array Buffer", sharedarraybuffer: "Shared Array Buffer", dataview: "Data View", arraybufferview: "Array Buffer View", // collections map: "Map", set: "Set", weakmap: "Weak Map", weakset: "Weak Set", // iterators (note: toString tag can be "Map Iterator" etc.) mapiterator: "Map Iterator", weakmapiterator: "Weak Map Iterator", setiterator: "Set Iterator", weaksetiterator: "Weak Set Iterator", arrayiterator: "Array Iterator", stringiterator: "String Iterator", asynciterator: "Async Iterator", iteratorresult: "Iterator Result", arrayiteratorresult: "Array Iterator Result", // streams / fetch / web readablestream: "Readable Stream", writablestream: "Writable Stream", transformstream: "Transform Stream", readablestreamdefaultreader: "Readable Stream Default Reader", writablestreamdefaultwriter: "Writable Stream Default Writer", readablestreamdefaultcontroller: "Readable Stream Default Controller", transformstreamdefaultcontroller: "Transform Stream Default Controller", abortcontroller: "Abort Controller", abortsignal: "Abort Signal", fetch: "fetch", request: "Request", response: "Response", headers: "Headers", formdata: "FormData", blob: "Blob", file: "File", filelist: "FileList", filereader: "FileReader", // intl intl: "Intl", collator: "Intl. Collator", datetimeformat: "Intl. Date Time Format", displaynames: "Intl. Display Names", listformat: "Intl. List Format", locale: "Intl. Locale", numberformat: "Intl. Number Format", pluralrules: "Intl. Plural Rules", relativetimeformat: "Intl. Relative Time Format", segmenter: "Intl. Segmenter", // es2021+ weakref: "Weak Ref", urlpattern: "URLPattern", structuredclone: "structured Clone", finalizationregistry: "Finalization Registry", // performance / observers performance: "Performance", performanceobserver: "Performance Observer", performanceentry: "Performance Entry", performancemark: "Performance Mark", performancemeasure: "Performance Measure", // webassembly webassembly: "Web Assembly", wasmmodule: "WebAssembly. Module", wasminstance: "WebAssembly. Instance", wasmmemory: "WebAssembly. Memory", wasmtable: "WebAssembly. Table", // node-ish / common hosts buffer: "Buffer", process: "Process", eventemitter: "Event Emitter", stream: "Stream", fs: "fs", path: "path", url: "URL", urlsearchparams: "URL Search Params", // DOM basics node: "Node", element: "Element", htmlelement: "HTML Element", svgelement: "SVG Element", document: "Document", documentfragment: "Document Fragment", shadowroot: "Shadow Root", nodelist: "Node List", htmlcollection: "HTML Collection", // observers / misc DOM resizeobserver: "Resize Observer", mutationobserver: "Mutation Observer", intersectionobserver: "Intersection Observer", // Reflection / Symbolic symboliterator: "Symbol. Iterator", symbolasynciterator: "Symbol. Async Iterator", symboltostringtag: "Symbol. To String Tag", symbolspecies: "Symbol. Species", symbolhasinstance: "Symbol. Has Instance", symbolisconcatspreadable: "Symbol. Is Concat Spreadable", symbolunscopables: "Symbol. Unscopables", symbolmatch: "Symbol. Match", symbolreplace: "Symbol. Replace", symbolsearch: "Symbol. Search", symbolsplit: "Symbol. Split", symboltoprimitive: "Symbol. To Primitive", symbolmatchall: "Symbol. Match All", symbolarguments: "Symbol. Arguments", // deprecated // Numbers & Math math: "Math", bigintconstructor: "Bigint Constructor", numberconstructor: "Number Constructor", stringconstructor: "String Constructor", booleanconstructor: "Boolean Constructor", // URL / Networking (modern web) formdataevent: "Form Data Event", customevent: "Custom Event", messagechannel: "Message Channel", messageport: "Message Port", messageevent: "Message Event", websocket: "Web Socket", eventsource: "Event Source", // Storage APIs indexeddb: "IndexedDB", idbrequest: "IDB Request", idbtransaction: "IDB Transaction", idbobjectstore: "IDB Object Store", idbcursor: "IDB Cursor", localstorage: "Local Storage", sessionstorage: "Session Storage", // Navigator / Browser APIs navigator: "Navigator", geolocation: "Geolocation", clipboard: "Clipboard", notification: "Notification", // Canvas / Graphics canvas: "Canvas", canvasrenderingcontext2d: "Canvas Rendering Context 2D", offscreencanvas: "Offscreen Canvas", webglrenderingcontext: "WebGL Rendering Context", imagedata: "Image Data", imagebitmap: "Image Bitmap", // Media mediastream: "Media Stream", mediarecorder: "Media Recorder", mediastreamtrack: "Media Stream Track", audiocontext: "Audio Context", audiobuffer: "Audio Buffer", audioworklet: "Audio Worklet", // Workers worker: "Worker", sharedworker: "Shared Worker", serviceworker: "Service Worker", workerglobalscope: "Worker Global Scope", // Structured Clone / Transferable structuredcloneerror: "Structured Clone Error", transferable: "Transferable", // Testing / Diagnostics report: "Report", console: "Console", diagnosticreport: "Diagnostic Report", // Misc domrect: "DOM Rect", dompoint: "DOM Point", dommatrix: "DOM Matrix", domparser: "DOM Parser", xmlhttprequest: "XML HTTP Request", customelementregistry: "Custom Element Registry", // additions-ons text: "Text", comment: "Comment", animation: "Animation", documenttype: "Document Type", characterdata: "Character Data", animationevent: "Animation Event", customemmetregistry: "Custom Emmet Registry", websocketmessageevent: "WebSocket Message Event" }); /** ---------------------------------------------------------- * * ***List of JavaScript special numeric values.*** * ---------------------------------------------------------- * * - Contains special values recognized by {@link getPreciseType | `getPreciseType`}, * such as `"Infinity"`, `"-Infinity"`, and `"NaN"`. * * - **⚠️ Internal:** * - Used by {@link getPreciseType | `getPreciseType`} for numeric edge-case detection. * * @internal */ static SPECIAL_TYPE = Object.freeze([ "-Infinity", "Infinity", "NaN" ]); /** ---------------------------------------------------------- * * ***List of acronyms to keep uppercase in formatted output.*** * ---------------------------------------------------------- * * - **Behavior:** * - Prevents transformations (like camelCase or kebab-case) from altering * known acronyms such as `HTML`, `URL`, `API`, etc. * - Extend this list if you want more acronyms to remain uppercase. * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`} and related formatters. * * @internal */ static ACRONYMS = Object.freeze([ // Web & Protocols "URI", "URL", "URN", "HTTP", "HTTPS", "FTP", "FTPS", "SFTP", "SSH", "SMTP", "POP3", "IMAP", "WS", "WSS", "TCP", "UDP", "IP", "ICMP", "ARP", "RTP", "RTSP", "SIP", // Web APIs & Standards "HTML", "XHTML", "XML", "WBR", "CSS", "SVG", "JSON", "JSONP", "DOM", "IDB", "DB", "RTC", "ICE", "TLS", "SSL", "CORS", "WASM", "CSR", "SSR", "PWA", "DPI", "CDN", // Programming / JS Ecosystem "JS", "TS", "JSX", "TSX", "CLI", "API", "SDK", "UI", "UX", "OS", "ID", "UUID", "PID", "NPM", "YARN", "ESM", "CJS", "BOM", "MVC", "MVVM", "ORM", "DAO", "CRUD", "FIFO", "LIFO", "OOP", "FP", "REPL", // Data Formats & Types "CSV", "TSV", "SQL", "YAML", "JSON", "MD", "INI", "PDF", "XLS", "XLSX", "RTF", "XML", "BMP", "GIF", "PNG", "JPEG", "WEBP", "MP3", "MP4", "AVI", "MOV", "FLAC", "MKV", "WAV", // Common Abbreviations "URLSearchParams", "XHR", "2D", "3D", "GL", "WebGL", "TTL", "UID", "GID", "MAC", "IP", "DNS", "DHCP", "VPN", "LAN", "WAN", "SSID", "IoT", "API", "SDK", "CLI", "LTS", "EOL", // Hardware & Infrastructure "CPU", "GPU", "RAM", "ROM", "SSD", "HDD", "BIOS", "USB", "PCI", "SATA", "DIMM", "DDR", "VGA", "HDMI", "KVM", "ASIC", "FPGA", "SoC", "NAS", "SAN", // Networking "TCP", "UDP", "IP", "MAC", "DNS", "DHCP", "VPN", "LAN", "WAN", "SSID", "NAT", "QoS", "MPLS", "BGP", "OSPF", "ICMP", "IGMP", "LLDP", "ARP", "RARP", // Security "AES", "RSA", "OTP", "MFA", "PKI", "VPN", "IAM", "ACL", "CSP", "XSS", "CSRF", "HSTS", "WAF", "DDoS", "IDS", "IPS", "SOC", "SIEM", // Cloud / DevOps / Infrastructure "AWS", "GCP", "AZURE", "CI", "CD", "K8S", "IaC", "PaaS", "SaaS", "IaaS", "API", "CLI", "SDK", "REST", "SOAP", "JSON-RPC", "gRPC", "ELB", "EKS", "AKS", "FaaS", "CaaS", // User Interface & Tools "GUI", "IDE", "FAQ", "UX", "UI", "CLI", "API", "SDK", "LTS", "EOL", "WYSIWYG", "CMS", "CRM", // Miscellaneous "GPS", "LED", "OLED", "LCD", "RFID", "NFC", "CPU", "GPU", "AI", "ML", "DL", "DB", "SQL", "NoSQL", "ORM", "JSON", "XML", "CSV", "HTTP", "HTTPS", // Testing & QA "TDD", "BDD", "CI", "CD", "QA", "SLA", "SLO", "MTTR", "MTBF", "UAT", "RPA", // Business & Project Management "KPI", "OKR", "ROI", "RFP", "SLA", "CRM", "ERP", "PMO", "SCRUM", "KANBAN", // Multimedia & Graphics "FPS", "HDR", "VR", "AR", "3D", "2D", "MP3", "MP4", "GIF", "PNG", "JPEG", "SVG", "BMP", "TIFF", // Operating Systems & File Systems "POSIX", "NTFS", "FAT", "EXT", "EXT4", "APFS", "HFS", "ISO", // Programming Languages & Tools "HTML", "CSS", "JS", "TS", "PHP", "SQL", "JSON", "XML", "YAML", "BASH", "ZSH", "JSON", "YAML", "INI", "DOTENV", // Containers & Virtualization "VM", "VMM", "VPC", "OCI", "LXC", "Docker", "K8S", "CRI", "CNI" ]); /** ---------------------------------------------------------- * * ***Normalized lookup table for type mapping.*** * ---------------------------------------------------------- * * - **Behavior:** * - Converts all keys from {@link FIXES_RAW | `FIXES_RAW`} into normalized form * (lowercased and stripped of separators) for consistent lookup. * - Values remain the formatted human-readable type names. * * - **⚠️ Internal:** * - Helper table for {@link getPreciseType | `getPreciseType`} and related matchers. * * @internal */ static FIXES_CASTABLE_TABLE = Object.freeze( Object.entries(_PreciseType.FIXES_RAW).reduce((acc, [k, v]) => { acc[_PreciseType.normalizeKeyForCase(k)] = v; return acc; }, {}) ); /** @internal */ formatCase = "toKebabCase"; /** @internal */ useAcronyms = false; constructor(params) { this.formatCase = params?.formatCase; this.useAcronyms = params?.useAcronyms; } /** @internal */ determineOptions(options) { return { formatCase: options?.formatCase || this.formatCase, useAcronyms: options?.useAcronyms ?? this.useAcronyms }; } // ------------------------ // Helpers for DOM detection // ------------------------ /** @internal */ getHtmlElementType(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); if (typeof HTMLElement === "undefined" || !(value instanceof HTMLElement)) return null; const tagName = value.tagName; const DEFAULTS = { a: "Anchor", abbr: "Abbreviation", address: "Address", area: "Area", article: "Article", aside: "Aside", audio: "Audio", b: "Bold", base: "Base", bdi: "BDI", bdo: "BDO", blockquote: "Blockquote", body: "Body", br: "Break", button: "Button", canvas: "Canvas", caption: "Caption", cite: "Cite", code: "Code", col: "Column", colgroup: "Column Group", data: "Data", datalist: "Datalist", dd: "Definition Description", del: "Deleted Text", details: "Details", dfn: "Definition", dialog: "Dialog", div: "Div", dl: "Definition List", dt: "Definition Term", em: "Emphasis", embed: "Embed", fieldset: "Fieldset", figcaption: "Figcaption", figure: "Figure", footer: "Footer", form: "Form", h1: "Heading 1", h2: "Heading 2", h3: "Heading 3", h4: "Heading 4", h5: "Heading 5", h6: "Heading 6", head: "Head", header: "Header", hr: "Horizontal Rule", html: "HTML", i: "Italic", iframe: "IFrame", img: "Image", input: "Input", ins: "Inserted Text", kbd: "Keyboard", label: "Label", legend: "Legend", li: "List Item", link: "Link", main: "Main", map: "Map", mark: "Mark", meta: "Meta", meter: "Meter", nav: "Nav", noscript: "NoScript", object: "Object", ol: "Ordered List", optgroup: "Option Group", option: "Option", output: "Output", p: "Paragraph", param: "Param", picture: "Picture", pre: "Preformatted", progress: "Progress", q: "Quote", rp: "RP", rt: "RT", ruby: "Ruby", s: "Strikethrough", samp: "Sample", script: "Script", section: "Section", select: "Select", small: "Small", source: "Source", span: "Span", strong: "Strong", style: "Style", sub: "Subscript", summary: "Summary", sup: "Superscript", table: "Table", tbody: "Table Body", td: "Table Data", template: "Template", textarea: "Textarea", tfoot: "Table Footer", th: "Table Header", thead: "Table Head", time: "Time", title: "Title", tr: "Table Row", track: "Track", u: "Underline", ul: "Unordered List", var: "Variable", video: "Video", wbr: "WBR" }; const displayName = _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase(tagName)] ?? (DEFAULTS[tagName] ? `HTML ${DEFAULTS[tagName]} Element` : "HTML Element"); return this.converter(displayName, { formatCase, useAcronyms }); } /** @internal */ getCommentNodeType(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); if (value instanceof Comment) { return this.converter( _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase("comment")] ?? "Comment", { formatCase, useAcronyms } ); } return null; } /** @internal */ getTextNodeType(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); if (value instanceof Text) { return this.converter( _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase("text")] ?? "Text", { formatCase, useAcronyms } ); } return null; } /** @internal */ getOtherNodeType(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); if (typeof Node !== "undefined" && value instanceof Node) { return this.converter( _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase("node")] ?? "Node", { formatCase, useAcronyms } ); } return null; } /** ---------------------------------------------------------- * * ***Retrieves the canonical string representation of a given `Symbol`.*** * ---------------------------------------------------------- * * - **Description:** * - Converts a JavaScript `Symbol` (including well-known symbols) into a standardized, * human-readable name string. * - Maps **well-known symbols** (e.g., `Symbol.iterator`, `Symbol.asyncIterator`, `Symbol.toStringTag`) * to their corresponding normalized key in {@link PreciseType.castableTable | `castableTable`}. * - Supports formatted output according to the given `formatCase` and `useAcronyms` options. * - Falls back to the general `"Symbol"` type name if the provided symbol is not recognized. * * - **Example:** * ```ts * const precise = new PreciseType(); * * precise.getSymbolName(Symbol.iterator); * // ➜ "symbol-iterator" * * precise.getSymbolName(Symbol.toStringTag, { formatCase: "toPascalCase" }); * // ➜ "SymbolToStringTag" * * precise.getSymbolName(Symbol("custom")); * // ➜ "symbol" * ``` * * - **Options:** * - `formatCase` → Determines the string case style for the resulting symbol name. * - `useAcronyms` → Preserves known acronyms (like `URL`, `DOM`, `HTML`) if set to `true`. * * - **⚠️ Internal:** * - Helper for {@link getPreciseType | `getPreciseType`} that normalizes `Symbol` detection. * - Not recommended for direct external use. * * @param value - The `Symbol` instance to analyze. * @param options - Optional settings for case formatting and acronym preservation. * @returns The formatted symbol name string. * * @internal */ getSymbolName(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); const symbolMap = /* @__PURE__ */ new Map([ [Symbol.iterator, "symboliterator"], [Symbol.asyncIterator, "symbolasynciterator"], [Symbol.toStringTag, "symboltostringtag"], [Symbol.species, "symbolspecies"], [Symbol.hasInstance, "symbolhasinstance"], [Symbol.isConcatSpreadable, "symbolisconcatspreadable"], [Symbol.unscopables, "symbolunscopables"], [Symbol.match, "symbolmatch"], [Symbol.replace, "symbolreplace"], [Symbol.search, "symbolsearch"], [Symbol.split, "symbolsplit"], [Symbol.toPrimitive, "symboltoprimitive"], [Symbol.matchAll, "symbolmatchall"] ]); const key = symbolMap.get(value); if (key) { return this.converter( _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase(key)] ?? key, { formatCase, useAcronyms } ); } return this.converter( _PreciseType.FIXES_CASTABLE_TABLE[_PreciseType.normalizeKeyForCase("symbol")] ?? "Symbol", { formatCase, useAcronyms } ); } /** ---------------------------------------------------------- * * ***Detects the precise DOM node type of a given value.*** * ---------------------------------------------------------- * * - **Description:** * - Determines the specific **DOM Node subtype** (e.g., `HTMLDivElement`, `Comment`, `Text`, etc.) * based on the given input `value`. * - This method sequentially checks various DOM-related helpers: * - {@link PreciseType.getHtmlElementType | `getHtmlElementType`} * - {@link PreciseType.getCommentNodeType | `getCommentNodeType`} * - {@link PreciseType.getTextNodeType | `getTextNodeType`} * - {@link PreciseType.getOtherNodeType | `getOtherNodeType`} * - Returns the first non-null type result found. * - If no valid DOM node type is detected or an error occurs, it gracefully returns `null`. * * - **Example:** * ```ts * const detector = new PreciseType(); * detector.detectDomNodeType(document.createElement("div")); * // ➜ "HTMLDivElement" * * detector.detectDomNodeType(document.createComment("test")); * // ➜ "Comment" * * detector.detectDomNodeType("not a node"); * // ➜ null * ``` * * - **Options:** * - `formatCase` → Controls the output formatting (e.g., `"toKebabCase"`, `"toPascalCase"`, etc.). * - `useAcronyms` → Determines if acronyms like `"HTML"` or `"SVG"` remain uppercase. * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`} to refine DOM-related type detection. * - Not intended for direct external use. * * @param value - The value to be inspected for a DOM node type. * @param options - Optional configuration to adjust case formatting and acronym behavior. * @returns The detected DOM node type string, or `null` if not applicable. * * @internal */ detectDomNodeType(value, options) { const { formatCase, useAcronyms } = this.determineOptions(options); try { return this.getHtmlElementType(value, { formatCase, useAcronyms }) || this.getCommentNodeType(value, { formatCase, useAcronyms }) || this.getTextNodeType(value, { formatCase, useAcronyms }) || this.getOtherNodeType(value, { formatCase, useAcronyms }); } catch { return null; } } /** ---------------------------------------------------------- * * ***Detects whether a given value is a Proxy instance.*** * ---------------------------------------------------------- * * - **Behavior:** * - Attempts to define and delete a temporary property to trigger potential Proxy traps. * - Works because most Proxy handlers will throw or behave differently during these operations. * - Transparent Proxies (without traps) will **not** be detected. * * @description * This method performs a heuristic check — it’s **not foolproof**, but reliably distinguishes * most Proxy-wrapped objects from ordinary ones without using non-standard APIs. * * @param value - The value to inspect. * @returns `true` if the value behaves like a Proxy (throws on property mutation), * otherwise `false`. * * @example * ```ts * const target = {}; * const proxy = new Proxy(target, {}); * * console.log(preciseType.isProxy(target)); // false * console.log(preciseType.isProxy(proxy)); // false (transparent proxy) * * const proxyWithTrap = new Proxy(target, { * set() { throw new Error("trap!"); } * }); * * console.log(preciseType.isProxy(proxyWithTrap)); // true * ``` * * @note * - Skips built-in native types (like `Array`, `Date`, `Map`, etc.) to prevent false positives. * - This is an **internal heuristic**, not a guaranteed Proxy detector. * * @internal */ isProxy(value) { if (isNull(value) || !isObjectOrArray(value)) return false; const tag = Object.prototype.toString.call(value); const skipTags = [ "[object Array]", "[object Date]", "[object RegExp]", "[object Map]", "[object Set]", "[object WeakMap]", "[object WeakSet]", "[object Function]", "[object Error]", "[object Promise]", "[object Generator]", "[object GeneratorFunction]", "[object AsyncFunction]" ]; if (skipTags.includes(tag)) return false; try { Reflect.defineProperty(value, "__proxy_detect__", { configurable: true, value: 1 }); Reflect.deleteProperty(value, "__proxy_detect__"); return false; } catch { return true; } } /** ---------------------------------------------------------- * * ***Helper function to convert an input string to a specific casing/format.*** * ---------------------------------------------------------- * * @description * - Chooses the conversion function based on the `formatCase` option. * - Supports multiple casing/formatting functions: * - `toPascalCaseSpace`. * - `toPascalCase`. * - `toCamelCase`. * - `toKebabCase`. * - `toSnakeCase`. * - `toDotCase`. * - `slugify`. * - Uses `ACRONYMS` as ignored words for certain conversion functions. * * @param {string} input - The string to convert. * @param {GetPreciseTypeOptions["formatCase"]} formatCase - The conversion method to apply. * @returns {string} The converted string according to the selected format. * * @example * converterHelper("hello world", "toCamelCase"); * // ➔ "helloWorld" * * @example * converterHelper("my URL path", "slugify"); * // ➔ "my-URL-path" * * @internal */ converter(input, options) { const { formatCase, useAcronyms } = this.determineOptions(options); const ignoreWord = useAcronyms ? _PreciseType.ACRONYMS : []; switch (formatCase) { case "slugify": return slugify(input, ignoreWord); case "toDotCase": return toDotCase(input, ignoreWord); case "toCamelCase": return toCamelCase(input, ignoreWord); case "toSnakeCase": return toSnakeCase(input, ignoreWord); case "toLowerCase": return toLowerCase(input, ignoreWord); case "toPascalCase": return toPascalCase(input, ignoreWord); case "toPascalCaseSpace": return toPascalCaseSpace(input, ignoreWord); default: return toKebabCase(input, ignoreWord); } } /** ---------------------------------------------------------- * * ***Normalizes a string key for consistent case-insensitive matching.*** * ---------------------------------------------------------- * * - **Description:** * - This method removes all **spaces**, **underscores**, and **hyphens** from the given string, * then converts the result to **lowercase**. * - Used internally to ensure uniformity in key lookups and matching logic across * type mapping tables like {@link PreciseType.fixesRaw | `fixesRaw`} and * {@link PreciseType.castableTable | `castableTable`}. * * - **Example:** * ```ts * PreciseType.normalizeKeyForCase("Map.Type"); // ➔ "maptype" * PreciseType.normalizeKeyForCase("Map-Type"); // ➔ "maptype" * PreciseType.normalizeKeyForCase("Set Type"); // ➔ "settype" * PreciseType.normalizeKeyForCase("Array_Type"); // ➔ "arraytype" * ``` * * - **⚠️ Internal:** * - Helper method used by {@link getPreciseType | `getPreciseType`} and internal mapping constants. * - Not intended for direct use in user code. * * @param k - The input string key to normalize. * @returns The normalized lowercase key with all separators removed. * * @internal */ static normalizeKeyForCase(k) { return k.replace(/[\s_\-\.]+/g, "").toLowerCase(); } /** ---------------------------------------------------------- * * ***Getting the internal map of type castable relationships used by {@link getPreciseType | `getPreciseType`}.*** * ---------------------------------------------------------- * * - **Description:** * - Returns an internal static mapping table that defines which primitive or structural types * can be cast or interpreted as another related type within the internal logic of * {@link getPreciseType | `getPreciseType`}. * * - **⚠️ Internal:** * - This is an internal helper of {@link getPreciseType | `getPreciseType`}. * - Do not modify or rely on this table directly — it is **readonly** and may change without notice. * * @readonly */ static get castableTable() { return _PreciseType.FIXES_CASTABLE_TABLE; } /** ---------------------------------------------------------- * * ***Retrieves the internal list of special type cases handled by {@link getPreciseType | `getPreciseType`}.*** * ---------------------------------------------------------- * * - **Description:** * - Returns an internal readonly list of specific type identifiers that require * *custom handling* during type detection. * - These are **exceptional values** or **edge cases** that don’t follow the normal * JavaScript type resolution flow. * * - **Example Values:** * - `"Infinity"`, `"-Infinity"`, `"NaN"`, `"undefined"`, etc. * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`}. * - This property is **readonly** and should not be modified directly. * * @readonly */ static get specialType() { return this.SPECIAL_TYPE; } /** ---------------------------------------------------------- * * ***Retrieves the internal mapping of JavaScript built-in and environment-specific * type identifiers to their canonical PascalCase names.*** * ---------------------------------------------------------- * * - **Description:** * - Provides a mapping table where **keys** represent normalized raw type names * (as obtained from `Object.prototype.toString.call(value)` or environment checks), * and **values** represent their **canonical PascalCase equivalents**. * - This table ensures consistent, human-readable type strings across different environments. * * - **Example Mapping:** * ```ts * { * "[object Map]": "Map", * "[object WeakMap]": "WeakMap", * "[object AsyncFunction]": "AsyncFunction", * "[object GeneratorFunction]": "GeneratorFunction", * "[object BigInt]": "BigInt", * } * ``` * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`}. * - This property is **readonly** and should not be modified directly. * * @readonly */ static get fixesRaw() { return this.FIXES_RAW; } /** ---------------------------------------------------------- * * ***Retrieves the internal list of common acronyms that should remain fully uppercase during string formatting.*** * ---------------------------------------------------------- * * - **Description:** * - This list defines acronyms (e.g., `"URL"`, `"HTTP"`, `"HTML"`, `"SVG"`, `"XML"`, `"DOM"`) * that will be **preserved in uppercase** when applying case transformations through * {@link getPreciseType | `getPreciseType`} or any formatting utility using it. * - Ensures consistency in output for technical identifiers that are conventionally capitalized. * * - **Example:** * ```ts * ["URL", "HTTP", "HTML", "SVG", "XML", "DOM"] * ``` * * - **⚠️ Internal:** * - Used internally by {@link getPreciseType | `getPreciseType`}. * - This property is **readonly** and not intended for modification. * * @readonly */ static get acronymsList() { return this.ACRONYMS; } }; var getPreciseType = /* @__PURE__ */ (() => { const cache = /* @__PURE__ */ new Map(); const MAX_CACHE_SIZE = 25; return (value, options = {}) => { if (!isPlainObject(options)) options = {}; const key = JSON.stringify({ formatCase: options.formatCase || "toKebabCase", useAcronyms: options.useAcronyms ?? false }); let ClassPrecise = cache.get(key); if (!ClassPrecise) { if (cache.size >= MAX_CACHE_SIZE) cache.clear(); ClassPrecise = new PreciseType(options); cache.set(key, ClassPrecise); } if (isNull(value)) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("null")] ?? "Null" ); } if (isNaN(value)) return "NaN"; if (isInfinityNumber(value)) return String(value); if (typeof BigInt !== "undefined" && value === BigInt) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("bigint constructor")] ); } if (isNumberObject(value) || value === Number) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("number constructor")] ); } if (isStringObject(value) || value === String) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("string constructor")] ); } if (isBooleanObject(value) || value === Boolean) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("boolean constructor")] ); } const prim = typeof value; if (!isObjectOrArray(value) && !isFunction(value) && prim !== "symbol") { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase(prim)] ?? prim ); } if (prim === "symbol") { return ClassPrecise.getSymbolName(value); } if (isObjectOrArray(value) && value.constructor?.name === "EventEmitter") { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("event emitter")] ?? "Event Emitter" ); } const domType = ClassPrecise.detectDomNodeType(value); if (domType) return domType; if (isBuffer(value)) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("buffer")] ?? "Buffer" ); } if (ClassPrecise.isProxy(value)) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("proxy")] ?? "Proxy" ); } if (isObject(value) && isFunction(value?.next) && isFunction(value?.throw)) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("generator")] ?? "Generator" ); } if (isError(value)) { const ctorName2 = value.constructor?.name ?? "Error"; return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase(ctorName2)] ?? PreciseType.castableTable[PreciseType.normalizeKeyForCase(ctorName2.replace(/\s+/g, ""))] ?? ctorName2 ); } if (isObjectOrArray(value) && "done" in value && "value" in value && Object.keys(value).length === 2) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("iterator result")] ); } if (isNull(Object.getPrototypeOf(value))) { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase("object")] ?? "Object" ); } const tag = Object.prototype.toString.call(value).slice(8, -1) || "Object"; const mapped = PreciseType.castableTable[PreciseType.normalizeKeyForCase(tag)]; if (mapped) return ClassPrecise.converter(mapped); const ctorName = value?.constructor?.name; if (ctorName && ctorName !== "Object") { return ClassPrecise.converter( PreciseType.castableTable[PreciseType.normalizeKeyForCase(ctorName)] ?? ctorName ); } return ClassPrecise.converter(tag); }; })(); var determineErrorTypeAssertion = (type, message) => { switch (type) { case "Error": throw new Error(message); case "EvalError": throw new EvalError(message); case "RangeError": throw new RangeError(message); case "ReferenceError": throw new ReferenceError(message); case "SyntaxError": throw new SyntaxError(message); case "URIError": throw new URIError(message); case "TypeError": throw new TypeError(message); default: throw new TypeError(message); } }; function resolveErrorMessageAssertions(params) { const { requiredValidType, value, options } = params || {}; const { message, formatCase, useAcronyms, errorType = "TypeError" } = isPlainObject(options) ? options : {}; const validType = toKebabCase(requiredValidType); const currentType = getPreciseType(value, { formatCase, useAcronyms }); const messageFnOptions = { currentType, validType }; const defaultMessage = `Parameter input (\`value\`) must be of type \`${validType}\`, but received: \`${currentType}\`.`; const errorMessage = isFunction(message) ? isNonEmptyString(message(messageFnOptions)) ? message(messageFnOptions).trim() : defaultMessage : isNonEmptyString(message) ? message.trim() : defaultMessage; return determineErrorTypeAssertion(errorType, errorMessage); } function assertIsPlainObject(value, options = {}) { if (isPlainObject(value)) return; resolveErrorMessageAssertions({ value, options, requiredValidType: "plain object" }); } exports.assertIsBoolean = assertIsBoolean; exports.assertIsPlainObject = assertIsPlainObject; exports.getPreciseType = getPreciseType; exports.hasOwnProp = hasOwnProp; exports.isArray = isArray; exports.isBoolean = isBoolean; exports.isBoole