@itshackers/utilix 0.0.0-stage → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +304 -3
- package/dist/common/index.cjs +102 -0
- package/dist/common/index.cjs.map +1 -0
- package/dist/common/index.d.cts +58 -0
- package/dist/common/index.d.ts +58 -0
- package/dist/common/index.js +93 -0
- package/dist/common/index.js.map +1 -0
- package/dist/date/index.cjs +154 -0
- package/dist/date/index.cjs.map +1 -0
- package/dist/date/index.d.cts +65 -0
- package/dist/date/index.d.ts +65 -0
- package/dist/date/index.js +146 -0
- package/dist/date/index.js.map +1 -0
- package/dist/format/index.cjs +136 -0
- package/dist/format/index.cjs.map +1 -0
- package/dist/format/index.d.cts +56 -0
- package/dist/format/index.d.ts +56 -0
- package/dist/format/index.js +130 -0
- package/dist/format/index.js.map +1 -0
- package/dist/id/index.cjs +66 -0
- package/dist/id/index.cjs.map +1 -0
- package/dist/id/index.d.cts +19 -0
- package/dist/id/index.d.ts +19 -0
- package/dist/id/index.js +64 -0
- package/dist/id/index.js.map +1 -0
- package/dist/index.cjs +906 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +853 -0
- package/dist/index.js.map +1 -0
- package/dist/number/index.cjs +107 -0
- package/dist/number/index.cjs.map +1 -0
- package/dist/number/index.d.cts +90 -0
- package/dist/number/index.d.ts +90 -0
- package/dist/number/index.js +99 -0
- package/dist/number/index.js.map +1 -0
- package/dist/password/index.cjs +71 -0
- package/dist/password/index.cjs.map +1 -0
- package/dist/password/index.d.cts +15 -0
- package/dist/password/index.d.ts +15 -0
- package/dist/password/index.js +69 -0
- package/dist/password/index.js.map +1 -0
- package/dist/phone/index.cjs +19 -0
- package/dist/phone/index.cjs.map +1 -0
- package/dist/phone/index.d.cts +12 -0
- package/dist/phone/index.d.ts +12 -0
- package/dist/phone/index.js +17 -0
- package/dist/phone/index.js.map +1 -0
- package/dist/regex/index.cjs +73 -0
- package/dist/regex/index.cjs.map +1 -0
- package/dist/regex/index.d.cts +65 -0
- package/dist/regex/index.d.ts +65 -0
- package/dist/regex/index.js +67 -0
- package/dist/regex/index.js.map +1 -0
- package/dist/response/index.cjs +43 -0
- package/dist/response/index.cjs.map +1 -0
- package/dist/response/index.d.cts +41 -0
- package/dist/response/index.d.ts +41 -0
- package/dist/response/index.js +40 -0
- package/dist/response/index.js.map +1 -0
- package/dist/sanitize/index.cjs +83 -0
- package/dist/sanitize/index.cjs.map +1 -0
- package/dist/sanitize/index.d.cts +20 -0
- package/dist/sanitize/index.d.ts +20 -0
- package/dist/sanitize/index.js +80 -0
- package/dist/sanitize/index.js.map +1 -0
- package/dist/slug/index.cjs +33 -0
- package/dist/slug/index.cjs.map +1 -0
- package/dist/slug/index.d.cts +38 -0
- package/dist/slug/index.d.ts +38 -0
- package/dist/slug/index.js +31 -0
- package/dist/slug/index.js.map +1 -0
- package/dist/string/index.cjs +130 -0
- package/dist/string/index.cjs.map +1 -0
- package/dist/string/index.d.cts +112 -0
- package/dist/string/index.d.ts +112 -0
- package/dist/string/index.js +115 -0
- package/dist/string/index.js.map +1 -0
- package/package.json +187 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/validation.ts","../src/string/index.ts","../src/number/index.ts","../src/slug/index.ts","../src/common/index.ts","../src/format/index.ts","../src/phone/index.ts","../src/internal/random.ts","../src/password/index.ts","../src/id/index.ts","../src/date/index.ts","../src/sanitize/index.ts","../src/response/index.ts","../src/regex/index.ts"],"names":["DEFAULT_LOCALE","pad"],"mappings":"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","file":"index.js","sourcesContent":["export function assertFiniteNumber(\r\n value: unknown,\r\n name: string,\r\n): asserts value is number {\r\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\r\n throw new TypeError(`${name} must be a finite number`);\r\n }\r\n}\r\n\r\nexport function escapeRegExp(value: string): string {\r\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n","import { escapeRegExp } from \"../internal/validation.js\";\r\n\r\nexport type TextCase =\r\n | \"title\"\r\n | \"titlecase\"\r\n | \"lower\"\r\n | \"lowercase\"\r\n | \"upper\"\r\n | \"uppercase\"\r\n | \"camel\"\r\n | \"camelcase\"\r\n | \"pascal\"\r\n | \"pascalcase\"\r\n | \"snake\"\r\n | \"snakecase\"\r\n | \"kebab\"\r\n | \"kebabcase\";\r\n\r\nconst HTML_ESCAPE_MAP: Record<string, string> = {\r\n \"&\": \"&\",\r\n \"<\": \"<\",\r\n \">\": \">\",\r\n '\"': \""\",\r\n \"'\": \"'\",\r\n};\r\n\r\n/**\r\n * Splits mixed naming conventions into discrete words.\r\n * Handles spaces, hyphens, underscores, dots, and camel/PascalCase boundaries.\r\n */\r\nfunction splitWords(value: string): string[] {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return [];\r\n }\r\n\r\n return trimmed\r\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\r\n .replace(/([A-Z]+)([A-Z][a-z])/g, \"$1 $2\")\r\n .split(/[\\s._-]+/u)\r\n .filter((word) => word.length > 0);\r\n}\r\n\r\nfunction toLowerWords(value: string): string[] {\r\n return splitWords(value).map((word) => word.toLowerCase());\r\n}\r\n\r\nfunction capitalizeWord(word: string): string {\r\n const [first = \"\", ...rest] = [...word];\r\n return `${first.toUpperCase()}${rest.join(\"\").toLowerCase()}`;\r\n}\r\n\r\n/**\r\n * Converts a string to camelCase.\r\n *\r\n * @example\r\n * toCamelCase(\"hello-world\") // \"helloWorld\"\r\n * toCamelCase(\"XMLHttpRequest\") // \"xmlHttpRequest\"\r\n */\r\nexport function toCamelCase(value: string): string {\r\n const words = toLowerWords(value);\r\n if (words.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = words;\r\n return `${first}${rest.map(capitalizeWord).join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Converts a string to PascalCase.\r\n *\r\n * @example\r\n * toPascalCase(\"hello_world\") // \"HelloWorld\"\r\n */\r\nexport function toPascalCase(value: string): string {\r\n return toLowerWords(value).map(capitalizeWord).join(\"\");\r\n}\r\n\r\n/**\r\n * Converts a string to snake_case.\r\n *\r\n * @example\r\n * toSnakeCase(\"Hello World\") // \"hello_world\"\r\n */\r\nexport function toSnakeCase(value: string): string {\r\n return toLowerWords(value).join(\"_\");\r\n}\r\n\r\n/**\r\n * Converts a string to kebab-case.\r\n *\r\n * @example\r\n * toKebabCase(\"HelloWorld\") // \"hello-world\"\r\n */\r\nexport function toKebabCase(value: string): string {\r\n return toLowerWords(value).join(\"-\");\r\n}\r\n\r\n/**\r\n * Trims the string and uppercases its first Unicode character.\r\n * The remaining characters are left unchanged.\r\n *\r\n * @example\r\n * capitalize(\" hello world\") // \"Hello world\"\r\n */\r\nexport function capitalize(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n const [first = \"\", ...rest] = [...trimmed];\r\n return `${first.toUpperCase()}${rest.join(\"\")}`;\r\n}\r\n\r\n/**\r\n * Trims leading and trailing whitespace and collapses internal\r\n * whitespace runs to a single space.\r\n *\r\n * @example\r\n * normalizeWhitespace(\" hello \\t\\n world \") // \"hello world\"\r\n */\r\nexport function normalizeWhitespace(value: string): string {\r\n return value.trim().replace(/\\s+/gu, \" \");\r\n}\r\n\r\n/**\r\n * Escapes `&`, `<`, `>`, `\"`, and `'` for safe interpolation into HTML text\r\n * or quoted attributes.\r\n *\r\n * This is not an HTML sanitizer. It does not parse markup, remove scripts,\r\n * or make untrusted HTML safe to render.\r\n *\r\n * @example\r\n * escapeHtml(`<img alt=\"O'Reilly & Co\">`)\r\n * // \"<img alt="O'Reilly & Co">\"\r\n */\r\nexport function escapeHtml(value: string): string {\r\n return value.replace(/[&<>\"']/g, (character) => HTML_ESCAPE_MAP[character] ?? character);\r\n}\r\n\r\n/**\r\n * Escapes special regular-expression characters in a string.\r\n *\r\n * @example\r\n * escapeRegex(\"file.name.txt\") // \"file\\\\.name\\\\.txt\"\r\n */\r\nexport function escapeRegex(value: string): string {\r\n return escapeRegExp(value);\r\n}\r\n\r\nexport { escapeRegex as escapeRegExp };\r\n\r\n/**\r\n * Converts a string to Title Case using word boundaries.\r\n *\r\n * @example\r\n * toTitleCase(\"hello world\") // \"Hello World\"\r\n * toTitleCase(\"used-truck\") // \"Used-Truck\"\r\n */\r\nexport function toTitleCase(value: string): string {\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0) {\r\n return \"\";\r\n }\r\n\r\n return trimmed.toLowerCase().replace(/\\b\\w/g, (character) => character.toUpperCase());\r\n}\r\n\r\n/**\r\n * Converts a string to one of the supported case styles.\r\n * Unknown styles throw rather than silently falling back.\r\n *\r\n * @example\r\n * convertCase(\"hello world\", \"title\") // \"Hello World\"\r\n * convertCase(\"hello-world\", \"camel\") // \"helloWorld\"\r\n */\r\nexport function convertCase(value: string, casing: TextCase = \"title\"): string {\r\n switch (casing.toLowerCase() as TextCase) {\r\n case \"title\":\r\n case \"titlecase\":\r\n return toTitleCase(value);\r\n case \"lower\":\r\n case \"lowercase\":\r\n return value.trim().toLowerCase();\r\n case \"upper\":\r\n case \"uppercase\":\r\n return value.trim().toUpperCase();\r\n case \"camel\":\r\n case \"camelcase\":\r\n return toCamelCase(value);\r\n case \"pascal\":\r\n case \"pascalcase\":\r\n return toPascalCase(value);\r\n case \"snake\":\r\n case \"snakecase\":\r\n return toSnakeCase(value);\r\n case \"kebab\":\r\n case \"kebabcase\":\r\n return toKebabCase(value);\r\n default:\r\n throw new TypeError(`Unsupported case style: ${casing}`);\r\n }\r\n}\r\n\r\n/**\r\n * Replaces hyphens and underscores with spaces, then title-cases the result.\r\n *\r\n * @example\r\n * replaceSeparatorsWithSpace(\"used-truck\") // \"Used Truck\"\r\n * replaceSeparatorsWithSpace(\"hello_world\") // \"Hello World\"\r\n */\r\nexport function replaceSeparatorsWithSpace(value: string): string {\r\n return toTitleCase(value.replace(/[-_]+/g, \" \").replace(/\\s+/g, \" \"));\r\n}\r\n\r\n/**\r\n * Strips HTML tags and collapses whitespace into a single-line plain-text string.\r\n *\r\n * This is not an HTML sanitizer or a complete HTML parser. It does not decode\r\n * all entities or preserve document structure.\r\n *\r\n * @example\r\n * htmlToPlainText(\"<p>Hello<br>World</p>\") // \"Hello World\"\r\n */\r\nexport function htmlToPlainText(value: string): string {\r\n if (value.trim().length === 0) {\r\n return \"\";\r\n }\r\n\r\n return value\r\n .replace(/<(br|\\/p|\\/div|\\/pre|\\/li)\\b[^>]*>/gi, \" \")\r\n .replace(/<[^>]*>/g, \" \")\r\n .replace(/[\\n\\t]+/g, \" \")\r\n .replace(/\\s+/g, \" \")\r\n .trim();\r\n}\r\n\r\n/**\r\n * Returns a trimmed string, or `null` when the value is not a non-empty string.\r\n *\r\n * @example\r\n * nonEmptyString(\" Gold \") // \"Gold\"\r\n * nonEmptyString(\" \") // null\r\n */\r\nexport function nonEmptyString(value: unknown): string | null {\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n return trimmed.length === 0 ? null : trimmed;\r\n}\r\n","import { assertFiniteNumber } from \"../internal/validation.js\";\r\n\r\nconst DEFAULT_LOCALE = \"en-IN\";\r\nconst DEFAULT_CURRENCY = \"INR\";\r\nconst MAX_DECIMAL_PLACES = 15;\r\nconst DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\r\n\r\n/**\r\n * `Intl.NumberFormatOptions` plus an optional BCP 47 locale.\r\n * Defaults to `en-IN` when `locale` is omitted.\r\n */\r\nexport interface FormatNumberOptions extends Intl.NumberFormatOptions {\r\n locale?: string;\r\n}\r\n\r\n/**\r\n * Converts a value to a finite number.\r\n * Returns `null` for invalid, empty, non-finite, or locale-formatted input.\r\n *\r\n * Strings such as `\"1,234\"` are rejected because grouping separators are\r\n * locale-specific and are not parsed without an explicit strategy.\r\n *\r\n * @example\r\n * toNumber(\"42\") // 42\r\n * toNumber(\"1,234\") // null\r\n * toNumber(Number.NaN) // null\r\n */\r\nexport function toNumber(value: unknown): number | null {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : null;\r\n }\r\n\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0 || /[,\\s]/.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n const parsed = Number(trimmed);\r\n return Number.isFinite(parsed) ? parsed : null;\r\n}\r\n\r\n/**\r\n * Formats a finite number with `Intl.NumberFormat`.\r\n * Defaults to the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n *\r\n * @example\r\n * formatNumber(1234567.89) // \"12,34,567.89\"\r\n * formatNumber(12.3456, { maximumFractionDigits: 2 }) // \"12.35\"\r\n */\r\nexport function formatNumber(value: number, options?: FormatNumberOptions): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n const { locale = DEFAULT_LOCALE, ...intlOptions } = options ?? {};\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, intlOptions).format(value);\r\n}\r\n\r\n/**\r\n * Formats a finite number as currency with `Intl.NumberFormat`.\r\n * Defaults to INR in the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not finite or `currency`/`locale` are empty.\r\n *\r\n * @example\r\n * formatCurrency(1500) // \"₹1,500.00\"\r\n * formatCurrency(1500, \"USD\", \"en-US\") // \"$1,500.00\"\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n currency: string = DEFAULT_CURRENCY,\r\n locale: string = DEFAULT_LOCALE,\r\n): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (typeof currency !== \"string\" || currency.trim().length === 0) {\r\n throw new TypeError(\"currency must be a non-empty ISO 4217 currency code\");\r\n }\r\n\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, {\r\n style: \"currency\",\r\n currency,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Restricts a finite number to the inclusive `[min, max]` range.\r\n *\r\n * @throws {TypeError} When any argument is not a finite number.\r\n * @throws {RangeError} When `min` is greater than `max`.\r\n *\r\n * @example\r\n * clamp(15, 0, 10) // 10\r\n * clamp(-4, 0, 10) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n assertFiniteNumber(value, \"value\");\r\n assertFiniteNumber(min, \"min\");\r\n assertFiniteNumber(max, \"max\");\r\n\r\n if (min > max) {\r\n throw new RangeError(\"min must be less than or equal to max\");\r\n }\r\n\r\n return Math.min(max, Math.max(min, value));\r\n}\r\n\r\n/**\r\n * Rounds a finite number to the given number of decimal places.\r\n * Defaults to `0` decimal places.\r\n *\r\n * Uses exponential notation to reduce common binary floating-point surprises,\r\n * but IEEE 754 values still cannot represent every decimal exactly.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n * @throws {RangeError} When `decimalPlaces` is not an integer from 0 to 15.\r\n *\r\n * @example\r\n * roundTo(1.2345, 2) // 1.23\r\n * roundTo(1.5) // 2\r\n */\r\nexport function roundTo(value: number, decimalPlaces = 0): number {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (\r\n !Number.isInteger(decimalPlaces) ||\r\n decimalPlaces < 0 ||\r\n decimalPlaces > MAX_DECIMAL_PLACES\r\n ) {\r\n throw new RangeError(\r\n `decimalPlaces must be an integer between 0 and ${MAX_DECIMAL_PLACES}`,\r\n );\r\n }\r\n\r\n if (Object.is(value, -0)) {\r\n return 0;\r\n }\r\n\r\n const [significand = \"0\", exponent = \"0\"] = `${value}e`.split(\"e\");\r\n const shifted = Number(`${significand}e${Number(exponent) + decimalPlaces}`);\r\n const rounded = Math.round(shifted);\r\n const [roundedSignificand = \"0\", roundedExponent = \"0\"] = `${rounded}e`.split(\"e\");\r\n\r\n const result = Number(\r\n `${roundedSignificand}e${Number(roundedExponent) - decimalPlaces}`,\r\n );\r\n\r\n return Object.is(result, -0) ? 0 : result;\r\n}\r\n\r\n/**\r\n * Parses a positive integer. Returns `fallback` when the value is missing,\r\n * non-numeric, zero, or negative.\r\n *\r\n * @example\r\n * parsePositiveInt(\"12\", 1) // 12\r\n * parsePositiveInt(\"abc\", 1) // 1\r\n * parsePositiveInt(0, 10) // 10\r\n */\r\nexport function parsePositiveInt(value: unknown, fallback: number): number {\r\n assertFiniteNumber(fallback, \"fallback\");\r\n\r\n const parsed = typeof value === \"number\" ? value : Number.parseInt(String(value ?? \"\"), 10);\r\n\r\n return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;\r\n}\r\n\r\n/**\r\n * Converts digit-only strings to numbers and leaves everything else unchanged.\r\n * Unlike `toNumber`, invalid values are not converted to `null`.\r\n *\r\n * @example\r\n * toNumberIfValid(\"08\") // 8\r\n * toNumberIfValid(\"gold\") // \"gold\"\r\n */\r\nexport function toNumberIfValid<T>(value: T): T | number {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : value;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n const trimmed = value.trim();\r\n if (/^\\d+$/.test(trimmed)) {\r\n return Number(trimmed);\r\n }\r\n }\r\n\r\n return value;\r\n}\r\n","import { escapeRegExp } from \"../internal/validation.js\";\r\n\r\nexport interface SlugifyOptions {\r\n /**\r\n * Word separator used in the generated slug.\r\n * Must be a non-empty string that contains no whitespace.\r\n * @default \"-\"\r\n */\r\n separator?: string;\r\n /**\r\n * Maximum slug length. Trailing separators are removed after truncation.\r\n */\r\n maxLength?: number;\r\n /**\r\n * When `true`, Unicode letters and numbers are kept after diacritic stripping.\r\n * When `false`, only ASCII `[a-z0-9]` characters remain.\r\n * @default true\r\n */\r\n preserveUnicode?: boolean;\r\n}\r\n\r\n/**\r\n * Converts text into a URL-friendly slug.\r\n *\r\n * The result is lowercased. Unicode is normalized with NFD and combining\r\n * marks are removed, so `\"Café\"` becomes `\"cafe\"`. This is not full\r\n * language transliteration, and generated slugs are not guaranteed unique.\r\n *\r\n * @throws {TypeError} When `separator` is empty or contains whitespace.\r\n * @throws {TypeError} When `preserveUnicode` is not a boolean.\r\n * @throws {RangeError} When `maxLength` is not a positive integer.\r\n *\r\n * @example\r\n * slugify(\"Cavalo Care — RSA Plans\") // \"cavalo-care-rsa-plans\"\r\n * slugify(\"Hello World\", { separator: \"_\" }) // \"hello_world\"\r\n * slugify(\"Café Products\") // \"cafe-products\"\r\n */\r\nexport function slugify(value: string, options: SlugifyOptions = {}): string {\r\n const separator = options.separator ?? \"-\";\r\n const preserveUnicode = options.preserveUnicode ?? true;\r\n const { maxLength } = options;\r\n\r\n if (typeof separator !== \"string\" || separator.length === 0 || /\\s/u.test(separator)) {\r\n throw new TypeError(\"separator must be a non-empty string without whitespace\");\r\n }\r\n\r\n if (options.preserveUnicode !== undefined && typeof options.preserveUnicode !== \"boolean\") {\r\n throw new TypeError(\"preserveUnicode must be a boolean\");\r\n }\r\n\r\n if (maxLength !== undefined && (!Number.isInteger(maxLength) || maxLength <= 0)) {\r\n throw new RangeError(\"maxLength must be a positive integer\");\r\n }\r\n\r\n const escapedSeparator = escapeRegExp(separator);\r\n const disallowedPattern = preserveUnicode ? /[^\\p{L}\\p{N}]+/gu : /[^a-z0-9]+/g;\r\n\r\n let slug = value\r\n .normalize(\"NFD\")\r\n .replace(/\\p{M}/gu, \"\")\r\n .toLowerCase()\r\n .replace(disallowedPattern, separator)\r\n .replace(new RegExp(`${escapedSeparator}+`, \"g\"), separator)\r\n .replace(new RegExp(`^${escapedSeparator}|${escapedSeparator}$`, \"g\"), \"\");\r\n\r\n if (maxLength !== undefined && slug.length > maxLength) {\r\n slug = slug\r\n .slice(0, maxLength)\r\n .replace(new RegExp(`${escapedSeparator}+$`, \"g\"), \"\");\r\n }\r\n\r\n return slug;\r\n}\r\n","import { assertFiniteNumber } from \"../internal/validation.js\";\r\n\r\n/**\r\n * Returns `true` when the value is a plain object created by `{}`,\r\n * `Object.create(null)`, or `new Object()`. Arrays, `null`, and class\r\n * instances are rejected.\r\n */\r\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\r\n if (value === null || typeof value !== \"object\") {\r\n return false;\r\n }\r\n\r\n const prototype = Object.getPrototypeOf(value);\r\n return prototype === null || prototype === Object.prototype;\r\n}\r\n\r\n/**\r\n * Returns `true` for `null`, `undefined`, and whitespace-only strings.\r\n * `0` and `false` are not treated as empty.\r\n */\r\nexport function isNilOrEmpty(value: unknown): boolean {\r\n if (value == null) {\r\n return true;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n return value.trim().length === 0;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Returns `value` unless it is `null` or `undefined`, in which case\r\n * `fallback` is returned.\r\n */\r\nexport function coalesce<T>(value: T | null | undefined, fallback: T): T {\r\n return value ?? fallback;\r\n}\r\n\r\n/**\r\n * Coerces common truthy/falsey inputs to a boolean.\r\n * `null`, `undefined`, and empty or whitespace-only strings return `fallback`.\r\n *\r\n * @example\r\n * toBoolean(\"true\") // true\r\n * toBoolean(\"0\") // false\r\n * toBoolean(null, true) // true\r\n */\r\nexport function toBoolean(value: unknown, fallback = false): boolean {\r\n if (value === true || value === 1 || value === \"1\") {\r\n return true;\r\n }\r\n\r\n if (value === false || value === 0 || value === \"0\") {\r\n return false;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n const normalized = value.trim().toLowerCase();\r\n if (normalized.length === 0) {\r\n return fallback;\r\n }\r\n if (normalized === \"true\") {\r\n return true;\r\n }\r\n if (normalized === \"false\") {\r\n return false;\r\n }\r\n }\r\n\r\n if (value == null) {\r\n return fallback;\r\n }\r\n\r\n return fallback;\r\n}\r\n\r\n/**\r\n * Recursively trims strings in arrays and plain objects.\r\n * Dates, class instances, and other non-plain objects are left unchanged.\r\n *\r\n * @example\r\n * deepTrim({ name: \" Gold \", tags: [\" rsa \"] })\r\n * // { name: \"Gold\", tags: [\"rsa\"] }\r\n */\r\nexport function deepTrim<T>(value: T): T {\r\n if (typeof value === \"string\") {\r\n return value.trim() as T;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value.map((item) => deepTrim(item)) as T;\r\n }\r\n\r\n if (isPlainObject(value)) {\r\n return Object.fromEntries(\r\n Object.entries(value).map(([key, nested]) => [key, deepTrim(nested)]),\r\n ) as T;\r\n }\r\n\r\n return value;\r\n}\r\n\r\n/**\r\n * Returns a shallow copy of a plain object without `null` or empty-string values.\r\n * Non-plain values are returned unchanged.\r\n *\r\n * @example\r\n * omitEmpty({ name: \"Gold\", note: \"\", city: null })\r\n * // { name: \"Gold\" }\r\n */\r\nexport function omitEmpty<T>(value: T): T {\r\n if (!isPlainObject(value)) {\r\n return value;\r\n }\r\n\r\n const cleaned = { ...value };\r\n for (const key of Object.keys(cleaned)) {\r\n if (cleaned[key] === \"\" || cleaned[key] === null) {\r\n delete cleaned[key];\r\n }\r\n }\r\n\r\n return cleaned as T;\r\n}\r\n\r\n/**\r\n * Returns `value` when it is one of the allowed values, otherwise `fallback`.\r\n *\r\n * @example\r\n * pickAllowed(\"hi\", [\"en\", \"hi\"] as const, \"en\") // \"hi\"\r\n * pickAllowed(\"fr\", [\"en\", \"hi\"] as const, \"en\") // \"en\"\r\n */\r\nexport function pickAllowed<T>(\r\n value: unknown,\r\n allowed: readonly T[],\r\n fallback: T,\r\n): T {\r\n return allowed.includes(value as T) ? (value as T) : fallback;\r\n}\r\n\r\n/**\r\n * Resolves after the given number of milliseconds.\r\n */\r\nexport function sleep(milliseconds: number): Promise<void> {\r\n assertFiniteNumber(milliseconds, \"milliseconds\");\r\n\r\n if (milliseconds < 0) {\r\n throw new RangeError(\"milliseconds must be greater than or equal to 0\");\r\n }\r\n\r\n return new Promise((resolve) => {\r\n setTimeout(resolve, milliseconds);\r\n });\r\n}\r\n","import { assertFiniteNumber } from \"../internal/validation.js\";\r\n\r\nconst DEFAULT_LOCALE = \"en-IN\";\r\nconst DEFAULT_TIME_ZONE = \"Asia/Kolkata\";\r\nconst FILE_SIZE_UNITS = [\"Bytes\", \"KB\", \"MB\", \"GB\", \"TB\", \"PB\"] as const;\r\n\r\nexport interface FormatDateTimeOptions extends Intl.DateTimeFormatOptions {\r\n locale?: string;\r\n}\r\n\r\nexport interface FormatDurationOptions {\r\n /**\r\n * Interpret `value` as milliseconds instead of seconds.\r\n * @default \"seconds\"\r\n */\r\n unit?: \"seconds\" | \"milliseconds\";\r\n}\r\n\r\n/**\r\n * Formats a date with `Intl.DateTimeFormat`.\r\n * Defaults to `en-IN` in the `Asia/Kolkata` time zone, including time.\r\n * Returns `null` for missing or invalid values.\r\n *\r\n * @example\r\n * formatDateTime(\"2024-01-15T00:00:00.000Z\")\r\n * formatDateTime(date, { hour: undefined, minute: undefined, second: undefined })\r\n */\r\nexport function formatDateTime(\r\n value: Date | string | number | null | undefined,\r\n options: FormatDateTimeOptions = {},\r\n): string | null {\r\n if (value == null || value === \"\") {\r\n return null;\r\n }\r\n\r\n const date = value instanceof Date ? value : new Date(value);\r\n if (Number.isNaN(date.getTime())) {\r\n return null;\r\n }\r\n\r\n const { locale = DEFAULT_LOCALE, ...intlOptions } = options;\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.DateTimeFormat(locale, {\r\n timeZone: DEFAULT_TIME_ZONE,\r\n day: \"2-digit\",\r\n month: \"short\",\r\n year: \"numeric\",\r\n hour: \"2-digit\",\r\n minute: \"2-digit\",\r\n second: \"2-digit\",\r\n hour12: true,\r\n ...intlOptions,\r\n }).format(date);\r\n}\r\n\r\n/**\r\n * Formats a byte count as a human-readable file size.\r\n *\r\n * @example\r\n * formatFileSize(0) // \"0 Bytes\"\r\n * formatFileSize(1536) // \"1.5 KB\"\r\n */\r\nexport function formatFileSize(bytes: number, decimals = 2): string {\r\n assertFiniteNumber(bytes, \"bytes\");\r\n if (bytes < 0) {\r\n throw new RangeError(\"bytes must be greater than or equal to 0\");\r\n }\r\n\r\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 8) {\r\n throw new RangeError(\"decimals must be an integer between 0 and 8\");\r\n }\r\n\r\n if (bytes === 0) {\r\n return \"0 Bytes\";\r\n }\r\n\r\n const unitIndex = Math.min(\r\n Math.floor(Math.log(bytes) / Math.log(1024)),\r\n FILE_SIZE_UNITS.length - 1,\r\n );\r\n const value = bytes / 1024 ** unitIndex;\r\n const unit = FILE_SIZE_UNITS[unitIndex] ?? \"Bytes\";\r\n\r\n return `${Number(value.toFixed(decimals))} ${unit}`;\r\n}\r\n\r\n/**\r\n * Formats a duration in hours, minutes, and seconds.\r\n *\r\n * @example\r\n * formatDuration(3661) // \"1 hr 1 min 1 sec\"\r\n * formatDuration(0) // \"0 sec\"\r\n */\r\nexport function formatDuration(seconds: number): string {\r\n assertFiniteNumber(seconds, \"seconds\");\r\n\r\n if (seconds <= 0) {\r\n return \"0 sec\";\r\n }\r\n\r\n const total = Math.floor(seconds);\r\n const hours = Math.floor(total / 3600);\r\n const minutes = Math.floor((total % 3600) / 60);\r\n const remainingSeconds = total % 60;\r\n\r\n const parts: string[] = [];\r\n if (hours > 0) {\r\n parts.push(`${hours} hr`);\r\n }\r\n if (minutes > 0) {\r\n parts.push(`${minutes} min`);\r\n }\r\n if (remainingSeconds > 0 || parts.length === 0) {\r\n parts.push(`${remainingSeconds} sec`);\r\n }\r\n\r\n return parts.join(\" \");\r\n}\r\n\r\n/**\r\n * Formats a duration as a compact `y d h m s` string.\r\n * Month and year units use fixed 30-day and 365-day approximations.\r\n *\r\n * @example\r\n * formatDurationCompact(3661) // \"1h 1m 1s\"\r\n * formatDurationCompact(1500, { unit: \"milliseconds\" }) // \"1s\"\r\n */\r\nexport function formatDurationCompact(\r\n value: number,\r\n options: FormatDurationOptions = {},\r\n): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n const unit = options.unit ?? \"seconds\";\r\n if (unit !== \"seconds\" && unit !== \"milliseconds\") {\r\n throw new TypeError('unit must be \"seconds\" or \"milliseconds\"');\r\n }\r\n\r\n let remaining = Math.floor(unit === \"milliseconds\" ? value / 1000 : value);\r\n if (remaining <= 0) {\r\n return \"0s\";\r\n }\r\n\r\n const years = Math.floor(remaining / 31_536_000);\r\n remaining %= 31_536_000;\r\n const months = Math.floor(remaining / 2_592_000);\r\n remaining %= 2_592_000;\r\n const days = Math.floor(remaining / 86_400);\r\n remaining %= 86_400;\r\n const hours = Math.floor(remaining / 3600);\r\n remaining %= 3600;\r\n const minutes = Math.floor(remaining / 60);\r\n const seconds = remaining % 60;\r\n\r\n const parts: string[] = [];\r\n if (years > 0) {\r\n parts.push(`${years}y`);\r\n }\r\n if (months > 0) {\r\n parts.push(`${months}mo`);\r\n }\r\n if (days > 0) {\r\n parts.push(`${days}d`);\r\n }\r\n if (hours > 0) {\r\n parts.push(`${hours}h`);\r\n }\r\n if (minutes > 0) {\r\n parts.push(`${minutes}m`);\r\n }\r\n if (seconds > 0 || parts.length === 0) {\r\n parts.push(`${seconds}s`);\r\n }\r\n\r\n return parts.join(\" \");\r\n}\r\n\r\n/**\r\n * Formats a price in Indian lakh units.\r\n * Returns an empty string for missing or invalid values.\r\n *\r\n * @example\r\n * formatPriceToLakh(2_000_000) // \"20.00 Lakh\"\r\n */\r\nexport function formatPriceToLakh(price: unknown, decimals = 2): string {\r\n if (!Number.isInteger(decimals) || decimals < 0 || decimals > 8) {\r\n throw new RangeError(\"decimals must be an integer between 0 and 8\");\r\n }\r\n\r\n const numeric =\r\n typeof price === \"number\"\r\n ? price\r\n : typeof price === \"string\"\r\n ? Number(price.trim())\r\n : Number.NaN;\r\n\r\n if (!Number.isFinite(numeric)) {\r\n return \"\";\r\n }\r\n\r\n return `${(numeric / 100_000).toFixed(decimals)} Lakh`;\r\n}\r\n","const INDIAN_MOBILE_PATTERN = /^[6-9]\\d{9}$/;\r\n\r\n/**\r\n * Normalizes an Indian mobile number to 10 digits starting with 6-9.\r\n * Country-code prefixes such as `+91` or `91` are removed when present.\r\n * Returns `null` for empty or invalid numbers.\r\n *\r\n * @example\r\n * normalizeMobile(\"+91 98765 43210\") // \"9876543210\"\r\n * normalizeMobile(\"12345\") // null\r\n */\r\nexport function normalizeMobile(value: unknown): string | null {\r\n if (value == null) {\r\n return null;\r\n }\r\n\r\n const digits = String(value).replace(/\\D/g, \"\");\r\n if (digits.length === 0) {\r\n return null;\r\n }\r\n\r\n const withoutCountryCode =\r\n digits.length > 10 && (digits.startsWith(\"91\") || digits.startsWith(\"0\"))\r\n ? digits.slice(-10)\r\n : digits.length >= 10\r\n ? digits.slice(-10)\r\n : digits;\r\n\r\n return INDIAN_MOBILE_PATTERN.test(withoutCountryCode) ? withoutCountryCode : null;\r\n}\r\n","function getCrypto(): Crypto {\r\n const cryptoApi = globalThis.crypto;\r\n if (!cryptoApi?.getRandomValues) {\r\n throw new Error(\"Secure random number generation is not available in this runtime\");\r\n }\r\n\r\n return cryptoApi;\r\n}\r\n\r\nexport function randomIndex(length: number): number {\r\n if (length <= 0) {\r\n throw new RangeError(\"length must be greater than 0\");\r\n }\r\n\r\n const cryptoApi = getCrypto();\r\n const limit = 0x1_0000_0000;\r\n const unbiasedMax = Math.floor(limit / length) * length;\r\n const bytes = new Uint32Array(1);\r\n\r\n let value = 0;\r\n do {\r\n cryptoApi.getRandomValues(bytes);\r\n value = bytes[0] ?? 0;\r\n } while (value >= unbiasedMax);\r\n\r\n return value % length;\r\n}\r\n\r\nexport function pickCharacter(charset: string): string {\r\n return charset[randomIndex(charset.length)] ?? charset[0] ?? \"A\";\r\n}\r\n\r\nexport function randomString(length: number, charset: string): string {\r\n return Array.from({ length }, () => pickCharacter(charset)).join(\"\");\r\n}\r\n\r\nexport function shuffle<T>(items: T[]): T[] {\r\n const result = [...items];\r\n for (let index = result.length - 1; index > 0; index -= 1) {\r\n const swapIndex = randomIndex(index + 1);\r\n const current = result[index];\r\n const other = result[swapIndex];\r\n if (current === undefined || other === undefined) {\r\n continue;\r\n }\r\n result[index] = other;\r\n result[swapIndex] = current;\r\n }\r\n return result;\r\n}\r\n","import { pickCharacter, shuffle } from \"../internal/random.js\";\r\n\r\nconst UPPERCASE = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ\";\r\nconst LOWERCASE = \"abcdefghijklmnopqrstuvwxyz\";\r\nconst NUMBERS = \"0123456789\";\r\nconst SPECIAL = \"!@#$%^&*()_+-=[]{}|;:,.<>?\";\r\nconst ALL_CHARACTERS = `${UPPERCASE}${LOWERCASE}${NUMBERS}${SPECIAL}`;\r\nconst MIN_PASSWORD_LENGTH = 8;\r\nconst DEFAULT_PASSWORD_LENGTH = 12;\r\n\r\n/**\r\n * Generates a password with at least one uppercase letter, lowercase letter,\r\n * number, and special character. Uses `crypto.getRandomValues`.\r\n *\r\n * This is not a password-policy engine and does not hash passwords.\r\n *\r\n * @throws {RangeError} When `length` is below 8 or not an integer.\r\n *\r\n * @example\r\n * generatePassword()\r\n * generatePassword(16)\r\n */\r\nexport function generatePassword(length = DEFAULT_PASSWORD_LENGTH): string {\r\n if (!Number.isInteger(length) || length < MIN_PASSWORD_LENGTH) {\r\n throw new RangeError(`length must be an integer greater than or equal to ${MIN_PASSWORD_LENGTH}`);\r\n }\r\n\r\n const required = [\r\n pickCharacter(UPPERCASE),\r\n pickCharacter(LOWERCASE),\r\n pickCharacter(NUMBERS),\r\n pickCharacter(SPECIAL),\r\n ];\r\n\r\n const remaining = Array.from({ length: length - required.length }, () =>\r\n pickCharacter(ALL_CHARACTERS),\r\n );\r\n\r\n return shuffle([...required, ...remaining]).join(\"\");\r\n}\r\n","import { randomString } from \"../internal/random.js\";\r\n\r\nconst DEFAULT_CHARSET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\";\r\n\r\nexport interface GeneratePrefixedCodeOptions {\r\n prefix: string;\r\n randomLength?: number;\r\n includeTimestamp?: boolean;\r\n now?: Date;\r\n charset?: string;\r\n}\r\n\r\nfunction pad(value: number): string {\r\n return String(value).padStart(2, \"0\");\r\n}\r\n\r\n/**\r\n * Builds a configurable unique-looking code such as `PLAN1503AB12X0931`.\r\n * Uses `crypto.getRandomValues`. This does not guarantee global uniqueness.\r\n *\r\n * @example\r\n * generatePrefixedCode({ prefix: \"PLAN\" })\r\n * generatePrefixedCode({ prefix: \"SAVE\", randomLength: 6, includeTimestamp: false })\r\n */\r\nexport function generatePrefixedCode(options: GeneratePrefixedCodeOptions): string {\r\n const prefix = options.prefix.trim();\r\n if (prefix.length === 0) {\r\n throw new TypeError(\"prefix must be a non-empty string\");\r\n }\r\n\r\n const randomLength = options.randomLength ?? 5;\r\n if (!Number.isInteger(randomLength) || randomLength < 0) {\r\n throw new RangeError(\"randomLength must be an integer greater than or equal to 0\");\r\n }\r\n\r\n const charset = options.charset ?? DEFAULT_CHARSET;\r\n if (charset.length === 0) {\r\n throw new TypeError(\"charset must be a non-empty string\");\r\n }\r\n\r\n const includeTimestamp = options.includeTimestamp ?? true;\r\n const now = options.now ?? new Date();\r\n const randomPart = randomLength > 0 ? randomString(randomLength, charset) : \"\";\r\n\r\n if (!includeTimestamp) {\r\n return `${prefix}${randomPart}`;\r\n }\r\n\r\n const day = pad(now.getDate());\r\n const month = pad(now.getMonth() + 1);\r\n const hour = pad(now.getHours());\r\n const minute = pad(now.getMinutes());\r\n\r\n return `${prefix}${day}${month}${randomPart}${hour}${minute}`;\r\n}\r\n","const IST_OFFSET_MS = 330 * 60 * 1000;\r\nconst IST_DATETIME_RE =\r\n /^(\\d{4})-(\\d{2})-(\\d{2})[ T](\\d{2}):(\\d{2})(?::(\\d{2}))?/;\r\n\r\nexport interface IstDateParts {\r\n year: number;\r\n month: number;\r\n day: number;\r\n hour: number;\r\n}\r\n\r\nexport interface ExpiryInfo {\r\n expiresAt: Date;\r\n remainingSeconds: number;\r\n remainingHuman: string;\r\n daysLeft: number;\r\n isExpired: boolean;\r\n needsRefresh: boolean;\r\n}\r\n\r\nexport interface ExpiryInfoOptions {\r\n warningDays?: number;\r\n compact?: boolean;\r\n now?: Date;\r\n}\r\n\r\nexport interface CalendarWindowOptions {\r\n now?: Date;\r\n cutoffHour?: number;\r\n windowDays?: number;\r\n startOffsetBeforeCutoff?: number;\r\n startOffsetAfterCutoff?: number;\r\n}\r\n\r\nfunction pad(value: number, length = 2): string {\r\n return String(value).padStart(length, \"0\");\r\n}\r\n\r\n/**\r\n * Reads calendar parts of a date in Asia/Kolkata.\r\n */\r\nexport function getIstDateParts(date: Date = new Date()): IstDateParts {\r\n const parts = new Intl.DateTimeFormat(\"en-CA\", {\r\n timeZone: \"Asia/Kolkata\",\r\n year: \"numeric\",\r\n month: \"2-digit\",\r\n day: \"2-digit\",\r\n hour: \"2-digit\",\r\n hourCycle: \"h23\",\r\n }).formatToParts(date);\r\n\r\n const read = (type: Intl.DateTimeFormatPartTypes): number => {\r\n const value = parts.find((part) => part.type === type)?.value;\r\n return Number(value);\r\n };\r\n\r\n return {\r\n year: read(\"year\"),\r\n month: read(\"month\"),\r\n day: read(\"day\"),\r\n hour: read(\"hour\"),\r\n };\r\n}\r\n\r\n/**\r\n * Adds calendar days to a year/month/day triple without DST surprises.\r\n */\r\nexport function addCalendarDays(\r\n year: number,\r\n month: number,\r\n day: number,\r\n days: number,\r\n): { year: number; month: number; day: number } {\r\n const utc = new Date(Date.UTC(year, month - 1, day + days));\r\n return {\r\n year: utc.getUTCFullYear(),\r\n month: utc.getUTCMonth() + 1,\r\n day: utc.getUTCDate(),\r\n };\r\n}\r\n\r\n/**\r\n * Builds a Date for an Asia/Kolkata wall-clock time.\r\n */\r\nexport function istDateTime(\r\n year: number,\r\n month: number,\r\n day: number,\r\n hour = 0,\r\n minute = 0,\r\n second = 0,\r\n millisecond = 0,\r\n): Date {\r\n return new Date(\r\n `${year}-${pad(month)}-${pad(day)}T${pad(hour)}:${pad(minute)}:${pad(second)}.${pad(millisecond, 3)}+05:30`,\r\n );\r\n}\r\n\r\n/**\r\n * Parses a naive IST datetime as Asia/Kolkata and returns a UTC Date.\r\n * Values with an explicit timezone (`Z` or `±HH:mm`) are treated as absolute instants.\r\n */\r\nexport function parseIstDateTimeToUtc(value: Date | string | number | null | undefined): Date | null {\r\n if (value == null || value === \"\") {\r\n return null;\r\n }\r\n\r\n if (value instanceof Date) {\r\n return Number.isNaN(value.getTime()) ? null : value;\r\n }\r\n\r\n if (typeof value === \"number\") {\r\n const parsed = new Date(value);\r\n return Number.isNaN(parsed.getTime()) ? null : parsed;\r\n }\r\n\r\n const raw = value.trim();\r\n if (raw.length === 0) {\r\n return null;\r\n }\r\n\r\n if (/[zZ]$/.test(raw) || /[+-]\\d{2}:?\\d{2}$/.test(raw)) {\r\n const parsed = new Date(raw);\r\n return Number.isNaN(parsed.getTime()) ? null : parsed;\r\n }\r\n\r\n const match = raw.match(IST_DATETIME_RE);\r\n if (!match) {\r\n const parsed = new Date(raw);\r\n return Number.isNaN(parsed.getTime()) ? null : parsed;\r\n }\r\n\r\n const [, year = \"0\", month = \"1\", day = \"1\", hour = \"0\", minute = \"0\", second = \"0\"] = match;\r\n const istAsUtcMs = Date.UTC(\r\n Number(year),\r\n Number(month) - 1,\r\n Number(day),\r\n Number(hour),\r\n Number(minute),\r\n Number(second),\r\n );\r\n\r\n return new Date(istAsUtcMs - IST_OFFSET_MS);\r\n}\r\n\r\n/**\r\n * Formats a UTC instant as `YYYY-MM-DD HH:mm:ss` in Asia/Kolkata.\r\n */\r\nexport function formatUtcToIstDateTime(value: Date | string | number | null | undefined): string {\r\n if (value == null || value === \"\") {\r\n return \"\";\r\n }\r\n\r\n const date = value instanceof Date ? value : new Date(value);\r\n if (Number.isNaN(date.getTime())) {\r\n return \"\";\r\n }\r\n\r\n const ist = new Date(date.getTime() + IST_OFFSET_MS);\r\n return `${ist.getUTCFullYear()}-${pad(ist.getUTCMonth() + 1)}-${pad(ist.getUTCDate())} ${pad(ist.getUTCHours())}:${pad(ist.getUTCMinutes())}:${pad(ist.getUTCSeconds())}`;\r\n}\r\n\r\n/**\r\n * Returns remaining time until `expiresAt`.\r\n */\r\nexport function getExpiryInfo(expiresAt: Date, options: ExpiryInfoOptions = {}): ExpiryInfo | null {\r\n if (!(expiresAt instanceof Date) || Number.isNaN(expiresAt.getTime())) {\r\n return null;\r\n }\r\n\r\n const warningDays = options.warningDays ?? 7;\r\n const compact = options.compact ?? false;\r\n const now = options.now ?? new Date();\r\n\r\n let remainingSeconds = Math.floor((expiresAt.getTime() - now.getTime()) / 1000);\r\n if (remainingSeconds < 0) {\r\n remainingSeconds = 0;\r\n }\r\n\r\n const units = [\r\n { label: \"day\", short: \"d\", value: 86_400 },\r\n { label: \"hour\", short: \"h\", value: 3_600 },\r\n { label: \"minute\", short: \"m\", value: 60 },\r\n { label: \"second\", short: \"s\", value: 1 },\r\n ] as const;\r\n\r\n const parts: string[] = [];\r\n let remaining = remainingSeconds;\r\n for (const unit of units) {\r\n const count = Math.floor(remaining / unit.value);\r\n if (count > 0) {\r\n parts.push(compact ? `${count}${unit.short}` : `${count} ${unit.label}${count > 1 ? \"s\" : \"\"}`);\r\n remaining -= count * unit.value;\r\n }\r\n }\r\n\r\n const daysLeft = Math.ceil(remainingSeconds / 86_400);\r\n\r\n return {\r\n expiresAt,\r\n remainingSeconds,\r\n remainingHuman: parts.join(\" \") || \"Expired\",\r\n daysLeft,\r\n isExpired: remainingSeconds === 0,\r\n needsRefresh: daysLeft <= warningDays,\r\n };\r\n}\r\n\r\n/**\r\n * Builds a configurable IST calendar window, typically for booking start/end dates.\r\n */\r\nexport function getCalendarWindow(options: CalendarWindowOptions = {}): { min: Date; max: Date } {\r\n const now = options.now ?? new Date();\r\n const cutoffHour = options.cutoffHour ?? 14;\r\n const windowDays = options.windowDays ?? 36;\r\n const startOffsetBeforeCutoff = options.startOffsetBeforeCutoff ?? 1;\r\n const startOffsetAfterCutoff = options.startOffsetAfterCutoff ?? 2;\r\n\r\n if (!Number.isInteger(cutoffHour) || cutoffHour < 0 || cutoffHour > 23) {\r\n throw new RangeError(\"cutoffHour must be an integer between 0 and 23\");\r\n }\r\n if (!Number.isInteger(windowDays) || windowDays < 0) {\r\n throw new RangeError(\"windowDays must be an integer greater than or equal to 0\");\r\n }\r\n\r\n const { year, month, day, hour } = getIstDateParts(now);\r\n const startOffsetDays = hour < cutoffHour ? startOffsetBeforeCutoff : startOffsetAfterCutoff;\r\n const minYmd = addCalendarDays(year, month, day, startOffsetDays);\r\n const maxYmd = addCalendarDays(minYmd.year, minYmd.month, minYmd.day, windowDays);\r\n\r\n return {\r\n min: istDateTime(minYmd.year, minYmd.month, minYmd.day, 0, 0, 0, 0),\r\n max: istDateTime(maxYmd.year, maxYmd.month, maxYmd.day, 23, 59, 59, 999),\r\n };\r\n}\r\n","import { isPlainObject } from \"../common/index.js\";\r\n\r\nconst DEFAULT_SENSITIVE_KEYS = [\r\n \"authorization\",\r\n \"password\",\r\n \"client_secret\",\r\n \"otp\",\r\n \"otp_hash\",\r\n \"api_key\",\r\n \"x-api-key\",\r\n \"token\",\r\n \"access_token\",\r\n \"refresh_token\",\r\n \"jwt\",\r\n \"secret\",\r\n] as const;\r\n\r\nexport interface SanitizeOptions {\r\n sensitiveKeys?: readonly string[];\r\n maxDepth?: number;\r\n maxString?: number;\r\n maxArray?: number;\r\n redactedValue?: string;\r\n truncatedValue?: string;\r\n}\r\n\r\nfunction resolveOptions(options: SanitizeOptions = {}) {\r\n return {\r\n sensitiveKeys: new Set(\r\n (options.sensitiveKeys ?? DEFAULT_SENSITIVE_KEYS).map((key) => key.toLowerCase()),\r\n ),\r\n maxDepth: options.maxDepth ?? 6,\r\n maxString: options.maxString ?? 2_000,\r\n maxArray: options.maxArray ?? 50,\r\n redactedValue: options.redactedValue ?? \"[REDACTED]\",\r\n truncatedValue: options.truncatedValue ?? \"[truncated]\",\r\n };\r\n}\r\n\r\n/**\r\n * Deep-clones a value and redacts configured secret keys for safe logging.\r\n * Arrays, string length, and recursion depth are truncated.\r\n */\r\nexport function sanitizeForLog(value: unknown, options: SanitizeOptions = {}, depth = 0): unknown {\r\n const config = resolveOptions(options);\r\n if (depth > config.maxDepth) {\r\n return config.truncatedValue;\r\n }\r\n\r\n if (value == null || typeof value === \"number\" || typeof value === \"boolean\") {\r\n return value;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n return value.length > config.maxString ? `${value.slice(0, config.maxString)}…` : value;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value\r\n .slice(0, config.maxArray)\r\n .map((item) => sanitizeForLog(item, options, depth + 1));\r\n }\r\n\r\n if (isPlainObject(value)) {\r\n const output: Record<string, unknown> = {};\r\n for (const [key, nested] of Object.entries(value)) {\r\n output[key] = config.sensitiveKeys.has(key.toLowerCase())\r\n ? config.redactedValue\r\n : sanitizeForLog(nested, options, depth + 1);\r\n }\r\n return output;\r\n }\r\n\r\n if (value instanceof Date) {\r\n return value.toISOString();\r\n }\r\n\r\n return String(value);\r\n}\r\n\r\n/**\r\n * Returns a shallow copy of headers with secret keys redacted.\r\n */\r\nexport function sanitizeHeaders(\r\n headers: Record<string, unknown>,\r\n options: SanitizeOptions = {},\r\n): Record<string, unknown> {\r\n const config = resolveOptions(options);\r\n const output: Record<string, unknown> = {};\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n if (config.sensitiveKeys.has(key.toLowerCase())) {\r\n output[key] = config.redactedValue;\r\n } else if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\r\n output[key] = value;\r\n } else if (Array.isArray(value)) {\r\n output[key] = value.map(String);\r\n }\r\n }\r\n\r\n return output;\r\n}\r\n","export interface SuccessResponse<T = unknown> {\r\n success: true;\r\n message?: string;\r\n data?: T;\r\n meta?: unknown;\r\n request_id?: string;\r\n}\r\n\r\nexport interface ErrorResponse {\r\n success: false;\r\n message?: string;\r\n code?: string | number;\r\n errors?: unknown;\r\n details?: unknown;\r\n request_id?: string;\r\n}\r\n\r\nexport interface CreateSuccessResponseOptions<T> {\r\n data?: T;\r\n message?: string;\r\n meta?: unknown;\r\n requestId?: string;\r\n}\r\n\r\nexport interface CreateErrorResponseOptions {\r\n message?: string;\r\n code?: string | number;\r\n errors?: unknown;\r\n details?: unknown;\r\n requestId?: string;\r\n}\r\n\r\n/**\r\n * Builds a framework-independent success payload.\r\n * This does not write HTTP headers or call Express `res.json`.\r\n */\r\nexport function createSuccessResponse<T>(\r\n options: CreateSuccessResponseOptions<T> = {},\r\n): SuccessResponse<T> {\r\n const response: SuccessResponse<T> = { success: true };\r\n\r\n if (options.message) {\r\n response.message = options.message;\r\n }\r\n if (options.data !== undefined) {\r\n response.data = options.data;\r\n }\r\n if (options.meta !== undefined) {\r\n response.meta = options.meta;\r\n }\r\n if (options.requestId) {\r\n response.request_id = options.requestId;\r\n }\r\n\r\n return response;\r\n}\r\n\r\n/**\r\n * Builds a framework-independent error payload.\r\n * This does not write HTTP headers or call Express `res.json`.\r\n */\r\nexport function createErrorResponse(options: CreateErrorResponseOptions = {}): ErrorResponse {\r\n const response: ErrorResponse = { success: false };\r\n\r\n if (options.message) {\r\n response.message = options.message;\r\n }\r\n if (options.code !== undefined) {\r\n response.code = options.code;\r\n }\r\n if (options.errors !== undefined) {\r\n response.errors = options.errors;\r\n }\r\n if (options.details !== undefined) {\r\n response.details = options.details;\r\n }\r\n if (options.requestId) {\r\n response.request_id = options.requestId;\r\n }\r\n\r\n return response;\r\n}\r\n","import { escapeRegExp } from \"../internal/validation.js\";\r\n\r\n/**\r\n * Shared validation regular expressions for Indian and general form fields.\r\n * These patterns check shape only. They do not verify checksums, ownership,\r\n * or whether a value is officially issued.\r\n */\r\nexport const ValidationPatterns = {\r\n YEAR: /^\\d{4}$/,\r\n OTP: /^\\d{6}$/,\r\n PINCODE: /^\\d{6}$/,\r\n POSTAL_CODE: /^\\d{6}$/,\r\n NUMERIC: /^[0-9]+$/,\r\n MOBILE: /^[6-9]\\d{9}$/,\r\n NAME: /^[a-zA-Z\\s\\-']+$/,\r\n ALPHABETIC: /^[a-zA-Z]+$/,\r\n LOWERCASE_ONLY: /^[a-z_]+$/,\r\n UPPERCASE_ONLY: /^[A-Z_]+$/,\r\n USERNAME: /^[a-zA-Z0-9_-]+$/,\r\n LOWER_NUMERIC: /^[a-z0-9_]+$/,\r\n UPPER_NUMERIC: /^[A-Z0-9_]+$/,\r\n LOWER_WITH_HYPHENS: /^[a-z-]+$/,\r\n UPPER_WITH_HYPHENS: /^[A-Z-]+$/,\r\n ALPHANUMERIC: /^[a-zA-Z0-9-\\s]+$/,\r\n PERMISSION_NAME: /^[a-z0-9._-]+$/,\r\n AADHAR_CARD: /^[2-9][0-9]{11}$/,\r\n LOWER_NUMERIC_WITH_HYPHENS: /^[a-z0-9-]+$/,\r\n UPPER_NUMERIC_WITH_HYPHENS: /^[A-Z0-9-]+$/,\r\n ALPHANUMERIC_WITH_SPACES: /^[a-zA-Z0-9\\s]+$/,\r\n ALPHANUMERIC_WITHOUT_SPACES: /^[a-zA-Z0-9]+$/,\r\n PAN_CARD: /^[A-Za-z]{5}[0-9]{4}[A-Za-z]$/,\r\n ALPHANUMERIC_WITH_UNDERSCORES: /^[a-zA-Z0-9-_]+$/,\r\n MODEL_NAME: /^[a-zA-Z0-9_\\s\\-/\\\\*+()[\\]:'\",.%&]+$/,\r\n NOTE: /^[a-zA-Z0-9\\s/\\\\,.\\-_+=<>()[\\]{}@#$%^&*~`\"',;:’]+$/,\r\n EMAIL: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/,\r\n VEHICLE_NUMBER: /^[A-Za-z]{2}\\d{1,2}[A-Za-z]{1,3}\\d{1,4}$/,\r\n PASSWORD: /^(?=.*[a-zA-Z])(?=.*[0-9])(?=.*[@$!%*?&])[a-zA-Z0-9@$!%*?&]{8,16}$/,\r\n URL: /^https?:\\/\\/(?:www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/,\r\n DATE: /^\\d{4}-\\d{2}-\\d{2}$/,\r\n CURRENCY: /^\\d+(?:\\.\\d{1,2})?$/,\r\n TIME: /^(?:[01]?\\d|2[0-3]):[0-5]\\d$/,\r\n MESSAGE: /^[a-zA-Z0-9\\s.,!?_\\-@#()&%$+=:;\"'<>[\\]{}|\\\\/]+$/,\r\n DOMAIN_HOSTNAME:\r\n /^(?=.{1,253}$)(?:localhost|(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\\.)+[a-z]{2,}|[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)$/i,\r\n} as const;\r\n\r\nexport type ValidationPatternName = keyof typeof ValidationPatterns;\r\n\r\n/**\r\n * Tests a string against a named validation pattern or a custom regular expression.\r\n *\r\n * @example\r\n * testPattern(\"9876543210\", \"MOBILE\") // true\r\n * testPattern(\"user@example.com\", ValidationPatterns.EMAIL) // true\r\n */\r\nexport function testPattern(\r\n value: string,\r\n pattern: ValidationPatternName | RegExp,\r\n): boolean {\r\n if (typeof pattern === \"string\") {\r\n const namedPattern = ValidationPatterns[pattern];\r\n if (!namedPattern) {\r\n throw new TypeError(`Unknown validation pattern: ${pattern}`);\r\n }\r\n return namedPattern.test(value);\r\n }\r\n\r\n return pattern.test(value);\r\n}\r\n\r\n/**\r\n * Returns a named validation pattern.\r\n *\r\n * @example\r\n * getPattern(\"PINCODE\") // /^\\d{6}$/\r\n */\r\nexport function getPattern(name: ValidationPatternName): RegExp {\r\n const pattern = ValidationPatterns[name];\r\n if (!pattern) {\r\n throw new TypeError(`Unknown validation pattern: ${name}`);\r\n }\r\n\r\n return pattern;\r\n}\r\n\r\n/**\r\n * Escapes special regular-expression characters in a string.\r\n */\r\nexport function escapeRegex(value: string): string {\r\n return escapeRegExp(value);\r\n}\r\n\r\nexport { escapeRegex as escapeRegExp };\r\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/internal/validation.ts
|
|
4
|
+
function assertFiniteNumber(value, name) {
|
|
5
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
6
|
+
throw new TypeError(`${name} must be a finite number`);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// src/number/index.ts
|
|
11
|
+
var DEFAULT_LOCALE = "en-IN";
|
|
12
|
+
var DEFAULT_CURRENCY = "INR";
|
|
13
|
+
var MAX_DECIMAL_PLACES = 15;
|
|
14
|
+
var DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
15
|
+
function toNumber(value) {
|
|
16
|
+
if (typeof value === "number") {
|
|
17
|
+
return Number.isFinite(value) ? value : null;
|
|
18
|
+
}
|
|
19
|
+
if (typeof value !== "string") {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const trimmed = value.trim();
|
|
23
|
+
if (trimmed.length === 0 || /[,\s]/.test(trimmed)) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const parsed = Number(trimmed);
|
|
30
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
31
|
+
}
|
|
32
|
+
function formatNumber(value, options) {
|
|
33
|
+
assertFiniteNumber(value, "value");
|
|
34
|
+
const { locale = DEFAULT_LOCALE, ...intlOptions } = options ?? {};
|
|
35
|
+
if (typeof locale !== "string" || locale.trim().length === 0) {
|
|
36
|
+
throw new TypeError("locale must be a non-empty BCP 47 locale tag");
|
|
37
|
+
}
|
|
38
|
+
return new Intl.NumberFormat(locale, intlOptions).format(value);
|
|
39
|
+
}
|
|
40
|
+
function formatCurrency(value, currency = DEFAULT_CURRENCY, locale = DEFAULT_LOCALE) {
|
|
41
|
+
assertFiniteNumber(value, "value");
|
|
42
|
+
if (typeof currency !== "string" || currency.trim().length === 0) {
|
|
43
|
+
throw new TypeError("currency must be a non-empty ISO 4217 currency code");
|
|
44
|
+
}
|
|
45
|
+
if (typeof locale !== "string" || locale.trim().length === 0) {
|
|
46
|
+
throw new TypeError("locale must be a non-empty BCP 47 locale tag");
|
|
47
|
+
}
|
|
48
|
+
return new Intl.NumberFormat(locale, {
|
|
49
|
+
style: "currency",
|
|
50
|
+
currency
|
|
51
|
+
}).format(value);
|
|
52
|
+
}
|
|
53
|
+
function clamp(value, min, max) {
|
|
54
|
+
assertFiniteNumber(value, "value");
|
|
55
|
+
assertFiniteNumber(min, "min");
|
|
56
|
+
assertFiniteNumber(max, "max");
|
|
57
|
+
if (min > max) {
|
|
58
|
+
throw new RangeError("min must be less than or equal to max");
|
|
59
|
+
}
|
|
60
|
+
return Math.min(max, Math.max(min, value));
|
|
61
|
+
}
|
|
62
|
+
function roundTo(value, decimalPlaces = 0) {
|
|
63
|
+
assertFiniteNumber(value, "value");
|
|
64
|
+
if (!Number.isInteger(decimalPlaces) || decimalPlaces < 0 || decimalPlaces > MAX_DECIMAL_PLACES) {
|
|
65
|
+
throw new RangeError(
|
|
66
|
+
`decimalPlaces must be an integer between 0 and ${MAX_DECIMAL_PLACES}`
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
if (Object.is(value, -0)) {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
const [significand = "0", exponent = "0"] = `${value}e`.split("e");
|
|
73
|
+
const shifted = Number(`${significand}e${Number(exponent) + decimalPlaces}`);
|
|
74
|
+
const rounded = Math.round(shifted);
|
|
75
|
+
const [roundedSignificand = "0", roundedExponent = "0"] = `${rounded}e`.split("e");
|
|
76
|
+
const result = Number(
|
|
77
|
+
`${roundedSignificand}e${Number(roundedExponent) - decimalPlaces}`
|
|
78
|
+
);
|
|
79
|
+
return Object.is(result, -0) ? 0 : result;
|
|
80
|
+
}
|
|
81
|
+
function parsePositiveInt(value, fallback) {
|
|
82
|
+
assertFiniteNumber(fallback, "fallback");
|
|
83
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
84
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
85
|
+
}
|
|
86
|
+
function toNumberIfValid(value) {
|
|
87
|
+
if (typeof value === "number") {
|
|
88
|
+
return Number.isFinite(value) ? value : value;
|
|
89
|
+
}
|
|
90
|
+
if (typeof value === "string") {
|
|
91
|
+
const trimmed = value.trim();
|
|
92
|
+
if (/^\d+$/.test(trimmed)) {
|
|
93
|
+
return Number(trimmed);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return value;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
exports.clamp = clamp;
|
|
100
|
+
exports.formatCurrency = formatCurrency;
|
|
101
|
+
exports.formatNumber = formatNumber;
|
|
102
|
+
exports.parsePositiveInt = parsePositiveInt;
|
|
103
|
+
exports.roundTo = roundTo;
|
|
104
|
+
exports.toNumber = toNumber;
|
|
105
|
+
exports.toNumberIfValid = toNumberIfValid;
|
|
106
|
+
//# sourceMappingURL=index.cjs.map
|
|
107
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/validation.ts","../../src/number/index.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export function assertFiniteNumber(\r\n value: unknown,\r\n name: string,\r\n): asserts value is number {\r\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\r\n throw new TypeError(`${name} must be a finite number`);\r\n }\r\n}\r\n\r\nexport function escapeRegExp(value: string): string {\r\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n","import { assertFiniteNumber } from \"../internal/validation.js\";\r\n\r\nconst DEFAULT_LOCALE = \"en-IN\";\r\nconst DEFAULT_CURRENCY = \"INR\";\r\nconst MAX_DECIMAL_PLACES = 15;\r\nconst DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\r\n\r\n/**\r\n * `Intl.NumberFormatOptions` plus an optional BCP 47 locale.\r\n * Defaults to `en-IN` when `locale` is omitted.\r\n */\r\nexport interface FormatNumberOptions extends Intl.NumberFormatOptions {\r\n locale?: string;\r\n}\r\n\r\n/**\r\n * Converts a value to a finite number.\r\n * Returns `null` for invalid, empty, non-finite, or locale-formatted input.\r\n *\r\n * Strings such as `\"1,234\"` are rejected because grouping separators are\r\n * locale-specific and are not parsed without an explicit strategy.\r\n *\r\n * @example\r\n * toNumber(\"42\") // 42\r\n * toNumber(\"1,234\") // null\r\n * toNumber(Number.NaN) // null\r\n */\r\nexport function toNumber(value: unknown): number | null {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : null;\r\n }\r\n\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0 || /[,\\s]/.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n const parsed = Number(trimmed);\r\n return Number.isFinite(parsed) ? parsed : null;\r\n}\r\n\r\n/**\r\n * Formats a finite number with `Intl.NumberFormat`.\r\n * Defaults to the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n *\r\n * @example\r\n * formatNumber(1234567.89) // \"12,34,567.89\"\r\n * formatNumber(12.3456, { maximumFractionDigits: 2 }) // \"12.35\"\r\n */\r\nexport function formatNumber(value: number, options?: FormatNumberOptions): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n const { locale = DEFAULT_LOCALE, ...intlOptions } = options ?? {};\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, intlOptions).format(value);\r\n}\r\n\r\n/**\r\n * Formats a finite number as currency with `Intl.NumberFormat`.\r\n * Defaults to INR in the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not finite or `currency`/`locale` are empty.\r\n *\r\n * @example\r\n * formatCurrency(1500) // \"₹1,500.00\"\r\n * formatCurrency(1500, \"USD\", \"en-US\") // \"$1,500.00\"\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n currency: string = DEFAULT_CURRENCY,\r\n locale: string = DEFAULT_LOCALE,\r\n): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (typeof currency !== \"string\" || currency.trim().length === 0) {\r\n throw new TypeError(\"currency must be a non-empty ISO 4217 currency code\");\r\n }\r\n\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, {\r\n style: \"currency\",\r\n currency,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Restricts a finite number to the inclusive `[min, max]` range.\r\n *\r\n * @throws {TypeError} When any argument is not a finite number.\r\n * @throws {RangeError} When `min` is greater than `max`.\r\n *\r\n * @example\r\n * clamp(15, 0, 10) // 10\r\n * clamp(-4, 0, 10) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n assertFiniteNumber(value, \"value\");\r\n assertFiniteNumber(min, \"min\");\r\n assertFiniteNumber(max, \"max\");\r\n\r\n if (min > max) {\r\n throw new RangeError(\"min must be less than or equal to max\");\r\n }\r\n\r\n return Math.min(max, Math.max(min, value));\r\n}\r\n\r\n/**\r\n * Rounds a finite number to the given number of decimal places.\r\n * Defaults to `0` decimal places.\r\n *\r\n * Uses exponential notation to reduce common binary floating-point surprises,\r\n * but IEEE 754 values still cannot represent every decimal exactly.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n * @throws {RangeError} When `decimalPlaces` is not an integer from 0 to 15.\r\n *\r\n * @example\r\n * roundTo(1.2345, 2) // 1.23\r\n * roundTo(1.5) // 2\r\n */\r\nexport function roundTo(value: number, decimalPlaces = 0): number {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (\r\n !Number.isInteger(decimalPlaces) ||\r\n decimalPlaces < 0 ||\r\n decimalPlaces > MAX_DECIMAL_PLACES\r\n ) {\r\n throw new RangeError(\r\n `decimalPlaces must be an integer between 0 and ${MAX_DECIMAL_PLACES}`,\r\n );\r\n }\r\n\r\n if (Object.is(value, -0)) {\r\n return 0;\r\n }\r\n\r\n const [significand = \"0\", exponent = \"0\"] = `${value}e`.split(\"e\");\r\n const shifted = Number(`${significand}e${Number(exponent) + decimalPlaces}`);\r\n const rounded = Math.round(shifted);\r\n const [roundedSignificand = \"0\", roundedExponent = \"0\"] = `${rounded}e`.split(\"e\");\r\n\r\n const result = Number(\r\n `${roundedSignificand}e${Number(roundedExponent) - decimalPlaces}`,\r\n );\r\n\r\n return Object.is(result, -0) ? 0 : result;\r\n}\r\n\r\n/**\r\n * Parses a positive integer. Returns `fallback` when the value is missing,\r\n * non-numeric, zero, or negative.\r\n *\r\n * @example\r\n * parsePositiveInt(\"12\", 1) // 12\r\n * parsePositiveInt(\"abc\", 1) // 1\r\n * parsePositiveInt(0, 10) // 10\r\n */\r\nexport function parsePositiveInt(value: unknown, fallback: number): number {\r\n assertFiniteNumber(fallback, \"fallback\");\r\n\r\n const parsed = typeof value === \"number\" ? value : Number.parseInt(String(value ?? \"\"), 10);\r\n\r\n return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;\r\n}\r\n\r\n/**\r\n * Converts digit-only strings to numbers and leaves everything else unchanged.\r\n * Unlike `toNumber`, invalid values are not converted to `null`.\r\n *\r\n * @example\r\n * toNumberIfValid(\"08\") // 8\r\n * toNumberIfValid(\"gold\") // \"gold\"\r\n */\r\nexport function toNumberIfValid<T>(value: T): T | number {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : value;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n const trimmed = value.trim();\r\n if (/^\\d+$/.test(trimmed)) {\r\n return Number(trimmed);\r\n }\r\n }\r\n\r\n return value;\r\n}\r\n"]}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Intl.NumberFormatOptions` plus an optional BCP 47 locale.
|
|
3
|
+
* Defaults to `en-IN` when `locale` is omitted.
|
|
4
|
+
*/
|
|
5
|
+
interface FormatNumberOptions extends Intl.NumberFormatOptions {
|
|
6
|
+
locale?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Converts a value to a finite number.
|
|
10
|
+
* Returns `null` for invalid, empty, non-finite, or locale-formatted input.
|
|
11
|
+
*
|
|
12
|
+
* Strings such as `"1,234"` are rejected because grouping separators are
|
|
13
|
+
* locale-specific and are not parsed without an explicit strategy.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* toNumber("42") // 42
|
|
17
|
+
* toNumber("1,234") // null
|
|
18
|
+
* toNumber(Number.NaN) // null
|
|
19
|
+
*/
|
|
20
|
+
declare function toNumber(value: unknown): number | null;
|
|
21
|
+
/**
|
|
22
|
+
* Formats a finite number with `Intl.NumberFormat`.
|
|
23
|
+
* Defaults to the `en-IN` locale.
|
|
24
|
+
*
|
|
25
|
+
* @throws {TypeError} When `value` is not a finite number.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* formatNumber(1234567.89) // "12,34,567.89"
|
|
29
|
+
* formatNumber(12.3456, { maximumFractionDigits: 2 }) // "12.35"
|
|
30
|
+
*/
|
|
31
|
+
declare function formatNumber(value: number, options?: FormatNumberOptions): string;
|
|
32
|
+
/**
|
|
33
|
+
* Formats a finite number as currency with `Intl.NumberFormat`.
|
|
34
|
+
* Defaults to INR in the `en-IN` locale.
|
|
35
|
+
*
|
|
36
|
+
* @throws {TypeError} When `value` is not finite or `currency`/`locale` are empty.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* formatCurrency(1500) // "₹1,500.00"
|
|
40
|
+
* formatCurrency(1500, "USD", "en-US") // "$1,500.00"
|
|
41
|
+
*/
|
|
42
|
+
declare function formatCurrency(value: number, currency?: string, locale?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Restricts a finite number to the inclusive `[min, max]` range.
|
|
45
|
+
*
|
|
46
|
+
* @throws {TypeError} When any argument is not a finite number.
|
|
47
|
+
* @throws {RangeError} When `min` is greater than `max`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* clamp(15, 0, 10) // 10
|
|
51
|
+
* clamp(-4, 0, 10) // 0
|
|
52
|
+
*/
|
|
53
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* Rounds a finite number to the given number of decimal places.
|
|
56
|
+
* Defaults to `0` decimal places.
|
|
57
|
+
*
|
|
58
|
+
* Uses exponential notation to reduce common binary floating-point surprises,
|
|
59
|
+
* but IEEE 754 values still cannot represent every decimal exactly.
|
|
60
|
+
*
|
|
61
|
+
* @throws {TypeError} When `value` is not a finite number.
|
|
62
|
+
* @throws {RangeError} When `decimalPlaces` is not an integer from 0 to 15.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* roundTo(1.2345, 2) // 1.23
|
|
66
|
+
* roundTo(1.5) // 2
|
|
67
|
+
*/
|
|
68
|
+
declare function roundTo(value: number, decimalPlaces?: number): number;
|
|
69
|
+
/**
|
|
70
|
+
* Parses a positive integer. Returns `fallback` when the value is missing,
|
|
71
|
+
* non-numeric, zero, or negative.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* parsePositiveInt("12", 1) // 12
|
|
75
|
+
* parsePositiveInt("abc", 1) // 1
|
|
76
|
+
* parsePositiveInt(0, 10) // 10
|
|
77
|
+
*/
|
|
78
|
+
declare function parsePositiveInt(value: unknown, fallback: number): number;
|
|
79
|
+
/**
|
|
80
|
+
* Converts digit-only strings to numbers and leaves everything else unchanged.
|
|
81
|
+
* Unlike `toNumber`, invalid values are not converted to `null`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* toNumberIfValid("08") // 8
|
|
85
|
+
* toNumberIfValid("gold") // "gold"
|
|
86
|
+
*/
|
|
87
|
+
declare function toNumberIfValid<T>(value: T): T | number;
|
|
88
|
+
|
|
89
|
+
export { clamp, formatCurrency, formatNumber, parsePositiveInt, roundTo, toNumber, toNumberIfValid };
|
|
90
|
+
export type { FormatNumberOptions };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `Intl.NumberFormatOptions` plus an optional BCP 47 locale.
|
|
3
|
+
* Defaults to `en-IN` when `locale` is omitted.
|
|
4
|
+
*/
|
|
5
|
+
interface FormatNumberOptions extends Intl.NumberFormatOptions {
|
|
6
|
+
locale?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Converts a value to a finite number.
|
|
10
|
+
* Returns `null` for invalid, empty, non-finite, or locale-formatted input.
|
|
11
|
+
*
|
|
12
|
+
* Strings such as `"1,234"` are rejected because grouping separators are
|
|
13
|
+
* locale-specific and are not parsed without an explicit strategy.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* toNumber("42") // 42
|
|
17
|
+
* toNumber("1,234") // null
|
|
18
|
+
* toNumber(Number.NaN) // null
|
|
19
|
+
*/
|
|
20
|
+
declare function toNumber(value: unknown): number | null;
|
|
21
|
+
/**
|
|
22
|
+
* Formats a finite number with `Intl.NumberFormat`.
|
|
23
|
+
* Defaults to the `en-IN` locale.
|
|
24
|
+
*
|
|
25
|
+
* @throws {TypeError} When `value` is not a finite number.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* formatNumber(1234567.89) // "12,34,567.89"
|
|
29
|
+
* formatNumber(12.3456, { maximumFractionDigits: 2 }) // "12.35"
|
|
30
|
+
*/
|
|
31
|
+
declare function formatNumber(value: number, options?: FormatNumberOptions): string;
|
|
32
|
+
/**
|
|
33
|
+
* Formats a finite number as currency with `Intl.NumberFormat`.
|
|
34
|
+
* Defaults to INR in the `en-IN` locale.
|
|
35
|
+
*
|
|
36
|
+
* @throws {TypeError} When `value` is not finite or `currency`/`locale` are empty.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* formatCurrency(1500) // "₹1,500.00"
|
|
40
|
+
* formatCurrency(1500, "USD", "en-US") // "$1,500.00"
|
|
41
|
+
*/
|
|
42
|
+
declare function formatCurrency(value: number, currency?: string, locale?: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Restricts a finite number to the inclusive `[min, max]` range.
|
|
45
|
+
*
|
|
46
|
+
* @throws {TypeError} When any argument is not a finite number.
|
|
47
|
+
* @throws {RangeError} When `min` is greater than `max`.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* clamp(15, 0, 10) // 10
|
|
51
|
+
* clamp(-4, 0, 10) // 0
|
|
52
|
+
*/
|
|
53
|
+
declare function clamp(value: number, min: number, max: number): number;
|
|
54
|
+
/**
|
|
55
|
+
* Rounds a finite number to the given number of decimal places.
|
|
56
|
+
* Defaults to `0` decimal places.
|
|
57
|
+
*
|
|
58
|
+
* Uses exponential notation to reduce common binary floating-point surprises,
|
|
59
|
+
* but IEEE 754 values still cannot represent every decimal exactly.
|
|
60
|
+
*
|
|
61
|
+
* @throws {TypeError} When `value` is not a finite number.
|
|
62
|
+
* @throws {RangeError} When `decimalPlaces` is not an integer from 0 to 15.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* roundTo(1.2345, 2) // 1.23
|
|
66
|
+
* roundTo(1.5) // 2
|
|
67
|
+
*/
|
|
68
|
+
declare function roundTo(value: number, decimalPlaces?: number): number;
|
|
69
|
+
/**
|
|
70
|
+
* Parses a positive integer. Returns `fallback` when the value is missing,
|
|
71
|
+
* non-numeric, zero, or negative.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* parsePositiveInt("12", 1) // 12
|
|
75
|
+
* parsePositiveInt("abc", 1) // 1
|
|
76
|
+
* parsePositiveInt(0, 10) // 10
|
|
77
|
+
*/
|
|
78
|
+
declare function parsePositiveInt(value: unknown, fallback: number): number;
|
|
79
|
+
/**
|
|
80
|
+
* Converts digit-only strings to numbers and leaves everything else unchanged.
|
|
81
|
+
* Unlike `toNumber`, invalid values are not converted to `null`.
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* toNumberIfValid("08") // 8
|
|
85
|
+
* toNumberIfValid("gold") // "gold"
|
|
86
|
+
*/
|
|
87
|
+
declare function toNumberIfValid<T>(value: T): T | number;
|
|
88
|
+
|
|
89
|
+
export { clamp, formatCurrency, formatNumber, parsePositiveInt, roundTo, toNumber, toNumberIfValid };
|
|
90
|
+
export type { FormatNumberOptions };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// src/internal/validation.ts
|
|
2
|
+
function assertFiniteNumber(value, name) {
|
|
3
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
4
|
+
throw new TypeError(`${name} must be a finite number`);
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/number/index.ts
|
|
9
|
+
var DEFAULT_LOCALE = "en-IN";
|
|
10
|
+
var DEFAULT_CURRENCY = "INR";
|
|
11
|
+
var MAX_DECIMAL_PLACES = 15;
|
|
12
|
+
var DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?$/;
|
|
13
|
+
function toNumber(value) {
|
|
14
|
+
if (typeof value === "number") {
|
|
15
|
+
return Number.isFinite(value) ? value : null;
|
|
16
|
+
}
|
|
17
|
+
if (typeof value !== "string") {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const trimmed = value.trim();
|
|
21
|
+
if (trimmed.length === 0 || /[,\s]/.test(trimmed)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const parsed = Number(trimmed);
|
|
28
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
29
|
+
}
|
|
30
|
+
function formatNumber(value, options) {
|
|
31
|
+
assertFiniteNumber(value, "value");
|
|
32
|
+
const { locale = DEFAULT_LOCALE, ...intlOptions } = options ?? {};
|
|
33
|
+
if (typeof locale !== "string" || locale.trim().length === 0) {
|
|
34
|
+
throw new TypeError("locale must be a non-empty BCP 47 locale tag");
|
|
35
|
+
}
|
|
36
|
+
return new Intl.NumberFormat(locale, intlOptions).format(value);
|
|
37
|
+
}
|
|
38
|
+
function formatCurrency(value, currency = DEFAULT_CURRENCY, locale = DEFAULT_LOCALE) {
|
|
39
|
+
assertFiniteNumber(value, "value");
|
|
40
|
+
if (typeof currency !== "string" || currency.trim().length === 0) {
|
|
41
|
+
throw new TypeError("currency must be a non-empty ISO 4217 currency code");
|
|
42
|
+
}
|
|
43
|
+
if (typeof locale !== "string" || locale.trim().length === 0) {
|
|
44
|
+
throw new TypeError("locale must be a non-empty BCP 47 locale tag");
|
|
45
|
+
}
|
|
46
|
+
return new Intl.NumberFormat(locale, {
|
|
47
|
+
style: "currency",
|
|
48
|
+
currency
|
|
49
|
+
}).format(value);
|
|
50
|
+
}
|
|
51
|
+
function clamp(value, min, max) {
|
|
52
|
+
assertFiniteNumber(value, "value");
|
|
53
|
+
assertFiniteNumber(min, "min");
|
|
54
|
+
assertFiniteNumber(max, "max");
|
|
55
|
+
if (min > max) {
|
|
56
|
+
throw new RangeError("min must be less than or equal to max");
|
|
57
|
+
}
|
|
58
|
+
return Math.min(max, Math.max(min, value));
|
|
59
|
+
}
|
|
60
|
+
function roundTo(value, decimalPlaces = 0) {
|
|
61
|
+
assertFiniteNumber(value, "value");
|
|
62
|
+
if (!Number.isInteger(decimalPlaces) || decimalPlaces < 0 || decimalPlaces > MAX_DECIMAL_PLACES) {
|
|
63
|
+
throw new RangeError(
|
|
64
|
+
`decimalPlaces must be an integer between 0 and ${MAX_DECIMAL_PLACES}`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (Object.is(value, -0)) {
|
|
68
|
+
return 0;
|
|
69
|
+
}
|
|
70
|
+
const [significand = "0", exponent = "0"] = `${value}e`.split("e");
|
|
71
|
+
const shifted = Number(`${significand}e${Number(exponent) + decimalPlaces}`);
|
|
72
|
+
const rounded = Math.round(shifted);
|
|
73
|
+
const [roundedSignificand = "0", roundedExponent = "0"] = `${rounded}e`.split("e");
|
|
74
|
+
const result = Number(
|
|
75
|
+
`${roundedSignificand}e${Number(roundedExponent) - decimalPlaces}`
|
|
76
|
+
);
|
|
77
|
+
return Object.is(result, -0) ? 0 : result;
|
|
78
|
+
}
|
|
79
|
+
function parsePositiveInt(value, fallback) {
|
|
80
|
+
assertFiniteNumber(fallback, "fallback");
|
|
81
|
+
const parsed = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
|
|
82
|
+
return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;
|
|
83
|
+
}
|
|
84
|
+
function toNumberIfValid(value) {
|
|
85
|
+
if (typeof value === "number") {
|
|
86
|
+
return Number.isFinite(value) ? value : value;
|
|
87
|
+
}
|
|
88
|
+
if (typeof value === "string") {
|
|
89
|
+
const trimmed = value.trim();
|
|
90
|
+
if (/^\d+$/.test(trimmed)) {
|
|
91
|
+
return Number(trimmed);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return value;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export { clamp, formatCurrency, formatNumber, parsePositiveInt, roundTo, toNumber, toNumberIfValid };
|
|
98
|
+
//# sourceMappingURL=index.js.map
|
|
99
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/internal/validation.ts","../../src/number/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["export function assertFiniteNumber(\r\n value: unknown,\r\n name: string,\r\n): asserts value is number {\r\n if (typeof value !== \"number\" || !Number.isFinite(value)) {\r\n throw new TypeError(`${name} must be a finite number`);\r\n }\r\n}\r\n\r\nexport function escapeRegExp(value: string): string {\r\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\r\n}\r\n","import { assertFiniteNumber } from \"../internal/validation.js\";\r\n\r\nconst DEFAULT_LOCALE = \"en-IN\";\r\nconst DEFAULT_CURRENCY = \"INR\";\r\nconst MAX_DECIMAL_PLACES = 15;\r\nconst DECIMAL_NUMBER_PATTERN = /^[+-]?(?:\\d+\\.?\\d*|\\.\\d+)(?:[eE][+-]?\\d+)?$/;\r\n\r\n/**\r\n * `Intl.NumberFormatOptions` plus an optional BCP 47 locale.\r\n * Defaults to `en-IN` when `locale` is omitted.\r\n */\r\nexport interface FormatNumberOptions extends Intl.NumberFormatOptions {\r\n locale?: string;\r\n}\r\n\r\n/**\r\n * Converts a value to a finite number.\r\n * Returns `null` for invalid, empty, non-finite, or locale-formatted input.\r\n *\r\n * Strings such as `\"1,234\"` are rejected because grouping separators are\r\n * locale-specific and are not parsed without an explicit strategy.\r\n *\r\n * @example\r\n * toNumber(\"42\") // 42\r\n * toNumber(\"1,234\") // null\r\n * toNumber(Number.NaN) // null\r\n */\r\nexport function toNumber(value: unknown): number | null {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : null;\r\n }\r\n\r\n if (typeof value !== \"string\") {\r\n return null;\r\n }\r\n\r\n const trimmed = value.trim();\r\n if (trimmed.length === 0 || /[,\\s]/.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n if (!DECIMAL_NUMBER_PATTERN.test(trimmed)) {\r\n return null;\r\n }\r\n\r\n const parsed = Number(trimmed);\r\n return Number.isFinite(parsed) ? parsed : null;\r\n}\r\n\r\n/**\r\n * Formats a finite number with `Intl.NumberFormat`.\r\n * Defaults to the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n *\r\n * @example\r\n * formatNumber(1234567.89) // \"12,34,567.89\"\r\n * formatNumber(12.3456, { maximumFractionDigits: 2 }) // \"12.35\"\r\n */\r\nexport function formatNumber(value: number, options?: FormatNumberOptions): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n const { locale = DEFAULT_LOCALE, ...intlOptions } = options ?? {};\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, intlOptions).format(value);\r\n}\r\n\r\n/**\r\n * Formats a finite number as currency with `Intl.NumberFormat`.\r\n * Defaults to INR in the `en-IN` locale.\r\n *\r\n * @throws {TypeError} When `value` is not finite or `currency`/`locale` are empty.\r\n *\r\n * @example\r\n * formatCurrency(1500) // \"₹1,500.00\"\r\n * formatCurrency(1500, \"USD\", \"en-US\") // \"$1,500.00\"\r\n */\r\nexport function formatCurrency(\r\n value: number,\r\n currency: string = DEFAULT_CURRENCY,\r\n locale: string = DEFAULT_LOCALE,\r\n): string {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (typeof currency !== \"string\" || currency.trim().length === 0) {\r\n throw new TypeError(\"currency must be a non-empty ISO 4217 currency code\");\r\n }\r\n\r\n if (typeof locale !== \"string\" || locale.trim().length === 0) {\r\n throw new TypeError(\"locale must be a non-empty BCP 47 locale tag\");\r\n }\r\n\r\n return new Intl.NumberFormat(locale, {\r\n style: \"currency\",\r\n currency,\r\n }).format(value);\r\n}\r\n\r\n/**\r\n * Restricts a finite number to the inclusive `[min, max]` range.\r\n *\r\n * @throws {TypeError} When any argument is not a finite number.\r\n * @throws {RangeError} When `min` is greater than `max`.\r\n *\r\n * @example\r\n * clamp(15, 0, 10) // 10\r\n * clamp(-4, 0, 10) // 0\r\n */\r\nexport function clamp(value: number, min: number, max: number): number {\r\n assertFiniteNumber(value, \"value\");\r\n assertFiniteNumber(min, \"min\");\r\n assertFiniteNumber(max, \"max\");\r\n\r\n if (min > max) {\r\n throw new RangeError(\"min must be less than or equal to max\");\r\n }\r\n\r\n return Math.min(max, Math.max(min, value));\r\n}\r\n\r\n/**\r\n * Rounds a finite number to the given number of decimal places.\r\n * Defaults to `0` decimal places.\r\n *\r\n * Uses exponential notation to reduce common binary floating-point surprises,\r\n * but IEEE 754 values still cannot represent every decimal exactly.\r\n *\r\n * @throws {TypeError} When `value` is not a finite number.\r\n * @throws {RangeError} When `decimalPlaces` is not an integer from 0 to 15.\r\n *\r\n * @example\r\n * roundTo(1.2345, 2) // 1.23\r\n * roundTo(1.5) // 2\r\n */\r\nexport function roundTo(value: number, decimalPlaces = 0): number {\r\n assertFiniteNumber(value, \"value\");\r\n\r\n if (\r\n !Number.isInteger(decimalPlaces) ||\r\n decimalPlaces < 0 ||\r\n decimalPlaces > MAX_DECIMAL_PLACES\r\n ) {\r\n throw new RangeError(\r\n `decimalPlaces must be an integer between 0 and ${MAX_DECIMAL_PLACES}`,\r\n );\r\n }\r\n\r\n if (Object.is(value, -0)) {\r\n return 0;\r\n }\r\n\r\n const [significand = \"0\", exponent = \"0\"] = `${value}e`.split(\"e\");\r\n const shifted = Number(`${significand}e${Number(exponent) + decimalPlaces}`);\r\n const rounded = Math.round(shifted);\r\n const [roundedSignificand = \"0\", roundedExponent = \"0\"] = `${rounded}e`.split(\"e\");\r\n\r\n const result = Number(\r\n `${roundedSignificand}e${Number(roundedExponent) - decimalPlaces}`,\r\n );\r\n\r\n return Object.is(result, -0) ? 0 : result;\r\n}\r\n\r\n/**\r\n * Parses a positive integer. Returns `fallback` when the value is missing,\r\n * non-numeric, zero, or negative.\r\n *\r\n * @example\r\n * parsePositiveInt(\"12\", 1) // 12\r\n * parsePositiveInt(\"abc\", 1) // 1\r\n * parsePositiveInt(0, 10) // 10\r\n */\r\nexport function parsePositiveInt(value: unknown, fallback: number): number {\r\n assertFiniteNumber(fallback, \"fallback\");\r\n\r\n const parsed = typeof value === \"number\" ? value : Number.parseInt(String(value ?? \"\"), 10);\r\n\r\n return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback;\r\n}\r\n\r\n/**\r\n * Converts digit-only strings to numbers and leaves everything else unchanged.\r\n * Unlike `toNumber`, invalid values are not converted to `null`.\r\n *\r\n * @example\r\n * toNumberIfValid(\"08\") // 8\r\n * toNumberIfValid(\"gold\") // \"gold\"\r\n */\r\nexport function toNumberIfValid<T>(value: T): T | number {\r\n if (typeof value === \"number\") {\r\n return Number.isFinite(value) ? value : value;\r\n }\r\n\r\n if (typeof value === \"string\") {\r\n const trimmed = value.trim();\r\n if (/^\\d+$/.test(trimmed)) {\r\n return Number(trimmed);\r\n }\r\n }\r\n\r\n return value;\r\n}\r\n"]}
|