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 🙏

© 2025 – Pkg Stats / Ryan Hefner

teadux

v1.3.2

Published

The Elm archicture + Redux

Downloads

14

Readme

TEADUX

Overview

  • Tea = The Elm Architecture
  • Dux = Redux

This is a simple library to provide 3 things:

  1. Managing effects
  • Side effects are serialized into "Commands"

  • Commands are easily runnable later and compared against for safe testing

  1. Scalability
  • Scale your reducer/actions via Cmd.fmap or Cmd.list.fmap, by breaking down reducers into fractal pattern. Factal pattern allows one to reason locally, thereby easier to scale.

  • Side effects & state are consolidated into reducer files. This overcomes the one of the major short comings of redux-observable and redux-saga.

  • Dependencies are declared and passed to your reducer via the runtime. This reduces dependencies and allows you to reason more locally. In addition, mocks for dependencies can be easily passed in during testing to simulate side effects.

  1. Type safe (as much as possible via typescript)
  • And also nice to have intelli-sense.

This is heavily inspired by redux-loop and Elm.

How to use

import {
  // since reducer is returns state and side effect, need a special `createStore`
  // to type check
  createStore,
  Runtime,
  createEnhancer,
  mcompose
  makeSanitizers,
} from 'teadux'

// enhancer enqueues commands from your reducers into your runtime
// runtime executes and dispatches success/fail actions
const deps: Deps = { queryData, mutateData }
const teaRuntime = new Runtime<State, Action, Deps>(deps)

const {actionSanitizer, stateSanitizer} = makeSanitizers(teaRuntime, 'subAction')

// with the following you can see a `@@cmds` key in the STATE panel of the
// redux devtool, as well as actions formatted as `POSTS -> NEW_MESSAGE -> SUBMIT`
const composeEnhancers = windowIfDefined.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
    ? windowIfDefined.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
        actionSanitizer,
        stateSanitizer,
      })
    : compose;

const routerMiddleware = ... // react router e.g.

const store = createStore(
  reducer,
  initialState,
  composeEnhancers(createEnhancer(teaRuntime>, applyMiddleware(routerMiddleware))
);

Reducer

Reducer in teadux has the following signature:

export interface TeaReducer<S, A extends Action, D = {}> {
  (state: S | undefined, action: A, dependencies: D, dispatch: Dispatch<A>): [
    S,
    Command<A>[]
  ];
}

// where
export type Dispatch<A> = (action: A) => void;

export type Command<A extends Action, R=any> =
  | ActionCommand<A>
  | RunCommand<A, R>;

The list of Command<A, R> would be something that runs a http request, etc. (Docs to come)

Example

You can find a full-fledged example here.

Kitchen sink

You can also find an example of how this lib works in the index.test.ts file.

Testing

Testing should be easy as side effects are "serialized" into commands with which you can use "deep equal" tests. Example:


import { Cmd, actionCreator, effect } from 'teadux'

async function doWork(name: string): Promise<string> {
  return await Promise.resolve(name);
}

function onSuccess(name: string) {
  return { type: 'SUCCESS', name };
}

function onFail(name: string) {
  return { type: 'FAIL', name };
}

test('Cmd.run', () => {
  expect(
    Cmd.run(effect(doWork, 'hello world'), {
      success: actionCreator(onSuccess),
      fail: actionCreator(onFail),
    })
  ).toEqual({
    type: 'RUN',
    effect: {
      name: 'doWork',
      func: doWork,
      args: ['hello world'],
    },
    success: {
      name: 'onSuccess',
      func: onSuccess,
      args: [],
    },
    fail: {
      name: 'onFail',
      func: onFail,
      args: [],
    },
  });
});

test('Cmd.action', () => {
  expect(Cmd.action({ type: 'HELLO' })).toEqual({
    type: 'ACTION',
    name: 'HELLO',
    actionToDispatch: {
      type: 'HELLO',
    },
  });
});

Dependencies

In addition, although you may directly reference side effect with effect, it is better to specify them during runtime construction. Since root reducer is passed the dependencies, you can pass mocks during testing.

Finally, being specific about dependencies allows you to do more local reasoning.

Type safety

TBD