money-lib
Version:
TypeScript library to work with money
139 lines (107 loc) • 3.49 kB
text/typescript
import * as money from "../core";
import type { ChainedMoneyV2, ConfigV2, MoneyV2 } from "./types";
import { symbolChain } from "./types";
import { setConfig, config } from "../config";
import { parseMoneyInput } from "./helpers";
/**
* @beta This is an beta API V2.
*/
export const moneyChain = <CC extends string, CS extends string>(
input?: MoneyV2<CC, CS> | ChainedMoneyV2<CC, CS>,
currency?: CC | Lowercase<CC>
): ChainedMoneyV2<CC, CS> => {
const nextChain = moneyChain<CC, CS>;
const parse = parseMoneyInput<CC, CS>;
const _m = parse(input);
_m.currency = currency || _m.currency || config.defaultCurrency;
const _chain: ChainedMoneyV2<CC, CS> = {
int: () => money.toInt(_m),
cents: () => money.toInt(_m),
float: () => money.toFloat(_m),
number: () => money.toFloat(_m),
string: () => money.toFloatString(_m),
centStr: () => money.toString(_m),
cmp: (m) => money.compare(_m, parse(m)),
eq: (m) => money.equals(_m, parse(m)),
gt: (m) => money.greaterThan(_m, parse(m)),
gte: (m) => money.greaterThanOrEqual(_m, parse(m)),
lt: (m) => money.lessThan(_m, parse(m)),
lte: (m) => money.lessThanOrEqual(_m, parse(m)),
is0: () => money.isZero(_m),
isPos: () => money.isPositive(_m),
isNeg: () => money.isNegative(_m),
min: (m1, ...m) => nextChain(money.min(parse(m1), ...m.map(parse))),
max: (m1, ...m) => nextChain(money.max(parse(m1), ...m.map(parse))),
validate: () => money.isValid(_m),
split: () => {
const split = money.split(_m);
return {
base: split.whole,
cents: split.cents,
};
},
add: (m1, ...m) => nextChain(money.add(_m, parse(m1), ...m.map(parse))),
sub: (m1, ...m) =>
nextChain(money.subtract(_m, parse(m1), ...m.map(parse))),
mul: (multiplier: number, round = Math.round) =>
nextChain(money.multiply(_m, multiplier, round)),
div: (divider: number, round = Math.round) =>
nextChain(money.divide(_m, divider, round)),
abs: () => nextChain(money.abs(_m)),
fmt: (ops?: {
locale?: string;
cents?: boolean;
withPlusSign?: boolean;
trailingZeros?: boolean;
}) => money.format(_m, ops),
fmts: (locale?: string) => {
const fmtd = money.formatParts(_m, locale);
return {
base: fmtd.whole,
cents: fmtd.cents,
baseFormatted: fmtd.wholeFormatted,
currencySymbol: fmtd.currencySymbol,
decimalSeparator: fmtd.decimalSeparator,
sign: fmtd.sign,
};
},
parse: (s: string, currency?: string) => {
const parsed = parse(s as any);
return nextChain({
amount: parsed.amount,
currency: currency ?? parsed.currency ?? config.defaultCurrency,
});
},
debug: (prefix = "money:") => {
console.log(prefix, {
cents: _m.amount,
currency: _m.currency,
});
return nextChain(_m);
},
json: () => _m,
[symbolChain]: true,
};
return _chain;
};
export const setupMoney = <CC extends string, CS extends string>(
cfg: ConfigV2<CC, CS>
) => {
setConfig({
defaultCurrency: cfg.defaultCurrency,
defaultRoundingMethod: cfg.defaultRoundingMethod,
currencies: Object.fromEntries(
cfg.currencies.map((c) => [
c.code,
{
code: c.code,
symbol: c.symbol,
precision: c.scale,
},
])
),
});
return {
money: moneyChain<CC, CS>,
};
};