nhb-toolbox 4.20.91 → 4.21.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/CHANGELOG.md CHANGED
@@ -6,6 +6,15 @@ All notable changes to the package will be documented here.
6
6
 
7
7
  ---
8
8
 
9
+ ## [4.21.0] - 2025-10-12
10
+
11
+ - **Renamed** `RomanNumeralCap` type to `RomanCapital` and allow only strict `1-3999` and `RomanNumeral` type to `LooseRomanNumeral`.
12
+ - **Removed** all _Roman numeral type helpers_ and **recreated** a _strict_ `RomanNumeral` with other _internal types_.
13
+
14
+ ## [4.20.92] - 2025-10-12
15
+
16
+ - **Fixed** `RomanNumeralCap` type and **added** _@remarks_ section.
17
+
9
18
  ## [4.20.91] - 2025-10-12
10
19
 
11
20
  - **Updated** _tsdoc_ for `fromNow()` `Chronos` method: modified _@remarks_ section.
@@ -37,8 +37,8 @@ function numberToWords(num) {
37
37
  }
38
38
  const convertToRomanNumerals = (value) => {
39
39
  let num = (0, utilities_1.normalizeNumber)(value);
40
- if (!num || num <= 0 || num >= 4000) {
41
- throw new RangeError('Number must be between 1 and 3999');
40
+ if (!(0, primitives_1.isInteger)(num) || num <= 0 || num >= 4000) {
41
+ throw new RangeError('Value must be an integer and between 1 and 3999');
42
42
  }
43
43
  const romanMap = [
44
44
  [1000, 'M'],
@@ -1,5 +1,5 @@
1
1
  import type { Numeric } from '../types/index';
2
- import type { RomanNumeral, RomanNumeralCap } from './types';
2
+ import type { LooseRomanNumeral, RomanCapital } from './types';
3
3
  /**
4
4
  * * Converts a numeric value into its corresponding English word representation.
5
5
  * @warning ***Supports numeric values up to `10e19` or `10^20` (one hundred quintillion).***
@@ -9,23 +9,23 @@ import type { RomanNumeral, RomanNumeralCap } from './types';
9
9
  */
10
10
  export declare function numberToWords(num: Numeric): string;
11
11
  /**
12
- * * Converts a number to a Roman numeral.
13
- * @param value - The number to convert. Number must be `between 1 and 3999`.
14
- * @returns The Roman numeral representation.
12
+ * * Converts a number to an uppercase Roman numeral.
13
+ * @param value - The number to convert. Number must be an integer and `between 1 and 3999`.
14
+ * @returns The Roman numeral representation in uppercase.
15
15
  *
16
- * @example convertToRomanNumerals(29) → "XXIX"
16
+ * @example convertToRomanNumerals(29) // → "XXIX"
17
17
  */
18
- export declare const convertToRomanNumerals: (value: Numeric) => RomanNumeralCap;
18
+ export declare const convertToRomanNumerals: (value: Numeric) => RomanCapital;
19
19
  /**
20
20
  * * Converts a Roman numeral to its Arabic numeric representation.
21
- * @param roman - The Roman numeral to convert. Case-insensitive but must represent a valid Roman numeral (IMMMCMXCIX) otherwise throws error.
22
- * @returns The numeric (Arabic) representation.
21
+ * @param roman - The Roman numeral to convert. Case-insensitive but must represent a valid Roman numeral (`I`–`MMMCMXCIX`) otherwise throws runtime error.
22
+ * @returns The numeric (Arabic) representation of the Roman numeral.
23
23
  *
24
24
  * @example
25
- * romanToInteger("XXIX") → 29
26
- * romanToInteger("mmxxv") → 2025
25
+ * romanToInteger("XXIX") // → 29
26
+ * romanToInteger("mmxxv") // → 2025
27
27
  */
28
- export declare const romanToInteger: (roman: RomanNumeral) => number;
28
+ export declare const romanToInteger: (roman: LooseRomanNumeral) => number;
29
29
  /**
30
30
  * * Converts a number, numeric string, or cardinal word string into its ordinal word representation.
31
31
  *
@@ -1,4 +1,4 @@
1
- import type { LooseLiteral, Repeat } from '../utils/types';
1
+ import type { LooseLiteral } from '../utils/types';
2
2
  import type { CURRENCY_CODES, CURRENCY_LOCALES, LOCALE_CODES, PREFIX_MULTIPLIERS, SUPPORTED_CURRENCIES, UNITS } from './constants';
3
3
  import type { Unit } from './Unit';
4
4
  /** Enumerate & Enumerate Internal: builds a union of all numbers from 0 to N - 1 */
@@ -166,60 +166,49 @@ export type UnitKey = keyof typeof UNITS;
166
166
  export type UnitLabel = (typeof UNITS)[UnitKey];
167
167
  /** - Prefixes for SI units */
168
168
  export type SIPrefix = keyof typeof PREFIX_MULTIPLIERS;
169
+ /** Roman numerals representing only the thousand (1000, 2000 and 3000) */
170
+ type $Thousands = '' | 'M' | 'MM' | 'MMM';
171
+ /** Roman numerals representing only the hundreds (100, 200, ... 900) */
172
+ type $Hundreds = '' | 'C' | 'CC' | 'CCC' | 'CD' | 'D' | 'DC' | 'DCC' | 'DCCC' | 'CM';
173
+ /** Roman numerals representing only the tens (10, 20, ... 90) */
174
+ type $Tens = '' | 'X' | 'XX' | 'XXX' | 'XL' | 'L' | 'LX' | 'LXX' | 'LXXX' | 'XC';
175
+ /** Roman numerals representing only the ones (1-9) */
176
+ type $Ones = '' | 'I' | 'II' | 'III' | 'IV' | 'V' | 'VI' | 'VII' | 'VIII' | 'IX';
177
+ /** Roman numerals representing the combination of thousands, hundreds, tens and ones */
178
+ type $RawRoman = `${$Thousands}${$Hundreds}${$Tens}${$Ones}`;
169
179
  /**
170
- * * Roman numeral base letters (upper-case only).
180
+ * * Literal type representing every valid Roman numeral (uppercase) from 1 to 3999 (I .. MMMCMXCIX).
171
181
  *
172
- * Includes:
173
- * - `I` 1
174
- * - `V` 5
175
- * - `X` 10
176
- * - `L` → 50
177
- * - `C` → 100
178
- * - `D` → 500
179
- * - `M` → 1000
182
+ * @example
183
+ * const a: RomanCapital = "MMXXV"; // ✅ OK
184
+ * const b: RomanCapital = "MMMM"; // 🛑 Error (4000 not allowed)
185
+ * const c: RomanCapital = ""; // 🛑 Error (0 not allowed)
180
186
  */
181
- export type $RomanBase = 'I' | 'V' | 'X' | 'L' | 'C' | 'D' | 'M';
187
+ export type RomanCapital = Exclude<$RawRoman, ''>;
182
188
  /**
183
- * * Represents repeated Roman numeral sequences (1–5 characters long), enabling IntelliSense autocompletion for sequential Roman characters.
184
- *
185
- * - Suggests Roman base letters after each character.
186
- * - Supports up to 5-character combinations for performance.
187
- * - Does **not** validate Roman numeral correctness (e.g., `VVVV` is allowed).
189
+ * * Strict Roman numeral in both literal lower and uppercase (1-3999).
188
190
  *
189
191
  * @example
190
192
  * ```ts
191
- * // Valid according to type (even if not a real Roman numeral)
192
- * const a: $RomanRepeated = 'MMXII';
193
- * const b: $RomanRepeated = 'VVVV';
193
+ * const a: RomanNumeral = 'xiv'; // Lowercase: OK
194
+ * const b: RomanNumeral = 'MMX'; // ✅ Uppercase: OK
195
+ * const c: RomanNumeral = 'xyz'; // 🛑 Invalid: Error (xyz not allowed)
194
196
  * ```
195
- *
196
- * @remarks
197
- * **Limitations:**
198
- * - Only supports up to **5-character** combinations (`Repeat<$RomanBase, 5>`) using {@link Repeat}.
199
- * - Increasing beyond 5 leads to TypeScript recursion/union complexity issues.
200
- * - Designed purely for **editor IntelliSense**, not runtime validation.
201
197
  */
202
- export type $RomanNumeralCap = $RomanBase | Repeat<$RomanBase, 2> | Repeat<$RomanBase, 3> | Repeat<$RomanBase, 4> | Repeat<$RomanBase, 5>;
203
- /** * Represents repeated Roman numeral sequences (1–5 characters long) in uppercase letters and any string */
204
- export type RomanNumeralCap = Uppercase<LooseLiteral<$RomanNumeralCap>>;
198
+ export type RomanNumeral = RomanCapital | Lowercase<RomanCapital>;
205
199
  /**
206
- * * Comprehensive Roman numeral string type.
207
- *
208
- * Includes both upper and lowercase Roman letters, with support for loose
209
- * literal fallbacks (via {@link LooseLiteral}) to accept arbitrary strings
210
- * while still providing IntelliSense suggestions for known Roman combinations.
200
+ * * Comprehensive valid Roman numeral in both literal lower and uppercase (1-3999) & any string type.
211
201
  *
212
202
  * @example
213
203
  * ```ts
214
- * const a: RomanNumeral = 'xiv'; // ✅ IntelliSense suggests Roman letters
215
- * const b: RomanNumeral = 'MMX'; // ✅ Supported
216
- * const c: RomanNumeral = 'xyz'; // ⚠️ Allowed only via LooseLiteral fallback
204
+ * const a: LooseRomanNumeral = 'xiv'; // ✅ IntelliSense suggests Roman letters
205
+ * const b: LooseRomanNumeral = 'MMX'; // ✅ Supported
206
+ * const c: LooseRomanNumeral = 'xyz'; // ⚠️ Allowed only via LooseLiteral fallback
217
207
  * ```
218
208
  *
219
209
  * @remarks
220
- * - Combines {@link $RomanNumeralCap} and its lowercase variants.
210
+ * - Combines {@link RomanCapital} and its lowercase variants, see {@link RomanNumeral}.
221
211
  * - The {@link LooseLiteral} wrapper allows non-literal strings (e.g., variables) without losing IntelliSense for literals.
222
- * - Does not enforce valid Roman numeral formation.
223
212
  */
224
- export type RomanNumeral = LooseLiteral<$RomanNumeralCap | Lowercase<$RomanNumeralCap>>;
213
+ export type LooseRomanNumeral = LooseLiteral<RomanNumeral>;
225
214
  export {};
@@ -1,4 +1,4 @@
1
- import { isNonEmptyString, isNumber } from '../guards/primitives.js';
1
+ import { isInteger, isNonEmptyString, isNumber } from '../guards/primitives.js';
2
2
  import { isNumericString } from '../guards/specials.js';
3
3
  import { ONES, ORDINAL_TO_CARDINAL, ORDINAL_UNDER_TEEN, TEENS, TENS, THOUSANDS, } from './constants.js';
4
4
  import { _convertLessThanThousand } from './helpers.js';
@@ -31,8 +31,8 @@ export function numberToWords(num) {
31
31
  }
32
32
  export const convertToRomanNumerals = (value) => {
33
33
  let num = normalizeNumber(value);
34
- if (!num || num <= 0 || num >= 4000) {
35
- throw new RangeError('Number must be between 1 and 3999');
34
+ if (!isInteger(num) || num <= 0 || num >= 4000) {
35
+ throw new RangeError('Value must be an integer and between 1 and 3999');
36
36
  }
37
37
  const romanMap = [
38
38
  [1000, 'M'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nhb-toolbox",
3
- "version": "4.20.91",
3
+ "version": "4.21.0",
4
4
  "description": "A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",