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 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-eventstore

v0.1.0

Published

CQRS, event sourcing, and event collaboration made easy with Node.js, Redux, and Event Store!

Downloads

16

Readme

redux-eventstore

Build Status

CQRS, event sourcing, and event collaboration made easy with Node.js, Redux, and Event Store!

Use this library on your Node.js backend to easily write Redux-style events (usually known as actions) to an Event Store stream. You can also subscribe a Redux store (still on the backend) to the stream, allowing you to page through all the events and reduce it to the current, in-memory state. You can then query that state in response to API requests, to provide data to a client (for example).

(These docs assume some familiarity with Redux. If concepts like actions and reducers are new to you, you may first want to go check out the official Redux docs.)

import { createStream } from 'redux-eventstore';
import { createStore } from 'redux';
import rootReducer from './reducers';

// Initalise a stream object, which we'll use to write or subscribe to an Event Store stream. You would
// typically do this once, when your application starts up. Think of it like a database connection.
const stream = createStream('http://localhost:2113', 'my-stream');


// Write an event to the stream. This might be triggered by an POST request from your frontend, a
// nightly batch job, in response to another event that was read off the stream, etc. The event object
// is given inline here, but it's a good idea to write redux action creators, so that the type and
// structure of your events is abstracted away.
stream.write({ type: 'USER_CREATED', name: "Jane Smith" });


// Create a Redux store that will receive all events read from the stream. This too, would be done once,
// at app start up. The given reducer function will process the events, calculating the reduced state.
const store = createStore(rootReducer);


// Subscribe the Redux store to the event stream. It will quickly iterate through all existing events,
// and then poll forever. Each event is dispatched, synchronously, in order. The store's reducers will
// calculate state based on the events.
stream.subscribe(store.dispatch);


// Get the current state of the in-memory store. We might do this to respond to a GET request.
const currentState = store.getState();

For a full example, see demo-app.js. It shows two Express.js apps communicating asynchronously via Event Store:

  • one receives events via POST request and writes to a stream
  • the other subscribes to the stream, aggregates the state, and exposes it via GET request.

API

createStream(host, stream)

Initialises a stream object, for subscribing or writing to the Event Store.

Parameters:

  • host (String): The host where your Event Store is located. Include the scheme (protocol), FQDN, and port
  • stream (String): The name of the stream to subscribe to
  • [opts] (Object): Other, optional configuration:
    • [logger] (Function(msg): A function that will be invoked with log messages
    • [auth] (Object): Basic auth credentials
      • user (String): The EventStore username
      • pass (String): The user's password

Returns:

A stream object with the two methods documented below.

stream.write(event)

Writes an event to the stream. If you write an event using this method, don't also dispatch it to your store manually. Instead, use the subscribe method below to have your store read the event back off the stream. This will help ensure consistency across subscribers, especially in cases where events fail to write to the stream, or when multiple writes happen in quick succession, from different sources.

Parameters:

  • event (Object): The event to write to the store. Must have a type property, as a non-empty string.

Returns:

(Promise) Resolves or rejects based on the server response.

stream.subscribe(dispatch, [pollPeriod=1000])

Subscribes to an Event Store stream, dispatching all events from that stream to your redux store. Initially, all previous events will be played through as fast as possible, after which the stream will be polled for new events periodically. Events are dispatched synchronously, in the order in which they appear in the stream.

Note: If an error occurs when dispatching an event, the subscription loop will ignore it, and move on to the next event in the stream.

Parameters:

  • dispatch (Function(event)): The callback function that will receive each event read off the stream
  • [pollPeriod] (Number): How many milliseconds to wait between polls of the stream (default: 1000)

Events vs. actions

Typically with redux, you dispatch actions, which are imperatively named. For example: CREATE_USER. This makes sense when you are asking for something to happen, and some other part of the application (e.g. a reducer) is going to handle the request.

However, with Event Store (or event sourcing in general), it makes more sense to talk about events in the past tense, representing something that has already happened. For example: USER_CREATED. More explanation here.

This is why the redux-eventstore docs, examples, and source code all refer to events, rather than actions. You should keep this in mind when using it.