# IPFS Observed-Remove Set and Map

[![CircleCI](https://circleci.com/gh/wehriam/ipfs-observed-remove.svg?style=svg)](https://circleci.com/gh/wehriam/ipfs-observed-remove) [![npm version](https://badge.fury.io/js/ipfs-observed-remove.svg)](http://badge.fury.io/js/ipfs-observed-remove) [![codecov](https://codecov.io/gh/wehriam/ipfs-observed-remove/branch/master/graph/badge.svg)](https://codecov.io/gh/wehriam/ipfs-observed-remove)

Eventually-consistent, conflict-free replicated data types (CRDT) [implemented](https://github.com/wehriam/ipfs-observed-remove/blob/master/src/index.js) using IPFS and native `Map` and `Set` objects.

This module and the IPFS PubSub system are experimental. If you encounter an issue, fork the repository, [write tests demonstrating](https://github.com/wehriam/ipfs-observed-remove/tree/master/tests) the issue, and create a [pull request](https://github.com/wehriam/ipfs-observed-remove).

```js
const ipfsAPI = require('ipfs-http-client');
const { IpfsObservedRemoveSet } = require('ipfs-observed-remove');

// IPFS nodes with PubSub enabled
const ipfs1 = ipfsAPI('/ip4/127.0.0.1/tcp/5001'); 
const ipfs2 = ipfsAPI('/ip4/127.0.0.1/tcp/5002');

const topic = "CRDT_SET";

const alice = new IpfsObservedRemoveSet(ipfs1, topic);
const bob = new IpfsObservedRemoveSet(ipfs2, topic);

alice.on('add', (value) => {
  console.log(value); // logs foo, bar
});

alice.add('foo');
bob.add('bar');

// Later

alice.has('bar'); // true
bob.has('foo'); // true
```

```js
const ipfsAPI = require('ipfs-http-client');
const { IpfsObservedRemoveMap } = require('ipfs-observed-remove');

// IPFS nodes with PubSub enabled
const ipfs1 = ipfsAPI('/ip4/127.0.0.1/tcp/5001'); 
const ipfs2 = ipfsAPI('/ip4/127.0.0.1/tcp/5002');

const topic = "CRDT_MAP";

const alice = new IpfsObservedRemoveMap(ipfs1, topic);
const bob = new IpfsObservedRemoveMap(ipfs2, topic);

alice.on('set', (key, value) => {
  console.log(key, value); // logs [a, 1], [b, 2]
});

alice.set('a', 1);
bob.add('b', 2);

// Later

alice.get('b'); // 2
bob.get('a'); // 1
```

## Install

`yarn add ipfs-observed-remove`

## Set API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

-   [constructor](#constructor)
    -   [Parameters](#parameters)
-   [ipfsSync](#ipfssync)
-   [dump](#dump)
-   [getIpfsHash](#getipfshash)
-   [ipfsPeerCount](#ipfspeercount)
-   [shutdown](#shutdown)
-   [IpfsObservedRemoveSet#readyPromise](#ipfsobservedremovesetreadypromise)

### constructor

Create an observed-remove CRDT.

#### Parameters

-   `ipfs` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Object implementing the [core IPFS API](https://github.com/ipfs/interface-ipfs-core#api), most likely a [js-ipfs](https://github.com/ipfs/js-ipfs) or [ipfs-http-client](https://github.com/ipfs/js-ipfs-http-client) object.
-   `topic` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** IPFS pubub topic to use in synchronizing the CRDT.
-   `entries` **Iterable&lt;V>** Iterable of initial values (optional, default `[]`)
-   `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**  (optional, default `{}`)
    -   `options.maxAge` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Max age of insertion/deletion identifiers (optional, default `5000`)
    -   `options.bufferPublishing` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Interval by which to buffer 'publish' events (optional, default `20`)

### ipfsSync

Publish an IPFS hash of an array containing all of the object's insertions and deletions.

Returns **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;any>>** 

### dump

Return a sorted array containing all of the set's insertions and deletions.

### getIpfsHash

Stores and returns an IPFS hash of the current insertions and deletions

Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>** 

### ipfsPeerCount

Current number of IPFS pubsub peers.

Returns **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** 

### shutdown

Gracefully shutdown

Returns **void** 

### IpfsObservedRemoveSet#readyPromise

Resolves when IPFS topic subscriptions are confirmed.

Type: [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;void>

## Map API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

-   [constructor](#constructor)
    -   [Parameters](#parameters)
-   [ipfsSync](#ipfssync)
-   [dump](#dump)
-   [getIpfsHash](#getipfshash)
-   [ipfsPeerCount](#ipfspeercount)
-   [shutdown](#shutdown)
-   [IpfsObservedRemoveSet#readyPromise](#ipfsobservedremovesetreadypromise)

### constructor

Create an observed-remove CRDT.

#### Parameters

-   `ipfs` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)?** Object implementing the [core IPFS API](https://github.com/ipfs/interface-ipfs-core#api), most likely a [js-ipfs](https://github.com/ipfs/js-ipfs) or [ipfs-http-client](https://github.com/ipfs/js-ipfs-http-client) object.
-   `topic` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?** IPFS pubub topic to use in synchronizing the CRDT.
-   `entries` **Iterable&lt;V>** Iterable of initial values (optional, default `[]`)
-   `options` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)**  (optional, default `{}`)
    -   `options.maxAge` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Max age of insertion/deletion identifiers (optional, default `5000`)
    -   `options.bufferPublishing` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** Interval by which to buffer 'publish' events (optional, default `20`)

### ipfsSync

Publish an IPFS hash of an array containing all of the object's insertions and deletions.

Returns **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)&lt;any>>** 

### dump

Return a sorted array containing all of the set's insertions and deletions.

### getIpfsHash

Stores and returns an IPFS hash of the current insertions and deletions

Returns **[Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>** 

### ipfsPeerCount

Current number of IPFS pubsub peers.

Returns **[number](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Number)** 

### shutdown

Gracefully shutdown

Returns **void** 

### IpfsObservedRemoveSet#readyPromise

Resolves when IPFS topic subscriptions are confirmed.

Type: [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)&lt;void>
