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

@nexus-state/middleware

v1.0.3

Published

Middleware plugin for Nexus State with plugin hooks support

Readme

@nexus-state/middleware

Middleware plugin for Nexus State with plugin hooks support

npm version Coverage for middleware package License

DocumentationRepository


📦 Installation

npm install @nexus-state/middleware

Required:

npm install @nexus-state/core

🔗 See Also

Full ecosystem: Nexus State Packages


Description

The @nexus-state/middleware package provides a plugin-based approach to intercept and modify store operations in Nexus State. It uses the core plugin hooks system (onSet, afterSet) to provide middleware functionality.

Installation

npm install @nexus-state/middleware

Key Features

  • Plugin-based architecture - Uses core plugin hooks system
  • Intercept store operations - beforeSet and afterSet hooks
  • Value transformation - Modify values before they're set
  • Atom-specific middleware - Apply middleware to specific atoms only
  • Multiple middleware support - Chain multiple middleware on the same atom
  • Backward compatible - Legacy API still supported
  • Disposable - Clean up middleware when no longer needed

Usage

New API (Recommended)

import { createStore, atom } from '@nexus-state/core';
import { createMiddlewarePlugin } from '@nexus-state/middleware';

const store = createStore();
const countAtom = atom(0);

// Create and apply middleware plugin
const plugin = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => {
>
> [![Coverage for middleware package](https://coveralls.io/repos/github/eustatos/nexus-state/badge.svg?branch=main&job_name=middleware)](https://coveralls.io/github/eustatos/nexus-state?branch=main)
    console.log('Before set:', value);
    // Ensure non-negative values
    return Math.max(0, value);
  },
  afterSet: (atom, value) => {
    console.log('After set:', value);
    // Side effects only (logging, analytics, etc.)
  }
});

store.applyPlugin(plugin);

// Use the store
store.set(countAtom, 5);  // Logs: "Before set: 5", "After set: 5"
store.set(countAtom, -3); // Value becomes 0 (non-negative)

Middleware Chain

Multiple middleware can be applied to the same atom. They execute in order:

const plugin1 = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => value + 1,
});

const plugin2 = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => value * 2,
});

store.applyPlugin(plugin1);
store.applyPlugin(plugin2);

store.set(countAtom, 5); 
// Execution: 5 → +1 = 6 → *2 = 12
// Result: 12

Different Middleware for Different Atoms

const countAtom = atom(0);
const nameAtom = atom('');

// Count middleware - ensure non-negative
store.applyPlugin(
  createMiddlewarePlugin(countAtom, {
    beforeSet: (atom, value) => Math.max(0, value),
  })
);

// Name middleware - trim and validate
store.applyPlugin(
  createMiddlewarePlugin(nameAtom, {
    beforeSet: (atom, value) => value.trim().slice(0, 50),
  })
);

Disposing Middleware

const plugin = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => value,
});

store.applyPlugin(plugin);

// ... later, when middleware is no longer needed
if (plugin.dispose) {
  plugin.dispose();
}

Legacy API (Deprecated)

The old API is still supported but will be removed in the next major version:

import { createStore, atom } from '@nexus-state/core';
import { middleware } from '@nexus-state/middleware';

const store = createStore();
const countAtom = atom(0);

// Legacy approach - wraps store.set method
store.applyPlugin(
  middleware(countAtom, {
    beforeSet: (atom, value) => value,
    afterSet: (atom, value) => {},
  })
);

API Reference

createMiddlewarePlugin<T>(atom: Atom<T>, config: MiddlewareConfig<T>): Plugin

Creates a middleware plugin for a specific atom.

Parameters:

  • atom - The target atom to intercept
  • config - Configuration object with hooks

Returns: Plugin function that can be applied to a store

MiddlewareConfig<T>

interface MiddlewareConfig<T> {
  /**
   * Hook called before setting a new value.
   * Can modify the value by returning a new value.
   * Return undefined to keep the original value.
   */
  beforeSet?: (atom: any, newValue: T) => T | void;
  
  /**
   * Hook called after setting a new value.
   * Side effects only - cannot modify the value.
   */
  afterSet?: (atom: any, newValue: T) => void;
}

middleware<T>(atom: Atom<T>, config: MiddlewareConfig<T>): (store: Store) => void

@deprecated Use createMiddlewarePlugin instead.

Legacy middleware function that wraps store.set method.

Hook Execution Order

store.set(atom, value)
  ↓
[onSet hooks] - beforeSet (can modify value)
  ↓
originalSet(atom, modifiedValue)
  ↓
notify subscribers & dependents
  ↓
[afterSet hooks] - afterSet (side effects only)

Examples

Logger Middleware

const loggerPlugin = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => {
    console.log(`[${atom.name || 'atom'}] Setting value:`, value);
    return value;
  },
  afterSet: (atom, value) => {
    console.log(`[${atom.name || 'atom'}] Value set to:`, value);
  },
});

Validation Middleware

const validationPlugin = createMiddlewarePlugin(ageAtom, {
  beforeSet: (atom, value) => {
    if (typeof value !== 'number' || value < 0 || value > 150) {
      throw new Error('Age must be between 0 and 150');
    }
    return value;
  },
});

Analytics Middleware

const analyticsPlugin = createMiddlewarePlugin(purchaseAtom, {
  afterSet: (atom, value) => {
    // Send analytics event
    analytics.track('purchase', {
      amount: value.amount,
      timestamp: Date.now(),
    });
  },
});

License

MIT


Migration Guide

Migrating from v0.x to v1.x

What Changed

In version 1.0.0, the middleware package has been refactored to use the new plugin hooks system from @nexus-state/core. This provides better integration and cleaner architecture.

Before (v0.x)

import { createStore, atom } from '@nexus-state/core';
import { middleware } from '@nexus-state/middleware';

const store = createStore();
const countAtom = atom(0);

// Old approach - wraps store.set method
store.applyPlugin(
  middleware(countAtom, {
    beforeSet: (atom, value) => {
      console.log('Before:', value);
      return Math.max(0, value);
    },
    afterSet: (atom, value) => {
      console.log('After:', value);
    }
  })
);

After (v1.x)

import { createStore, atom } from '@nexus-state/core';
import { createMiddlewarePlugin } from '@nexus-state/middleware';

const store = createStore();
const countAtom = atom(0);

// New approach - uses plugin hooks
const plugin = createMiddlewarePlugin(countAtom, {
  beforeSet: (atom, value) => {
    console.log('Before:', value);
    return Math.max(0, value);
  },
  afterSet: (atom, value) => {
    console.log('After:', value);
  }
});

store.applyPlugin(plugin);

Key Differences

| Aspect | v0.x (Legacy) | v1.x (New) | |--------|---------------|------------| | Function | middleware() | createMiddlewarePlugin() | | Return type | (store) => void | Plugin (with hooks) | | Architecture | Wraps store.set | Uses core hooks | | Disposal | Not supported | plugin.dispose() | | Multiple middleware | Reverse order | Application order |

Migration Steps

  1. Replace import:

    - import { middleware } from '@nexus-state/middleware';
    + import { createMiddlewarePlugin } from '@nexus-state/middleware';
  2. Update function call:

    - store.applyPlugin(middleware(atom, config));
    + store.applyPlugin(createMiddlewarePlugin(atom, config));
  3. Remove store creation wrapper:

    - const store = createStore([middleware(...)]);
    + const store = createStore();
    + store.applyPlugin(createMiddlewarePlugin(...));

Backward Compatibility

The legacy middleware() function is still available but marked as deprecated. It will be removed in version 2.0.0.