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

stock-monitoring

v0.0.6

Published

Monitor product inventory levels and send email notifications for low stock, out of stock, and slow-moving products.

Readme

stock-monitoring

Medusa v2 plugin that monitors inventory levels (low, out-of-stock, and slow-moving) and sends admin notification alerts.

Plugin Overview

stock-monitoring adds stock alert monitoring to Medusa by:

  • Evaluating inventory quantities per variant and per warehouse/location level.
  • Detecting three alert types:
    • low_stock
    • out_of_stock
    • slow_moving
  • Running a scheduled daily stock check job.
  • Sending notification emails to configured admin recipients via Medusa notification module.
  • Exposing an admin API for listing/filtering alerts.
  • Providing an admin route page for alert visualization and filtering.

This plugin is built for Medusa v2 (uses Medusa module/workflow/job/admin-sdk APIs).

Installation & Setup

1) Install package

npm install stock-monitoring
# or
yarn add stock-monitoring

2) Register in medusa-config.ts

import { defineConfig } from "@medusajs/framework/utils"

export default defineConfig({
  modules: {
    stock_monitoring: {
      resolve: "stock-monitoring",
      options: {
        low_stock_threshold: 10,
        slow_moving_days_threshold: 90,
        low_stock_threshold_per_warehouse: {
          // "sloc_...": 5
        },
        admin_notification_emails: ["[email protected]"],
      },
    },
  },
  plugins: [
    {
      resolve: "stock-monitoring",
      options: {
        low_stock_threshold: 10,
        slow_moving_days_threshold: 90,
        low_stock_threshold_per_warehouse: {},
        admin_notification_emails: ["[email protected]"],
      },
    },
  ],
})

3) Migrations

No plugin-specific database models/migrations are defined in this codebase.

You can still run standard app migrations as usual:

npx medusa db:migrate

Configuration (config.ts / plugin options)

Configuration is defined by StockMonitoringPluginOptions (src/types/stock-monitoring.ts) and validated in src/modules/stock-monitoring/service.ts.

| Option | Type | Required | Default | Description | |---|---|---|---|---| | low_stock_threshold | number | Optional | 10 | Global threshold used for low-stock alerts. | | slow_moving_days_threshold | number | Optional | 90 | Days-since-update threshold for slow-moving alerts. | | low_stock_threshold_per_warehouse | Record<string, number> | Optional | {} | Per-location threshold override keyed by location_id. | | admin_notification_emails | string[] | Optional | [] | Recipients for stock alert notifications. If empty, job skips sending notifications. |

Validation behavior:

  • Thresholds must be integers and >= 0.
  • Email list must be an array of strings; empty/whitespace entries are ignored.

Complete example config block

{
  modules: {
    stock_monitoring: {
      resolve: "stock-monitoring",
      options: {
        low_stock_threshold: 12,
        slow_moving_days_threshold: 120,
        low_stock_threshold_per_warehouse: {
          sloc_warehouse_a: 5,
          sloc_warehouse_b: 20,
        },
        admin_notification_emails: [
          "[email protected]",
          "[email protected]",
        ],
      },
    },
  },
  plugins: [
    {
      resolve: "stock-monitoring",
      options: {
        low_stock_threshold: 12,
        slow_moving_days_threshold: 120,
        low_stock_threshold_per_warehouse: {
          sloc_warehouse_a: 5,
          sloc_warehouse_b: 20,
        },
        admin_notification_emails: [
          "[email protected]",
          "[email protected]",
        ],
      },
    },
  ],
}

Environment Variables

No runtime process.env.* usage is present in this plugin’s src code.

| Variable | Used in src runtime code? | Notes | |---|---|---| | None | No | All plugin behavior is configured through Medusa module/plugin options. |

REST APIs / Routes

Admin APIs

GET /admin/stock-monitoring/alerts

  • Auth requirement: Admin JWT (admin namespace route)
  • Query params:

| Param | Type | Required | Default | Notes | |---|---|---|---|---| | limit | number string | No | 50 | Clamped to 1..200. | | offset | number string | No | 0 | Min 0. | | alert_type | enum | No | — | low_stock, out_of_stock, slow_moving. | | product_id | string | No | — | Exact product id filter. | | variant_id | string | No | — | Exact variant id filter. | | search | string | No | — | Case-insensitive title search (product or variant). |

  • Response schema:

| Field | Type | |---|---| | alerts | StockAlertInput[] | | count | number | | limit | number | | offset | number |

StockAlertInput includes:

  • variant_id

  • product_id

  • product_title

  • variant_title

  • current_quantity

  • alert_type

  • optional threshold

  • optional days_unchanged

  • optional location_id

  • optional location_name

  • Description: Computes current alert list from product + inventory queries, applies filters, returns paginated results.

Health routes

  • GET /admin/plugin -> 200
  • GET /store/plugin -> 200

Important endpoint examples

# List alerts (first page)
curl "http://localhost:9000/admin/stock-monitoring/alerts?limit=50&offset=0" \
  -H "Authorization: Bearer <ADMIN_JWT>"
