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

mongoose-currency-convert

v0.1.5

Published

A lightweight Mongoose plugin for automatic currency conversion at save time - flexible, extensible, and service-agnostic.

Downloads

9

Readme

mongoose-currency-convert

npm version Release License: MIT

A lightweight Mongoose plugin for automatic currency conversion at save time - flexible, extensible, and service-agnostic.

Features

  • Automatic currency conversion for specified fields when saving documents or updating them.
  • Customizable exchange rate logic via a user-provided function or extension plugin.
  • Support for nested paths in documents.
  • Pluggable rounding function (default: round to 2 decimals).
  • Simple in-memory cache for exchange rates (optional).
  • Error handling and rollback on conversion failure.
  • Fully tested with high code coverage.
  • Compatible with ESM and CommonJS.

Installation

npm install mongoose-currency-convert
# or
pnpm add mongoose-currency-convert

Usage

import mongoose, { Schema } from 'mongoose';
import { currencyConversionPlugin } from 'mongoose-currency-convert';

const ProductSchema = new Schema({
  price: {
    amount: Number,
    currency: String,
    date: Date,
  },
  priceConversion: {
    amount: Number,
    currency: String,
    date: Date,
  },
});

ProductSchema.plugin(currencyConversionPlugin, {
  fields: [
    {
      sourcePath: 'price.amount',
      currencyPath: 'price.currency',
      datePath: 'price.date',
      targetPath: 'priceConversion',
      toCurrency: 'EUR',
    },
  ],
  getRate: async (from, to, date) => {
    // Implement your logic to fetch the exchange rate
    return 0.85; // Example: USD → EUR
  },
  // Optional: custom rounding function
  round: (value) => Math.round(value * 100) / 100,
});

const Product = mongoose.model('Product', ProductSchema);

Supported Mongoose Operations

  • save
  • updateOne
  • findOneAndUpdate

Currency conversion is automatically applied when saving or updating documents using these operations.

Plugin Options

  • fields: Array of field mapping objects:
    • sourcePath: Path to the source amount (supports nested and array paths).
    • currencyPath: Path to the source currency.
    • datePath (optional): Path to the date for conversion.
    • targetPath: Path to write the converted value.
    • toCurrency: Target currency code.
  • getRate(from: string, to: string, date: Date): Async function returning the exchange rate.
  • round(value: number): Optional rounding function.
  • allowedCurrencyCodes: Optional array of allowed currency codes (ISO 4217).
  • onError(ctx): Optional callback called when a conversion error occurs. Receives an object with details.
  • fallbackRate: Optional fallback rate if the conversion rate is invalid or missing.
  • rollbackOnError: Optional boolean. If true, revokes all conversions made if there's an error.
  • cache: Optional cache object for exchange rates (see SimpleCache).
  • dateTransform(date: Date): Optional function to transform the conversion date.

Caching Exchange Rates

You can use the built-in in-memory cache (SimpleCache in src/utils/cache.ts) or provide your own cache implementation (e.g. backed by Redis, Memcached, etc.).

Using the Internal SimpleCache

import { SimpleCache } from 'mongoose-currency-convert/cache';

const cache = new SimpleCache<number>();

ProductSchema.plugin(currencyConversionPlugin, {
  fields: [/* ... */],
  getRate: async (from, to, date) => { /* ... */ },
  cache,
});

Using an External Cache (e.g. Redis)

You can implement the CurrencyRateCache interface to use any external service:

import { createClient } from 'redis';
import type { CurrencyRateCache } from 'mongoose-currency-convert/types';

class RedisCache implements CurrencyRateCache<number> {
  private client = createClient({ url: 'redis://localhost:6379' });
  constructor() { this.client.connect(); }

  async get(key: string): Promise<number | undefined> {
    const value = await this.client.get(key);
    return value ? Number(value) : undefined;
  }
  async set(key: string, value: number): Promise<void> {
    await this.client.set(key, value.toString(), { EX: 86400 }); // 1 day expiry
  }
}

const cache = new RedisCache();

ProductSchema.plugin(currencyConversionPlugin, {
  fields: [/* ... */],
  getRate: async (from, to, date) => { /* ... */ },
  cache,
});

Error Handling Example

You can handle conversion errors using the onError callback:

ProductSchema.plugin(currencyConversionPlugin, {
  fields: [/* ... */],
  getRate: async () => { throw new Error('rate error'); },
  onError: (ctx) => {
    console.error('Conversion error:', ctx);
  },
  rollbackOnError: true,
});

TypeScript Support

  • Fully typed, with exported types for plugin options and error context.
  • Example:
import type { CurrencyPluginOptions, CurrencyPluginErrorContext } from 'mongoose-currency-convert/types';

Extension Plugins (e.g. BCE)

You can use or create extension plugins that provide a ready-to-use getRate function for external services (e.g. European Central Bank, exchangerate.host, etc.).

| Package | Description | |---------|-------------| | mongoose-currency-converter-bce | BCE provider for automatic exchange rate lookup. |

How to Create Your Own Extension Plugin

  1. Import the types from the base plugin:
    import type { GetRateFn } from 'mongoose-currency-convert';
  2. Implement a factory function that returns a getRate function:
    export function createMyGetRate(): GetRateFn {
      return async function getRate(from, to, date) {
        // Fetch rate from your service
        // Return the rate
      };
    }
  3. Use your plugin in the base plugin configuration:
    ProductSchema.plugin(currencyConversionPlugin, {
      fields: [/* ... */],
      getRate: createMyGetRate(),
      cache,
    });

Note: The cache is managed by the base plugin. Extension plugins should not read or write to the cache directly; they only fetch rates from external services.

Limitations & Known Issues

  • Only save, updateOne, and findOneAndUpdate are supported for automatic conversion.
  • Array paths are supported, but deep array updates (e.g. items.$.price) may require manual handling.
  • Only $set and direct field updates are converted in update operations; other MongoDB operators ($inc, $push, etc.) are not automatically converted.
  • The list of supported currency codes is static (ISO 4217).
  • If you use custom cache, ensure it implements the required interface.

Compatibility

  • Node.js >= 18.x
  • Mongoose >= 7.x
  • TypeScript >= 5.x (optional)

Contributing

Contributions are welcome! To contribute:

  • Fork the repository and create a new branch.
  • Submit a pull request with a clear description of your changes.
  • Follow the coding style and add tests for new features or bug fixes.
  • For major changes, open an issue first to discuss your idea.

See CONTRIBUTING.md for more details (if available).

Changelog

See CHANGELOG.md for a list of changes and release history.

License

MIT