Better repo architecture.
This commit is contained in:
parent
dd1d16f91c
commit
5ba7493613
65
packages/xo-collection/.editorconfig
Normal file
65
packages/xo-collection/.editorconfig
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# http://EditorConfig.org
|
||||||
|
#
|
||||||
|
# Julien Fontanet's configuration
|
||||||
|
# https://gist.github.com/julien-f/8096213
|
||||||
|
|
||||||
|
# Top-most EditorConfig file.
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Common config.
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespaces = true
|
||||||
|
|
||||||
|
# CoffeeScript
|
||||||
|
#
|
||||||
|
# https://github.com/polarmobile/coffeescript-style-guide/blob/master/README.md
|
||||||
|
[*.{,lit}coffee]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Markdown
|
||||||
|
[*.{md,mdwn,mdown,markdown}]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Package.json
|
||||||
|
#
|
||||||
|
# This indentation style is the one used by npm.
|
||||||
|
[/package.json]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Jade
|
||||||
|
[*.jade]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# JavaScript
|
||||||
|
#
|
||||||
|
# Two spaces seems to be the standard most common style, at least in
|
||||||
|
# Node.js (http://nodeguide.com/style.html#tabs-vs-spaces).
|
||||||
|
[*.js]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Less
|
||||||
|
[*.less]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# Sass
|
||||||
|
#
|
||||||
|
# Style used for http://libsass.com
|
||||||
|
[*.s[ac]ss]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
# YAML
|
||||||
|
#
|
||||||
|
# Only spaces are allowed.
|
||||||
|
[*.yaml]
|
||||||
|
indent_size = 2
|
||||||
|
indent_style = space
|
31
packages/xo-collection/.gitignore
vendored
31
packages/xo-collection/.gitignore
vendored
@ -1,28 +1,7 @@
|
|||||||
# Logs
|
/bower_components/
|
||||||
logs
|
/dist/
|
||||||
*.log
|
|
||||||
|
|
||||||
# Runtime data
|
npm-debug.log
|
||||||
pids
|
|
||||||
*.pid
|
|
||||||
*.seed
|
|
||||||
|
|
||||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
!node_modules/*
|
||||||
lib-cov
|
node_modules/*/
|
||||||
|
|
||||||
# Coverage directory used by tools like istanbul
|
|
||||||
coverage
|
|
||||||
|
|
||||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
|
||||||
.grunt
|
|
||||||
|
|
||||||
# Compiled binary addons (http://nodejs.org/api/addons.html)
|
|
||||||
build/Release
|
|
||||||
|
|
||||||
# Dependency directory
|
|
||||||
# Commenting this out is preferred by some people, see
|
|
||||||
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
|
|
||||||
node_modules
|
|
||||||
|
|
||||||
# Users Environment Variables
|
|
||||||
.lock-wscript
|
|
||||||
|
2
packages/xo-collection/.npmignore
Normal file
2
packages/xo-collection/.npmignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.spec.js
|
||||||
|
*.spec.js.map
|
5
packages/xo-collection/.travis.yml
Normal file
5
packages/xo-collection/.travis.yml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- 'iojs'
|
||||||
|
- '0.12'
|
||||||
|
- '0.10'
|
@ -1,2 +1,182 @@
|
|||||||
# collection
|
# collection [](https://travis-ci.org/marsaud/collection)
|
||||||
A collection class with a batch feature with commit/rollback/replay
|
|
||||||
|
> Generic in-memory collection with events
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
Installation of the [npm package](https://npmjs.org/package/collection):
|
||||||
|
|
||||||
|
```
|
||||||
|
> npm install --save collection
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var Collection = require('collection')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Creation
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Creates a new collection.
|
||||||
|
var col = new Collection()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Manipulation
|
||||||
|
|
||||||
|
**Inserting a new entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.add('foo', true)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Updating an existing entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.update('foo', false)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Inserting or updating an entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.set('bar', true)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Notifying an external update**
|
||||||
|
|
||||||
|
> If an entry is an object, it can be updated directly without using
|
||||||
|
> the `set`/`update` methods.
|
||||||
|
>
|
||||||
|
> To make sure the collection stay in sync and the correct events are
|
||||||
|
> sent, the `touch` method can be used to notify the change.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var baz = {}
|
||||||
|
|
||||||
|
col.add('baz', baz)
|
||||||
|
|
||||||
|
baz.prop = true
|
||||||
|
col.touch('baz')
|
||||||
|
```
|
||||||
|
|
||||||
|
> Because this is a much used pattern, `touch` returns the entry to
|
||||||
|
> allow its direct modification.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.touch('baz').prop = false
|
||||||
|
```
|
||||||
|
|
||||||
|
**Removing an existing entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.unset('bar')
|
||||||
|
```
|
||||||
|
|
||||||
|
**Removing all entries**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.clear()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query
|
||||||
|
|
||||||
|
**Checking the existence of an entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var hasBar = col.has('bar')
|
||||||
|
```
|
||||||
|
|
||||||
|
**Getting an existing entry**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var foo = col.get('foo')
|
||||||
|
|
||||||
|
// The second parameter can be used to specify a fallback in case the
|
||||||
|
// entry does not exist.
|
||||||
|
var bar = col.get('bar', 6.28)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Getting the number of entries**
|
||||||
|
|
||||||
|
```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.
|
||||||
|
|
||||||
|
**New entries**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.on('add', (added) => {
|
||||||
|
forEach(added, (value, key) => {
|
||||||
|
console.log('+ %s: %j', key, value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Updated entries**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.on('update', (updated) => {
|
||||||
|
forEach(updated, (value, key) => {
|
||||||
|
console.log('- %s: %j', key, value)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Removed entries**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
col.on('remove', (removed) => {
|
||||||
|
// For consistency, `removed` is also a map but contrary to `ædded`
|
||||||
|
// and `updated`, the values associated to the keys are not
|
||||||
|
// significant since the entries have already be removed.
|
||||||
|
|
||||||
|
forEach(removed, (value, key) => {
|
||||||
|
console.log('± %s', key)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
### Installing dependencies
|
||||||
|
|
||||||
|
```
|
||||||
|
> npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compilation
|
||||||
|
|
||||||
|
The sources files are watched and automatically recompiled on changes.
|
||||||
|
|
||||||
|
```
|
||||||
|
> npm run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Tests
|
||||||
|
|
||||||
|
```
|
||||||
|
> npm run test-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributions
|
||||||
|
|
||||||
|
Contributions are *very* welcomed, either on the documentation or on
|
||||||
|
the code.
|
||||||
|
|
||||||
|
You may:
|
||||||
|
|
||||||
|
- report any [issue](https://github.com/marsaud/collection/issues)
|
||||||
|
you've encountered;
|
||||||
|
- fork and create a pull request.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
ISC © [Vates SAS](http://vates.fr)
|
||||||
|
@ -1,24 +1,50 @@
|
|||||||
{
|
{
|
||||||
"name": "xo-collection",
|
"private": true,
|
||||||
|
"name": "collection",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"description": "A generice batch collection attempt",
|
"license": "ISC",
|
||||||
"main": "collection.js",
|
"description": "Generic in-memory collection with events",
|
||||||
|
"keywords": [],
|
||||||
|
"homepage": "https://github.com/marsaud/collection",
|
||||||
|
"bugs": "https://github.com/marsaud/collection/issues",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/marsaud/collection.git"
|
||||||
|
},
|
||||||
|
"author": {
|
||||||
|
"name": "Fabrice Marsaud",
|
||||||
|
"email": "fabrice.marsaud@vates.fr"
|
||||||
|
},
|
||||||
|
"preferGlobal": false,
|
||||||
|
"main": "dist/",
|
||||||
|
"files": [
|
||||||
|
"dist/"
|
||||||
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"babel-runtime": "^5",
|
||||||
"lodash.foreach": "^3.0.2",
|
"lodash.foreach": "^3.0.2",
|
||||||
"make-error": "^0.3.0"
|
"make-error": "^0.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"babel": "^4.7.16",
|
"babel": "^5",
|
||||||
"chai": "^2.2.0",
|
"chai": "*",
|
||||||
"dirty-chai": "^1.2.0",
|
"dirty-chai": "^1.2.0",
|
||||||
"event-to-promise": "^0.3.2",
|
"event-to-promise": "^0.3.2",
|
||||||
"leche": "^2.1.1",
|
"leche": "^2.1.1",
|
||||||
"mocha": "^2.2.1",
|
"mocha": "*",
|
||||||
"sinon": "^1.14.1"
|
"sinon": "^1.14.1",
|
||||||
|
"standard": "*"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "mocha --require babel/register *.spec.js"
|
"build": "mkdir --parents dist && babel --optional=runtime --compact=true --source-maps --out-dir=dist/ src/",
|
||||||
|
"dev": "mkdir --parents dist && babel --watch --optional=runtime --compact=true --source-maps --out-dir=dist/ src/",
|
||||||
|
"prepublish": "npm run build",
|
||||||
|
"test": "standard && npm run build && mocha 'dist/**/*.spec.js'",
|
||||||
|
"test-dev": "standard && mocha --watch --reporter=min 'dist/**/*.spec.js'"
|
||||||
},
|
},
|
||||||
"author": "Fabrice Marsaud <fabrice.marsaud@vates.fr>",
|
"standard": {
|
||||||
"license": "aGPLv3"
|
"ignore": [
|
||||||
|
"dist/**"
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import events from 'events'
|
import events from 'events'
|
||||||
import makeError from 'make-error'
|
import makeError from 'make-error'
|
||||||
|
|
||||||
export const DuplicateEntry = makeError('DuplicateEntry')
|
|
||||||
export const BufferAlreadyFlushed = makeError('BufferAlreadyFlushed')
|
export const BufferAlreadyFlushed = makeError('BufferAlreadyFlushed')
|
||||||
|
export const DuplicateEntry = makeError('DuplicateEntry')
|
||||||
export const IllegalAdd = makeError('IllegalAdd')
|
export const IllegalAdd = makeError('IllegalAdd')
|
||||||
export const NoSuchEntry = makeError('NoSuchEntry')
|
|
||||||
export const IllegalTouch = makeError('IllegalTouch')
|
export const IllegalTouch = makeError('IllegalTouch')
|
||||||
|
export const NoSuchEntry = makeError('NoSuchEntry')
|
||||||
|
|
||||||
export default class Collection extends events.EventEmitter {
|
export default class Collection extends events.EventEmitter {
|
||||||
constructor () {
|
constructor () {
|
@ -1,12 +1,11 @@
|
|||||||
/* eslint-env mocha */
|
/* eslint-env mocha */
|
||||||
|
|
||||||
import Collection, {DuplicateEntry, NoSuchEntry} from './collection'
|
import Collection, {DuplicateEntry, NoSuchEntry} from './index'
|
||||||
|
|
||||||
import eventToPromise from 'event-to-promise'
|
import eventToPromise from 'event-to-promise'
|
||||||
import sinon from 'sinon'
|
import sinon from 'sinon'
|
||||||
|
|
||||||
import chai from 'chai'
|
import chai, {expect} from 'chai'
|
||||||
const expect = chai.expect
|
|
||||||
import dirtyChai from 'dirty-chai'
|
import dirtyChai from 'dirty-chai'
|
||||||
chai.use(dirtyChai)
|
chai.use(dirtyChai)
|
||||||
|
|
@ -1,81 +0,0 @@
|
|||||||
import Collection from './collection';
|
|
||||||
|
|
||||||
let col = new Collection.Collection();
|
|
||||||
|
|
||||||
col.add('foo', 1);
|
|
||||||
|
|
||||||
// An object with id property
|
|
||||||
|
|
||||||
// ====================
|
|
||||||
// Jouer sur le passage par référence, et la convention d'objets avec une prop ID
|
|
||||||
|
|
||||||
let obj = {id: 'bar', content: 2};
|
|
||||||
col.add(obj);
|
|
||||||
console.log(obj.get('bar'));
|
|
||||||
// > {id: 'bar', content: 2}
|
|
||||||
|
|
||||||
col.bufferChanges(true);
|
|
||||||
col.update('bar').content = 4;
|
|
||||||
// update accesses obj at bar key and marks bar as updated. No event emitted.
|
|
||||||
|
|
||||||
col.get('bar').content = 5;
|
|
||||||
obj.content = 6;
|
|
||||||
// bar is already marked as updated, so ...
|
|
||||||
|
|
||||||
col.flush();
|
|
||||||
// ...Emits an update as bar has been "updated to 6"
|
|
||||||
|
|
||||||
col.bufferChanges(true);
|
|
||||||
col.update(obj).content = 7; // Short writing without knowing ID
|
|
||||||
// WARNING, do not change ID after adding ...
|
|
||||||
|
|
||||||
col.bufferChanges(false);
|
|
||||||
col.flush();
|
|
||||||
// No event emitted ... exception thrown ?...
|
|
||||||
col.bufferChanges(true);
|
|
||||||
col.update(obj);
|
|
||||||
col.flush();
|
|
||||||
// Emits an update event as bar has been "updated to 7"
|
|
||||||
|
|
||||||
// ------------------------------------------------------------
|
|
||||||
// Special cases :
|
|
||||||
let foo = {id: 'foo'};
|
|
||||||
let bar = {id: 'bar'};
|
|
||||||
col.add(foo);
|
|
||||||
|
|
||||||
try {
|
|
||||||
col.update(foo, bar);
|
|
||||||
} catch(e) {
|
|
||||||
// Throws an instant exception on ID violation
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
col.udpate('foo', bar);
|
|
||||||
} catch(e) {
|
|
||||||
// Same
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
col.update(foo).id = 'bar';
|
|
||||||
} catch (e) {
|
|
||||||
// Throws an exception at Event emission (key !== content.id)
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
col.bufferChanges(true);
|
|
||||||
col.remove(foo);
|
|
||||||
col.add(foo);
|
|
||||||
col.bufferChanges(false);
|
|
||||||
// Silent...(No events)
|
|
||||||
|
|
||||||
col.bufferChanges(true);
|
|
||||||
col.update(foo).id = 'bar';
|
|
||||||
// Nothing happens
|
|
||||||
try {
|
|
||||||
col.flush();
|
|
||||||
} catch (e) {
|
|
||||||
// Throws
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user