@classytic/primitives 0.26.4 → 0.28.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 +1119 -1057
- package/dist/bank-transaction.d.mts +1 -1
- package/dist/csv.d.mts +36 -0
- package/dist/csv.mjs +50 -0
- package/dist/currency.d.mts +1 -1
- package/dist/monetization.d.mts +92 -6
- package/dist/monetization.mjs +68 -5
- package/dist/money-BBOARE5f.mjs +204 -0
- package/dist/{money-CfAvfNiM.d.mts → money-C9iLWiWR.d.mts} +21 -1
- package/dist/money.d.mts +2 -2
- package/dist/money.mjs +3 -177
- package/dist/payment-events.d.mts +1 -1
- package/dist/payment-gateway.d.mts +1 -1
- package/dist/proration.d.mts +1 -1
- package/dist/unit-cost-rate.d.mts +1 -1
- package/dist/unit-cost-rate.mjs +1 -1
- package/package.json +285 -281
package/dist/money.mjs
CHANGED
|
@@ -1,177 +1,3 @@
|
|
|
1
|
-
import { CurrencyMismatchError
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Cast a raw number to {@link MinorUnits}. Pass the currency as the second
|
|
5
|
-
* argument to fix the phantom type. With no second arg, `MinorUnits<string>`
|
|
6
|
-
* — useful for generic SDK boundaries that don't know the currency yet.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* MinorUnits(489900, 'BDT') // typed MinorUnits<'BDT'>
|
|
10
|
-
* MinorUnits(199, 'USD') // typed MinorUnits<'USD'>
|
|
11
|
-
*/
|
|
12
|
-
function MinorUnits(amount, _currency) {
|
|
13
|
-
return amount;
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Construct {@link Money} from an integer minor-unit amount.
|
|
17
|
-
*
|
|
18
|
-
* @throws TypeError if `amount` is not a finite integer.
|
|
19
|
-
* @throws InvalidCurrencyCodeError if `currency` is not ISO 4217 format.
|
|
20
|
-
*/
|
|
21
|
-
function money(amount, currency) {
|
|
22
|
-
if (!Number.isFinite(amount) || !Number.isInteger(amount)) throw new TypeError(`Money.amount must be a finite integer in minor units, got ${amount}`);
|
|
23
|
-
return {
|
|
24
|
-
amount,
|
|
25
|
-
currency: currencyCode(currency)
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Construct {@link Money} from a major-unit number (e.g. dollars, taka) by
|
|
30
|
-
* scaling to the currency's minor unit and rounding half-away-from-zero.
|
|
31
|
-
*
|
|
32
|
-
* Uses `toPrecision(15)` to strip the trailing-bit noise that appears in
|
|
33
|
-
* multiply-then-round (e.g. `0.1 + 0.2 = 0.30000000000000004`). This is
|
|
34
|
-
* enough for the vast majority of decimals encountered in real-world pricing.
|
|
35
|
-
*
|
|
36
|
-
* **Precision caveat.** A handful of decimals cannot be represented exactly
|
|
37
|
-
* in IEEE 754 and will round to the IEEE-closest integer rather than the
|
|
38
|
-
* mathematically-expected one — e.g. `1.005` is stored as `1.00499999…` and
|
|
39
|
-
* rounds to `100` minor units, not `101`. If you need decimal-exact rounding,
|
|
40
|
-
* construct money from a string or use integer minor units directly via
|
|
41
|
-
* {@link money}.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* fromMajor(19.99, 'USD') // { amount: 1999, currency: 'USD' }
|
|
45
|
-
* fromMajor(0.1 + 0.2, 'USD') // { amount: 30, currency: 'USD' }
|
|
46
|
-
* fromMajor(1500, 'JPY') // { amount: 1500, currency: 'JPY' }
|
|
47
|
-
*/
|
|
48
|
-
function fromMajor(major, currency) {
|
|
49
|
-
if (!Number.isFinite(major)) throw new TypeError(`fromMajor received non-finite value: ${major}`);
|
|
50
|
-
const raw = major * minorUnitFactor(currency);
|
|
51
|
-
const cleaned = Number(raw.toPrecision(15));
|
|
52
|
-
return {
|
|
53
|
-
amount: Math.round(Math.abs(cleaned)) * (cleaned < 0 ? -1 : 1),
|
|
54
|
-
currency: currencyCode(currency)
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/** Convert {@link Money} back to its major-unit floating-point representation. */
|
|
58
|
-
function toMajor(m) {
|
|
59
|
-
return m.amount / minorUnitFactor(m.currency);
|
|
60
|
-
}
|
|
61
|
-
function assertSameCurrency(a, b) {
|
|
62
|
-
if (a.currency !== b.currency) throw new CurrencyMismatchError(a.currency, b.currency);
|
|
63
|
-
}
|
|
64
|
-
function addMoney(a, b) {
|
|
65
|
-
assertSameCurrency(a, b);
|
|
66
|
-
return {
|
|
67
|
-
amount: a.amount + b.amount,
|
|
68
|
-
currency: a.currency
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
function subtractMoney(a, b) {
|
|
72
|
-
assertSameCurrency(a, b);
|
|
73
|
-
return {
|
|
74
|
-
amount: a.amount - b.amount,
|
|
75
|
-
currency: a.currency
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Multiply money by a scalar. The result is rounded to an integer number of
|
|
80
|
-
* minor units using half-away-from-zero rounding.
|
|
81
|
-
*/
|
|
82
|
-
function multiplyMoney(m, scalar) {
|
|
83
|
-
if (!Number.isFinite(scalar)) throw new TypeError(`multiplyMoney received non-finite scalar: ${scalar}`);
|
|
84
|
-
const raw = m.amount * scalar;
|
|
85
|
-
return {
|
|
86
|
-
amount: Math.round(Math.abs(raw)) * (raw < 0 ? -1 : 1),
|
|
87
|
-
currency: m.currency
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
/** Sum a list of {@link Money}. Returns zero in the given currency for empty input. */
|
|
91
|
-
function sumMoney(values, currency) {
|
|
92
|
-
return values.reduce((acc, v) => addMoney(acc, v), {
|
|
93
|
-
amount: 0,
|
|
94
|
-
currency: currencyCode(currency)
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
/** Strict equality (amount and currency both match). */
|
|
98
|
-
function equalsMoney(a, b) {
|
|
99
|
-
return a.amount === b.amount && a.currency === b.currency;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Ordering predicate. Returns -1, 0, or 1. Throws on currency mismatch — use
|
|
103
|
-
* {@link equalsMoney} for a total equality check across currencies.
|
|
104
|
-
*/
|
|
105
|
-
function compareMoney(a, b) {
|
|
106
|
-
assertSameCurrency(a, b);
|
|
107
|
-
if (a.amount < b.amount) return -1;
|
|
108
|
-
if (a.amount > b.amount) return 1;
|
|
109
|
-
return 0;
|
|
110
|
-
}
|
|
111
|
-
function isZeroMoney(m) {
|
|
112
|
-
return m.amount === 0;
|
|
113
|
-
}
|
|
114
|
-
function isPositiveMoney(m) {
|
|
115
|
-
return m.amount > 0;
|
|
116
|
-
}
|
|
117
|
-
function isNegativeMoney(m) {
|
|
118
|
-
return m.amount < 0;
|
|
119
|
-
}
|
|
120
|
-
function negateMoney(m) {
|
|
121
|
-
return {
|
|
122
|
-
amount: m.amount === 0 ? 0 : -m.amount,
|
|
123
|
-
currency: m.currency
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
function absMoney(m) {
|
|
127
|
-
return m.amount < 0 ? negateMoney(m) : m;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Decimal major-unit number → integer minor units by decimal exponent.
|
|
131
|
-
* Rounding: raw IEEE `Math.round` — half-up toward +∞ (so `-10.5 → -10`),
|
|
132
|
-
* documented above. Throws when the result leaves the safe-integer range
|
|
133
|
-
* (also catches `NaN`/`Infinity` inputs).
|
|
134
|
-
*
|
|
135
|
-
* @example
|
|
136
|
-
* majorToMinorUnits(10.5) // 1050
|
|
137
|
-
* majorToMinorUnits(1000, 0) // 1000 (JPY-style)
|
|
138
|
-
* majorToMinorUnits(1.005) // 100 — IEEE, see note above
|
|
139
|
-
*/
|
|
140
|
-
function majorToMinorUnits(major, minorUnitDecimals = 2) {
|
|
141
|
-
const factor = 10 ** minorUnitDecimals;
|
|
142
|
-
const minor = Math.round(major * factor);
|
|
143
|
-
if (!Number.isSafeInteger(minor)) throw new RangeError(`Amount ${major} exceeds safe integer limit when converted to minor units. Max safe amount: ${Number.MAX_SAFE_INTEGER / factor}`);
|
|
144
|
-
return minor;
|
|
145
|
-
}
|
|
146
|
-
/** Integer minor units → decimal major-unit number by decimal exponent: `1050 → 10.5`. */
|
|
147
|
-
function minorUnitsToMajor(minor, minorUnitDecimals = 2) {
|
|
148
|
-
return minor / 10 ** minorUnitDecimals;
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Percentage of an integer minor-unit amount → integer minor units.
|
|
152
|
-
* EXACT multiply-then-round: `Math.round((minor × ratePercent) / 100)` —
|
|
153
|
-
* one rounding point, half-up toward +∞. Handles genuinely fractional rates
|
|
154
|
-
* (QST 9.975 %) without precision loss: `percentOfMinor(20000, 9.975) === 1995`.
|
|
155
|
-
*
|
|
156
|
-
* Hosts whose domain guarantees at-most-2-decimal rates MAY snap the rate to
|
|
157
|
-
* integer basis points BEFORE calling (be-prod's `#shared/money` seam does) —
|
|
158
|
-
* that is host policy layered on top, not part of this primitive.
|
|
159
|
-
*/
|
|
160
|
-
function percentOfMinor(minor, ratePercent) {
|
|
161
|
-
if (!Number.isFinite(minor) || !Number.isFinite(ratePercent)) throw new TypeError(`percentOfMinor received non-finite input: minor=${minor}, ratePercent=${ratePercent}`);
|
|
162
|
-
return Math.round(minor * ratePercent / 100);
|
|
163
|
-
}
|
|
164
|
-
/**
|
|
165
|
-
* Integer minor units → plain decimal string (no currency symbol, no locale):
|
|
166
|
-
* `formatMinorUnits(10550) → "105.50"`, `formatMinorUnits(1000, 0) → "1000"`.
|
|
167
|
-
* For localized currency strings use `Intl.NumberFormat` at the display layer.
|
|
168
|
-
*/
|
|
169
|
-
function formatMinorUnits(minor, minorUnitDecimals = 2) {
|
|
170
|
-
return minorUnitsToMajor(minor, minorUnitDecimals).toFixed(minorUnitDecimals);
|
|
171
|
-
}
|
|
172
|
-
/** Structural type guard. */
|
|
173
|
-
function isMoney(value) {
|
|
174
|
-
return typeof value === "object" && value !== null && typeof value.amount === "number" && Number.isInteger(value.amount) && isCurrencyCode(value.currency);
|
|
175
|
-
}
|
|
176
|
-
//#endregion
|
|
177
|
-
export { CurrencyMismatchError, MinorUnits, absMoney, addMoney, compareMoney, equalsMoney, formatMinorUnits, fromMajor, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, majorToMinorUnits, minorUnitsToMajor, money, multiplyMoney, negateMoney, percentOfMinor, subtractMoney, sumMoney, toMajor };
|
|
1
|
+
import { CurrencyMismatchError } from "./currency.mjs";
|
|
2
|
+
import { C as isCashDestination, S as cashDestinationLabel, _ as percentOfMinor, a as equalsMoney, b as toMajor, c as isMoney, d as isZeroMoney, f as majorToMinorUnits, g as negateMoney, h as multiplyMoney, i as compareMoney, l as isNegativeMoney, m as money, n as absMoney, o as formatMinorUnits, p as minorUnitsToMajor, r as addMoney, s as fromMajor, t as MinorUnits, u as isPositiveMoney, v as subtractMoney, x as CASH_DESTINATIONS, y as sumMoney } from "./money-BBOARE5f.mjs";
|
|
3
|
+
export { CASH_DESTINATIONS, CurrencyMismatchError, MinorUnits, absMoney, addMoney, cashDestinationLabel, compareMoney, equalsMoney, formatMinorUnits, fromMajor, isCashDestination, isMoney, isNegativeMoney, isPositiveMoney, isZeroMoney, majorToMinorUnits, minorUnitsToMajor, money, multiplyMoney, negateMoney, percentOfMinor, subtractMoney, sumMoney, toMajor };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Money } from "./money-
|
|
1
|
+
import { n as Money } from "./money-C9iLWiWR.mjs";
|
|
2
2
|
import { PaymentMethodKind } from "./payment-method-kind.mjs";
|
|
3
3
|
import { ProviderUnknownCause } from "./payment-gateway.mjs";
|
|
4
4
|
//#region src/events/payment-events.d.ts
|
package/dist/proration.d.mts
CHANGED
package/dist/unit-cost-rate.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MinorUnits } from "./money.mjs";
|
|
1
|
+
import { t as MinorUnits } from "./money-BBOARE5f.mjs";
|
|
2
2
|
import { t as roundedDiv } from "./rounded-div-BWJb98Ws.mjs";
|
|
3
3
|
//#region src/money/unit-cost-rate.ts
|
|
4
4
|
/** Fixed, ecosystem-wide rate scale: 6 decimal places below the minor unit. */
|