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

redux-intervention

v0.3.1

Published

Middlewares and Middleware Reducers for use with Redux.

Readme

Redux Intervention

A collection of functions for composing and simplifying middleware in Redux.

:construction: :construction: This is currently a work in progress. Pull requests and discussion are very welcome.

npm install redux-intervention
import { promote } from 'redux-intervention';
promote(whatYouThunk);

Overview

  • capture - Stop an action from propogating and optionally use it to dispatch a new action.
  • combine - Efficiently combine and limit middleware to action types.
  • promiseNext - Wrap middleware(s) to return the value of next(action) as a promise.
  • promote - Promotes a thunk or action creator into a middleware.
  • request - Wrap a middleware with additional actions that are dispatched on request, fulfillment, and failure.

Promote

Most of the logic of the application is most naturally expressed as thunks and action creators. Middleware can be a great place to consolidate and expose that logic.

Promote a thunk to a middleware by writing a promoter (a function that takes an action, and optionally a next function) and passing it to promote.

Combine

Problem: The suggested way to write middleware (with switch statements) can result in some hard to debug problems, like missed breaks applying actions to extra cases, and results in middleware functions that are inflexible.

Combine middleware based on action type cases. Order is preserved.

const userMiddleware = combine(
  [login, "LOGIN"],
  [logout, "LOGOUT"]
)
const articlesMiddleware = combine(
  [getArticles, "REQUESTED_ARTICLES"],
  [getCategories, "REQUESTED_CATEGORIES"]
)
const middleware = combine(
  userMiddleware,
  articlesMiddleware
)

Capture

Problem: Dropping dispatches of invalid actions or during invalid states is a common problem. This provides a very simple interface to handle capturing and re-dispatching or dropping actions.

For example, block actions that request a resource before that resource can be accessed.

import check from 'check-types';

const logInvalidAction = capture((state, action) => {
  const invalidAction = (switch (action.type) {
    case "REQUESTED_USER_INFORMATION":
      return check.string(state.userToken);
      break;
    default:
      return false;
  })()
  console.warn('Invalid Action');
  return 
})

PromiseNext

Problems:

  • The only way to know if an action has resolved in the reducer is to subscribe to the state and know what the state should look like after it’s resolved.
  • If you want your middleware to return a Promise, you must return the promise through all middleware.

Returns a promise that resolves when next(action) is called. So this will resolve when the action has resolved to either the last promiseNext middleware or the reducer.

In practice:

// store.createStore(reducer, applyMiddleware(thunk, promiseNext()))

const loadSomeStuffMiddleware = store => next => action =>
// if (action.type === "REQUESTED_USER_THINGS")
  Promise.all(
    store.dispatch({ type: "REQUESTED_CATEGORIES", payload: { userId, token }}),
    store.dispatch({ type: "REQUESTED_ARTICLES", payload: { userId, token }}),
    store.dispatch({ type: "REQUESTED_FLOWERS", payload: { userId, token }})
  ).then(() => next(action))

Note: Don’t wrap thunk in promiseNext(), since thunk doesn’t call next(action).

Request

Problem: redux-saga, etc. are all really bloated, and hard to make clean code from, and result in weird reducers that don’t always play well.

Wraps the middleware, dispatching additional REQUESTED, FULFILLED, FAILED actions when the middleware has resolved the action.

In action:

const types = {
  REQUESTED: {},
  FULFILLED: {},
  FAILED: {}
};

const pendingActionMiddlewareReducer = (state = [], action) => {
  switch (action.type) {
    case types.REQUESTED:
      return [...state, action.payload];
    case types.FAILED:
    case types.FULFILLED:
      return state.filter(a => a !== action.payload)
    default:
      return state;
  }
}
const fulfilledActionMiddlewareReducer = (state = [], action) => {
  switch (action.type) {
    case types.FULFILLED:
      return [...state, action.payload];
    default:
      return state;
  }
}

const reducer = combineReducers({
  pending: pendingActionMiddlewareReducer,
  fulfilled: fulfilledActionMiddlewareReducer
})

const store = createStore(pendingActionMiddlewareReducer, applyMiddleware(request(middleware)))

store.dispatch({ type: "ASYNC" }).then(() => {
  store.getState()
  // success { pending: [], fulfilled: [{type: "ASYNC"}] }
  // failure { pending: [], fulfilled: [] }
})
store.getState() // { pending: [{type: "ASYNC"}], fulfilled: [] }