0.4.2 • Published 3 years ago

@soldi/core v0.4.2

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

@soldi/core

Soldi is a simple currency manipulation library for safely calculating with monetary values in JavaScript.

codecov quality dependencies npm (scoped) GitHub npm bundle size (scoped) Snyk Vulnerabilities for npm scoped package

Benefits of Soldi

  • Fluent, immutable, and chainable API
  • Easily extensible, with several extensions already written
  • Overflow detection
  • Currency exchange features
  • Formatting Options via Extensions
  • 100% test coverage
  • Enthusiastic maintainer open to community contributions

Installation

For new users we recommend using @soldi/core directly.

npm install @soldi/core

or

yarn add @soldi/core

Usage

Soldi makes it easy to create and calculate using monetary values.

Amounts are specified in minor currency units (e.g.: "cents" for the dollar). You must also specify a currency. We suggest using ISO 4217 currency codes, but you are free to use anything you want.

For example to construct €1:

let oneEuro = Soldi({ amount: 100, currency: 'EUR' });

You can add and subtract amounts provided they have the same currency:

// returns a Soldi object with amount: 600 and currency 'EUR'
oneEuro.add(Soldi({ amount: 500, currency: 'EUR' }));
// returns a Soldi object with amount: 4500 and currency 'EUR'
price.subtract(Soldi({ amount: 500, currency: 'EUR' }));

Soldi is immutable, which means you always receive a new Soldi instance when you perform any operation on it. The original instance is unmodified by any operation.

All transformative operations return a Soldi instance, so you can chain methods to perform a series of operations.

// Calculates ( 50 + 50 ) * 4 => 400
// not: 50 + 50 * 4 => 250
// as would be expected using normal operator precedence
Soldi({ amount: 50, currency: 'EUR' })
  .add(Soldi({ amount: 50, currency: 'EUR' }))
  .multiply(4);

Operations are executed in the chained order, so operator precedence is as written in the chain, not as it would be for an equivalently expressed mathematical expression.

You can also introspect your Soldi instance in various ways:

// returns true
Soldi({ amount: 500, currency }).isEqualTo(Soldi({ amount: 500, currency }));

// returns false
Soldi({ amount: 100, currency }).isZero();

// returns true
Soldi({ amount: 50, currency }).hasSubUnits();

Soldi can also be constructed with a precision, which tells Soldi how many sub-units the currency supports, or to support more sub-units than is common for the currency. For example if you wanted to create a system capable of accounting hundredths of a cent, you could use a higher precision soldi to do the calculations.

const onePreciseEuro = Soldi({ amount: 10000, precision: 4, currency });

Soldi also handles mixing precisions, and promotes lower precision numbers to the highest precision amongst the Soldi in the operations.

// Returns Soldi { amount: 20000, precision: 4, currency: 'EUR' };
onePreciseEuro.add({ amount: 100, currency });

For most currencies, Soldi will infer the default precision for that currency, if it is known, and will not include precision in the toObject() version of the Soldi to save storage space if it matches what Soldi would infer from the currency.

Finally, Soldi is easily extensible to offer additional features. See the source code for: @soldi/locale or @soldi/dinero for examples of how to extend Soldi with additional features. If your extension would be of bennefit to others, consider opening a PR to add your extension to @soldi directly.