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

medusa-stats

v1.0.9

Published

The most flexible statistics plugin for the most flexible commerce platform.

Readme

Overview

medusa-stats is a flexible statistics module for Medusa that features:

  • Pluggable statistics providers
  • Views, options, and chart composition
  • Composite statistics (statistics depending on other statistics)
  • Statistics-triggered configurable alerts
  • UI interface and admin routes for full statistics lifecycle management
  • Caching for optimized performance

Installation

npm install medusa-stats
# or
yarn add medusa-stats

Configuration

Add the plugin to your medusa-config.ts:

modules: [
  {
    resolve: "medusa-stats/modules/statistics",
    dependencies: [ContainerRegistrationKeys.QUERY], // Query dependency is required in order to be injected into the providers
    options: {
      providers: [
        {
          resolve: "medusa-stats/providers/common",
        },
      ],
    },
  },
],
plugins: [
  `medusa-stats`
]

Basic Usage

The plugin provides a framework for defining and calculating statistics as well as an admin interface for their management and visualization. The primary goal of the module is to provide a flexible way to create custom statistics and views that suit your business needs, without being limited to predefined metrics.

The module can also be used out-of-the-box with pre-defined statistics providers and the admin interface.

Views

Views are collections of related statistics visualizations. They allow you to organize statistics in any way that suits your needs. Every chart in a view can display multiple statistical measurements, each based on a different statistic option.

Views Image

Options

Options are instances of statistics that are calculated with specific parameters. By changing an option's parameters, you can adjust the underlying statistic calculation.

Options Parameters Image

When editing, options can also be configured in terms of their visualization (chart type, dimensions, etc.), cache settings and other parameters.

Visualization Settings Image

Providers

Providers define what statistics are available and how they are calculated.

Add provider to project

Register your provider in medusa-config.ts under the medusa-stats module:

modules: [
  {
    resolve: "medusa-stats",
    options: {
      providers: [
        { resolve: "medusa-stats/providers/common" },
        { resolve: "medusa-stats/providers/composite" },
        { resolve: "./src/providers/statistics/my-provider" },
      ],
    },
  },
]

Included providers

medusa-stats includes two built-in providers:

  • medusa-stats/providers/common
    • General commerce statistics (orders, carts, sales, channels, regions, and related aggregates).
  • medusa-stats/providers/composite
    • Composite/stat-transform statistics that consume other statistic outputs.
    • Included statistics: moving_average, rate_of_change.

Creating a Statistics Provider

Create a provider class by extending AbstractStatisticsProvider, expose available statistics in getAvailableStatistics, and implement calculation logic in calculateStatistic.

Example: a total_cart_value statistic (available in the Common Statistics Provider) with filters for currency and cart status.

import { ModuleProvider } from "@medusajs/framework/utils"
import {
  AbstractStatisticsProvider,
  StatBuilder,
  createTimeSeries,
  sum,
  type AvailableStatistic,
  type CalculateStatisticInput,
  type StatisticResult,
} from "medusa-stats"

class MyStatisticsProvider extends AbstractStatisticsProvider {
  static identifier = "my-statistics"
  static displayName = "My Statistics Provider"

  async getAvailableStatistics(): Promise<AvailableStatistic[]> {
    return [
      new StatBuilder("total_cart_value", "Total Cart Value")
            .description("Total value of all carts over time")
            .field({
                name: "currency_code",
                label: "Currency",
                description: "Filter by currency code",
                schema: z.string().optional(),
                fieldType: "text",
                placeholder: "USD"
            })
            .chart("line")
            .dimension("time")
            .build(),
    ]
  }

  async calculateStatistic(input: CalculateStatisticInput): Promise<StatisticResult> {
    const { id, parameters, periodStart, periodEnd, interval } = input;
    
    switch(id) {
        case "total_cart_value": {
            const currencyCode = parameters.currency_code;

            const filters: any = {
                created_at: { $gte: periodStart, $lte: periodEnd }
            };

            if (currencyCode) {
                filters.currency_code = currencyCode;
            }

            const { data: carts } = await this.query.graph({
                entity: "cart",
                fields: ["id", "created_at", "total"],
                filters
            });

            const timeSeries = createTimeSeries( // helper function for time series creation
                carts,
                periodStart,
                periodEnd,
                interval,
                sum('total') // helper accumulator function
            );

            return {
                value: timeSeries,
                metadata: { totalCarts: carts.length }
            };
        }
    }
  }
}

export default ModuleProvider("statistics", {
  services: [MyStatisticsProvider],
})

Composite Statistics

Composite statistics allow one statistic option to use another option's output as an input.

Admin Usage

A stat option can be configured to receive another statistic's output by settings its value in the Dependecnies section when editing a stat instance in the admin dashboard.

Dependencies Image

Using composite fields in providers

To make a statistic composable, define a provider parameter with fieldType: "stat". At runtime, that parameter receives dependency output data and can be processed like any other input.

import { z } from "zod"
import { StatBuilder } from "medusa-stats"

new StatBuilder("moving_average", "Moving Average")
  .description("Smooth a time series by averaging values over a rolling window")
  .field(
    {
      name: "input_series",
      label: "Input Series",
      description: "Dependency result to analyze",
      fieldType: "stat",
      schema: TimeSeriesSchema
    }
  )
  .field(
    {
      name: "window_size",
      label: "Window Size",
      fieldType: "number",
      schema: z.number().int().min(2).max(365).default(7),
    },
    7 // initial value
  )
  .build()

Alerts

Alerts can be configured per option to trigger when conditions are met.

Features

  • Absolute and comparative conditions
  • Alert logs
  • Scheduled evaluation job
  • Event emission for custom handling

Emitted Events

To handle the alert triggers, register a subscriber for the statistics.alert event type.

type StatisticsAlertEventData = {
  alert_id: string
  alert_name: string
  severity: "info" | "warning" | "critical"
  option_id: string
  current_value: number
  reference_value: number | null
  compare_value: number | [number, number]
  operator: "lt" | "gt" | "lte" | "gte" | "eq" | "neq" | "between"
  comparison_type: string
}

Caching

In order to optimize performance, statistic results are cached for a configurable amount of time. When a statistic is requested, the module first checks if a valid cached result exists and returns it if available. If not, it calculates the statistic, stores the result in the cache, and then returns it.

Cache Configuration

To use caching, CachingModule must be enabled in the Medusa project.

{
  resolve: "@medusajs/medusa/caching",
  options: {
    providers: [
      {
        resolve: "@medusajs/caching-redis",
        id: "caching-redis",
        is_default: true,
        options: {
          redisUrl: process.env.CACHE_REDIS_URL,
        },
      },
    ],
  },
},

The CachingModule's feature flag needs to be enabled as well:

in .env file:

MEDUSA_FF_CACHING=true

or

in medusa-config.ts:

featureFlags: {
  caching: true,
}

Planned features and improvements

  • More built-in chart types and visualization options
  • Visualization providers for custom chart types and UI components
  • Visualization on entities' details pages (e.g. product statistics on product page)