Package Exports
- pricing-core
- pricing-core/currency
- pricing-core/math
- pricing-core/rounding
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (pricing-core) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
PricingCore
A high-precision, currency-agnostic pricing engine built in Node.js using BigInt for financial calculations. Perfect for e-commerce, retail, and financial applications that need accurate pricing across multiple currencies.
๐ Quick Start for Developers
# Install
npm install pricing-core
# Import and use
import { calculatePrice, pctToBps, toSmallestUnit, formatPrice } from 'pricing-core';
# Calculate price with 30% margin
const cost = toSmallestUnit(2.50, 'USD'); // $2.50 โ 250 cents
const margin = pctToBps(30); // 30% โ 3000 bps
const price = calculatePrice(cost, margin, 'ceilStepUSD'); // Round to nickels
console.log(formatPrice(price, 'USD', true)); // "$3.60"
๐ฏ Why PricingCore?
- ๐ข BigInt Precision - No floating-point errors in financial calculations
- ๐ 180+ Currencies - Full ISO 4217 support via currency-codes package
- โก High Performance - Integer-only arithmetic for maximum speed
- ๐ง Developer Friendly - Clean API, comprehensive examples, ES modules
- ๐ฑ CLI Testing - Interactive testing environment included
โจ Key Features
- ๐ข BigInt Precision: All calculations use BigInt to avoid floating-point errors
- ๐ Currency Agnostic: Support for any currency with configurable decimal places
- ๐ Margin-Based Pricing: Calculate prices using gross margin on selling price
- ๐ฏ Multiple Rounding Strategies: Built-in and custom rounding options
- โก High Performance: Integer-only arithmetic for maximum speed
- ๐ง Extensible: Easy to add new rounding strategies and currencies
- ๐ฑ CLI Testing: Interactive command-line interface for testing
๐ Quick Start
Installation
npm install pricing-core
# Install specific version
npm install pricing-core@v1.0.12
Basic Usage
import { calculatePrice, pctToBps, toSmallestUnit, formatPrice } from 'pricing-core';
// Calculate price for a $2.50 item with 30% margin
const cost = toSmallestUnit(2.50, 'USD'); // Convert to cents
const margin = pctToBps(30); // 30% โ 3000 bps
const price = calculatePrice(cost, margin, 'margin', 'ceilStepUSD'); // Round to nickels
console.log(formatPrice(price, 'USD', true)); // "$3.60"
๐ Core API
Main Functions
calculatePrice(costUnits, markupValue, strategy, rounding)
Calculate the selling price based on cost and markup strategy.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency units (e.g., cents)markupValue
(BigInt | number): Markup amount based on strategystrategy
(string): Markup strategy to use (default: 'margin')rounding
(string | function): Rounding strategy or custom function
Returns: BigInt - Price in smallest currency units
Supported Strategies:
margin
: Margin on selling price (price = cost / (1 - margin))costPlus
: Fixed percentage added to cost (price = cost * (1 + markup))keystone
: Double the cost (price = cost * 2)keystonePlus
: Keystone plus additional percentage (price = cost * 2 * (1 + markup))fixedAmount
: Fixed amount added to cost (price = cost + markup)targetMargin
: Target margin on cost (price = cost / (1 - margin))markupOnCost
: Percentage markup on cost (price = cost * (1 + markup))
Examples:
// Margin strategy (original behavior)
const cost = toSmallestUnit(10.99, 'USD'); // 1099 cents
const margin = pctToBps(35); // 35% margin
const price = calculatePrice(cost, margin, 'margin', 'charm99');
// Cost-plus strategy
const markup = pctToBps(25); // 25% markup
const costPlusPrice = calculatePrice(cost, markup, 'costPlus', 'ceilStepUSD');
// Keystone strategy
const keystonePrice = calculatePrice(cost, 0, 'keystone', 'identity');
pctToBps(percentage)
Convert percentage to basis points.
Parameters:
percentage
(number): Percentage value (e.g., 30 for 30%)
Returns: number - Basis points (e.g., 3000 for 30%)
Convenience Functions
calculatePriceWithMargin(costUnits, marginBps, rounding)
Legacy function for backward compatibility - uses margin strategy.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsmarginBps
(BigInt | number): Margin in basis pointsrounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
calculateCostPlusPrice(costUnits, markupBps, rounding)
Calculate price using cost-plus markup strategy.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsmarkupBps
(BigInt | number): Markup in basis points (e.g., 2500 for 25%)rounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
calculateKeystonePrice(costUnits, rounding)
Calculate price using keystone markup (double the cost).
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsrounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
calculateKeystonePlusPrice(costUnits, additionalMarkupBps, rounding)
Calculate price using keystone plus additional markup.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsadditionalMarkupBps
(BigInt | number): Additional markup in basis pointsrounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
calculateFixedAmountPrice(costUnits, fixedAmount, rounding)
Calculate price by adding a fixed amount to cost.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsfixedAmount
(BigInt | number): Fixed amount to add in smallest currency unitsrounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
calculateMarkupOnCostPrice(costUnits, markupBps, rounding)
Calculate price using markup on cost percentage.
Parameters:
costUnits
(BigInt | number): Cost in smallest currency unitsmarkupBps
(BigInt | number): Markup percentage in basis pointsrounding
(string | function): Rounding strategy
Returns: BigInt - Price in smallest currency units
Currency Utilities
toSmallestUnit(amount, currency)
Convert decimal amount to smallest currency unit.
Parameters:
amount
(number): Amount in base currency (e.g., 2.50 for $2.50)currency
(string | CurrencyConfig): Currency code or config
Returns: BigInt - Amount in smallest units
Example:
const cents = toSmallestUnit(2.50, 'USD'); // 250n
const yen = toSmallestUnit(1000, 'JPY'); // 1000n
const euros = toSmallestUnit(5.75, 'EUR'); // 575n
fromSmallestUnit(units, currency)
Convert from smallest currency unit back to decimal.
Parameters:
units
(BigInt): Amount in smallest unitscurrency
(string | CurrencyConfig): Currency code or config
Returns: number - Amount in base currency
formatPrice(amount, currency, inSmallestUnits)
Format price with proper currency formatting.
Parameters:
amount
(BigInt | number): Amount to formatcurrency
(string | CurrencyConfig): Currency code or configinSmallestUnits
(boolean): Whether amount is in smallest units
Returns: string - Formatted price string
Example:
formatPrice(250, 'USD', true); // "$2.50"
formatPrice(1000, 'JPY', true); // "ยฅ1,000"
formatPrice(575, 'EUR', true); // "โฌ5.75"
createCurrency(code, symbol, decimalPlaces)
Create a custom currency configuration.
Parameters:
code
(string): ISO currency codesymbol
(string): Currency symboldecimalPlaces
(number): Number of decimal places
Returns: CurrencyConfig - Custom currency configuration
Example:
const btc = createCurrency('BTC', 'โฟ', 8); // Bitcoin with 8 decimals
const satoshis = toSmallestUnit(0.001, btc); // 100000n
Currency Information Functions
getSupportedCurrencies()
Get all supported currency codes.
Returns: string[] - Array of supported currency codes
getCurrenciesByDecimalPlaces(decimalPlaces)
Get currencies filtered by number of decimal places.
Parameters:
decimalPlaces
(number): Number of decimal places to filter by
Returns: string[] - Array of currency codes with the specified decimal places
Example:
const zeroDecimalCurrencies = getCurrenciesByDecimalPlaces(0); // ['JPY', 'KRW', 'XOF', ...]
const twoDecimalCurrencies = getCurrenciesByDecimalPlaces(2); // ['USD', 'EUR', 'GBP', ...]
getCurrenciesByRegion()
Get currencies grouped by geographical region.
Returns: Object - Currencies grouped by region
Example:
const regions = getCurrenciesByRegion();
console.log(regions['Asia Pacific']); // ['JPY', 'CNY', 'KRW', 'INR', ...]
getCurrencyByNumber(number)
Get currency information by ISO 4217 number.
Parameters:
number
(number): ISO 4217 currency number (e.g., 840 for USD)
Returns: CurrencyConfig | null - Currency configuration or null if not found
Example:
const usd = getCurrencyByNumber(840); // Returns USD configuration
getCurrenciesByCountry(country)
Get currencies used by a specific country.
Parameters:
country
(string): Country name (case-insensitive)
Returns: CurrencyConfig[] - Array of currency configurations for the country
Example:
const colombiaCurrencies = getCurrenciesByCountry('colombia'); // Returns COP and COU
getISOPublishDate()
Get the publish date of the ISO 4217 data.
Returns: string - Publish date in YYYY-MM-DD format
Example:
const publishDate = getISOPublishDate(); // "2024-06-25"
getCurrencyDetails(code)
Get detailed currency information including countries and ISO number.
Parameters:
code
(string): ISO currency code
Returns: Object | null - Detailed currency information or null if not found
Example:
const eurDetails = getCurrencyDetails('EUR');
console.log(eurDetails.countries); // ['andorra', 'austria', 'belgium', ...]
๐ Supported Currencies
The package includes complete ISO 4217 currency support via the currency-codes package, providing 180+ currencies from around the world with automatic updates:
Major Currencies
Currency | Code | Symbol | Decimal Places | Smallest Unit |
---|---|---|---|---|
US Dollar | USD | $ | 2 | $0.01 |
Euro | EUR | โฌ | 2 | โฌ0.01 |
British Pound | GBP | ยฃ | 2 | ยฃ0.01 |
Japanese Yen | JPY | ยฅ | 0 | ยฅ1 |
Chinese Yuan | CNY | ยฅ | 2 | ยฅ0.01 |
Indian Rupee | INR | โน | 2 | โน0.01 |
Canadian Dollar | CAD | C$ | 2 | C$0.01 |
Australian Dollar | AUD | A$ | 2 | A$0.01 |
Swiss Franc | CHF | CHF | 2 | CHF0.01 |
South Korean Won | KRW | โฉ | 0 | โฉ1 |
Currency Categories by Decimal Places
- 0 decimal places: JPY, KRW, XOF, XAF, KMF, CLP, DJF, GNF, ISK, PYG, VUV, XPF, XDR, XAU, XAG, XPT, XPD, XTS, XXX
- 2 decimal places: Most currencies (USD, EUR, GBP, etc.)
- 3 decimal places: BHD, IQD, JOD, KWD, LYD, OMR, TND
- 4 decimal places: CLF, UYW
Regional Coverage
- North America: USD, CAD, MXN
- Europe: EUR, GBP, CHF, SEK, NOK, DKK, PLN, CZK, HUF
- Asia Pacific: JPY, CNY, KRW, INR, SGD, HKD, TWD, THB, MYR
- Latin America: BRL, ARS, CLP, COP, PEN, UYU, PYG
- Africa: ZAR, EGP, NGN, KES, GHS, MAD, TND, DZD
- Middle East: SAR, AED, QAR, KWD, BHD, OMR, JOD, LBP, ILS
- Oceania: AUD, NZD, FJD, PGK, WST, TOP, VUV
Special Currencies
- Precious Metals: XAU (Gold), XAG (Silver), XPT (Platinum), XPD (Palladium)
- Special Drawing Rights: XDR (IMF SDR)
- Testing: XTS (Testing purposes)
- No Currency: XXX (Transactions without currency)
Currency-Codes Integration
This package leverages the currency-codes package for:
- Automatic Updates: Currency data is automatically updated when the underlying package updates
- Official Data: Uses official ISO 4217 data from the maintainer
- Rich Metadata: Includes country information, ISO numbers, and currency names
- Maintenance: No need to manually maintain currency data
๐ฏ Markup Strategies
The pricing engine supports multiple markup strategies to fit different business models and pricing philosophies:
Available Strategies
margin
: Margin on selling price (price = cost / (1 - margin))- Best for: Maintaining consistent profit margins
- Example: 30% margin means 30% of the selling price is profit
costPlus
: Fixed percentage added to cost (price = cost * (1 + markup))- Best for: Simple, predictable markup
- Example: 25% markup means add 25% to the cost
keystone
: Double the cost (price = cost * 2)- Best for: Traditional retail markup
- Example: $10 cost โ $20 price
keystonePlus
: Keystone plus additional percentage (price = cost * 2 * (1 + markup))- Best for: Premium retail with additional markup
- Example: $10 cost โ $20 keystone โ $25 with 25% additional markup
fixedAmount
: Fixed amount added to cost (price = cost + markup)- Best for: Low-cost items or minimum pricing
- Example: $5 cost + $2 markup = $7 price
targetMargin
: Target margin on cost (price = cost / (1 - margin))- Best for: Cost-based margin calculations
- Example: 40% margin on cost means 40% of cost is profit
markupOnCost
: Percentage markup on cost (price = cost * (1 + markup))- Best for: Cost-based percentage markup
- Example: 50% markup on cost means add 50% to cost
Strategy Selection Guide
Business Type | Recommended Strategy | Reasoning |
---|---|---|
E-commerce | margin |
Consistent profit margins across products |
Retail | keystone or keystonePlus |
Traditional retail markup |
Restaurants | costPlus |
Simple food cost markup |
Services | fixedAmount |
Predictable service fees |
Luxury Goods | keystonePlus |
Premium positioning with additional markup |
Wholesale | markupOnCost |
Cost-based pricing for B2B |
๐ฏ Rounding Strategies
Built-in Strategies
identity
: No rounding (keep computed price as-is)ceilStep5
: Round up to next 5ยข incrementceilStep10
: Round up to next 10ยข incrementceilStepUSD
: Round up to next nickel (USD-specific)ceilStepEUR
: Round up to next 5 centimes (EUR-specific)ceilStepJPY
: Round up to next yen (JPY-specific)ceilStepINR
: Round up to next 5 paise (INR-specific)charm99
: Force .99 ending for psychological pricing
Custom Rounding
Create your own rounding functions:
// Round to nearest quarter (25ยข)
const roundToQuarter = (units) => {
const quarter = 25n;
const remainder = units % quarter;
if (remainder === 0n) return units;
const halfQuarter = quarter / 2n;
if (remainder >= halfQuarter) {
return units + (quarter - remainder);
} else {
return units - remainder;
}
};
const price = calculatePrice(cost, margin, roundToQuarter);
๐ Examples
Example 1: Basic USD Pricing
import { calculatePrice, pctToBps, toSmallestUnit, formatPrice } from 'pricing-core';
const cost = toSmallestUnit(2.50, 'USD'); // $2.50 โ 250 cents
const margin = pctToBps(30); // 30% โ 3000 bps
const price = calculatePrice(cost, margin, 'margin', 'ceilStepUSD');
console.log(formatPrice(price, 'USD', true)); // "$3.60"
Example 2: Multi-Currency Batch Pricing
const products = [
{ name: 'Widget A', cost: 10.99, currency: 'USD', margin: 35 },
{ name: 'Widget B', cost: 15.50, currency: 'EUR', margin: 30 },
{ name: 'Widget C', cost: 2000, currency: 'JPY', margin: 25 }
];
products.forEach(product => {
const costUnits = toSmallestUnit(product.cost, product.currency);
const marginBps = pctToBps(product.margin);
const price = calculatePrice(costUnits, marginBps, 'margin', 'identity');
console.log(`${product.name}: ${formatPrice(price, product.currency, true)}`);
});
Example 3: Different Markup Strategies
const cost = toSmallestUnit(20.00, 'USD'); // $20.00 cost
// 1. Margin strategy (30% margin on selling price)
const marginPrice = calculatePrice(cost, pctToBps(30), 'margin', 'ceilStepUSD');
console.log(`Margin pricing: ${formatPrice(marginPrice, 'USD', true)}`);
// 2. Cost-plus strategy (25% markup on cost)
const costPlusPrice = calculatePrice(cost, pctToBps(25), 'costPlus', 'ceilStepUSD');
console.log(`Cost-plus pricing: ${formatPrice(costPlusPrice, 'USD', true)}`);
// 3. Keystone strategy (double the cost)
const keystonePrice = calculatePrice(cost, 0, 'keystone', 'ceilStepUSD');
console.log(`Keystone pricing: ${formatPrice(keystonePrice, 'USD', true)}`);
// 4. Fixed amount markup ($5.00)
const fixedPrice = calculatePrice(cost, toSmallestUnit(5.00, 'USD'), 'fixedAmount', 'ceilStepUSD');
console.log(`Fixed amount pricing: ${formatPrice(fixedPrice, 'USD', true)}`);
Example 3: Custom Currency (Crypto)
const btc = createCurrency('BTC', 'โฟ', 8); // Bitcoin with 8 decimal places
const btcCost = toSmallestUnit(0.001, btc); // 0.001 BTC โ 100000 satoshis
const btcMargin = pctToBps(15); // 15% margin
const btcPrice = calculatePrice(btcCost, btcMargin, 'margin', 'identity');
console.log(formatPrice(btcPrice, btc, true)); // "โฟ0.00115000"
๐งช Developer Experience
Quick Commands
npm run dev # Run tests + examples
npm start # Launch interactive CLI
npm run demo # Run comprehensive examples
npm test # Run test suite
npm run examples # Run pricing examples
npm run cli # Interactive testing environment
ES Modules Support
This package is built with ES modules and is fully compatible with modern Node.js. All functions include JSDoc comments for excellent IDE support.
Installing from npm
# Install the package directly from npm
npm install pricing-core
๐ง Advanced Usage
Custom Currency Configuration
import { createCurrency } from 'pricing-core';
// Create a custom currency for a local market
const localCurrency = createCurrency('LOCAL', 'L', 3); // 3 decimal places
const amount = toSmallestUnit(12.345, localCurrency);
Batch Processing
// Process multiple items efficiently
const items = [
{ cost: 5.99, margin: 25, currency: 'USD' },
{ cost: 12.50, margin: 30, currency: 'EUR' },
{ cost: 1500, margin: 20, currency: 'JPY' }
];
const results = items.map(item => {
const costUnits = toSmallestUnit(item.cost, item.currency);
const marginBps = pctToBps(item.margin);
const price = calculatePrice(costUnits, marginBps, 'margin', 'identity');
return {
...item,
price: formatPrice(price, item.currency, true)
};
});
Error Handling
try {
const price = calculatePrice(cost, margin, 'unknownRounding');
} catch (error) {
if (error.message.includes('Unknown rounding style')) {
console.log('Invalid rounding strategy');
} else if (error.message.includes('marginBps must be between')) {
console.log('Invalid margin percentage');
}
}
๐ฆ Package Structure
pricing-core/
โโโ src/
โ โโโ index.js # Main exports
โ โโโ core/
โ โ โโโ calculator.js # BigInt pricing calculator
โ โ โโโ math.js # Integer-safe helpers
โ โโโ rounding/
โ โ โโโ index.js # Rounding registry
โ โ โโโ identity.js # No rounding
โ โ โโโ ceilStep.js # Step-based rounding
โ โ โโโ charm99.js # .99 ending
โ โโโ currency.js # Currency utilities
โโโ test/ # Test suite
โโโ cli.js # CLI testing environment
โโโ examples.js # Comprehensive examples
๐ค Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
๐ License
MIT License - see LICENSE file for details.
๐ Security
Please do NOT report security vulnerabilities through public GitHub issues.
If you discover a security vulnerability, please email security@fivespiceindiangrocery.com.
See SECURITY.md for more details.
๐ Support
- Issues: GitHub Issues
- Examples: Run
npm run examples
for comprehensive examples - CLI: Run
npm start
for interactive testing
๐ Related Packages
currency-codes
- ISO 4217 currency data and utilities
Made with โค๏ธ for accurate financial calculations