@vielzeug/coins 2.1.1 → 3.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 +12 -67
- package/dist/_decimal.cjs +2 -0
- package/dist/_decimal.cjs.map +1 -0
- package/dist/{decimal.d.ts → _decimal.d.ts} +2 -1
- package/dist/_decimal.d.ts.map +1 -0
- package/dist/_decimal.js +64 -0
- package/dist/_decimal.js.map +1 -0
- package/dist/aggregate.cjs +1 -1
- package/dist/aggregate.cjs.map +1 -1
- package/dist/aggregate.d.ts.map +1 -1
- package/dist/aggregate.js +34 -30
- package/dist/aggregate.js.map +1 -1
- package/dist/coins.cjs +1 -1
- package/dist/coins.cjs.map +1 -1
- package/dist/coins.iife.js +1 -1
- package/dist/coins.iife.js.map +1 -1
- package/dist/coins.js +1 -1
- package/dist/coins.js.map +1 -1
- package/dist/currency.cjs +1 -1
- package/dist/currency.cjs.map +1 -1
- package/dist/currency.d.ts +3 -4
- package/dist/currency.d.ts.map +1 -1
- package/dist/currency.js +21 -40
- package/dist/currency.js.map +1 -1
- package/dist/errors.cjs +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.d.ts +4 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +16 -5
- package/dist/errors.js.map +1 -1
- package/dist/exchange.cjs +1 -1
- package/dist/exchange.cjs.map +1 -1
- package/dist/exchange.d.ts +1 -0
- package/dist/exchange.d.ts.map +1 -1
- package/dist/exchange.js +13 -13
- package/dist/exchange.js.map +1 -1
- package/dist/format.cjs +1 -1
- package/dist/format.cjs.map +1 -1
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +54 -52
- package/dist/format.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -6
- package/dist/money.cjs +1 -1
- package/dist/money.cjs.map +1 -1
- package/dist/money.d.ts +13 -5
- package/dist/money.d.ts.map +1 -1
- package/dist/money.js +77 -65
- package/dist/money.js.map +1 -1
- package/dist/serialization.cjs +1 -1
- package/dist/serialization.cjs.map +1 -1
- package/dist/serialization.d.ts +1 -4
- package/dist/serialization.d.ts.map +1 -1
- package/dist/serialization.js +6 -38
- package/dist/serialization.js.map +1 -1
- package/package.json +8 -7
- package/dist/decimal.cjs +0 -2
- package/dist/decimal.cjs.map +0 -1
- package/dist/decimal.d.ts.map +0 -1
- package/dist/decimal.js +0 -52
- package/dist/decimal.js.map +0 -1
package/dist/format.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs"),t=require("./
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_decimal.cjs"),n=require("./money.cjs");var r=20,i=`halfAwayFromZero`,a={awayFromZero:`expand`,ceil:`ceil`,floor:`floor`,halfAwayFromZero:`halfExpand`,halfEven:`halfEven`,towardZero:`trunc`};function o(e,t={}){return s(e,t).map(e=>e.value).join(``)}function s(r,o={}){n.assertMoney(r),t.assertRoundingMode(o.rounding??i);let{maximum:s,minimum:l}=c(r.currency.minorUnit,o),d=o.style??`symbol`;try{return u(new Intl.NumberFormat(o.locale??`en-US`,{currency:r.currency.code,currencyDisplay:d,maximumFractionDigits:s,minimumFractionDigits:l,roundingMode:a[o.rounding??i],style:`currency`,useGrouping:!0}).formatToParts(n.toDecimal(r)))}catch(t){throw t instanceof e.CoinsError?t:new e.CoinsError(`FORMAT_ERROR`,`Cannot format currency "${r.currency.code}" for locale "${o.locale??`en-US`}"`,{cause:t})}}function c(t,n){let r=n.maximumFractionDigits,i=n.minimumFractionDigits;l(`maximumFractionDigits`,r),l(`minimumFractionDigits`,i);let a=r??Math.max(t,i??t),o=i??Math.min(t,r??t);if(o>a)throw new e.CoinsError(`FORMAT_ERROR`,`minimumFractionDigits cannot exceed maximumFractionDigits`);return{maximum:a,minimum:o}}function l(t,n){if(n!==void 0&&(!Number.isInteger(n)||n<0||n>r))throw new e.CoinsError(`FORMAT_ERROR`,`Fraction digits must be integers satisfying 0 ≤ minimum ≤ maximum ≤ ${r} (${t})`)}function u(e){let t=[];for(let n of e)if(n.type===`integer`||n.type===`group`){let e=t.at(-1);e?.type===`integer`?t[t.length-1]={type:`integer`,value:e.value+n.value}:t.push({type:`integer`,value:n.value})}else n.type===`currency`||n.type===`decimal`||n.type===`fraction`||n.type===`literal`||n.type===`minusSign`||n.type===`plusSign`?t.push({type:n.type,value:n.value}):t.push({type:`literal`,value:n.value});return t}exports.format=o,exports.formatParts=s;
|
|
2
2
|
//# sourceMappingURL=format.cjs.map
|
package/dist/format.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.cjs","names":[],"sources":["../src/format.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"format.cjs","names":[],"sources":["../src/format.ts"],"sourcesContent":["import { assertRoundingMode } from './_decimal';\nimport { CoinsError } from './errors';\nimport { assertMoney, toDecimal } from './money';\nimport type { FormatOptions, Money, MoneyFormatPart, RoundingMode } from './types';\n\nconst MAX_FRACTION_DIGITS = 20;\nconst defaultFormatRounding: RoundingMode = 'halfAwayFromZero';\nconst intlRoundingModes: Record<RoundingMode, Intl.NumberFormatOptions['roundingMode']> = {\n awayFromZero: 'expand',\n ceil: 'ceil',\n floor: 'floor',\n halfAwayFromZero: 'halfExpand',\n halfEven: 'halfEven',\n towardZero: 'trunc',\n};\n\nexport function format(value: Money, options: FormatOptions = {}): string {\n return formatParts(value, options)\n .map((part) => part.value)\n .join('');\n}\n\nexport function formatParts(value: Money, options: FormatOptions = {}): MoneyFormatPart[] {\n assertMoney(value);\n assertRoundingMode(options.rounding ?? defaultFormatRounding);\n\n const { maximum, minimum } = fractionDigits(value.currency.minorUnit, options);\n const style = options.style ?? 'symbol';\n\n try {\n const formatter = new Intl.NumberFormat(options.locale ?? 'en-US', {\n currency: value.currency.code,\n currencyDisplay: style,\n maximumFractionDigits: maximum,\n minimumFractionDigits: minimum,\n roundingMode: intlRoundingModes[options.rounding ?? defaultFormatRounding],\n style: 'currency',\n useGrouping: true,\n });\n\n return normalizeParts(formatter.formatToParts(toDecimal(value) as unknown as number));\n } catch (error) {\n if (error instanceof CoinsError) throw error;\n\n throw new CoinsError(\n 'FORMAT_ERROR',\n `Cannot format currency \"${value.currency.code}\" for locale \"${options.locale ?? 'en-US'}\"`,\n { cause: error },\n );\n }\n}\n\nfunction fractionDigits(scale: number, options: FormatOptions): { maximum: number; minimum: number } {\n const requestedMaximum = options.maximumFractionDigits;\n const requestedMinimum = options.minimumFractionDigits;\n\n validateFractionDigit('maximumFractionDigits', requestedMaximum);\n validateFractionDigit('minimumFractionDigits', requestedMinimum);\n\n const maximum = requestedMaximum ?? Math.max(scale, requestedMinimum ?? scale);\n const minimum = requestedMinimum ?? Math.min(scale, requestedMaximum ?? scale);\n\n if (minimum > maximum) {\n throw new CoinsError('FORMAT_ERROR', 'minimumFractionDigits cannot exceed maximumFractionDigits');\n }\n\n return { maximum, minimum };\n}\n\nfunction validateFractionDigit(name: string, value: number | undefined): void {\n if (value !== undefined && (!Number.isInteger(value) || value < 0 || value > MAX_FRACTION_DIGITS)) {\n throw new CoinsError(\n 'FORMAT_ERROR',\n `Fraction digits must be integers satisfying 0 ≤ minimum ≤ maximum ≤ ${MAX_FRACTION_DIGITS} (${name})`,\n );\n }\n}\n\nfunction normalizeParts(raw: Intl.NumberFormatPart[]): MoneyFormatPart[] {\n const parts: MoneyFormatPart[] = [];\n\n for (const part of raw) {\n if (part.type === 'integer' || part.type === 'group') {\n const previous = parts.at(-1);\n\n if (previous?.type === 'integer') {\n parts[parts.length - 1] = { type: 'integer', value: previous.value + part.value };\n } else {\n parts.push({ type: 'integer', value: part.value });\n }\n } else if (\n part.type === 'currency' ||\n part.type === 'decimal' ||\n part.type === 'fraction' ||\n part.type === 'literal' ||\n part.type === 'minusSign' ||\n part.type === 'plusSign'\n ) {\n parts.push({ type: part.type, value: part.value });\n } else {\n parts.push({ type: 'literal', value: part.value });\n }\n }\n\n return parts;\n}\n"],"mappings":"qFAKA,IAAM,EAAsB,GACtB,EAAsC,mBACtC,EAAoF,CACxF,aAAc,SACd,KAAM,OACN,MAAO,QACP,iBAAkB,aAClB,SAAU,WACV,WAAY,OACd,EAEA,SAAgB,EAAO,EAAc,EAAyB,CAAC,EAAW,CACxE,OAAO,EAAY,EAAO,CAAO,CAAC,CAC/B,IAAK,GAAS,EAAK,KAAK,CAAC,CACzB,KAAK,EAAE,CACZ,CAEA,SAAgB,EAAY,EAAc,EAAyB,CAAC,EAAsB,CACxF,EAAA,YAAY,CAAK,EACjB,EAAA,mBAAmB,EAAQ,UAAY,CAAqB,EAE5D,GAAM,CAAE,UAAS,WAAY,EAAe,EAAM,SAAS,UAAW,CAAO,EACvE,EAAQ,EAAQ,OAAS,SAE/B,GAAI,CAWF,OAAO,EAAe,IAVA,KAAK,aAAa,EAAQ,QAAU,QAAS,CACjE,SAAU,EAAM,SAAS,KACzB,gBAAiB,EACjB,sBAAuB,EACvB,sBAAuB,EACvB,aAAc,EAAkB,EAAQ,UAAY,GACpD,MAAO,WACP,YAAa,EACf,CAEsB,CAAA,CAAU,cAAc,EAAA,UAAU,CAAK,CAAsB,CAAC,CACtF,OAAS,EAAO,CAGd,MAFI,aAAiB,EAAA,WAAkB,EAEjC,IAAI,EAAA,WACR,eACA,2BAA2B,EAAM,SAAS,KAAK,gBAAgB,EAAQ,QAAU,QAAQ,GACzF,CAAE,MAAO,CAAM,CACjB,CACF,CACF,CAEA,SAAS,EAAe,EAAe,EAA8D,CACnG,IAAM,EAAmB,EAAQ,sBAC3B,EAAmB,EAAQ,sBAEjC,EAAsB,wBAAyB,CAAgB,EAC/D,EAAsB,wBAAyB,CAAgB,EAE/D,IAAM,EAAU,GAAoB,KAAK,IAAI,EAAO,GAAoB,CAAK,EACvE,EAAU,GAAoB,KAAK,IAAI,EAAO,GAAoB,CAAK,EAE7E,GAAI,EAAU,EACZ,MAAM,IAAI,EAAA,WAAW,eAAgB,2DAA2D,EAGlG,MAAO,CAAE,UAAS,SAAQ,CAC5B,CAEA,SAAS,EAAsB,EAAc,EAAiC,CAC5E,GAAI,IAAU,IAAA,KAAc,CAAC,OAAO,UAAU,CAAK,GAAK,EAAQ,GAAK,EAAQ,GAC3E,MAAM,IAAI,EAAA,WACR,eACA,uEAAuE,EAAoB,IAAI,EAAK,EACtG,CAEJ,CAEA,SAAS,EAAe,EAAiD,CACvE,IAAM,EAA2B,CAAC,EAElC,IAAK,IAAM,KAAQ,EACjB,GAAI,EAAK,OAAS,WAAa,EAAK,OAAS,QAAS,CACpD,IAAM,EAAW,EAAM,GAAG,EAAE,EAExB,GAAU,OAAS,UACrB,EAAM,EAAM,OAAS,GAAK,CAAE,KAAM,UAAW,MAAO,EAAS,MAAQ,EAAK,KAAM,EAEhF,EAAM,KAAK,CAAE,KAAM,UAAW,MAAO,EAAK,KAAM,CAAC,CAErD,MACE,EAAK,OAAS,YACd,EAAK,OAAS,WACd,EAAK,OAAS,YACd,EAAK,OAAS,WACd,EAAK,OAAS,aACd,EAAK,OAAS,WAEd,EAAM,KAAK,CAAE,KAAM,EAAK,KAAM,MAAO,EAAK,KAAM,CAAC,EAEjD,EAAM,KAAK,CAAE,KAAM,UAAW,MAAO,EAAK,KAAM,CAAC,EAIrD,OAAO,CACT"}
|
package/dist/format.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAanF,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,aAAkB,GAAG,MAAM,CAIxE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,GAAE,aAAkB,GAAG,eAAe,EAAE,CA4BxF"}
|
package/dist/format.js
CHANGED
|
@@ -1,65 +1,67 @@
|
|
|
1
1
|
import { CoinsError as e } from "./errors.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { assertRoundingMode as t } from "./_decimal.js";
|
|
3
|
+
import { assertMoney as n, toDecimal as r } from "./money.js";
|
|
4
4
|
//#region src/format.ts
|
|
5
|
-
var
|
|
5
|
+
var i = 20, a = "halfAwayFromZero", o = {
|
|
6
|
+
awayFromZero: "expand",
|
|
7
|
+
ceil: "ceil",
|
|
8
|
+
floor: "floor",
|
|
9
|
+
halfAwayFromZero: "halfExpand",
|
|
10
|
+
halfEven: "halfEven",
|
|
11
|
+
towardZero: "trunc"
|
|
12
|
+
};
|
|
6
13
|
function s(e, t = {}) {
|
|
7
14
|
return c(e, t).map((e) => e.value).join("");
|
|
8
15
|
}
|
|
9
|
-
function c(
|
|
10
|
-
|
|
11
|
-
let {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
value: e.value
|
|
26
|
-
}) : x.push({
|
|
27
|
-
type: "literal",
|
|
28
|
-
value: e.value
|
|
29
|
-
}));
|
|
30
|
-
return x;
|
|
16
|
+
function c(i, s = {}) {
|
|
17
|
+
n(i), t(s.rounding ?? a);
|
|
18
|
+
let { maximum: c, minimum: u } = l(i.currency.minorUnit, s), f = s.style ?? "symbol";
|
|
19
|
+
try {
|
|
20
|
+
return d(new Intl.NumberFormat(s.locale ?? "en-US", {
|
|
21
|
+
currency: i.currency.code,
|
|
22
|
+
currencyDisplay: f,
|
|
23
|
+
maximumFractionDigits: c,
|
|
24
|
+
minimumFractionDigits: u,
|
|
25
|
+
roundingMode: o[s.rounding ?? a],
|
|
26
|
+
style: "currency",
|
|
27
|
+
useGrouping: !0
|
|
28
|
+
}).formatToParts(r(i)));
|
|
29
|
+
} catch (t) {
|
|
30
|
+
throw t instanceof e ? t : new e("FORMAT_ERROR", `Cannot format currency "${i.currency.code}" for locale "${s.locale ?? "en-US"}"`, { cause: t });
|
|
31
|
+
}
|
|
31
32
|
}
|
|
32
33
|
function l(t, n) {
|
|
33
|
-
|
|
34
|
+
let r = n.maximumFractionDigits, i = n.minimumFractionDigits;
|
|
35
|
+
u("maximumFractionDigits", r), u("minimumFractionDigits", i);
|
|
36
|
+
let a = r ?? Math.max(t, i ?? t), o = i ?? Math.min(t, r ?? t);
|
|
37
|
+
if (o > a) throw new e("FORMAT_ERROR", "minimumFractionDigits cannot exceed maximumFractionDigits");
|
|
38
|
+
return {
|
|
39
|
+
maximum: a,
|
|
40
|
+
minimum: o
|
|
41
|
+
};
|
|
34
42
|
}
|
|
35
|
-
function u(t, n
|
|
36
|
-
|
|
37
|
-
if (s) return s;
|
|
38
|
-
try {
|
|
39
|
-
let e = new Intl.NumberFormat(t, {
|
|
40
|
-
currency: n,
|
|
41
|
-
currencyDisplay: r,
|
|
42
|
-
maximumFractionDigits: 1,
|
|
43
|
-
minimumFractionDigits: 1,
|
|
44
|
-
style: "currency"
|
|
45
|
-
}).formatToParts(i ? -1.1 : 1.1);
|
|
46
|
-
return o.set(a, e), e;
|
|
47
|
-
} catch (r) {
|
|
48
|
-
throw new e("FORMAT_ERROR", `Cannot format currency "${n}" for locale "${t}"`, { cause: r });
|
|
49
|
-
}
|
|
43
|
+
function u(t, n) {
|
|
44
|
+
if (n !== void 0 && (!Number.isInteger(n) || n < 0 || n > i)) throw new e("FORMAT_ERROR", `Fraction digits must be integers satisfying 0 ≤ minimum ≤ maximum ≤ ${i} (${t})`);
|
|
50
45
|
}
|
|
51
|
-
function d(
|
|
52
|
-
let
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
46
|
+
function d(e) {
|
|
47
|
+
let t = [];
|
|
48
|
+
for (let n of e) if (n.type === "integer" || n.type === "group") {
|
|
49
|
+
let e = t.at(-1);
|
|
50
|
+
e?.type === "integer" ? t[t.length - 1] = {
|
|
51
|
+
type: "integer",
|
|
52
|
+
value: e.value + n.value
|
|
53
|
+
} : t.push({
|
|
54
|
+
type: "integer",
|
|
55
|
+
value: n.value
|
|
58
56
|
});
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
57
|
+
} else n.type === "currency" || n.type === "decimal" || n.type === "fraction" || n.type === "literal" || n.type === "minusSign" || n.type === "plusSign" ? t.push({
|
|
58
|
+
type: n.type,
|
|
59
|
+
value: n.value
|
|
60
|
+
}) : t.push({
|
|
61
|
+
type: "literal",
|
|
62
|
+
value: n.value
|
|
63
|
+
});
|
|
64
|
+
return t;
|
|
63
65
|
}
|
|
64
66
|
//#endregion
|
|
65
67
|
export { s as format, c as formatParts };
|
package/dist/format.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"format.js","names":[],"sources":["../src/format.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"format.js","names":[],"sources":["../src/format.ts"],"sourcesContent":["import { assertRoundingMode } from './_decimal';\nimport { CoinsError } from './errors';\nimport { assertMoney, toDecimal } from './money';\nimport type { FormatOptions, Money, MoneyFormatPart, RoundingMode } from './types';\n\nconst MAX_FRACTION_DIGITS = 20;\nconst defaultFormatRounding: RoundingMode = 'halfAwayFromZero';\nconst intlRoundingModes: Record<RoundingMode, Intl.NumberFormatOptions['roundingMode']> = {\n awayFromZero: 'expand',\n ceil: 'ceil',\n floor: 'floor',\n halfAwayFromZero: 'halfExpand',\n halfEven: 'halfEven',\n towardZero: 'trunc',\n};\n\nexport function format(value: Money, options: FormatOptions = {}): string {\n return formatParts(value, options)\n .map((part) => part.value)\n .join('');\n}\n\nexport function formatParts(value: Money, options: FormatOptions = {}): MoneyFormatPart[] {\n assertMoney(value);\n assertRoundingMode(options.rounding ?? defaultFormatRounding);\n\n const { maximum, minimum } = fractionDigits(value.currency.minorUnit, options);\n const style = options.style ?? 'symbol';\n\n try {\n const formatter = new Intl.NumberFormat(options.locale ?? 'en-US', {\n currency: value.currency.code,\n currencyDisplay: style,\n maximumFractionDigits: maximum,\n minimumFractionDigits: minimum,\n roundingMode: intlRoundingModes[options.rounding ?? defaultFormatRounding],\n style: 'currency',\n useGrouping: true,\n });\n\n return normalizeParts(formatter.formatToParts(toDecimal(value) as unknown as number));\n } catch (error) {\n if (error instanceof CoinsError) throw error;\n\n throw new CoinsError(\n 'FORMAT_ERROR',\n `Cannot format currency \"${value.currency.code}\" for locale \"${options.locale ?? 'en-US'}\"`,\n { cause: error },\n );\n }\n}\n\nfunction fractionDigits(scale: number, options: FormatOptions): { maximum: number; minimum: number } {\n const requestedMaximum = options.maximumFractionDigits;\n const requestedMinimum = options.minimumFractionDigits;\n\n validateFractionDigit('maximumFractionDigits', requestedMaximum);\n validateFractionDigit('minimumFractionDigits', requestedMinimum);\n\n const maximum = requestedMaximum ?? Math.max(scale, requestedMinimum ?? scale);\n const minimum = requestedMinimum ?? Math.min(scale, requestedMaximum ?? scale);\n\n if (minimum > maximum) {\n throw new CoinsError('FORMAT_ERROR', 'minimumFractionDigits cannot exceed maximumFractionDigits');\n }\n\n return { maximum, minimum };\n}\n\nfunction validateFractionDigit(name: string, value: number | undefined): void {\n if (value !== undefined && (!Number.isInteger(value) || value < 0 || value > MAX_FRACTION_DIGITS)) {\n throw new CoinsError(\n 'FORMAT_ERROR',\n `Fraction digits must be integers satisfying 0 ≤ minimum ≤ maximum ≤ ${MAX_FRACTION_DIGITS} (${name})`,\n );\n }\n}\n\nfunction normalizeParts(raw: Intl.NumberFormatPart[]): MoneyFormatPart[] {\n const parts: MoneyFormatPart[] = [];\n\n for (const part of raw) {\n if (part.type === 'integer' || part.type === 'group') {\n const previous = parts.at(-1);\n\n if (previous?.type === 'integer') {\n parts[parts.length - 1] = { type: 'integer', value: previous.value + part.value };\n } else {\n parts.push({ type: 'integer', value: part.value });\n }\n } else if (\n part.type === 'currency' ||\n part.type === 'decimal' ||\n part.type === 'fraction' ||\n part.type === 'literal' ||\n part.type === 'minusSign' ||\n part.type === 'plusSign'\n ) {\n parts.push({ type: part.type, value: part.value });\n } else {\n parts.push({ type: 'literal', value: part.value });\n }\n }\n\n return parts;\n}\n"],"mappings":";;;;AAKA,IAAM,IAAsB,IACtB,IAAsC,oBACtC,IAAoF;CACxF,cAAc;CACd,MAAM;CACN,OAAO;CACP,kBAAkB;CAClB,UAAU;CACV,YAAY;AACd;AAEA,SAAgB,EAAO,GAAc,IAAyB,CAAC,GAAW;CACxE,OAAO,EAAY,GAAO,CAAO,CAAC,CAC/B,KAAK,MAAS,EAAK,KAAK,CAAC,CACzB,KAAK,EAAE;AACZ;AAEA,SAAgB,EAAY,GAAc,IAAyB,CAAC,GAAsB;CAExF,AADA,EAAY,CAAK,GACjB,EAAmB,EAAQ,YAAY,CAAqB;CAE5D,IAAM,EAAE,YAAS,eAAY,EAAe,EAAM,SAAS,WAAW,CAAO,GACvE,IAAQ,EAAQ,SAAS;CAE/B,IAAI;EAWF,OAAO,EAAe,IAVA,KAAK,aAAa,EAAQ,UAAU,SAAS;GACjE,UAAU,EAAM,SAAS;GACzB,iBAAiB;GACjB,uBAAuB;GACvB,uBAAuB;GACvB,cAAc,EAAkB,EAAQ,YAAY;GACpD,OAAO;GACP,aAAa;EACf,CAEsB,CAAA,CAAU,cAAc,EAAU,CAAK,CAAsB,CAAC;CACtF,SAAS,GAAO;EAGd,MAFI,aAAiB,IAAkB,IAEjC,IAAI,EACR,gBACA,2BAA2B,EAAM,SAAS,KAAK,gBAAgB,EAAQ,UAAU,QAAQ,IACzF,EAAE,OAAO,EAAM,CACjB;CACF;AACF;AAEA,SAAS,EAAe,GAAe,GAA8D;CACnG,IAAM,IAAmB,EAAQ,uBAC3B,IAAmB,EAAQ;CAGjC,AADA,EAAsB,yBAAyB,CAAgB,GAC/D,EAAsB,yBAAyB,CAAgB;CAE/D,IAAM,IAAU,KAAoB,KAAK,IAAI,GAAO,KAAoB,CAAK,GACvE,IAAU,KAAoB,KAAK,IAAI,GAAO,KAAoB,CAAK;CAE7E,IAAI,IAAU,GACZ,MAAM,IAAI,EAAW,gBAAgB,2DAA2D;CAGlG,OAAO;EAAE;EAAS;CAAQ;AAC5B;AAEA,SAAS,EAAsB,GAAc,GAAiC;CAC5E,IAAI,MAAU,KAAA,MAAc,CAAC,OAAO,UAAU,CAAK,KAAK,IAAQ,KAAK,IAAQ,IAC3E,MAAM,IAAI,EACR,gBACA,uEAAuE,EAAoB,IAAI,EAAK,EACtG;AAEJ;AAEA,SAAS,EAAe,GAAiD;CACvE,IAAM,IAA2B,CAAC;CAElC,KAAK,IAAM,KAAQ,GACjB,IAAI,EAAK,SAAS,aAAa,EAAK,SAAS,SAAS;EACpD,IAAM,IAAW,EAAM,GAAG,EAAE;EAE5B,AAAI,GAAU,SAAS,YACrB,EAAM,EAAM,SAAS,KAAK;GAAE,MAAM;GAAW,OAAO,EAAS,QAAQ,EAAK;EAAM,IAEhF,EAAM,KAAK;GAAE,MAAM;GAAW,OAAO,EAAK;EAAM,CAAC;CAErD,OAAO,AACL,EAAK,SAAS,cACd,EAAK,SAAS,aACd,EAAK,SAAS,cACd,EAAK,SAAS,aACd,EAAK,SAAS,eACd,EAAK,SAAS,aAEd,EAAM,KAAK;EAAE,MAAM,EAAK;EAAM,OAAO,EAAK;CAAM,CAAC,IAEjD,EAAM,KAAK;EAAE,MAAM;EAAW,OAAO,EAAK;CAAM,CAAC;CAIrD,OAAO;AACT"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./currency.cjs"),n=require("./money.cjs"),r=require("./aggregate.cjs"),i=require("./exchange.cjs"),a=require("./format.cjs"),o=require("./serialization.cjs");exports.BHD=t.BHD,exports.CoinsError=e.CoinsError,exports.CurrencyMismatchError=e.CurrencyMismatchError,exports.EUR=t.EUR,exports.GBP=t.GBP,exports.InvalidCurrencyError=e.InvalidCurrencyError,exports.JPY=t.JPY,exports.KRW=t.KRW,exports.KWD=t.KWD,exports.USD=t.USD,exports.abs=n.abs,exports.add=n.add,exports.allocate=r.allocate,exports.clamp=n.clamp,exports.compare=n.compare,exports.currency=t.currency,exports.
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./errors.cjs"),t=require("./currency.cjs"),n=require("./money.cjs"),r=require("./aggregate.cjs"),i=require("./exchange.cjs"),a=require("./format.cjs"),o=require("./serialization.cjs");exports.BHD=t.BHD,exports.CoinsError=e.CoinsError,exports.CurrencyMismatchError=e.CurrencyMismatchError,exports.EUR=t.EUR,exports.GBP=t.GBP,exports.InvalidCurrencyError=e.InvalidCurrencyError,exports.JPY=t.JPY,exports.KRW=t.KRW,exports.KWD=t.KWD,exports.USD=t.USD,exports.abs=n.abs,exports.add=n.add,exports.allocate=r.allocate,exports.clamp=n.clamp,exports.compare=n.compare,exports.currency=t.currency,exports.decodeMoney=n.decodeMoney,exports.divide=n.divide,exports.exchange=i.exchange,exports.exchangeRate=i.exchangeRate,exports.format=a.format,exports.formatParts=a.formatParts,exports.isCurrency=t.isCurrency,exports.isExchangeRate=i.isExchangeRate,exports.isMoney=n.isMoney,exports.money=n.money,exports.multiply=n.multiply,exports.negate=n.negate,exports.round=n.round,exports.subtract=n.subtract,exports.sum=r.sum,exports.toDecimal=n.toDecimal,exports.toJSON=o.toJSON;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export { allocate, sum } from './aggregate';
|
|
2
|
-
export { BHD, currency,
|
|
2
|
+
export { BHD, currency, EUR, GBP, isCurrency, JPY, KRW, KWD, USD } from './currency';
|
|
3
3
|
export type { CoinsErrorCode } from './errors';
|
|
4
4
|
export { CoinsError, CurrencyMismatchError, InvalidCurrencyError } from './errors';
|
|
5
|
-
export { exchange, exchangeRate } from './exchange';
|
|
5
|
+
export { exchange, exchangeRate, isExchangeRate } from './exchange';
|
|
6
6
|
export { format, formatParts } from './format';
|
|
7
|
-
export { abs, add, clamp, compare, divide, isMoney, money, multiply, negate,
|
|
8
|
-
export {
|
|
7
|
+
export { abs, add, clamp, compare, decodeMoney, divide, isMoney, money, multiply, negate, round, subtract, toDecimal, } from './money';
|
|
8
|
+
export { toJSON } from './serialization';
|
|
9
9
|
export type { Currency, CurrencyCode, Decimal, ExchangeRate, FormatOptions, Money, MoneyFormatPart, MoneyJSON, RoundingMode, } from './types';
|
|
10
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AACrF,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACnF,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EACL,GAAG,EACH,GAAG,EACH,KAAK,EACL,OAAO,EACP,WAAW,EACX,MAAM,EACN,OAAO,EACP,KAAK,EACL,QAAQ,EACR,MAAM,EACN,KAAK,EACL,QAAQ,EACR,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,aAAa,EACb,KAAK,EACL,eAAe,EACf,SAAS,EACT,YAAY,GACb,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { CoinsError as e, CurrencyMismatchError as t, InvalidCurrencyError as n } from "./errors.js";
|
|
2
|
-
import { BHD as r, EUR as i, GBP as a, JPY as o, KRW as s, KWD as c, USD as l, currency as u,
|
|
3
|
-
import { abs as
|
|
4
|
-
import { allocate as
|
|
5
|
-
import { exchange as
|
|
2
|
+
import { BHD as r, EUR as i, GBP as a, JPY as o, KRW as s, KWD as c, USD as l, currency as u, isCurrency as d } from "./currency.js";
|
|
3
|
+
import { abs as f, add as p, clamp as m, compare as h, decodeMoney as g, divide as _, isMoney as v, money as y, multiply as b, negate as x, round as S, subtract as C, toDecimal as w } from "./money.js";
|
|
4
|
+
import { allocate as T, sum as E } from "./aggregate.js";
|
|
5
|
+
import { exchange as D, exchangeRate as O, isExchangeRate as k } from "./exchange.js";
|
|
6
6
|
import { format as A, formatParts as j } from "./format.js";
|
|
7
|
-
import {
|
|
8
|
-
export { r as BHD, e as CoinsError, t as CurrencyMismatchError, i as EUR, a as GBP, n as InvalidCurrencyError, o as JPY, s as KRW, c as KWD, l as USD,
|
|
7
|
+
import { toJSON as M } from "./serialization.js";
|
|
8
|
+
export { r as BHD, e as CoinsError, t as CurrencyMismatchError, i as EUR, a as GBP, n as InvalidCurrencyError, o as JPY, s as KRW, c as KWD, l as USD, f as abs, p as add, T as allocate, m as clamp, h as compare, u as currency, g as decodeMoney, _ as divide, D as exchange, O as exchangeRate, A as format, j as formatParts, d as isCurrency, k as isExchangeRate, v as isMoney, y as money, b as multiply, x as negate, S as round, C as subtract, E as sum, w as toDecimal, M as toJSON };
|
package/dist/money.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("./errors.cjs"),t=require("./
|
|
1
|
+
const e=require("./errors.cjs"),t=require("./_decimal.cjs"),n=require("./currency.cjs");var r=new WeakSet,i=`halfAwayFromZero`,a=/^(?:0|-[1-9]\d*|[1-9]\d*)$/,o=1e3;function s(n,r,a){if(C(r),typeof n==`bigint`){if(!a||!(`unit`in a)||a.unit!==`minor`)throw new e.CoinsError(`INVALID_MONEY`,`Bigint amounts require { unit: 'minor' }`);return b(n,r)}if(a&&`unit`in a)throw new e.CoinsError(`INVALID_MONEY`,`Decimal strings do not accept a unit option`);let o=t.decimal(n),s=o.numerator*10n**BigInt(r.minorUnit);if(s%o.denominator!==0n&&a?.rounding===void 0)throw new e.CoinsError(`INVALID_MONEY`,`Amount "${n}" exceeds ${r.code} precision; provide rounding`);return b(t.roundDivision(s,o.denominator,a?.rounding??i),r)}function c(t,r){if(!w(t))throw new e.CoinsError(`INVALID_MONEY`,`Money must be a plain data object`);let i=Object.getOwnPropertyDescriptors(t),c=i.amount,l=i.currency;if(!T(c)||!T(l))throw new e.CoinsError(`INVALID_MONEY`,`Money properties must be plain data values`);let u=Reflect.ownKeys(t);if(typeof c.value==`bigint`&&n.isCurrency(l.value)){if(u.length!==2)throw new e.CoinsError(`INVALID_MONEY`,`Plain money must have exactly the keys amount and currency`);return b(c.value,l.value)}let d=i.unit;if(typeof c.value==`string`&&typeof l.value==`string`&&T(d)&&d.value===`minor`){if(u.length!==3)throw new e.CoinsError(`INVALID_MONEY`,`MoneyJSON must have exactly the keys amount, currency, unit`);if(c.value.length>o)throw new e.CoinsError(`INVALID_MONEY`,`Money JSON amount is too long; maximum ${o} characters`);if(!a.test(c.value))throw new e.CoinsError(`INVALID_MONEY`,`Invalid Money JSON amount "${c.value}"`);let t=r?.currency??n.currency;try{let r=t(l.value);if(!n.isCurrency(r)||r.code!==l.value)throw new e.CoinsError(`INVALID_CURRENCY`,`Currency resolver must return the canonical "${l.value}" definition`);return s(BigInt(c.value),r,{unit:`minor`})}catch(t){throw new e.CoinsError(`INVALID_MONEY`,`Invalid Money JSON for currency "${l.value}"`,{cause:t})}}throw new e.CoinsError(`INVALID_MONEY`,`Money must contain bigint amount and a registered currency, or a valid MoneyJSON shape`)}function l(e){return typeof e==`object`&&!!e&&r.has(e)}function u(e,t){return S(e,t),b(e.amount+t.amount,e.currency)}function d(e,t){return S(e,t),b(e.amount-t.amount,e.currency)}function f(e,n,r={}){x(e);let a=t.decimal(n);return b(t.roundDivision(e.amount*a.numerator,a.denominator,r.rounding??i),e.currency)}function p(n,r,a={}){x(n);let o=t.decimal(r);if(o.numerator===0n)throw new e.CoinsError(`DIVISION_BY_ZERO`,`Cannot divide money by zero`);let s=o.numerator<0n?-o.numerator:o.numerator,c=n.amount*o.denominator;return b(t.roundDivision(o.numerator<0n?-c:c,s,a.rounding??i),n.currency)}function m(e,t){return S(e,t),e.amount===t.amount?0:e.amount<t.amount?-1:1}function h(t,n){if(m(n.min,n.max)===1)throw new e.CoinsError(`INVALID_RANGE`,`Clamp minimum cannot exceed maximum`);return m(t,n.min)===-1?n.min:m(t,n.max)===1?n.max:t}function g(e){return x(e),b(e.amount<0n?-e.amount:e.amount,e.currency)}function _(e){return x(e),b(-e.amount,e.currency)}function v(n,r){x(n);let{fractionDigits:a,rounding:o=i}=r;if(!Number.isInteger(a)||a<0||a>n.currency.minorUnit)throw new e.CoinsError(`INVALID_ROUNDING`,`fractionDigits must be an integer from 0 to ${n.currency.minorUnit}`);let s=10n**BigInt(n.currency.minorUnit-a);return b(t.roundDivision(n.amount,s,o)*s,n.currency)}function y(e){return x(e),t.toDecimalString(e.amount,e.currency.minorUnit)}function b(e,t){let n=Object.freeze({amount:e,currency:t});return r.add(n),n}function x(t){if(!l(t))throw new e.CoinsError(`INVALID_MONEY`,`Money must be a canonical @vielzeug/coins value`)}function S(t,n){if(x(t),x(n),t.currency!==n.currency)throw new e.CurrencyMismatchError(t.currency.code,n.currency.code)}function C(t){if(!n.isCurrency(t))throw new e.CoinsError(`INVALID_CURRENCY`,`Money requires a registered currency`)}function w(e){if(typeof e!=`object`||!e)return!1;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function T(e){return e!==void 0&&`value`in e&&e.get===void 0&&e.set===void 0}exports.abs=g,exports.add=u,exports.assertMoney=x,exports.clamp=h,exports.compare=m,exports.createMoney=b,exports.decodeMoney=c,exports.divide=p,exports.isMoney=l,exports.money=s,exports.multiply=f,exports.negate=_,exports.round=v,exports.subtract=d,exports.toDecimal=y;
|
|
2
2
|
//# sourceMappingURL=money.cjs.map
|
package/dist/money.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.cjs","names":[],"sources":["../src/money.ts"],"sourcesContent":["import { isCurrency } from './currency';\nimport { decimal, roundDivision, toDecimalString } from './decimal';\nimport { CoinsError, CurrencyMismatchError } from './errors';\nimport type { Currency, Money, RoundingMode } from './types';\n\nconst defaultRounding: RoundingMode = 'halfAwayFromZero';\n\nexport function money<C extends Currency>(amount: string, currency: C): Money<C>;\nexport function money<C extends Currency>(amount: string, currency: C, options: { rounding: RoundingMode }): Money<C>;\nexport function money<C extends Currency>(amount: bigint, currency: C, options: { unit: 'minor' }): Money<C>;\nexport function money<C extends Currency>(\n amount: bigint | string,\n currency: C,\n options?: { rounding: RoundingMode } | { unit: 'minor' },\n): Money<C> {\n assertCurrency(currency);\n\n if (typeof amount === 'bigint') {\n if (!options || !('unit' in options) || options.unit !== 'minor') {\n throw new CoinsError('INVALID_MONEY', \"Bigint amounts require { unit: 'minor' }\");\n }\n\n return createMoney(amount, currency);\n }\n\n if (options && 'unit' in options)\n throw new CoinsError('INVALID_MONEY', 'Decimal strings do not accept a unit option');\n\n const value = decimal(amount);\n const scaled = value.numerator * 10n ** BigInt(currency.minorUnit);\n const remainder = scaled % value.denominator;\n\n if (remainder !== 0n && !options) {\n throw new CoinsError('INVALID_MONEY', `Amount \"${amount}\" exceeds ${currency.code} precision; provide rounding`);\n }\n\n return createMoney(roundDivision(scaled, value.denominator, options?.rounding ?? defaultRounding), currency);\n}\n\nexport function parseMoney(value: unknown): Money {\n if (!isPlainDataObject(value)) throw new CoinsError('INVALID_MONEY', 'Money must be a plain data object');\n\n const descriptors = Object.getOwnPropertyDescriptors(value);\n const amountDescriptor = descriptors.amount;\n const currencyDescriptor = descriptors.currency;\n\n if (!isDataProperty(amountDescriptor) || !isDataProperty(currencyDescriptor)) {\n throw new CoinsError('INVALID_MONEY', 'Money properties must be plain data values');\n }\n\n if (typeof amountDescriptor.value !== 'bigint' || !isCurrency(currencyDescriptor.value)) {\n throw new CoinsError('INVALID_MONEY', 'Money must contain bigint amount and a registered currency');\n }\n\n return createMoney(amountDescriptor.value, currencyDescriptor.value);\n}\n\nexport function isMoney(value: unknown): value is Money {\n try {\n parseMoney(value);\n\n return true;\n } catch {\n return false;\n }\n}\n\nexport function add<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C> {\n assertSameCurrency(left, right);\n\n return createMoney(left.amount + right.amount, left.currency);\n}\n\nexport function subtract<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C> {\n assertSameCurrency(left, right);\n\n return createMoney(left.amount - right.amount, left.currency);\n}\n\nexport function multiply<C extends Currency>(\n value: Money<C>,\n factor: string,\n options: { rounding?: RoundingMode } = {},\n): Money<C> {\n assertMoney(value);\n\n const scalar = decimal(factor);\n\n return createMoney(\n roundDivision(value.amount * scalar.numerator, scalar.denominator, options.rounding ?? defaultRounding),\n value.currency,\n );\n}\n\nexport function divide<C extends Currency>(\n value: Money<C>,\n divisor: string,\n options: { rounding?: RoundingMode } = {},\n): Money<C> {\n assertMoney(value);\n\n const scalar = decimal(divisor);\n\n if (scalar.numerator === 0n) throw new CoinsError('DIVISION_BY_ZERO', 'Cannot divide money by zero');\n\n const negative = scalar.numerator < 0n;\n const absoluteDivisor = negative ? -scalar.numerator : scalar.numerator;\n const quotient = roundDivision(\n value.amount * scalar.denominator,\n absoluteDivisor,\n options.rounding ?? defaultRounding,\n );\n\n return createMoney(negative ? -quotient : quotient, value.currency);\n}\n\nexport function compare<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): -1 | 0 | 1 {\n assertSameCurrency(left, right);\n\n return left.amount === right.amount ? 0 : left.amount < right.amount ? -1 : 1;\n}\n\nexport function clamp<C extends Currency>(\n value: Money<C>,\n options: { max: Money<NoInfer<C>>; min: Money<NoInfer<C>> },\n): Money<C> {\n if (compare(options.min, options.max) === 1) {\n throw new CoinsError('INVALID_MONEY', 'Clamp minimum cannot exceed maximum');\n }\n\n return compare(value, options.min) === -1 ? options.min : compare(value, options.max) === 1 ? options.max : value;\n}\n\nexport function abs<C extends Currency>(value: Money<C>): Money<C> {\n assertMoney(value);\n\n return createMoney(value.amount < 0n ? -value.amount : value.amount, value.currency);\n}\n\nexport function negate<C extends Currency>(value: Money<C>): Money<C> {\n assertMoney(value);\n\n return createMoney(-value.amount, value.currency);\n}\n\nexport function round<C extends Currency>(\n value: Money<C>,\n options: { fractionDigits: number; rounding?: RoundingMode },\n): Money<C> {\n assertMoney(value);\n\n const { fractionDigits, rounding = defaultRounding } = options;\n\n if (!Number.isInteger(fractionDigits) || fractionDigits < 0 || fractionDigits > value.currency.minorUnit) {\n throw new CoinsError('INVALID_ROUNDING', `fractionDigits must be an integer from 0 to ${value.currency.minorUnit}`);\n }\n\n const factor = 10n ** BigInt(value.currency.minorUnit - fractionDigits);\n\n return createMoney(roundDivision(value.amount, factor, rounding) * factor, value.currency);\n}\n\nexport function toDecimal(value: Money): string {\n assertMoney(value);\n\n return toDecimalString(value.amount, value.currency.minorUnit);\n}\n\nexport function withMinor<C extends Currency>(amount: bigint, currency: C): Money<C> {\n assertCurrency(currency);\n\n return createMoney(amount, currency);\n}\n\nfunction createMoney<C extends Currency>(amount: bigint, currency: C): Money<C> {\n return Object.freeze({ amount, currency }) as Money<C>;\n}\n\nfunction assertMoney(value: Money): void {\n if (!Object.isFrozen(value) || !isCurrency(value.currency)) {\n throw new CoinsError('INVALID_MONEY', 'Money must be a canonical Coins value');\n }\n}\n\nfunction assertSameCurrency(left: Money, right: Money): void {\n assertMoney(left);\n assertMoney(right);\n\n if (left.currency !== right.currency) {\n throw new CurrencyMismatchError(left.currency.code, right.currency.code);\n }\n}\n\nfunction assertCurrency(value: Currency): void {\n if (!isCurrency(value)) throw new CoinsError('INVALID_CURRENCY', 'Money requires a registered currency');\n}\n\nfunction isPlainDataObject(value: unknown): value is Record<PropertyKey, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction isDataProperty(\n descriptor: PropertyDescriptor | undefined,\n): descriptor is PropertyDescriptor & { value: unknown } {\n return (\n descriptor !== undefined && 'value' in descriptor && descriptor.get === undefined && descriptor.set === undefined\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"money.cjs","names":[],"sources":["../src/money.ts"],"sourcesContent":["import { decimal, roundDivision, toDecimalString } from './_decimal';\nimport { currency, isCurrency } from './currency';\nimport { CoinsError, CurrencyMismatchError } from './errors';\nimport type { Currency, Money, RoundingMode } from './types';\n\nconst canonicalMoney = new WeakSet<object>();\n\nconst defaultRounding: RoundingMode = 'halfAwayFromZero';\n\nconst INTEGER = /^(?:0|-[1-9]\\d*|[1-9]\\d*)$/;\nconst MAX_INTEGER_DIGITS = 1000;\n\nexport function money<C extends Currency>(amount: string, currency: C, options?: { rounding?: RoundingMode }): Money<C>;\nexport function money<C extends Currency>(amount: bigint, currency: C, options: { unit: 'minor' }): Money<C>;\nexport function money<C extends Currency>(\n amount: bigint | string,\n currency: C,\n options?: { rounding?: RoundingMode } | { unit: 'minor' },\n): Money<C> {\n assertCurrency(currency);\n\n if (typeof amount === 'bigint') {\n if (!options || !('unit' in options) || options.unit !== 'minor') {\n throw new CoinsError('INVALID_MONEY', \"Bigint amounts require { unit: 'minor' }\");\n }\n\n return createMoney(amount, currency);\n }\n\n if (options && 'unit' in options)\n throw new CoinsError('INVALID_MONEY', 'Decimal strings do not accept a unit option');\n\n const value = decimal(amount);\n const scaled = value.numerator * 10n ** BigInt(currency.minorUnit);\n const remainder = scaled % value.denominator;\n\n if (remainder !== 0n && options?.rounding === undefined) {\n throw new CoinsError('INVALID_MONEY', `Amount \"${amount}\" exceeds ${currency.code} precision; provide rounding`);\n }\n\n return createMoney(roundDivision(scaled, value.denominator, options?.rounding ?? defaultRounding), currency);\n}\n\n/**\n * Decodes untrusted/persisted data into canonical `Money`.\n * Accepts either a plain `Money`-shaped object (`{ amount: bigint, currency: Currency }`)\n * or a `MoneyJSON`-shaped object (`{ amount: string, currency: string, unit: 'minor' }`).\n * Use `money()` for trusted construction; use `decodeMoney()` for network/storage data.\n */\nexport function decodeMoney(value: unknown, options?: { currency?: (code: string) => Currency }): Money {\n if (!isPlainDataObject(value)) throw new CoinsError('INVALID_MONEY', 'Money must be a plain data object');\n\n const descriptors = Object.getOwnPropertyDescriptors(value);\n const amountDescriptor = descriptors.amount;\n const currencyDescriptor = descriptors.currency;\n\n if (!isDataProperty(amountDescriptor) || !isDataProperty(currencyDescriptor)) {\n throw new CoinsError('INVALID_MONEY', 'Money properties must be plain data values');\n }\n\n const ownKeys = Reflect.ownKeys(value);\n\n // Plain Money: bigint amount + registered currency\n if (typeof amountDescriptor.value === 'bigint' && isCurrency(currencyDescriptor.value)) {\n if (ownKeys.length !== 2) {\n throw new CoinsError('INVALID_MONEY', 'Plain money must have exactly the keys amount and currency');\n }\n\n return createMoney(amountDescriptor.value, currencyDescriptor.value);\n }\n\n // MoneyJSON: string amount + string currency code + unit: 'minor'\n const unitDescriptor = descriptors.unit;\n if (\n typeof amountDescriptor.value === 'string' &&\n typeof currencyDescriptor.value === 'string' &&\n isDataProperty(unitDescriptor) &&\n unitDescriptor.value === 'minor'\n ) {\n if (ownKeys.length !== 3) {\n throw new CoinsError('INVALID_MONEY', 'MoneyJSON must have exactly the keys amount, currency, unit');\n }\n if (amountDescriptor.value.length > MAX_INTEGER_DIGITS) {\n throw new CoinsError('INVALID_MONEY', `Money JSON amount is too long; maximum ${MAX_INTEGER_DIGITS} characters`);\n }\n if (!INTEGER.test(amountDescriptor.value)) {\n throw new CoinsError('INVALID_MONEY', `Invalid Money JSON amount \"${amountDescriptor.value}\"`);\n }\n const resolveCurrency = options?.currency ?? currency;\n try {\n const resolvedCurrency = resolveCurrency(currencyDescriptor.value);\n\n if (!isCurrency(resolvedCurrency) || resolvedCurrency.code !== currencyDescriptor.value) {\n throw new CoinsError(\n 'INVALID_CURRENCY',\n `Currency resolver must return the canonical \"${currencyDescriptor.value}\" definition`,\n );\n }\n\n return money(BigInt(amountDescriptor.value), resolvedCurrency, { unit: 'minor' });\n } catch (error) {\n throw new CoinsError('INVALID_MONEY', `Invalid Money JSON for currency \"${currencyDescriptor.value}\"`, {\n cause: error,\n });\n }\n }\n\n throw new CoinsError(\n 'INVALID_MONEY',\n 'Money must contain bigint amount and a registered currency, or a valid MoneyJSON shape',\n );\n}\n\nexport function isMoney(value: unknown): value is Money {\n return typeof value === 'object' && value !== null && canonicalMoney.has(value);\n}\n\nexport function add<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C> {\n assertSameCurrency(left, right);\n\n return createMoney(left.amount + right.amount, left.currency);\n}\n\nexport function subtract<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C> {\n assertSameCurrency(left, right);\n\n return createMoney(left.amount - right.amount, left.currency);\n}\n\nexport function multiply<C extends Currency>(\n value: Money<C>,\n factor: string,\n options: { rounding?: RoundingMode } = {},\n): Money<C> {\n assertMoney(value);\n\n const scalar = decimal(factor);\n\n return createMoney(\n roundDivision(value.amount * scalar.numerator, scalar.denominator, options.rounding ?? defaultRounding),\n value.currency,\n );\n}\n\nexport function divide<C extends Currency>(\n value: Money<C>,\n divisor: string,\n options: { rounding?: RoundingMode } = {},\n): Money<C> {\n assertMoney(value);\n\n const scalar = decimal(divisor);\n\n if (scalar.numerator === 0n) throw new CoinsError('DIVISION_BY_ZERO', 'Cannot divide money by zero');\n\n const divisorMagnitude = scalar.numerator < 0n ? -scalar.numerator : scalar.numerator;\n const dividend = value.amount * scalar.denominator;\n const quotient = roundDivision(\n scalar.numerator < 0n ? -dividend : dividend,\n divisorMagnitude,\n options.rounding ?? defaultRounding,\n );\n\n return createMoney(quotient, value.currency);\n}\n\nexport function compare<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): -1 | 0 | 1 {\n assertSameCurrency(left, right);\n\n return left.amount === right.amount ? 0 : left.amount < right.amount ? -1 : 1;\n}\n\nexport function clamp<C extends Currency>(\n value: Money<C>,\n options: { max: Money<NoInfer<C>>; min: Money<NoInfer<C>> },\n): Money<C> {\n if (compare(options.min, options.max) === 1) {\n throw new CoinsError('INVALID_RANGE', 'Clamp minimum cannot exceed maximum');\n }\n\n return compare(value, options.min) === -1 ? options.min : compare(value, options.max) === 1 ? options.max : value;\n}\n\nexport function abs<C extends Currency>(value: Money<C>): Money<C> {\n assertMoney(value);\n\n return createMoney(value.amount < 0n ? -value.amount : value.amount, value.currency);\n}\n\nexport function negate<C extends Currency>(value: Money<C>): Money<C> {\n assertMoney(value);\n\n return createMoney(-value.amount, value.currency);\n}\n\nexport function round<C extends Currency>(\n value: Money<C>,\n options: { fractionDigits: number; rounding?: RoundingMode },\n): Money<C> {\n assertMoney(value);\n\n const { fractionDigits, rounding = defaultRounding } = options;\n\n if (!Number.isInteger(fractionDigits) || fractionDigits < 0 || fractionDigits > value.currency.minorUnit) {\n throw new CoinsError('INVALID_ROUNDING', `fractionDigits must be an integer from 0 to ${value.currency.minorUnit}`);\n }\n\n const factor = 10n ** BigInt(value.currency.minorUnit - fractionDigits);\n\n return createMoney(roundDivision(value.amount, factor, rounding) * factor, value.currency);\n}\n\nexport function toDecimal(value: Money): string {\n assertMoney(value);\n\n return toDecimalString(value.amount, value.currency.minorUnit);\n}\n\nexport function createMoney<C extends Currency>(amount: bigint, currency: C): Money<C> {\n const value = Object.freeze({ amount, currency }) as Money<C>;\n\n canonicalMoney.add(value);\n\n return value;\n}\n\nexport function assertMoney(value: unknown): asserts value is Money {\n if (!isMoney(value)) {\n throw new CoinsError('INVALID_MONEY', 'Money must be a canonical @vielzeug/coins value');\n }\n}\n\nfunction assertSameCurrency(left: Money, right: Money): void {\n assertMoney(left);\n assertMoney(right);\n\n if (left.currency !== right.currency) {\n throw new CurrencyMismatchError(left.currency.code, right.currency.code);\n }\n}\n\nfunction assertCurrency(value: unknown): asserts value is Currency {\n if (!isCurrency(value)) throw new CoinsError('INVALID_CURRENCY', 'Money requires a registered currency');\n}\n\nfunction isPlainDataObject(value: unknown): value is Record<PropertyKey, unknown> {\n if (typeof value !== 'object' || value === null) return false;\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n\nfunction isDataProperty(\n descriptor: PropertyDescriptor | undefined,\n): descriptor is PropertyDescriptor & { value: unknown } {\n return (\n descriptor !== undefined && 'value' in descriptor && descriptor.get === undefined && descriptor.set === undefined\n );\n}\n"],"mappings":"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"}
|
package/dist/money.d.ts
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
import type { Currency, Money, RoundingMode } from './types';
|
|
2
|
-
export declare function money<C extends Currency>(amount: string, currency: C
|
|
3
|
-
|
|
4
|
-
rounding: RoundingMode;
|
|
2
|
+
export declare function money<C extends Currency>(amount: string, currency: C, options?: {
|
|
3
|
+
rounding?: RoundingMode;
|
|
5
4
|
}): Money<C>;
|
|
6
5
|
export declare function money<C extends Currency>(amount: bigint, currency: C, options: {
|
|
7
6
|
unit: 'minor';
|
|
8
7
|
}): Money<C>;
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* Decodes untrusted/persisted data into canonical `Money`.
|
|
10
|
+
* Accepts either a plain `Money`-shaped object (`{ amount: bigint, currency: Currency }`)
|
|
11
|
+
* or a `MoneyJSON`-shaped object (`{ amount: string, currency: string, unit: 'minor' }`).
|
|
12
|
+
* Use `money()` for trusted construction; use `decodeMoney()` for network/storage data.
|
|
13
|
+
*/
|
|
14
|
+
export declare function decodeMoney(value: unknown, options?: {
|
|
15
|
+
currency?: (code: string) => Currency;
|
|
16
|
+
}): Money;
|
|
10
17
|
export declare function isMoney(value: unknown): value is Money;
|
|
11
18
|
export declare function add<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C>;
|
|
12
19
|
export declare function subtract<C extends Currency>(left: Money<C>, right: Money<NoInfer<C>>): Money<C>;
|
|
@@ -28,5 +35,6 @@ export declare function round<C extends Currency>(value: Money<C>, options: {
|
|
|
28
35
|
rounding?: RoundingMode;
|
|
29
36
|
}): Money<C>;
|
|
30
37
|
export declare function toDecimal(value: Money): string;
|
|
31
|
-
export declare function
|
|
38
|
+
export declare function createMoney<C extends Currency>(amount: bigint, currency: C): Money<C>;
|
|
39
|
+
export declare function assertMoney(value: unknown): asserts value is Money;
|
|
32
40
|
//# sourceMappingURL=money.d.ts.map
|
package/dist/money.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"money.d.ts","sourceRoot":"","sources":["../src/money.ts"],"names":[],"mappings":"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"}
|