subunit-money 2.1.1 → 3.1.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.
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Currency registry and types.
3
+ * Manages ISO 4217 currency definitions and custom currencies.
4
+ */
5
+ export interface CurrencyDefinition {
6
+ code: string;
7
+ decimalDigits: number;
8
+ }
9
+ /**
10
+ * Register a new currency or update an existing one.
11
+ * @param code - ISO 4217 currency code (e.g., 'USD', 'EUR', 'BTC')
12
+ * @param decimalDigits - Number of decimal places (e.g., 2 for USD, 8 for BTC)
13
+ */
14
+ export declare function registerCurrency(code: string, decimalDigits: number): void;
15
+ /**
16
+ * Get a currency definition by code.
17
+ * @returns The currency definition, or undefined if not registered
18
+ */
19
+ export declare function getCurrency(code: string): CurrencyDefinition | undefined;
20
+ /**
21
+ * Check if a currency is registered.
22
+ */
23
+ export declare function hasCurrency(code: string): boolean;
24
+ /**
25
+ * Get all registered currencies, sorted by code.
26
+ */
27
+ export declare function getAllCurrencies(): CurrencyDefinition[];
28
+ /**
29
+ * Load currencies from the legacy currencymap.json format.
30
+ * @param map - Object with currency codes as keys and {decimal_digits: number} as values
31
+ */
32
+ export declare function loadCurrencyMap(map: Record<string, {
33
+ decimal_digits: number;
34
+ }>): void;
35
+ /**
36
+ * Clear all registered currencies. Useful for testing.
37
+ */
38
+ export declare function clearCurrencies(): void;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ /**
3
+ * Currency registry and types.
4
+ * Manages ISO 4217 currency definitions and custom currencies.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.registerCurrency = registerCurrency;
8
+ exports.getCurrency = getCurrency;
9
+ exports.hasCurrency = hasCurrency;
10
+ exports.getAllCurrencies = getAllCurrencies;
11
+ exports.loadCurrencyMap = loadCurrencyMap;
12
+ exports.clearCurrencies = clearCurrencies;
13
+ // Internal registry - mutable for registerCurrency()
14
+ const currencies = new Map();
15
+ /**
16
+ * Register a new currency or update an existing one.
17
+ * @param code - ISO 4217 currency code (e.g., 'USD', 'EUR', 'BTC')
18
+ * @param decimalDigits - Number of decimal places (e.g., 2 for USD, 8 for BTC)
19
+ */
20
+ function registerCurrency(code, decimalDigits) {
21
+ currencies.set(code, { code, decimalDigits });
22
+ }
23
+ /**
24
+ * Get a currency definition by code.
25
+ * @returns The currency definition, or undefined if not registered
26
+ */
27
+ function getCurrency(code) {
28
+ return currencies.get(code);
29
+ }
30
+ /**
31
+ * Check if a currency is registered.
32
+ */
33
+ function hasCurrency(code) {
34
+ return currencies.has(code);
35
+ }
36
+ /**
37
+ * Get all registered currencies, sorted by code.
38
+ */
39
+ function getAllCurrencies() {
40
+ return Array.from(currencies.values()).sort((a, b) => a.code.localeCompare(b.code));
41
+ }
42
+ /**
43
+ * Load currencies from the legacy currencymap.json format.
44
+ * @param map - Object with currency codes as keys and {decimal_digits: number} as values
45
+ */
46
+ function loadCurrencyMap(map) {
47
+ for (const [code, data] of Object.entries(map)) {
48
+ registerCurrency(code, data.decimal_digits);
49
+ }
50
+ }
51
+ /**
52
+ * Clear all registered currencies. Useful for testing.
53
+ */
54
+ function clearCurrencies() {
55
+ currencies.clear();
56
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Custom error types for Money operations.
3
+ * All errors extend built-in Error types for proper instanceof checks.
4
+ */
5
+ /**
6
+ * Thrown when attempting operations between different currencies.
7
+ * @example
8
+ * new Money('USD', 10).add(new Money('EUR', 5)) // throws CurrencyMismatchError
9
+ */
10
+ export declare class CurrencyMismatchError extends TypeError {
11
+ readonly fromCurrency: string;
12
+ readonly toCurrency: string;
13
+ constructor(fromCurrency: string, toCurrency: string);
14
+ }
15
+ /**
16
+ * Thrown when using an unregistered currency code.
17
+ * @example
18
+ * new Money('FAKE', 10) // throws CurrencyUnknownError
19
+ */
20
+ export declare class CurrencyUnknownError extends TypeError {
21
+ readonly currency: string;
22
+ constructor(currency: string);
23
+ }
24
+ /**
25
+ * Thrown when an amount has more decimal places than the currency allows.
26
+ * @example
27
+ * new Money('USD', '1.234') // throws SubunitError (USD only allows 2 decimals)
28
+ */
29
+ export declare class SubunitError extends RangeError {
30
+ readonly currency: string;
31
+ readonly maxDecimals: number;
32
+ constructor(currency: string, maxDecimals: number);
33
+ }
34
+ /**
35
+ * Thrown when an amount cannot be parsed as a valid number.
36
+ * @example
37
+ * new Money('USD', 'abc') // throws AmountError
38
+ */
39
+ export declare class AmountError extends TypeError {
40
+ readonly amount: unknown;
41
+ constructor(amount: unknown);
42
+ }
43
+ /**
44
+ * Thrown when an exchange rate is not available.
45
+ * @example
46
+ * converter.convert(usdMoney, 'XYZ') // throws ExchangeRateError if no USD->XYZ rate
47
+ */
48
+ export declare class ExchangeRateError extends Error {
49
+ readonly fromCurrency: string;
50
+ readonly toCurrency: string;
51
+ constructor(fromCurrency: string, toCurrency: string);
52
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ /**
3
+ * Custom error types for Money operations.
4
+ * All errors extend built-in Error types for proper instanceof checks.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.ExchangeRateError = exports.AmountError = exports.SubunitError = exports.CurrencyUnknownError = exports.CurrencyMismatchError = void 0;
8
+ /**
9
+ * Thrown when attempting operations between different currencies.
10
+ * @example
11
+ * new Money('USD', 10).add(new Money('EUR', 5)) // throws CurrencyMismatchError
12
+ */
13
+ class CurrencyMismatchError extends TypeError {
14
+ constructor(fromCurrency, toCurrency) {
15
+ super(`Cannot operate on ${fromCurrency} and ${toCurrency} - currencies must match`);
16
+ this.name = 'CurrencyMismatchError';
17
+ this.fromCurrency = fromCurrency;
18
+ this.toCurrency = toCurrency;
19
+ Error.captureStackTrace?.(this, CurrencyMismatchError);
20
+ }
21
+ }
22
+ exports.CurrencyMismatchError = CurrencyMismatchError;
23
+ /**
24
+ * Thrown when using an unregistered currency code.
25
+ * @example
26
+ * new Money('FAKE', 10) // throws CurrencyUnknownError
27
+ */
28
+ class CurrencyUnknownError extends TypeError {
29
+ constructor(currency) {
30
+ super(`Unknown currency '${currency}' - register it first with Money.registerCurrency()`);
31
+ this.name = 'CurrencyUnknownError';
32
+ this.currency = currency;
33
+ Error.captureStackTrace?.(this, CurrencyUnknownError);
34
+ }
35
+ }
36
+ exports.CurrencyUnknownError = CurrencyUnknownError;
37
+ /**
38
+ * Thrown when an amount has more decimal places than the currency allows.
39
+ * @example
40
+ * new Money('USD', '1.234') // throws SubunitError (USD only allows 2 decimals)
41
+ */
42
+ class SubunitError extends RangeError {
43
+ constructor(currency, maxDecimals) {
44
+ super(`${currency} only supports ${maxDecimals} decimal place(s)`);
45
+ this.name = 'SubunitError';
46
+ this.currency = currency;
47
+ this.maxDecimals = maxDecimals;
48
+ Error.captureStackTrace?.(this, SubunitError);
49
+ }
50
+ }
51
+ exports.SubunitError = SubunitError;
52
+ /**
53
+ * Thrown when an amount cannot be parsed as a valid number.
54
+ * @example
55
+ * new Money('USD', 'abc') // throws AmountError
56
+ */
57
+ class AmountError extends TypeError {
58
+ constructor(amount) {
59
+ super(`Invalid amount: ${JSON.stringify(amount)}`);
60
+ this.name = 'AmountError';
61
+ this.amount = amount;
62
+ Error.captureStackTrace?.(this, AmountError);
63
+ }
64
+ }
65
+ exports.AmountError = AmountError;
66
+ /**
67
+ * Thrown when an exchange rate is not available.
68
+ * @example
69
+ * converter.convert(usdMoney, 'XYZ') // throws ExchangeRateError if no USD->XYZ rate
70
+ */
71
+ class ExchangeRateError extends Error {
72
+ constructor(fromCurrency, toCurrency) {
73
+ super(`No exchange rate available from ${fromCurrency} to ${toCurrency}`);
74
+ this.name = 'ExchangeRateError';
75
+ this.fromCurrency = fromCurrency;
76
+ this.toCurrency = toCurrency;
77
+ Error.captureStackTrace?.(this, ExchangeRateError);
78
+ }
79
+ }
80
+ exports.ExchangeRateError = ExchangeRateError;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Exchange Rate Service - Central authority for currency conversion rates.
3
+ *
4
+ * Design principles:
5
+ * - Rates are stored as strings to preserve precision
6
+ * - Timestamps track when rates were set
7
+ * - Optional source tracking for audit trails
8
+ * - Inverse rates can be auto-generated or explicitly set
9
+ */
10
+ export interface ExchangeRate {
11
+ from: string;
12
+ to: string;
13
+ rate: string;
14
+ timestamp: Date;
15
+ source?: string;
16
+ }
17
+ export interface RatePair {
18
+ forward: ExchangeRate;
19
+ reverse: ExchangeRate;
20
+ /** Relative discrepancy between forward and 1/reverse rates */
21
+ discrepancy: number;
22
+ }
23
+ /**
24
+ * Service for managing exchange rates between currencies.
25
+ *
26
+ * @example
27
+ * const rates = new ExchangeRateService()
28
+ * rates.setRate('USD', 'EUR', 0.92, 'ECB')
29
+ * rates.getRate('USD', 'EUR') // { from: 'USD', to: 'EUR', rate: '0.92', ... }
30
+ */
31
+ export declare class ExchangeRateService {
32
+ #private;
33
+ /**
34
+ * Set an exchange rate.
35
+ *
36
+ * @param from - Source currency code
37
+ * @param to - Target currency code
38
+ * @param rate - Exchange rate (1 unit of 'from' = rate units of 'to')
39
+ * @param source - Optional source identifier (e.g., 'ECB', 'Coinbase')
40
+ * @param autoInverse - If true, automatically create inverse rate (default: true)
41
+ */
42
+ setRate(from: string, to: string, rate: number | string, source?: string, autoInverse?: boolean): void;
43
+ /**
44
+ * Get an exchange rate.
45
+ *
46
+ * @param from - Source currency code
47
+ * @param to - Target currency code
48
+ * @returns The exchange rate, or undefined if not set
49
+ */
50
+ getRate(from: string, to: string): ExchangeRate | undefined;
51
+ /**
52
+ * Check if a rate exists.
53
+ */
54
+ hasRate(from: string, to: string): boolean;
55
+ /**
56
+ * Remove a rate.
57
+ */
58
+ removeRate(from: string, to: string): boolean;
59
+ /**
60
+ * Get both forward and reverse rates, with discrepancy analysis.
61
+ * Useful for detecting rate inconsistencies.
62
+ *
63
+ * @param currencyA - First currency
64
+ * @param currencyB - Second currency
65
+ * @returns Rate pair with discrepancy, or undefined if either rate is missing
66
+ */
67
+ getRatePair(currencyA: string, currencyB: string): RatePair | undefined;
68
+ /**
69
+ * Get all rates for a specific base currency.
70
+ *
71
+ * @param base - The base currency code
72
+ * @returns Array of rates from this currency
73
+ */
74
+ getRatesFrom(base: string): ExchangeRate[];
75
+ /**
76
+ * Get all registered rates.
77
+ */
78
+ getAllRates(): ExchangeRate[];
79
+ /**
80
+ * Clear all rates.
81
+ */
82
+ clear(): void;
83
+ /**
84
+ * Load rates from a simple object.
85
+ *
86
+ * @param rates - Object where keys are "FROM:TO" and values are rates
87
+ * @param source - Optional source identifier
88
+ *
89
+ * @example
90
+ * service.loadRates({
91
+ * 'USD:EUR': 0.92,
92
+ * 'USD:GBP': 0.79,
93
+ * }, 'daily-update')
94
+ */
95
+ loadRates(rates: Record<string, number | string>, source?: string): void;
96
+ }
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ /**
3
+ * Exchange Rate Service - Central authority for currency conversion rates.
4
+ *
5
+ * Design principles:
6
+ * - Rates are stored as strings to preserve precision
7
+ * - Timestamps track when rates were set
8
+ * - Optional source tracking for audit trails
9
+ * - Inverse rates can be auto-generated or explicitly set
10
+ */
11
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
12
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
13
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
14
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
15
+ };
16
+ var _ExchangeRateService_instances, _ExchangeRateService_rates, _ExchangeRateService_key;
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.ExchangeRateService = void 0;
19
+ /**
20
+ * Service for managing exchange rates between currencies.
21
+ *
22
+ * @example
23
+ * const rates = new ExchangeRateService()
24
+ * rates.setRate('USD', 'EUR', 0.92, 'ECB')
25
+ * rates.getRate('USD', 'EUR') // { from: 'USD', to: 'EUR', rate: '0.92', ... }
26
+ */
27
+ class ExchangeRateService {
28
+ constructor() {
29
+ _ExchangeRateService_instances.add(this);
30
+ _ExchangeRateService_rates.set(this, new Map()
31
+ /**
32
+ * Create a rate key for storage.
33
+ */
34
+ );
35
+ }
36
+ /**
37
+ * Set an exchange rate.
38
+ *
39
+ * @param from - Source currency code
40
+ * @param to - Target currency code
41
+ * @param rate - Exchange rate (1 unit of 'from' = rate units of 'to')
42
+ * @param source - Optional source identifier (e.g., 'ECB', 'Coinbase')
43
+ * @param autoInverse - If true, automatically create inverse rate (default: true)
44
+ */
45
+ setRate(from, to, rate, source, autoInverse = true) {
46
+ const rateStr = typeof rate === 'number' ? rate.toPrecision(15) : rate;
47
+ __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").set(__classPrivateFieldGet(this, _ExchangeRateService_instances, "m", _ExchangeRateService_key).call(this, from, to), {
48
+ from,
49
+ to,
50
+ rate: rateStr,
51
+ timestamp: new Date(),
52
+ source,
53
+ });
54
+ // Auto-create inverse rate if requested and not already explicitly set
55
+ if (autoInverse) {
56
+ const inverseKey = __classPrivateFieldGet(this, _ExchangeRateService_instances, "m", _ExchangeRateService_key).call(this, to, from);
57
+ if (!__classPrivateFieldGet(this, _ExchangeRateService_rates, "f").has(inverseKey)) {
58
+ const inverseRate = 1 / Number(rateStr);
59
+ __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").set(inverseKey, {
60
+ from: to,
61
+ to: from,
62
+ rate: inverseRate.toPrecision(15),
63
+ timestamp: new Date(),
64
+ source: source ? `${source} (inverse)` : '(inverse)',
65
+ });
66
+ }
67
+ }
68
+ }
69
+ /**
70
+ * Get an exchange rate.
71
+ *
72
+ * @param from - Source currency code
73
+ * @param to - Target currency code
74
+ * @returns The exchange rate, or undefined if not set
75
+ */
76
+ getRate(from, to) {
77
+ // Same currency = rate of 1
78
+ if (from === to) {
79
+ return {
80
+ from,
81
+ to,
82
+ rate: '1',
83
+ timestamp: new Date(),
84
+ source: '(identity)',
85
+ };
86
+ }
87
+ return __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").get(__classPrivateFieldGet(this, _ExchangeRateService_instances, "m", _ExchangeRateService_key).call(this, from, to));
88
+ }
89
+ /**
90
+ * Check if a rate exists.
91
+ */
92
+ hasRate(from, to) {
93
+ return from === to || __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").has(__classPrivateFieldGet(this, _ExchangeRateService_instances, "m", _ExchangeRateService_key).call(this, from, to));
94
+ }
95
+ /**
96
+ * Remove a rate.
97
+ */
98
+ removeRate(from, to) {
99
+ return __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").delete(__classPrivateFieldGet(this, _ExchangeRateService_instances, "m", _ExchangeRateService_key).call(this, from, to));
100
+ }
101
+ /**
102
+ * Get both forward and reverse rates, with discrepancy analysis.
103
+ * Useful for detecting rate inconsistencies.
104
+ *
105
+ * @param currencyA - First currency
106
+ * @param currencyB - Second currency
107
+ * @returns Rate pair with discrepancy, or undefined if either rate is missing
108
+ */
109
+ getRatePair(currencyA, currencyB) {
110
+ const forward = this.getRate(currencyA, currencyB);
111
+ const reverse = this.getRate(currencyB, currencyA);
112
+ if (!forward || !reverse) {
113
+ return undefined;
114
+ }
115
+ // Calculate discrepancy: how far is forward * reverse from 1.0?
116
+ const product = Number(forward.rate) * Number(reverse.rate);
117
+ const discrepancy = Math.abs(1 - product);
118
+ return { forward, reverse, discrepancy };
119
+ }
120
+ /**
121
+ * Get all rates for a specific base currency.
122
+ *
123
+ * @param base - The base currency code
124
+ * @returns Array of rates from this currency
125
+ */
126
+ getRatesFrom(base) {
127
+ const rates = [];
128
+ for (const rate of __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").values()) {
129
+ if (rate.from === base) {
130
+ rates.push(rate);
131
+ }
132
+ }
133
+ return rates.sort((a, b) => a.to.localeCompare(b.to));
134
+ }
135
+ /**
136
+ * Get all registered rates.
137
+ */
138
+ getAllRates() {
139
+ return Array.from(__classPrivateFieldGet(this, _ExchangeRateService_rates, "f").values()).sort((a, b) => {
140
+ const fromCompare = a.from.localeCompare(b.from);
141
+ return fromCompare !== 0 ? fromCompare : a.to.localeCompare(b.to);
142
+ });
143
+ }
144
+ /**
145
+ * Clear all rates.
146
+ */
147
+ clear() {
148
+ __classPrivateFieldGet(this, _ExchangeRateService_rates, "f").clear();
149
+ }
150
+ /**
151
+ * Load rates from a simple object.
152
+ *
153
+ * @param rates - Object where keys are "FROM:TO" and values are rates
154
+ * @param source - Optional source identifier
155
+ *
156
+ * @example
157
+ * service.loadRates({
158
+ * 'USD:EUR': 0.92,
159
+ * 'USD:GBP': 0.79,
160
+ * }, 'daily-update')
161
+ */
162
+ loadRates(rates, source) {
163
+ for (const [key, rate] of Object.entries(rates)) {
164
+ const [from, to] = key.split(':');
165
+ if (from && to) {
166
+ this.setRate(from, to, rate, source, false); // Don't auto-inverse when batch loading
167
+ }
168
+ }
169
+ }
170
+ }
171
+ exports.ExchangeRateService = ExchangeRateService;
172
+ _ExchangeRateService_rates = new WeakMap(), _ExchangeRateService_instances = new WeakSet(), _ExchangeRateService_key = function _ExchangeRateService_key(from, to) {
173
+ return `${from}:${to}`;
174
+ };
@@ -0,0 +1,22 @@
1
+ /**
2
+ * subunit-money - A type-safe value object for monetary amounts
3
+ *
4
+ * @example
5
+ * import { Money, ExchangeRateService, MoneyConverter } from '@cbrunnkvist/subunit-money'
6
+ *
7
+ * // Basic usage
8
+ * const price = new Money('USD', '19.99')
9
+ * const tax = price.multiply(0.08)
10
+ * const total = price.add(tax)
11
+ *
12
+ * // Currency conversion
13
+ * const rates = new ExchangeRateService()
14
+ * rates.setRate('USD', 'EUR', 0.92)
15
+ * const converter = new MoneyConverter(rates)
16
+ * const euros = converter.convert(total, 'EUR')
17
+ */
18
+ export { Money, type MoneyObject } from './money.js';
19
+ export { ExchangeRateService, type ExchangeRate, type RatePair } from './exchange-rate-service.js';
20
+ export { MoneyConverter } from './money-converter.js';
21
+ export { CurrencyMismatchError, CurrencyUnknownError, SubunitError, AmountError, ExchangeRateError, } from './errors.js';
22
+ export { registerCurrency, getCurrency, hasCurrency, getAllCurrencies, loadCurrencyMap, clearCurrencies, type CurrencyDefinition, } from './currency.js';
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ /**
3
+ * subunit-money - A type-safe value object for monetary amounts
4
+ *
5
+ * @example
6
+ * import { Money, ExchangeRateService, MoneyConverter } from '@cbrunnkvist/subunit-money'
7
+ *
8
+ * // Basic usage
9
+ * const price = new Money('USD', '19.99')
10
+ * const tax = price.multiply(0.08)
11
+ * const total = price.add(tax)
12
+ *
13
+ * // Currency conversion
14
+ * const rates = new ExchangeRateService()
15
+ * rates.setRate('USD', 'EUR', 0.92)
16
+ * const converter = new MoneyConverter(rates)
17
+ * const euros = converter.convert(total, 'EUR')
18
+ */
19
+ var __importDefault = (this && this.__importDefault) || function (mod) {
20
+ return (mod && mod.__esModule) ? mod : { "default": mod };
21
+ };
22
+ Object.defineProperty(exports, "__esModule", { value: true });
23
+ exports.clearCurrencies = exports.loadCurrencyMap = exports.getAllCurrencies = exports.hasCurrency = exports.getCurrency = exports.registerCurrency = exports.ExchangeRateError = exports.AmountError = exports.SubunitError = exports.CurrencyUnknownError = exports.CurrencyMismatchError = exports.MoneyConverter = exports.ExchangeRateService = exports.Money = void 0;
24
+ // Core classes
25
+ var money_js_1 = require("./money.js");
26
+ Object.defineProperty(exports, "Money", { enumerable: true, get: function () { return money_js_1.Money; } });
27
+ var exchange_rate_service_js_1 = require("./exchange-rate-service.js");
28
+ Object.defineProperty(exports, "ExchangeRateService", { enumerable: true, get: function () { return exchange_rate_service_js_1.ExchangeRateService; } });
29
+ var money_converter_js_1 = require("./money-converter.js");
30
+ Object.defineProperty(exports, "MoneyConverter", { enumerable: true, get: function () { return money_converter_js_1.MoneyConverter; } });
31
+ // Error types
32
+ var errors_js_1 = require("./errors.js");
33
+ Object.defineProperty(exports, "CurrencyMismatchError", { enumerable: true, get: function () { return errors_js_1.CurrencyMismatchError; } });
34
+ Object.defineProperty(exports, "CurrencyUnknownError", { enumerable: true, get: function () { return errors_js_1.CurrencyUnknownError; } });
35
+ Object.defineProperty(exports, "SubunitError", { enumerable: true, get: function () { return errors_js_1.SubunitError; } });
36
+ Object.defineProperty(exports, "AmountError", { enumerable: true, get: function () { return errors_js_1.AmountError; } });
37
+ Object.defineProperty(exports, "ExchangeRateError", { enumerable: true, get: function () { return errors_js_1.ExchangeRateError; } });
38
+ // Currency utilities
39
+ var currency_js_1 = require("./currency.js");
40
+ Object.defineProperty(exports, "registerCurrency", { enumerable: true, get: function () { return currency_js_1.registerCurrency; } });
41
+ Object.defineProperty(exports, "getCurrency", { enumerable: true, get: function () { return currency_js_1.getCurrency; } });
42
+ Object.defineProperty(exports, "hasCurrency", { enumerable: true, get: function () { return currency_js_1.hasCurrency; } });
43
+ Object.defineProperty(exports, "getAllCurrencies", { enumerable: true, get: function () { return currency_js_1.getAllCurrencies; } });
44
+ Object.defineProperty(exports, "loadCurrencyMap", { enumerable: true, get: function () { return currency_js_1.loadCurrencyMap; } });
45
+ Object.defineProperty(exports, "clearCurrencies", { enumerable: true, get: function () { return currency_js_1.clearCurrencies; } });
46
+ // Auto-load default currencies
47
+ // The currencymap.json file is the official ISO 4217 currency list (List One) as of 2026-01-01,
48
+ // sourced from SIX Financial Information AG (the ISO 4217 Maintenance Agency).
49
+ //
50
+ // To regenerate:
51
+ // 1. Download list-one.xml from https://www.six-group.com/en/products-services/financial-information/data-standards.html
52
+ // 2. Convert with: yq -p xml -o json '.' list-one.xml | jq '.ISO_4217.CcyTbl.CcyNtry | map(select(.Ccy) | {(.Ccy): {decimal_digits: (if (.CcyMnrUnts == "N.A." or .CcyMnrUnts == null) then 0 else (.CcyMnrUnts | tonumber) end)}}) | add | to_entries | sort_by(.key) | from_entries' > currencymap.json
53
+ //
54
+ // Note: This excludes historical currencies, supranational funds, and precious metals,
55
+ // keeping only active national and regional currencies for practical use.
56
+ const currency_js_2 = require("./currency.js");
57
+ const currencymap_json_1 = __importDefault(require("../currencymap.json"));
58
+ (0, currency_js_2.loadCurrencyMap)(currencymap_json_1.default);
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Money Converter - Safe cross-currency operations.
3
+ *
4
+ * Bridges Money objects with ExchangeRateService to enable:
5
+ * - Currency conversion
6
+ * - Multi-currency arithmetic
7
+ * - Percentage calculations across currencies
8
+ */
9
+ import { Money } from './money.js';
10
+ import { ExchangeRateService } from './exchange-rate-service.js';
11
+ /**
12
+ * Converter for performing operations between different currencies.
13
+ *
14
+ * @example
15
+ * const rates = new ExchangeRateService()
16
+ * rates.setRate('USD', 'EUR', 0.92)
17
+ *
18
+ * const converter = new MoneyConverter(rates)
19
+ * const euros = converter.convert(new Money('USD', '100'), 'EUR')
20
+ * console.log(euros.toString()) // "92.00 EUR"
21
+ */
22
+ export declare class MoneyConverter {
23
+ #private;
24
+ constructor(rateService: ExchangeRateService);
25
+ /**
26
+ * Convert a Money amount to another currency.
27
+ *
28
+ * @param money - The amount to convert
29
+ * @param targetCurrency - The target currency code
30
+ * @returns A new Money in the target currency
31
+ * @throws {ExchangeRateError} If no rate is available
32
+ */
33
+ convert<From extends string, To extends string>(money: Money<From>, targetCurrency: To): Money<To>;
34
+ /**
35
+ * Add two Money amounts, converting as needed.
36
+ *
37
+ * @param a - First amount
38
+ * @param b - Second amount
39
+ * @param resultCurrency - Currency for the result (must be one of the input currencies)
40
+ * @returns Sum in the result currency
41
+ */
42
+ add<A extends string, B extends string, R extends A | B>(a: Money<A>, b: Money<B>, resultCurrency: R): Money<R>;
43
+ /**
44
+ * Subtract two Money amounts, converting as needed.
45
+ *
46
+ * @param a - Amount to subtract from
47
+ * @param b - Amount to subtract
48
+ * @param resultCurrency - Currency for the result
49
+ * @returns Difference in the result currency
50
+ */
51
+ subtract<A extends string, B extends string, R extends A | B>(a: Money<A>, b: Money<B>, resultCurrency: R): Money<R>;
52
+ /**
53
+ * Calculate what percentage one amount is of another.
54
+ * Converts both to the same currency before comparison.
55
+ *
56
+ * @param part - The partial amount
57
+ * @param whole - The whole amount
58
+ * @returns Percentage as a number (e.g., 25 for 25%)
59
+ */
60
+ percentageOf<A extends string, B extends string>(part: Money<A>, whole: Money<B>): number;
61
+ /**
62
+ * Sum multiple Money amounts, converting all to a target currency.
63
+ *
64
+ * @param amounts - Array of Money objects (can be different currencies)
65
+ * @param targetCurrency - Currency for the result
66
+ * @returns Total in the target currency
67
+ */
68
+ sum<C extends string>(amounts: Money<string>[], targetCurrency: C): Money<C>;
69
+ /**
70
+ * Compare two Money amounts across currencies.
71
+ * Returns negative if a < b, zero if equal, positive if a > b.
72
+ *
73
+ * @param a - First amount
74
+ * @param b - Second amount
75
+ * @returns Comparison result
76
+ */
77
+ compare<A extends string, B extends string>(a: Money<A>, b: Money<B>): -1 | 0 | 1;
78
+ /**
79
+ * Get the exchange rate service (for direct rate access).
80
+ */
81
+ get rateService(): ExchangeRateService;
82
+ }