Skip to content

sergiofasilva/object-state-history

Repository files navigation

ObjectStateHistory

npm version Build Status js-standard-style Known Vulnerabilities

 

ObjectStateHistory - A tool for state management

The ObjectStateHistory is a JavaScript implementation that allows you to keep track of changes in an object over time, creating a history of the modifications.

Maintaining the state of an application in a large software project can be challenging. One advantage of using ObjectStateHistory is that it maintains a history of all the changes to the object's state. This feature is essential when you have lots of data changes to monitor, and you do not want to spend too much time debugging.

Since each change creates a new state of the object without changing the previous states, we have, in a sense, an object with immutability characteristics, or a list of immutable objects.

 

Installation

To use ObjectStateHistory, simply install it via npm:

npm i object-state-history

  ... or via yarn:

yarn add object-state-history

 

Usage

The ObjectStateHistory can be used by importing it into your module using the import statement, like so:

import ObjectStateHistory from 'object-state-history'

  ... or with require (CommonJS):

const ObjectStateHistory = require('object-state-history')

Once imported, create a new instance of ObjectStateHistory by passing an object to the constructor like:

const theObject = { prop1: 'value1', prop2: 'value2' }
const objHistory = new ObjectStateHistory(theObject)

Once created, you can make changes to the object directly as usual, but they will be tracked automatically by ObjectStateHistory:

objHistory.prop3 = 'value3' // { prop1: 'value1', prop2: 'value2', prop3: 'value3' }
delete objHistory.prop1 // { prop2: 'value2', prop3: 'value3' }

To retrieve a snapshot of the object at any time, simply call the value getter:

console.log(objHistory.value) // { prop2: 'value2', prop3: 'value3' }

You can also get a list of all states and changes made to the object using the list() method:

console.log(objHistory.list())

And you can retrieve the state of the object at the given index in the history by calling the at() method with an index parameter:

console.log(objHistory.at(0))

 

 

Sample

import ObjectStateHistory from 'object-state-history'

const obj = { a: 1, b: 2 }
const objHistory = new ObjectStateHistory(obj)

// Change the value of a property
objHistory.a = 3 // { a: 3, b: 2 }

// Add a new property
objHistory.e = 6 // { a: 3, b: 2, e: 6 }

// Change or add multiple properties
objHistory.merge({ b: 4, c: 3, d: 5 }) // { a: 3, b: 4, e: 6, c: 3, d: 5 }

// Replace the entire object
objHistory.replace({ a: 4, b: 5 }) // { a: 4, b: 5 }

// Delete a property of the object
delete objHistory.a // { b: 5 }

// Get the current state of the object
const currentState = objHistory.value // { b: 5 }

// Get a specific state of the object by index
const stateAtIndex = objHistory.at(0) // { a: 1, b: 2 }

// Get a list of all states and the changes of the object
const stateList = objHistory.list()

 

API

The ObjectStateHistory provides the following:

 

Constructor

new ObjectStateHistory(object, history, options)

Creates a new instance of ObjectStateHistory with the initial value of object.

 

Parameters

object

The inicial object data.

history

The history of changes of the object. See Using history chapter.

options

The options of ObjectStateHistory. See Options chapter.

Properties

value

Returns the current state of the object.

 

Methods

at(index)

Returns the state of the object at the given index, allowing for positive and negative integers. Negative integers count back from the last item in the list history. Assumes index -1, if no argument is passed, which corresponds to the last item.

info()

Returns an object with the properties: options, list and value.

  • options: an object with the options assumed by ObjectStateHistory;
  • list: same as the list() method;
  • value: same as the valueOf() method or the value property.

list()

Returns a list of all the states of the object with the history of changes.

merge(data)

Merges the provided data into the current state of the object.

replace(data)

Replaces the current state of the object with the provided data.

toString()

Returns a JSON string representation of the current state of the object.

valueOf()

Returns the same as the property value.

 

Events

change

Event triggered whenever changes are made to the object. The changed information is passed as a callback parameter. It can be useful, for example, to save the last state of the object in an external cache system whenever there are changes.

const objHist = new ObjectStateHistory({ a: '1', b: '2' }) // initial object
// item is an object with the changed data
objHist.on('change', function (item) {
  console.log(item.data) // { c: '3' }), the changed data
  console.log(this.value) // { a: '1', b: '2', c: '3' }), the current state of the object
  console.log(this.at(0)) // { a: '1', b: '2' }), the state of the object at index 0
  console.log(this.list().length) // 2
})

objHist.c = '3' // trigger change event

 

Using history

If you need to share the object across more than one node instance, you can use the history parameter to create an object with a list containing the history of previous changes.

You can save the change history whenever changes are detected in the change event. See Events chapter.

Example of using history:

const obj = { a: '1', b: '2' }
const objInitial = new ObjectStateHistory(obj)
objInitial.c = '3'
console.log(objInitial.value) // { a: '1', b: '2', c: '3' }

// get the history of changes from another object
const history = objInitial.list()
// using the history in a new object
const objWithHistory = new ObjectStateHistory(null, history)
console.log(objWithHistory) // { a: '1', b: '2', c: '3' }

objWithHistory.d = '4'
console.log(objWithHistory.value) // { a: '1', b: '2', c: '3', d: '4' }

// using the history in a new object and merge the object from first parameter
const objWithHistoryAndMerge = new ObjectStateHistory({ e: '5' }, history)
console.log(objInitial.value) // { a: '1', b: '2', c: '3' }
console.log(objWithHistory.value) // { a: '1', b: '2', c: '3' }
console.log(objWithHistoryAndMerge.value) // { a: '1', b: '2', c: '3', e: '5' }
console.log(objWithHistory.list().length) // 4, includes the changes received in the history
console.log(objWithHistoryAndMerge.list().length) // 3, includes the changes received in the history

 

Options

In the constructor you can send as a third parameter an object with the options.

Limit

If you use very large objects and/or make many changes to objects, this can result in the ObjectStateHistory taking up a lot of memory. If this is a problem for you or if you don't need to have a very large history, it is possible to limit the number of changes stored in the list history.

const options = {
  limit: 5
}

const obj = { a: 1, b: 2 }
const objHistory = new ObjectStateHistory(obj, null, options)

The limit option accepts non-negative integer values (natural numbers). Where the value zero (0) means that it has no limits (default behavior).

 

Notes

Shallow history

Note that the history only works on the first level of the object, it's a shallow history, i.e. it doesn't work with multi-level objects. Deep objects work like regular objects, i.e. by reference.

Version changes

This version is not compatible with the previous one. The use of cache in the previous version had problems, so now it is not possible to use cache, instead it is recommended to use the history parameter. Please note that the constructor has changed, the options parameter is now the third parameter while in the second we have the history parameter.

Authors

 

License

The ObjectStateHistory is open source software licensed under the MIT License.

MIT

About

The ObjectStateHistory is a JavaScript implementation that allows you to keep track of changes in an object over time, creating a history of the modifications.

Resources

License

Stars

Watchers

Forks

Packages

No packages published