# observable-store

> An observable data store with dirty checking and computed properties

Latest version **0.0.5** (published 2015-04-08) · 0 weekly downloads

## Install

```sh
npm install observable-store
pnpm add observable-store
yarn add observable-store
bun add observable-store
```

## Health

**Score 15/100 (F)** — status: abandoned.

Positive: no vulnerabilities.

Warnings: low downloads; no types; no esm support; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.0.5 |
| Published | 2015-04-08 |
| First published | 2014-04-06 |
| Weekly downloads | 0 |
| TypeScript types | none |
| Module format | CommonJS |
| Dependencies | 7 |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 4 |
| Author | Olivier Scherrer |
| Maintainers | podefr |
| Keywords | data, store, datastore, observable, dirty, checking, computed |

## Links

- npm: https://www.npmjs.com/package/observable-store
- Repository: git@github.com:flams/observable-store
- Homepage: https://github.com/flams/observable-store
- Issues: https://github.com/flams/observable-store/issues
- npm.io page: https://npm.io/package/observable-store

## Dependencies (7)

- [simple-loop](https://npm.io/package/simple-loop.md) 0.0.3
- [object-count](https://npm.io/package/object-count.md) 0.0.1
- [shallow-copy](https://npm.io/package/shallow-copy.md) 0.0.1
- [shallow-diff](https://npm.io/package/shallow-diff.md) 0.0.2
- [watch-notify](https://npm.io/package/watch-notify.md) 0.0.3
- [compare-numbers](https://npm.io/package/compare-numbers.md) 0.0.1
- [nested-property](https://npm.io/package/nested-property.md) 0.0.6

## Alternatives

- [gamedig](https://npm.io/package/gamedig.md) — 29.3K weekly downloads
- [join-monster](https://npm.io/package/join-monster.md) — 12.8K weekly downloads
- [masked](https://npm.io/package/masked.md) — 5.5K weekly downloads
- [@comunica/actor-query-process-explain-logical](https://npm.io/package/@comunica/actor-query-process-explain-logical.md) — 4.7K weekly downloads
- [@veracity/vui](https://npm.io/package/@veracity/vui.md) — 4.6K weekly downloads

## Recent versions

- 0.0.5 (latest) — 2015-04-08
- 0.0.4 — 2015-04-05
- 0.0.3 — 2014-04-08
- 0.0.2 — 2014-04-06
- 0.0.1 — 2014-04-06

## README

<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

- [Observable store](#observable-store)
- [Installation](#installation)
- [How to use](#how-to-use)
	- [Initialization](#initialization)
	- [Standard CRUD methods](#standard-crud-methods)
	- [Watch changes on specific property/item](#watch-changes-on-specific-propertyitem)
	- [Watch changes on generic events such as added/updated/deleted](#watch-changes-on-generic-events-such-as-addedupdateddeleted)
	- [Unwatch changes](#unwatch-changes)
	- [Using an array's native mutative methods](#using-an-arrays-native-mutative-methods)
	- [Using an array's accessor methods.](#using-an-arrays-accessor-methods)
	- [Computed properties](#computed-properties)
	- [Store reset](#store-reset)
	- [Store utilities](#store-utilities)
- [LICENSE](#license)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Observable store
=============

An observable data store with dirty checking and computed properties.

Installation
============

```bash
npm install observable-store
```

How to use
==========

Require observable-store:

```js
var Store = require("observable-store");
```

## Initialization
It can be initialized with or without data. When initialized with data, a shallow clone is done first.

```js
// Without data, an object based store:
var store = new Store({});

// Without data, an array base store:
var store = new Store([]);

// With an array
var store = new Store(["array", "of", "items"]);

// With an object
var store = new Store({
  property1: "object",
  property2: "with",
  property3: "data"
});
```
## Standard CRUD methods

```js
store.get(0); // "array";
store.get("property1"); // "object"

store.set(0, "new value"); // set or update the value
store.set("property1", "new value"); // set or update the value

store.del(0); // remove an item for the array
store.del("property1"); // remove the property from the array

// several items can be removed at once too
store.delAll(["property1", "property2"]);
```

## Watch changes on specific property/item
The point of proxying accessing objects/arrays is that it can trigger events on what's changing. Examples of watching changes on specific properties or items:

```js
var handle = store.watchValue("property1", function onPropertyUpdated(newValue, action, oldValue) {
  // newValue == "new value";
  // action == "updated"
  // oldValue == "object"
}, scope /* optional */);

store.set("property1", "new value");
```

```js
var handle = store.watchValue(0, function onItemUpdated(newValue, action, oldValue) {
    // newValue is undefined
    // action == "deleted"
    // oldValue == "array"
}, scope /* optional */);

store.del(0);
```

```js
var handle = store.watchValue(3, function onItemUpdated(newValue, action, oldValue) {
    // newValue == "new value"
    // action == "added"
    // oldValue is undefined
}, scope /* optional */);

store.set(3, "new value");
```

## Watch changes on generic events such as added/updated/deleted

You can also watch generic events on the whole array/object to know when a new item or property is added, updated or deleted. The following examples are for an object-based store but work the same way with arrays.

```js
var handle = store.watch("added", function onPropertyAdded(propertyName, value) {
    // propertyName == "newProperty"
    // value == "new value"
}, scope /* optional */);

store.set("newProperty", "new value");
```

```js
var handle = store.watch("updated", function onPropertyUpdated(propertyName, newValue, oldValue) {
    // propertyName == "newProperty"
    // newValue == "updated value"
    // oldValue == "new value"
}, scope /* optional */);

store.set("newProperty", "updated value");
```

```js
var handle = store.watch("deleted", function onPropertyDeleted(propertyName, newValue, oldValue) {
    // propertyName == "newProperty"
    // newValue is undefined
    // oldValue == "updated value"
});

store.del("newProperty");
```

## Unwatch changes

To unwatch, pass the `handle` to `unwatch` or `unwatchValue`

```js
store.unwatch(handle); // for handles created by watch
store.unwatchValue(handle); // for handles created by watchValue
```

## Using an array's native mutative methods

The data store has a method for accessing the array's native mutative methods to mutate the data store. When the changes have been made, the data store does a dirty check to figure out the changes and publish events accordingly. This example would also work with other methods than `splice` like `pop`, `push`, `shift`, `unshift`, `sort`, `reverse`.

```js
// Let's remove item 0 and 1 from this store
var store = new Store([0, 1, 2, 3]);

store.watch("updated", function () {
    // this will be triggered two times:
    // The first item will be updated to 2
    // The second item will be updated to 3
});

store.watch("deleted", function () {
    // This will be triggered two times:
    // The first 3rd item will be deleted
    // The fourth item will be deleted
});

// For array-based stores
store.alter("splice", 0, 1); // returns [0, 1];
```

## Using an array's accessor methods.

While `alter` would work in these cases too, using `proxy` instead doesn't trigger the dirty checking, so `proxy` is as fast as the native method itself. Other accessor methods are: `concat`, `join`, `slice`, `toString`, `toLocalString`, `indexOf`, `lastIndexOf`.

```js
var store = new Store([0, 1, 2, 3]);

store.proxy("join", "|"); // returns "0|1|2|3";
```

## Computed properties

The data store can also create computed properties out of other properties:

```js
var store = new Store({
	"firstname": "John",
	"lastname": "Doe"
});

store.compute("name", ["firstname", "lastname"], function (firstname, lastname) {
	return this.get(firstname) + " " + this.get(lastname);
}, store /* optional */);

store.get("name"); // "John Doe"

store.isCompute("name"); // true

store.removeComputed("name");
```

A computed property can also be watched upon:

```js
// will be triggered if firstname or lastname changes
store.watchValue("name", function () { ... });

store.set("firstname", "Jim");
```

## Store reset

The store can be reused and its data reset. When calling reset, the store will do a diff with the previous data and publish the relevant events.

```js
// Will set the internal data and publish events for everything that has been changed/updated/added
store.reset({ ... });
```

## Store utilities

```js
store.toJSON(); // will serialize the data

store.dump(); // will return the internal structure

store.loop(function (value, key, object) {
	// do something with each value/key
	// object === store.dump();
}, scope /* optional */);
```

CHANGELOG
=========

### 0.0.5 - 7 APR 2015

* Update to watch-notify 0.0.3

#### 0.0.4 - 5 APR 2015

* Publish old value too when altering the store

LICENSE
=======

MIT

---
_Source: https://npm.io/package/observable-store · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
