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

eventuality

v0.3.0

Published

Some components for cqrs

Downloads

3

Readme

Eventuality

This is simply a POC and my way of writing down my thoughts about how I would want to implement a CQRS system. The focus here is on components/tools and functions that can be interchanged rather than a full framework.

components

  • Domain Model (Aggregate)

    This is the object that represents the state of our model. Only it can change its own state as a result of Commands. Each state change results in an Event.

  • EventStore

    A storage facility for events/history/facts. This can be in memory or backed by a database. What I have here is in memory.

  • EventBus

    The medium through which facts of state change are shared to interested observers.

  • EventListeners

    These are the observers of facts of state changes. They are functions to be invoked when the domain model has changed its state.

  • Repository

    A component through which we create and access the domain model.

  • Commands

    Objects representing an intent of state change by the user on the domain model.

  • CommandHandlers

    Functions with the purpose of communicating the intended state change to the domain model.

  • Events

    Objects representing a fact of state change in the domain model.

Based on these definitions of the components, the system should work like this:

CommandHandlers are effectively CH(Command) -> [...Event]

Actions the domain model can execute are A() -> [...Event]

This means every intention to change the state of the domain model results in n events (where n = 0 is a failure and n > 0 is success).

Examples of usage

Of course, I'll use a Todo application because that's the app any system can build.

Eventuality = require 'eventuality'

Todo = Eventuality.defineAggregate
  name: 'Todo'
  state:
    description: null
    completed: false
  methods:
    complete: ->
      @state.completed = true
      Eventuality.Event(aggregateId: @id, name: 'TodoCompletedEvent', payload: {completed: true}, state: @state)

TodoCommands =
  CreateTodo: ({id, description }) -> name: 'CreateTodo', message: {id, description}
  MarkAsCompleted: ({ id }) -> name: 'MarkAsCompleted', message: {id}

TodoEventStore = Eventuality.EventStore()
# If you want to persist events somewhere else
#
# TodoEventStore = Eventuality.EventStore({
#   add: (event) -> # put it somewhere
#   getEvents: -> # return an array of events
# })

TodoRepository = Eventuality.Repository 'Todo', Todo, TodoEventStore

TodoCommandHandlers =
  CreateTodo: (attrs) -> TodoRepository.add attrs
  MarkAsCompleted: ({ id }) ->
    todo = TodoRepository.load id
    todo.complete()

TodoEventBus = Eventuality.EventBus()

TodoCreatedEventListenerToUpdateDB = (event) -> # Update database...
TodoCreatedEventListenerToLogStuff = (event) -> # Do some logging...

TodoEventBus.registerListeners
  TodoCreatedEvent: [
    TodoCreatedEventListenerToUpdateDB
    TodoCreatedEventListenerToLogStuff
  ]
  TodoCompletedEvent: [
    (event) ->
      # More stuff to be done
  ]

It can(doesn't have to) all come together like so...

TodoFlow = Eventuality.Flow
  eventStore: TodoEventStore
  eventBus: TodoEventBus
  commandHandlers: TodoCommandHandlers

## Later when the user wants to do things...
TodoFlow.dispatch TodoCommands.CreateTodo id: 'todo1', description: 'Create a todo'
TodoFlow.dispatch TodoCommands.MarkAsCompleted id: 'todo1'