npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@final-commerce/common

v2.0.5

Published

Shared utilities, types, constants, and engineering governance configs for the Final Commerce platform.

Downloads

1,721

Readme

@final-commerce/common

Shared utilities, types, and constants for Final Commerce applications. This package provides framework-agnostic functionality that works across both frontend (React, Vue, etc.) and backend (Node.js, NestJS) environments.

Installation

npm install @final-commerce/common

Imports

Everything is re-exported from the package root:

import { CurrencyCode, toMinorUnits, formatCurrency, Amount } from '@final-commerce/common';

Sub-path imports also work:

import { toMinorUnits } from '@final-commerce/common/dist/utils/currency.util';
import { CurrencyCode } from '@final-commerce/common/dist/enums';

Enums

CurrencyCode

ISO 4217 currency codes. 41 currencies across three decimal groups:

| Decimal Places | Currencies | | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | 2 (standard) | USD, EUR, GBP, CAD, AUD, NZD, CHF, CNY, INR, MXN, BRL, ZAR, SGD, HKD, SEK, NOK, DKK, PLN, THB, MYR, PHP, IDR, AED, SAR, ILS, TRY, RUB | | 0 (zero-decimal) | JPY, KRW, VND, CLP, ISK, HUF, TWD | | 3 (three-decimal) | KWD, BHD, OMR, JOD, TND, LYD, IQD |

Interfaces

Amount

Represents a monetary value stored in the database.

{ amount: 3122, currency: 'USD', minorUnits: 2 }  // = $31.22

| Field | Type | Description | | ------------ | -------------- | --------------------------------- | | amount | number | Value in minor units (e.g. cents) | | currency | CurrencyCode | ISO 4217 code | | minorUnits | number | Decimal places (2, 0, or 3) |

CurrencyConfig

| Currency | Minor Units | Symbol | Example | | -------- | ----------- | ------ | -------- | | USD | 2 | $ | $10.50 | | EUR | 2 | € | €10.50 | | GBP | 2 | £ | £10.50 | | JPY | 0 | ¥ | ¥1000 | | KWD | 3 | KD | KD10.500 |

| Field | Type | Description | | ---------------- | ---------------------- | ------------------------------------ | | minorUnits | number | Decimal places | | symbol | string | Display symbol ($, , ¥, etc.) | | symbolPosition | 'prefix' \| 'suffix' | Where the symbol goes |


Utility Functions

Conversion

| Function | In | Out | What it does | | ---------------------------------------------- | ------------------ | ------ | ------------------------------------------------------------ | | toMinorUnits(amount, currency) | (10.50, 'USD') | 1050 | Major to minor units | | fromMinorUnits(minorAmount, currency) | (1050, 'USD') | 10.5 | Minor to major units | | stringifyMinorUnits(minorAmount, minorUnits) | (1050, 2) | 10.5 | Minor to major using decimal count directly | | parseAmountToMinorUnits(str, currency) | ('10.50', 'USD') | 1050 | Parse string input to minor units. Returns null on failure |

Formatting

| Function | In | Out | What it does | | --------------------------------------------------- | --------------- | ---------- | ----------------------------------------------------------------------------------------------- | | formatCurrency(minorAmount, currency, options?) | (1050, 'USD') | '$10.50' | Display string with symbol and grouping | | formatMinorUnitsToString(minorAmount, minorUnits) | (1050, 2) | '10.5' | Plain decimal string (no symbol, no trailing zeros). Useful for API payloads (e.g. WooCommerce) |

formatCurrency options:

  • includeSymbol (default: true) — include currency symbol
  • useGrouping (default: true) — thousands separators

Arithmetic

All inputs and outputs are in minor units (integers).

| Function | Example | Result | | ------------------------------------ | ------------- | ------ | | addAmounts(a, b) | (1050, 250) | 1300 | | subtractAmounts(a, b) | (1050, 250) | 800 | | multiplyAmount(amount, multiplier) | (1050, 2) | 2100 | | divideAmount(amount, divisor) | (1050, 2) | 525 | | calculatePercentage(amount, pct) | (10000, 15) | 1500 |