# Filter by out-of-stock alerts
curl "http://localhost:9000/admin/stock-monitoring/alerts?alert_type=out_of_stock" \
  -H "Authorization: Bearer <ADMIN_JWT>"
# Search by title
curl "http://localhost:9000/admin/stock-monitoring/alerts?search=laptop" \
  -H "Authorization: Bearer <ADMIN_JWT>"

Services

StockMonitoringModuleService

Located at src/modules/stock-monitoring/service.ts.

What it manages:

  • Option resolution/validation.
  • Exposes threshold and notification recipient getters used by jobs/routes.

Key methods:

  • getLowStockThreshold(): number
  • getSlowMovingDaysThreshold(): number
  • getLowStockThresholdForWarehouse(locationId: string): number
  • getAdminNotificationEmails(): string[]

Workflow step dependencies (notification sending)

send-stock-notification-step resolves:

  • Modules.NOTIFICATION service for sending email notifications.
  • ContainerRegistrationKeys.LOGGER for structured logs.

Workflows & Steps (Medusa v2)

Workflow: send-stock-alert

File: src/workflows/send-stock-alert-workflow.ts

  • Input:
    • alerts: StockAlertInput[]
    • adminEmails: string[]
  • Steps:
    • send-stock-notification
  • Output:
    • sent: boolean
    • alertsSent: number

Step: send-stock-notification

File: src/workflows/steps/send-stock-notification-step.ts

Behavior:

  • Skips if no alerts or no admin emails.
  • Builds email payload per recipient with alert summary text.
  • Uses notification service:
    • prefers createNotifications(payloads)
    • falls back to create(payload) one by one
  • Includes retry with exponential backoff:
    • max retries: 3
    • delays: 1s, 2s, 4s

Subscribers / Event Hooks

No subscribers are implemented in this plugin (src/subscribers contains README only).

Jobs

Job: check-stock-levels

File: src/jobs/check-stock-levels.ts
Schedule: 0 0 * * * (daily at midnight)

Behavior summary:

  • Resolves thresholds/emails from stock_monitoring service.
  • Loads products/variants and inventory items.
  • Resolves per-location inventory levels via:
    1. inventory module service (listInventoryLevels) if available,
    2. batch graph query fallback,
    3. per-item graph query fallback.
  • Generates:
    • out_of_stock alerts first (quantity <= 0)
    • low_stock alerts using warehouse-specific threshold (or global fallback)
    • slow_moving alerts based on days since location-level update.
  • Executes send-stock-alert workflow when alerts exist.

Admin UI / Widgets

This plugin adds an admin route (not a widget zone injection):

Admin Route: stock-monitoring-alerts

  • File: src/admin/routes/stock-monitoring-alerts/page.tsx
  • Route config label: Stock Alerts
  • UI renders:
    • alerts table
    • search input
    • alert-type filter dropdown
    • pagination/load-more controls
    • refresh action
    • action button to navigate to product detail (/products/:id)
  • Data source:
    • GET /admin/stock-monitoring/alerts

Models & Entities

No custom model/entity definitions are implemented in this plugin source.

Data sources used are Medusa core entities queried via graph/services:

  • product
  • product.variants
  • inventory_item
  • inventory levels/location relations (via inventory service or graph fields)

Use Cases & Examples

  1. Daily low-stock operations monitoring

    • Configure thresholds and recipient list, then rely on daily check-stock-levels job notifications.
  2. Warehouse-specific threshold enforcement

    • Use low_stock_threshold_per_warehouse to flag low stock differently across locations.
  3. Out-of-stock escalation

    • Detect immediate zero-quantity variants and trigger recipient notifications.
  4. Slow-moving inventory review

    • Use slow_moving_days_threshold to surface variants whose inventory hasn’t changed for long periods.
  5. Admin-side alert triage

    • Use /admin/stock-monitoring/alerts and admin route filters/search to prioritize replenishment actions.

Troubleshooting

No alert emails are sent

  • Cause: admin_notification_emails is empty/missing.
  • Fix: set non-empty recipient emails in plugin/module options.

Plugin startup fails with threshold validation errors

  • Cause: thresholds are non-numeric, non-integer, or negative.
  • Fix: set integer values >= 0 for:
    • low_stock_threshold
    • slow_moving_days_threshold
    • low_stock_threshold_per_warehouse[*]

Alerts show unexpected warehouse data

  • Cause: location level resolution falls back based on available query/service data.
  • Fix: verify inventory levels, location IDs, and location names are properly configured in inventory module data.

No alerts found even though stock is low

  • Cause: threshold/warehouse filter mismatch or inventory-level retrieval issues.
  • Fix: verify effective threshold (global vs per-warehouse), inventory quantities, and location-level links for variants.

Notification send failures

  • Cause: notification module unavailable or provider-level send failures.
  • Fix: ensure Modules.NOTIFICATION is configured and a notification provider is active; inspect logs for retry attempts/errors.

Admin alerts endpoint errors

  • Cause: graph query/runtime data issues.
  • Fix: inspect server logs, verify inventory/product graph entities and module health.