• Stars
    star
    284
  • Rank 145,041 (Top 3 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 11 years ago
  • Updated almost 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Tiny framework for building models with the event sourcing pattern (events and snapshots).

Build Status

REPO (TEMPORARILY?) MOVED: Currently being maintained at https://github.com/cloudnativeentrepreneur/sourced - publishing to same npm package!

sourced

Tiny framework for building models with the event sourcing pattern (events and snapshots). Unlike Active Record where entity state is persisted on a one-model-per row database format, event sourcing stores all the changes (events) to the entity, rather than just its current state. The current state is derived by loading all events, or a latest snapshot plus subsequent events, and replaying them against the entity.

One large benefit of event sourcing: your data is your audit trail. Zero discrepancies.

For example usage, see the examples and tests.

Sourced makes no assumptions about how you store your events and snapshots. The library is small and tight with only the required functionality to define entities and their logic, enqueue and emit events, and track event state to later be persisted. To actually persist, use one of the following libraries or implement your own:

ES6 Example

const Entity = require('sourced').SourcedEntity;

class Market extends Entity {
  constructor(snapshot, events) {
    super()
    this.orders = [];
    this.price = 0;

    this.rehydrate(snapshot, events)
  }

  init(param) {
    this.id = param.id;
    this.digest('init', param);
    this.emit('initialized', param, this);
  }

  createOrder(param) {
    this.orders.push(param);
    var total = 0;
    this.orders.forEach(function (order) {
      total += order.price;
    });
    this.price = total / this.orders.length;
    this.digest('createOrder', param);
    this.emit('done', param, this);
  };
}

Reference

Classes

Entity

{Function} Entity

EntityError

{Function} EntityError

Entity

{Function} Entity

Kind: global class Requires: module:events, module:debug, module:util, module:lodash License: MIT

new Entity([snapshot], [events])

Creates an event-sourced Entity.

Param Type Description
[snapshot] Object A previously saved snapshot of an entity.
[events] Array An array of events to apply on instantiation.

entity.emit()

Wrapper around the EventEmitter.emit method that adds a condition so events are not fired during replay.

Kind: instance method of Entity

entity.enqueue()

Add events to the queue of events to emit. If called during replay, this method does nothing.

Kind: instance method of Entity

entity.digest(method, data)

Digest a command with given data.This is called whenever you want to record a command into the events for the entity. If called during replay, this method does nothing.

Kind: instance method of Entity

Param Type Description
method String the name of the method/command you want to digest.
data Object the data that should be passed to the replay.

entity.merge(snapshot)

Merge a snapshot onto the entity.

For every property passed in the snapshot, the value is deep-cloned and then merged into the instance through mergeProperty. See mergeProperty for details.

Kind: instance method of Entity See: Entity.prototype.mergeProperty

Param Type Description
snapshot Object snapshot object.

entity.mergeProperty(name, value)

Merge a property onto the instance.

Given a name and a value, mergeProperty checks first attempt to find the property in the mergeProperties map using the constructor name as key. If it is found and it is a function, the function is called. If it is NOT found we check if the property is an object. If so, we merge. If not, we simply assign the passed value to the instance.

Kind: instance method of Entity See

  • mergeProperties
  • Entity.mergeProperty
Param Type Description
name String the name of the property being merged.
value Object the value of the property being merged.

entity.replay(events)

Replay an array of events onto the instance.

The goal here is to allow application of events without emitting, enqueueing nor digesting the replayed events. This is done by setting this.replaying to true which emit, enqueue and digest check for.

If the method in the event being replayed exists in the instance, we call the mathod with the data in the event and set the version of the instance to the version of the event. If the method is not found, we attempt to parse the constructor to give a more descriptive error.

Kind: instance method of Entity

Param Type Description
events Array an array of events to be replayed.

entity.snapshot() ⇒ Object

Create a snapshot of the current state of the entity instance.

Here the instance's snapshotVersion property is set to the current version, then the instance is deep-cloned and the clone is trimmed of the internal sourced attributes using trimSnapshot and returned.

Kind: instance method of Entity

entity.trimSnapshot(snapshot)

Remove the internal sourced properties from the passed snapshot.

Snapshots are to contain only entity data properties. This trims all other properties from the snapshot.

Kind: instance method of Entity See: Entity.prototype.snapshot

Param Type Description
snapshot Object the snapshot to be trimmed.

Entity.digestMethod(type, fn)

Helper function to automatically create a method that calls digest on the param provided. Use it to add methods that automatically call digest.

Kind: static method of Entity

Param Type Description
type Object the entity class to which the method will be added.
fn function the actual function to be added.

Example

Entity.digestMethod(Car, function clearSettings (param) {

    const self = this;

    this.settings.get(param.name).forEach((name, config) => {

      config.sources.forEach((source) => {

        source.remove();

      });

    });

    return this.settings;

   });

Entity.mergeProperty(type, name, fn)

Convenience function to store references to functions that should be run when mergin a particular property.

Kind: static method of Entity See: mergeProperties

Param Type Description
type Object the entity class to which the property->fn belongs to.
name String the name of the property that holds the fn.
fn function the function to execute when merging the property.

Example

function Wheel (status) {
   this.status = status;
 }

 Wheel.prototype.go = function () {
   this.status = 'going';
 }

 function Car () {
   this.id = null;
   this.wheel = new Wheel(); // for instantiating our default wheel, when we first 'new' up a Car

   Entity.apply(this, arguments);
 }

 util.inherits(Car, Entity);

 Entity.mergeProperty(Car, 'interests', function (obj) {
   this.wheel = new Wheel(); // for instantiating our wheel from saved values in a database
 });

eventsToEmit : Array

[Description]

Kind: global variable Todo

  • discuss the use of this so it can be documented better.

newEvents : Array

[Description]

Kind: global variable Todo

  • discuss the use of this so it can be documented better.

replaying : Boolean

Boolean to prevent emit, enqueue and digest from running during replay.

Kind: global variable

snapshotVersion : Number

Holds the version of the latest snapshot for the entity.

Kind: global variable

timestamp : Number

Holds the event's timestamp in the entity.

Kind: global variable

version : Number

Holds the current version of the entity.

Kind: global variable

mergeProperties

mergeProperties holds a map of entity types to properties.

Kind: global variable See

  • Entity.mergeProperty
  • Entity.prototype.mergeProperty

EntityError

{Function} EntityError

Kind: global class

new EntityError(msg, [constr])

Extending native Error.

Param Type Default Description
msg String The error message.
[constr] Object this The constructor or instance.

More Repositories

1

meta

tool for turning many repos into a meta repo. why choose many repos or a monolithic repo, when you can have both with a meta repo?
JavaScript
2,026
star
2

servicebus

Simple service bus for sending events between processes using amqp.
JavaScript
420
star
3

loop

loop through commands in fun and amazing ways!
JavaScript
126
star
4

forecast.io

wrapper for the forecast.io API
JavaScript
117
star
5

sourced-repo-mongo

mongo data store and repository for sourced-style event sourcing models
JavaScript
55
star
6

coinbase

wrapper for the coinbase bitcoin wallet & exchange API
JavaScript
48
star
7

meta-git

git plugin for meta
JavaScript
23
star
8

servicebus-retry

JavaScript
18
star
9

mockrequire

Simple module for mocking required dependencies. Works with any testing suite.
JavaScript
17
star
10

node-paypal-masspayments

Node PayPal Mass Payment NVM
JavaScript
14
star
11

servicebus-register-handlers

JavaScript
11
star
12

microsvc

tiny reusable framework for building microservices with messaging and rest
JavaScript
11
star
13

servicebus-trace

servicebus middleware to publish message receipt information to a central store, for message tracking and tracing purposes.
JavaScript
10
star
14

filecoin-lotus-docker

Dockerfile
9
star
15

meta-npm

npm plugin for meta
JavaScript
8
star
16

meta-yarn

yarn plugin for meta
JavaScript
6
star
17

node_hands_on-unit_testing

6
star
18

meta-project

JavaScript
6
star
19

july3rd

6
star
20

SeattleNodejs.SimpleServerWHerokuDeploy

JavaScript
5
star
21

amqp-match

transforms amqp routing keys to regular expressions for more convenient runtime matching
JavaScript
4
star
22

selenium-webdriver-slug

Starter project for getting rolling with Selenium Webdriver and PhantomJS
JavaScript
4
star
23

meta-gh

gh command plugin for meta
JavaScript
3
star
24

cconfig

JavaScript
3
star
25

kill-all-node-on-windows

JavaScript
3
star
26

meta-init

plugin for initializing new meta repositories
JavaScript
2
star
27

sample-service

JavaScript
2
star
28

servicebus-message-domain

JavaScript
2
star
29

gitslave

fork of gitslave from http://gitslave.sourceforge.net/ modified to work with current versions of git
Perl
2
star
30

meta-exec

exec plugin for meta
JavaScript
2
star
31

llog

JavaScript
2
star
32

find-file-recursively-up

returns the path at which a provided filename exists, checking the current directory and any parent folders recursively up.
JavaScript
2
star
33

pidler

simple module to create process pids
JavaScript
1
star
34

meta-loop

helper function to loop-exec in a meta repository and all child repositories
JavaScript
1
star
35

sample-site

CSS
1
star
36

microsvc-slave

JavaScript
1
star
37

objectify-folder

return all non index.js modules in a folder as a single object
JavaScript
1
star
38

thenodejsmeetup.com

JavaScript
1
star
39

servicebus-rabbitmq

rabbitmq bus provider for servicebus
JavaScript
1
star
40

get-meta-file

JavaScript
1
star
41

brb

1
star
42

symlink-meta-dependencies

symlink all of a project's dependencies which appear in the project's .meta file
JavaScript
1
star
43

sourced-queued-repo

JavaScript
1
star
44

google-cloud-run

google cloud run example project with build and deployment helpers
Makefile
1
star
45

find-module-bin

scan known node_modules directories to find installation directory of a particular bin file
JavaScript
1
star
46

microsvc-example

JavaScript
1
star