Files
xen-orchestra/packages/xo-collection/README.md
T

266 lines
5.0 KiB
Markdown
Raw Normal View History

2017-01-10 18:05:01 +01:00
# xo-collection [![Build Status](https://travis-ci.org/vatesfr/xen-orchestra.png?branch=master)](https://travis-ci.org/vatesfr/xen-orchestra)
2015-04-07 18:01:33 +02:00
> Generic in-memory collection with events
## Install
2015-04-10 11:51:54 +02:00
Installation of the [npm package](https://npmjs.org/package/xo-collection):
2015-04-07 18:01:33 +02:00
```
2015-04-10 11:51:54 +02:00
> npm install --save xo-collection
2015-04-07 18:01:33 +02:00
```
## Usage
```javascript
2015-04-10 11:51:54 +02:00
var Collection = require('xo-collection')
2015-04-07 18:01:33 +02:00
```
### Creation
```javascript
// Creates a new collection.
var col = new Collection()
```
### Manipulation
2015-04-08 11:49:25 +02:00
**Inserting a new item**
2015-04-07 18:01:33 +02:00
```javascript
col.add('foo', true)
```
2015-05-19 15:25:44 +02:00
- **Throws** `DuplicateItem` if the item is already in the collection.
2015-04-08 11:49:25 +02:00
**Updating an existing item**
2015-04-07 18:01:33 +02:00
```javascript
col.update('foo', false)
```
2015-05-19 15:25:44 +02:00
- **Throws** `NoSuchItem` if the item is not in the collection.
2015-04-08 11:49:25 +02:00
**Inserting or updating an item**
2015-04-07 18:01:33 +02:00
```javascript
col.set('bar', true)
```
**Notifying an external update**
2015-04-08 11:49:25 +02:00
> If an item is an object, it can be updated directly without using
2015-04-07 18:01:33 +02:00
> the `set`/`update` methods.
>
2015-04-07 18:06:17 +02:00
> To make sure the collection stays in sync and the correct events are
2015-04-07 18:01:33 +02:00
> sent, the `touch` method can be used to notify the change.
```javascript
var baz = {}
col.add('baz', baz)
baz.prop = true
col.touch('baz')
```
2015-04-08 11:49:25 +02:00
> Because this is a much used pattern, `touch` returns the item to
2015-04-07 18:01:33 +02:00
> allow its direct modification.
```javascript
col.touch('baz').prop = false
```
2015-05-19 15:25:44 +02:00
- **Throws** `NoSuchItem` if the item is not in the collection.
- **Throws** `IllegalTouch` if the item is not an object.
2015-04-08 11:49:25 +02:00
**Removing an existing item**
2015-04-07 18:01:33 +02:00
```javascript
2015-04-07 18:49:20 +02:00
col.remove('bar')
2015-04-07 18:01:33 +02:00
```
2015-05-19 15:25:44 +02:00
- **Throws** `NoSuchItem` if the item is not in the collection.
2015-06-26 11:20:50 +02:00
**Removing an item without error**
This is the symmetric method of `set()`: it removes the item if it
exists otherwise does nothing.
```javascript
col.unset('bar')
```
2015-04-08 11:49:25 +02:00
**Removing all items**
2015-04-07 18:01:33 +02:00
```javascript
col.clear()
```
### Query
2015-04-08 11:49:25 +02:00
**Checking the existence of an item**
2015-04-07 18:01:33 +02:00
```javascript
var hasBar = col.has('bar')
```
2015-04-08 11:49:25 +02:00
**Getting an existing item**
2015-04-07 18:01:33 +02:00
```javascript
var foo = col.get('foo')
// The second parameter can be used to specify a fallback in case the
2015-04-08 11:49:25 +02:00
// item does not exist.
2015-04-07 18:01:33 +02:00
var bar = col.get('bar', 6.28)
```
2015-05-19 15:25:44 +02:00
- **Throws** `NoSuchItem` if the item is not in the collection and no
fallback has been passed.
2015-04-07 18:15:38 +02:00
**Getting a read-only view of the collection**
> This property is useful for example to iterate over the collection
> or to make advanced queries with the help of utility libraries such
> as lodash.
```javascript
var _ = require('lodash')
2015-04-08 11:49:25 +02:00
// Prints all the items.
2015-04-07 18:15:38 +02:00
_.forEach(col.all, function (value, key) {
console.log('- %s: %j', key, value)
})
2015-04-08 11:49:25 +02:00
// Finds all the items which are objects and have a property
2015-04-07 18:15:38 +02:00
// `active` which equals `true`.
var results = _.where(col.all, { active: true })
```
2015-04-08 11:49:25 +02:00
**Getting the number of items**
2015-04-07 18:01:33 +02:00
```javascript
var size = col.size
```
### Events
> The events are emitted asynchronously (at the next turn/tick of the
> event loop) and are deduplicated which means, for instance, that an
> addition followed by an update will result only in a single
> addition.
2015-04-08 11:49:25 +02:00
**New items**
2015-04-07 18:01:33 +02:00
```javascript
col.on('add', (added) => {
forEach(added, (value, key) => {
console.log('+ %s: %j', key, value)
})
})
```
2015-04-08 11:49:25 +02:00
**Updated items**
2015-04-07 18:01:33 +02:00
```javascript
col.on('update', (updated) => {
forEach(updated, (value, key) => {
2015-04-08 10:04:58 +02:00
console.log('± %s: %j', key, value)
2015-04-07 18:01:33 +02:00
})
})
```
2015-04-08 11:49:25 +02:00
**Removed items**
2015-04-07 18:01:33 +02:00
```javascript
col.on('remove', (removed) => {
2015-04-08 10:04:58 +02:00
// For consistency, `removed` is also a map but contrary to `added`
2015-04-07 18:01:33 +02:00
// and `updated`, the values associated to the keys are not
2015-04-08 11:49:25 +02:00
// significant since the items have already be removed.
2015-04-07 18:01:33 +02:00
forEach(removed, (value, key) => {
2015-04-08 10:04:58 +02:00
console.log('- %s', key)
2015-04-07 18:01:33 +02:00
})
})
```
2015-05-19 15:25:30 +02:00
**End of update**
> Emitted when all the update process is finished and all the update
> events has been emitted.
```javascript
col.on('finish', () => {
console.log('the collection has been updated')
})
```
2015-04-18 22:33:32 +02:00
### Iteration
```javascript
2015-10-01 18:25:01 +02:00
for (const [key, value] of col) {
2015-04-18 22:33:32 +02:00
console.log('- %s: %j', key, value)
}
2015-10-01 18:25:01 +02:00
for (const key of col.keys()) {
2015-04-18 22:33:32 +02:00
console.log('- %s', key)
}
2015-10-01 18:25:01 +02:00
for (const value of col.values()) {
2015-04-18 22:33:32 +02:00
console.log('- %j', value)
}
```
2015-04-28 17:06:37 +02:00
### Views
```javascript
const View = require('xo-collection/view')
```
> A view is a read-only collection which contains only the items of a
> parent collection which satisfy a predicate.
>
> It is updated at most once per turn of the event loop and therefore
> can be briefly invalid.
```javascript
const myView = new View(parentCollection, function predicate (value, key) {
// This function should return a boolean indicating whether the
// current item should be in this view.
})
```
2015-04-07 18:01:33 +02:00
## Development
```
2016-11-02 15:03:45 +01:00
# Install dependencies
2015-04-07 18:01:33 +02:00
> npm install
2016-11-02 15:03:45 +01:00
# Run the tests
> npm test
2015-04-07 18:01:33 +02:00
2016-11-02 15:03:45 +01:00
# Continuously compile
2015-04-07 18:01:33 +02:00
> npm run dev
2016-11-02 15:03:45 +01:00
# Continuously run the tests
> npm run dev-test
2015-04-07 18:01:33 +02:00
2016-11-02 15:03:45 +01:00
# Build for production (automatically called by npm install)
> npm run build
2015-04-07 18:01:33 +02:00
```
## Contributions
Contributions are *very* welcomed, either on the documentation or on
the code.
You may:
2018-02-07 10:40:09 +01:00
- report any [issue](https://github.com/vatesfr/xen-orchestra/issues)
2015-04-07 18:01:33 +02:00
you've encountered;
- fork and create a pull request.
## License
ISC © [Vates SAS](http://vates.fr)