From 5ba74936133072f52e14b707018af758803a50ff Mon Sep 17 00:00:00 2001 From: Julien Fontanet Date: Tue, 7 Apr 2015 18:01:33 +0200 Subject: [PATCH] Better repo architecture. --- packages/xo-collection/.editorconfig | 65 +++++++ packages/xo-collection/.gitignore | 31 +-- packages/xo-collection/.npmignore | 2 + packages/xo-collection/.travis.yml | 5 + packages/xo-collection/README.md | 184 +++++++++++++++++- packages/xo-collection/package.json | 46 ++++- .../{collection.js => src/index.js} | 4 +- .../index.spec.js} | 5 +- packages/xo-collection/test.js | 81 -------- 9 files changed, 299 insertions(+), 124 deletions(-) create mode 100644 packages/xo-collection/.editorconfig create mode 100644 packages/xo-collection/.npmignore create mode 100644 packages/xo-collection/.travis.yml rename packages/xo-collection/{collection.js => src/index.js} (100%) rename packages/xo-collection/{collection.async.spec.js => src/index.spec.js} (96%) delete mode 100644 packages/xo-collection/test.js diff --git a/packages/xo-collection/.editorconfig b/packages/xo-collection/.editorconfig new file mode 100644 index 000000000..da21ef4c5 --- /dev/null +++ b/packages/xo-collection/.editorconfig @@ -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 diff --git a/packages/xo-collection/.gitignore b/packages/xo-collection/.gitignore index 59d842baa..a4a5666f8 100644 --- a/packages/xo-collection/.gitignore +++ b/packages/xo-collection/.gitignore @@ -1,28 +1,7 @@ -# Logs -logs -*.log +/bower_components/ +/dist/ -# Runtime data -pids -*.pid -*.seed +npm-debug.log -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# 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 +!node_modules/* +node_modules/*/ diff --git a/packages/xo-collection/.npmignore b/packages/xo-collection/.npmignore new file mode 100644 index 000000000..5f4b80cec --- /dev/null +++ b/packages/xo-collection/.npmignore @@ -0,0 +1,2 @@ +*.spec.js +*.spec.js.map diff --git a/packages/xo-collection/.travis.yml b/packages/xo-collection/.travis.yml new file mode 100644 index 000000000..5227e1127 --- /dev/null +++ b/packages/xo-collection/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 'iojs' + - '0.12' + - '0.10' \ No newline at end of file diff --git a/packages/xo-collection/README.md b/packages/xo-collection/README.md index abef15571..82bb27f97 100644 --- a/packages/xo-collection/README.md +++ b/packages/xo-collection/README.md @@ -1,2 +1,182 @@ -# collection -A collection class with a batch feature with commit/rollback/replay +# collection [![Build Status](https://travis-ci.org/marsaud/collection.png?branch=master)](https://travis-ci.org/marsaud/collection) + +> 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) diff --git a/packages/xo-collection/package.json b/packages/xo-collection/package.json index e5a0525bd..06d89e16f 100644 --- a/packages/xo-collection/package.json +++ b/packages/xo-collection/package.json @@ -1,24 +1,50 @@ { - "name": "xo-collection", + "private": true, + "name": "collection", "version": "0.0.0", - "description": "A generice batch collection attempt", - "main": "collection.js", + "license": "ISC", + "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": { + "babel-runtime": "^5", "lodash.foreach": "^3.0.2", "make-error": "^0.3.0" }, "devDependencies": { - "babel": "^4.7.16", - "chai": "^2.2.0", + "babel": "^5", + "chai": "*", "dirty-chai": "^1.2.0", "event-to-promise": "^0.3.2", "leche": "^2.1.1", - "mocha": "^2.2.1", - "sinon": "^1.14.1" + "mocha": "*", + "sinon": "^1.14.1", + "standard": "*" }, "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 ", - "license": "aGPLv3" + "standard": { + "ignore": [ + "dist/**" + ] + } } diff --git a/packages/xo-collection/collection.js b/packages/xo-collection/src/index.js similarity index 100% rename from packages/xo-collection/collection.js rename to packages/xo-collection/src/index.js index 4dcc9d4d9..b0ae01b95 100644 --- a/packages/xo-collection/collection.js +++ b/packages/xo-collection/src/index.js @@ -1,11 +1,11 @@ import events from 'events' import makeError from 'make-error' -export const DuplicateEntry = makeError('DuplicateEntry') export const BufferAlreadyFlushed = makeError('BufferAlreadyFlushed') +export const DuplicateEntry = makeError('DuplicateEntry') export const IllegalAdd = makeError('IllegalAdd') -export const NoSuchEntry = makeError('NoSuchEntry') export const IllegalTouch = makeError('IllegalTouch') +export const NoSuchEntry = makeError('NoSuchEntry') export default class Collection extends events.EventEmitter { constructor () { diff --git a/packages/xo-collection/collection.async.spec.js b/packages/xo-collection/src/index.spec.js similarity index 96% rename from packages/xo-collection/collection.async.spec.js rename to packages/xo-collection/src/index.spec.js index a94983e60..96edd61f9 100644 --- a/packages/xo-collection/collection.async.spec.js +++ b/packages/xo-collection/src/index.spec.js @@ -1,12 +1,11 @@ /* eslint-env mocha */ -import Collection, {DuplicateEntry, NoSuchEntry} from './collection' +import Collection, {DuplicateEntry, NoSuchEntry} from './index' import eventToPromise from 'event-to-promise' import sinon from 'sinon' -import chai from 'chai' -const expect = chai.expect +import chai, {expect} from 'chai' import dirtyChai from 'dirty-chai' chai.use(dirtyChai) diff --git a/packages/xo-collection/test.js b/packages/xo-collection/test.js deleted file mode 100644 index 2ac59da7f..000000000 --- a/packages/xo-collection/test.js +++ /dev/null @@ -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); -}