intl-currency-helper 1.0.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/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # Intl Currency Helper
2
+
3
+ A lightweight, zero-dependency JavaScript library for formatting numbers to currency strings using the native `Intl.NumberFormat` API. Compatible with both **Node.js** and **React**.
4
+
5
+ ## Features
6
+
7
+ - ๐Ÿ“‚ **Universal**: Works in the browser and Node.js.
8
+ - ๐Ÿ‡ฒ๐Ÿ‡ฝ **Smart Defaults**: Pre-configured for Mexican Peso (`MXN`) and Spanish (Mexico) (`es-MX`).
9
+ - ๐Ÿ› ๏ธ **Customizable**: Easy to override currency, locale, and decimal precision.
10
+ - ๐Ÿงช **Safe**: Includes input validation.
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ # If you published it to NPM
16
+ npm install intl-currency-helper
17
+ ```
18
+
19
+ Or just copy the files into your project.
20
+
21
+ ## Usage
22
+
23
+ ### Basic Usage (ES Modules)
24
+
25
+ ```javascript
26
+ import { formatCurrency } from './index.js';
27
+
28
+ // Default: MXN / es-MX
29
+ console.log(formatCurrency(1234.56)); // Output: "$1,234.56"
30
+ console.log(formatCurrency("100")); // Output: "$100.00"
31
+ ```
32
+
33
+ ### Advanced Usage
34
+
35
+ You can customize the formatting by passing an options object.
36
+
37
+ ```javascript
38
+ import { formatCurrency, CURRENCIES, LOCALES } from './index.js';
39
+
40
+ // US Dollars
41
+ formatCurrency(1234.56, {
42
+ currency: CURRENCIES.USD,
43
+ locale: LOCALES.US
44
+ });
45
+ // Output: "$1,234.56"
46
+
47
+ // Euros in Spain
48
+ formatCurrency(1234.56, {
49
+ currency: CURRENCIES.EUR,
50
+ locale: LOCALES.ES
51
+ });
52
+ // Output: "1.234,56 โ‚ฌ"
53
+
54
+ // No decimals
55
+ formatCurrency(1234.56, {
56
+ minimumFractionDigits: 0,
57
+ maximumFractionDigits: 0
58
+ });
59
+ // Output: "$1,235"
60
+ ```
61
+
62
+ ## API
63
+
64
+ ### `formatCurrency(amount, options)`
65
+
66
+ | Argument | Type | Description |
67
+ | :--- | :--- | :--- |
68
+ | `amount` | `Number`\|`String` | The value to format. |
69
+ | `options` | `Object` | (Optional) Configuration object. |
70
+
71
+ #### Options
72
+ - `locale` (String): BCP 47 language tag (default: `'es-MX'`).
73
+ - `currency` (String): ISO 4217 currency code (default: `'MXN'`).
74
+ - `minimumFractionDigits` (Number): Default `2`.
75
+ - `maximumFractionDigits` (Number): Default `2`.
76
+ - `useGrouping` (Boolean): Whether to use thousand separators (default: `true`).
77
+
78
+ ## License
79
+
80
+ MIT
package/index.js ADDED
@@ -0,0 +1,48 @@
1
+ import { validateNumber, normalizeOptions } from './utils.js';
2
+
3
+ /**
4
+ * Formats a number into a currency string using Intl.NumberFormat.
5
+ *
6
+ * @param {number|string} amount - The numeric value to format.
7
+ * @param {object} [options] - Optional configuration.
8
+ * @param {string} [options.locale='es-MX'] - The BCP 47 language tag (e.g., 'es-MX', 'en-US').
9
+ * @param {string} [options.currency='MXN'] - The ISO 4217 currency code (e.g., 'MXN', 'USD', 'EUR').
10
+ * @param {number} [options.minimumFractionDigits=2] - Minimum number of decimal places.
11
+ * @param {number} [options.maximumFractionDigits=2] - Maximum number of decimal places.
12
+ * @param {boolean} [options.useGrouping=true] - Whether to use thousand separators.
13
+ * @returns {string} The formatted currency string.
14
+ * @example
15
+ * formatCurrency(1234.56) // "$1,234.56" (default MXN)
16
+ * formatCurrency(1234.56, { currency: 'USD', locale: 'en-US' }) // "$1,234.56"
17
+ */
18
+ export const formatCurrency = (amount, options = {}) => {
19
+ const number = validateNumber(amount);
20
+ const config = normalizeOptions(options);
21
+
22
+ return new Intl.NumberFormat(config.locale, config).format(number);
23
+ };
24
+
25
+ /**
26
+ * Common currency codes for easy reference.
27
+ */
28
+ export const CURRENCIES = {
29
+ MXN: 'MXN',
30
+ USD: 'USD',
31
+ EUR: 'EUR',
32
+ GBP: 'GBP',
33
+ CAD: 'CAD',
34
+ JPY: 'JPY',
35
+ };
36
+
37
+ /**
38
+ * Common locales for easy reference.
39
+ */
40
+ export const LOCALES = {
41
+ MX: 'es-MX',
42
+ US: 'en-US',
43
+ ES: 'es-ES',
44
+ GB: 'en-GB',
45
+ JP: 'ja-JP',
46
+ };
47
+
48
+ export default formatCurrency;
package/package.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "intl-currency-helper",
3
+ "version": "1.0.0",
4
+ "description": "A lightweight library for formatting numbers to currency using Intl.NumberFormat, optimized for both Node.js and React.",
5
+ "main": "index.js",
6
+ "type": "module",
7
+ "scripts": {
8
+ "test": "node test.js"
9
+ },
10
+ "keywords": [
11
+ "currency",
12
+ "format",
13
+ "intl",
14
+ "money",
15
+ "react",
16
+ "nodejs"
17
+ ],
18
+ "author": "Antigravity",
19
+ "license": "MIT"
20
+ }
package/test.js ADDED
@@ -0,0 +1,78 @@
1
+ import { formatCurrency, CURRENCIES, LOCALES } from './index.js';
2
+
3
+ const tests = [
4
+ {
5
+ name: 'Default formatting (MXN / es-MX)',
6
+ input: 1234.56,
7
+ expected: '$1,234.56', // Note: specific spacing can vary by environment, we'll check contains
8
+ },
9
+ {
10
+ name: 'USD / en-US',
11
+ input: 1234.56,
12
+ options: { currency: CURRENCIES.USD, locale: LOCALES.US },
13
+ expected: '$1,234.56',
14
+ },
15
+ {
16
+ name: 'EUR / es-ES',
17
+ input: 1234.56,
18
+ options: { currency: CURRENCIES.EUR, locale: LOCALES.ES },
19
+ expected: '1.234,56\u00A0โ‚ฌ', // Note: \u00A0 is non-breaking space
20
+ },
21
+ {
22
+ name: 'Negative number',
23
+ input: -500,
24
+ expected: '-$500.00',
25
+ },
26
+ {
27
+ name: 'Zero',
28
+ input: 0,
29
+ expected: '$0.00',
30
+ },
31
+ {
32
+ name: 'String input',
33
+ input: "99.99",
34
+ expected: '$99.99',
35
+ }
36
+ ];
37
+
38
+ let passed = 0;
39
+ let total = tests.length;
40
+
41
+ console.log('--- Starting Tests ---\n');
42
+
43
+ tests.forEach(test => {
44
+ try {
45
+ const result = formatCurrency(test.input, test.options);
46
+ // Use includes/regex/normalize to avoid tiny formatting discrepancies in different environments (like nbsp)
47
+ const normalizedResult = result.replace(/\u00A0/g, ' ').trim();
48
+ const normalizedExpected = test.expected.replace(/\u00A0/g, ' ').trim();
49
+
50
+ if (normalizedResult === normalizedExpected || normalizedResult.includes(normalizedExpected)) {
51
+ console.log(`โœ… [PASS] ${test.name}`);
52
+ passed++;
53
+ } else {
54
+ console.log(`โŒ [FAIL] ${test.name}`);
55
+ console.log(` Expected: ${test.expected}`);
56
+ console.log(` Received: ${result}`);
57
+ }
58
+ } catch (error) {
59
+ console.log(`โŒ [ERROR] ${test.name}: ${error.message}`);
60
+ }
61
+ });
62
+
63
+ // Error handling test
64
+ console.log('\n--- Error Handling Test ---');
65
+ try {
66
+ formatCurrency('not-a-number');
67
+ console.log('โŒ [FAIL] Should have thrown an error for invalid input');
68
+ } catch (error) {
69
+ console.log('โœ… [PASS] Threw error for invalid input: ' + error.message);
70
+ }
71
+
72
+ console.log(`\n--- Summary: ${passed}/${total} passed ---`);
73
+
74
+ if (passed === total) {
75
+ process.exit(0);
76
+ } else {
77
+ process.exit(1);
78
+ }
package/utils.js ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Validates if the input is a valid number.
3
+ * @param {any} value - The value to validate.
4
+ * @returns {number} The validated number.
5
+ * @throws {Error} if the value is not a valid number.
6
+ */
7
+ export const validateNumber = (value) => {
8
+ const number = Number(value);
9
+ if (isNaN(number)) {
10
+ throw new Error(`Invalid input: expected a number, but received ${typeof value} (${value})`);
11
+ }
12
+ return number;
13
+ };
14
+
15
+ /**
16
+ * Normalizes options for Intl.NumberFormat.
17
+ * @param {object} options - User-provided options.
18
+ * @returns {object} Normalized options.
19
+ */
20
+ export const normalizeOptions = (options = {}) => {
21
+ const defaults = {
22
+ locale: 'es-MX',
23
+ currency: 'MXN',
24
+ minimumFractionDigits: 2,
25
+ maximumFractionDigits: 2,
26
+ style: 'currency',
27
+ useGrouping: true,
28
+ };
29
+
30
+ return { ...defaults, ...options };
31
+ };