divideAmount throws on division by zero. calculatePercentage takes percentage as a whole number (15 = 15%, not 0.15).

Config / Validation

| Function | What it does | | ---------------------------------- | --------------------------------------------------------------------------------------------- | | getCurrencyConfig(currency) | Returns CurrencyConfig for a code. Falls back to 2-decimal default for unknown currencies | | getMinorUnitMultiplier(currency) | Returns 10^minorUnits (100 for USD, 1 for JPY, 1000 for KWD) | | getMinorUnits(currency) | Returns decimal place count for a currency | | isSupportedCurrency(currency) | true if the currency has explicit config | | parseCurrencyCode(value) | Validates a raw string is a valid CurrencyCode. Throws with supported codes list if invalid |

Amount Object Helpers

Used in BuilderHub for converting between user input and the Amount storage format.

| Function | Example | Result | | ------------------------------- | ---------------------------------------------------- | -------------------------------------------------- | | createAmount(value, currency) | ('31.22', 'USD') | { amount: 3122, currency: 'USD', minorUnits: 2 } | | amountToString(amount) | ({ amount: 3122, currency: 'USD', minorUnits: 2 }) | '31.22' |

createAmount accepts string | number | null | undefined. Returns undefined for null, undefined, empty string, or NaN input. amountToString returns '' for null/undefined input.

Constants

CURRENCY_CONFIG — a Record<CurrencyCode | string, CurrencyConfig> mapping all 41 currencies to their config (symbol, decimal places, symbol position).


Local Development

npm install
npm run build       # build with tsup (CJS + ESM + types → dist/)
npm run dev         # watch mode — rebuilds on file changes
npm test            # vitest in watch mode
npm run test:run    # single test run
npm run test:ui     # vitest UI
npm run test:coverage

Link locally to another project

Use npm link to test changes in a consuming project without publishing:

# 1. In this package (common/) — build first so dist/ is up to date
npm run build
npm link

# 2. In the consuming project (e.g. hub-api/) — clear node_modules to avoid stale/duplicate copies
rm -rf node_modules/@final-commerce/common
npm link @final-commerce/common

# 3. Verify the symlink points to your local copy
ls -la node_modules/@final-commerce/common
# Should show a symlink → /path/to/common

# 4. When done, unlink and restore the published version
npm unlink @final-commerce/common   # in consumer
npm install                         # reinstall published version
npm unlink                          # in common/

If you change source files in common, run npm run build again (or use npm run dev for watch mode). The symlink means the consumer always reads from common's dist/, so it picks up new builds immediately.

Quick verification with node -p

After building, verify exports directly from the terminal:

# Check the package loads
node -p "require('./dist/index.js')"

# Test a conversion
node -p "const c = require('./dist/index.js'); c.toMinorUnits(10.50, 'USD')"
# → 1050

# Test formatting
node -p "const c = require('./dist/index.js'); c.formatCurrency(1050, 'USD')"
# → $10.50

# Test zero-decimal currency
node -p "const c = require('./dist/index.js'); c.toMinorUnits(1000, 'JPY')"
# → 1000

# Test three-decimal currency
node -p "const c = require('./dist/index.js'); c.toMinorUnits(10.5, 'KWD')"
# → 10500

# Test Amount helpers
node -p "const c = require('./dist/index.js'); c.createAmount('31.22', 'USD')"
# → { amount: 3122, currency: 'USD', minorUnits: 2 }

node -p "const c = require('./dist/index.js'); c.amountToString({ amount: 3122, currency: 'USD', minorUnits: 2 })"
# → 31.22

# List all exported keys
node -p "Object.keys(require('./dist/index.js'))"

Verify from a linked project

After npm link, verify the link works in the consuming project:

# In the consuming project directory
node -p "require('@final-commerce/common')"
node -p "const c = require('@final-commerce/common'); c.formatCurrency(2500, 'EUR')"
# → €25.00

License

Private — Final Commerce internal use only.