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

sourced-ts

v0.0.9

Published

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

Downloads

3

Readme

Build Status

sourced-ts

Tiny TypeScript framework forked from sourced 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-ts 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:

TypeScript 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

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. |