From 24025ee471c8fdc09deb460b1e0ae78ad6567fd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Ramos?= Date: Sat, 30 Nov 2013 12:20:35 -0800 Subject: [PATCH 01/20] update level --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2617e6..35009e4 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "keywords": [], "author": "matt mueller ", "dependencies": { - "level": "~0.17.0", + "level": "~0.18.x", "debug": "~0.7.2" }, "devDependencies": { From 800b191a84a65ffde1580b03c620434bc117c479 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 19:21:50 -0800 Subject: [PATCH 02/20] accept level instances and don't create them --- .coveralls | 2 + .gitignore | 56 +++++++++++++++ .jshintrc | 50 ++++++++++++++ .npmignore | 4 -- .tern-project | 7 ++ .travis.yml | 0 History.md | 26 ------- Makefile | 21 +++++- Readme.md | 66 ------------------ index.js | 124 --------------------------------- package.json | 49 +++++++++---- src/level-modella.js | 160 +++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 330 insertions(+), 235 deletions(-) create mode 100644 .coveralls create mode 100644 .jshintrc delete mode 100644 .npmignore create mode 100644 .tern-project create mode 100644 .travis.yml delete mode 100644 History.md delete mode 100644 Readme.md delete mode 100644 index.js create mode 100644 src/level-modella.js diff --git a/.coveralls b/.coveralls new file mode 100644 index 0000000..a957864 --- /dev/null +++ b/.coveralls @@ -0,0 +1,2 @@ +service_name: travis-ci +repo_token: \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3c3629e..e1fb190 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,57 @@ +# node + +lib-cov +*.seed +*.log +*.csv +*.dat +*.out +*.pid +*.gz + +pids +logs +results + +npm-debug.log node_modules + + +# osx + +.DS_Store +.AppleDouble +.LSOverride +Icon + + +## Thumbnails +._* + +## Files that might appear on external disk +.Spotlight-V100 +.Trashes + +# textmate + +*.tmproj +*.tmproject +tmtags + + +# vim + +*.s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + + +# subl + +*.sublime-workspace + +# component +components +build \ No newline at end of file diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..2de14f1 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,50 @@ +{ + "bitwise": true, + "camelcase": false, + "curly": false, + "eqeqeq": true, + "es3": false, + "forin": true, + "immed": true, + "indent": 2, + "latedef": "nofunc", + "newcap": true, + "noarg": true, + "noempty": true, + "nonew": true, + "plusplus": true, + "quotmark": true, + "undef": true, + "unused": true, + "strict": false, + "trailing": true, + "asi": true, + "boss": false, + "debug": true, + "eqnull": false, + "esnext": false, + "evil": false, + "expr": false, + "funcscope": false, + "globalstrict": false, + "iterator": false, + "lastsemic": true, + "laxbreak": false, + "laxcomma": false, + "loopfunc": false, + "moz": false, + "multistr": false, + "proto": false, + "scripturl": false, + "smarttabs": false, + "shadow": false, + "sub": false, + "supernew": false, + "validthis": false, + "browser": false, + "devel": false, + "jquery": false, + "devel": false, + "es5": true, + "node": true +} \ No newline at end of file diff --git a/.npmignore b/.npmignore deleted file mode 100644 index f1250e5..0000000 --- a/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -support -test -examples -*.sock diff --git a/.tern-project b/.tern-project new file mode 100644 index 0000000..22d0529 --- /dev/null +++ b/.tern-project @@ -0,0 +1,7 @@ +{ + "libs": ["ecma5"], + "plugins": { + "doc_comment": true, + "node": {} + } +} \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..e69de29 diff --git a/History.md b/History.md deleted file mode 100644 index a821ef7..0000000 --- a/History.md +++ /dev/null @@ -1,26 +0,0 @@ - -0.0.5 / 2013-11-15 -================== - - * updated to work with modella 0.2.0 - * updated level to work with node 0.11.8 - -0.0.4 / 2013-09-14 -================== - - * automatically close on termination - -0.0.3 / 2013-08-04 -================== - - * bump level version - -0.0.2 / 2013-07-30 -================== - - * removed log - -0.0.1 / 2013-07-23 -================== - - * Initial commit diff --git a/Makefile b/Makefile index 4e9c8d3..5a2e073 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,22 @@ +REPORTER = spec +UI = qunit test: - @./node_modules/.bin/mocha \ - --require should \ - --reporter spec + @NODE_ENV=test ./node_modules/.bin/mocha -u $(UI) -R $(REPORTER) -c -G -b + +lib-cov: + ./node_modules/jscoverage/bin/jscoverage src lib-cov + +test-cov: lib-cov + @LEVEL_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html + rm -rf lib-cov + +test-coveralls: lib-cov + echo TRAVIS_JOB_ID $(TRAVIS_JOB_ID) + @LEVEL_COV=1 $(MAKE) test REPORTER=mocha-lcov-reporter | ./node_modules/coveralls/bin/coveralls.js + rm -rf lib-cov + +clean: + @rm -rf node_modules components build .PHONY: test \ No newline at end of file diff --git a/Readme.md b/Readme.md deleted file mode 100644 index 117323c..0000000 --- a/Readme.md +++ /dev/null @@ -1,66 +0,0 @@ -# LevelDB - -[LevelDB](https://code.google.com/p/leveldb/) plugin for [modella](https://github.com/modella/modella). - -## Installation - - npm install modella-leveldb - -## Example - -```js -var model = require('modella'); -var level = require('modella-leveldb')('./mydb'); -var uid = require('uid'); - -var User = model('user') - .attr('id') - .attr('name') - .attr('email') - .attr('password'); - -User.use(level); - -/** - * Initialize - */ - -var user = new User; - -user.id(uid(6)) - .name('matt') - .email('mattmuelle@gmail.com') - .password('test'); - -user.save(function(err) { - console.log(user.toJSON()); -}); -``` - -## API - -### Level(path, options) - -Initialize leveldb with a `path` to the database. If path doesn't exist, it will be created. `options` will be passed through to [levelup](https://github.com/rvagg/node-levelup) - -### Model.all([options], fn) - -Get all models (static method) - -### Model.find(id, [options], fn) - -Find a model (static method) - -### model.save([options], fn) - -Save the model (instance method) - -### model.remove([options], fn) - -Remove the model (instance method) - -All `options` will be passed through to [levelup](https://github.com/rvagg/node-levelup). - -## License - -MIT diff --git a/index.js b/index.js deleted file mode 100644 index 6c82d84..0000000 --- a/index.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Module dependencies - */ - -var debug = require('debug')('modella:leveldb'); -var level = require('level'); -var sync = {}; - -/** - * Export `LevelDB` - */ - -module.exports = function(path, options) { - options = options || {}; - options.valueEncoding = options.valueEncoding || 'json'; - - var db = level(path, options); - - // automatically cleanup on termination - process.on('SIGTERM', db.close.bind(this)); - - return function(model) { - model.db = db; - for (fn in sync) model[fn] = sync[fn]; - }; -}; - -/** - * All - */ - -sync.all = function(options, fn) { - if (arguments.length == 1) { - fn = options; - options = {}; - } - - debug('getting all data with options %j', options); - - var rs = this.db.createReadStream(options); - var buffer = []; - - rs.on('error', function(err) { - return fn(err); - }); - - rs.on('data', function(data) { - buffer[buffer.length] = data.value; - }); - - rs.on('end', function() { - return fn(null, buffer); - }); -}; - -/** - * Get - */ - -sync.get = function(key, options, fn) { - var db = this.db; - - if(arguments.length == 2) { - fn = options; - options = {}; - } - - debug('getting %j with %j options...', key, options); - db.get(key, options, function(err, model) { - if(err) return fn(err); - else if(!model) return fn(null, false); - debug('got %j', model); - return fn(null, model); - }); -}; - -/** - * removeAll - */ - -sync.removeAll = function(query, fn) { - throw new Error('model.removeAll not implemented'); -}; - -/** - * save - */ - -sync.save = -sync.update = function(options, fn) { - if (1 == arguments.length) { - fn = options; - options = {}; - } - - var json = this.toJSON(); - debug('saving... %j', json); - var id = this.primary(); - this.model.db.put(id, json, function(err) { - if(err) return fn(err); - debug('saved %j', json); - return fn(null, json); - }); -}; - -/** - * remove - */ - -sync.remove = function(options, fn) { - if (1 == arguments.length) { - fn = options; - options = {}; - } - - var db = this.model.db; - var id = this.primary(); - debug('removing %s with options %j', id, options); - db.del(id, options, function(err) { - if(err) return fn(err); - debug('removed %s', id); - return fn(); - }); -}; diff --git a/package.json b/package.json index 35009e4..7841152 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,44 @@ { - "name": "modella-leveldb", - "version": "0.0.5", - "description": "modella plugin for leveldb", - "keywords": [], - "author": "matt mueller ", + "name": "level-modella", + "version": "0.1.0", + "description": "modella plugin for level", + "keywords": [ + "level", + "modella" + ], + "homepage": "https://github.com/modella/level-modella", + "bugs": "http://github.com/modella/level-modella/issues", + "license": "MIT", + "author": "Matt Mueller (http://mat.io)", + "contributors": [ + "Sérgio Ramos (http://sergioramos.me/)" + ], + "main": "src/vlevel-modella.js", + "directories": { + "lib": "src" + }, + "repository": { + "type": "git", + "url": "git://github.com/modella/level-modella.git" + }, + "scripts": { + "test": "make test" + }, "dependencies": { - "level": "~0.18.x", - "debug": "~0.7.2" + "debug": "0.7.x", + "type-component": "0.0.1", + "xtend": "2.1.x" }, "devDependencies": { + "mocha-lcov-reporter": "0.0.x", + "jscoverage": "0.3.x", + "coveralls": "2.0.x", + "mocha": "1.10.x", "modella": "*", - "mocha": "*", - "should": "*", - "pwd": "*", - "uid": "0.0.2" + "pwd": "0.0.x", + "uid": "0.0.x" }, - "main": "index" + "engines": { + "node": ">=0.8" + } } diff --git a/src/level-modella.js b/src/level-modella.js new file mode 100644 index 0000000..47de8ce --- /dev/null +++ b/src/level-modella.js @@ -0,0 +1,160 @@ +/** + * Module dependencies + */ +var debug = require('debug')('modella:level'), + type = require('type-component'), + xtend = require('xtend') + +// holds all the dbs, so that it can close them on process SIGTERM +var dbs = []; +// default options +var default_options = { + valueEncoding: 'json', + keyEncoding: 'utf8' +} + +/* Parses options/fn so that it handles situations where no options + * are passed to the function + * + * @param {object} options + * @param {function} [fn] + * @return {function} callback + * @api private + */ +function get_callback(options, fn) { + return type(options) === 'function' ? options : fn; +} + +/* if a function is passed, then it sends the error through that + * if not, it emits the error through the model + * + * @param {object} model + * @param {error} err + * @param {function} [fn] + * @api private + */ +function dispatch_error(model, err, fn) { + type(fn) === 'function' ? fn(err) : model.emit('error', err); +} + +// automatically cleanup on termination +process.on('SIGTERM', function() { + dbs.forEach(function(db) { + db.close(function (err) { + if(err) console.error(err); + }); + }); +}); + + +/* exports a function to be passed to `Model.use` + * + * ```javascript + * var level_modella = require('level-modella') + * var modella = require('modella') + * var level = require('level') + * + * User = modella('User'); + * + * User.use(level_modella(level)) + * ``` + * + * @param {object} db + * @return {fn} + * @api public + */ +var level_modella = module.exports = function(db) { + dbs.push(db); + + return function(model) { + Object.keys(level_modella).forEach(function(proto) { + model[proto] = level_modella[proto]; + }); + }; +}; + +/* save a model into the store + * + * ```javascript + * user.save(function(err) {}) + * ``` + * + * @param {object} [options] + * @param {function} fn + * @api public + */ +level_modella.put = level_modella.save = level_modella.update = function(options, fn) { + fn = get_callback(options, fn); + options = xtend(default_options, options); + + if (type(fn) !== 'function') + return dispatch_error(this, new Error('put() requires a callback arguments')) + + var value = this.toJSON(); + var key = this.primary(); + debug('put: %s -> %j', key, value); + + this.model.db.put(key, value, options, function(err) { + if (err) return fn(err); + + debug('success put: %s -> %j', key, value); + fn(err, value); + }); +}; + +/* gets a model from the store + * + * ```javascript + * User.get(1, function(err, user) {}) + * ``` + * + * @param {any} key + * @param {object} [options] + * @param {function} fn + * @api public + */ +level_modella.get = function(key, options, fn) { + fn = get_callback(options, fn); + options = xtend(default_options, options); + + if (type(fn) !== 'function') + return dispatch_error(this, new Error('get() requires key and callback arguments')) + + debug('get: %s', key); + var self = this; + + this.db.get(key, options, function(err, value) { + if (err) return fn(err); + + debug('success get: %s -> %j', key, value); + fn(null, self(value)); + }); +}; + +/* removes a model from the store + * + * ```javascript + * user.remove(function(err) {}) + * ``` + * + * @param {object} [options] + * @param {function} fn + * @api public + */ +level_modella.remove = level_modella.del = function(options, fn) { + fn = get_callback(options, fn); + options = xtend(default_options, options); + + if (type(fn) !== 'function') + return dispatch_error(this, new Error('remove() requires a callback arguments')) + + var key = this.primary(); + debug('remove: %s', key); + + this.db.del(key, options, function(err) { + if (err) return fn(err); + + debug('success remove: %s', key); + fn(err); + }); +}; \ No newline at end of file From da3af7d7f8532c7562a01031aa5aa6b7cf5a6f9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 19:37:50 -0800 Subject: [PATCH 03/20] add documentation --- .jshintrc | 2 +- history.md | 30 +++++++++++++++++++++ readme.md | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 history.md create mode 100644 readme.md diff --git a/.jshintrc b/.jshintrc index 2de14f1..b021673 100644 --- a/.jshintrc +++ b/.jshintrc @@ -18,7 +18,7 @@ "unused": true, "strict": false, "trailing": true, - "asi": true, + "asi": false, "boss": false, "debug": true, "eqnull": false, diff --git a/history.md b/history.md new file mode 100644 index 0000000..c94a68e --- /dev/null +++ b/history.md @@ -0,0 +1,30 @@ +0.1.0 / 2013-12-01 +================== + + * receive a level instance instead of creating it + +0.0.5 / 2013-11-15 +================== + + * updated to work with modella 0.2.0 + * updated level to work with node 0.11.8 + +0.0.4 / 2013-09-14 +================== + + * automatically close on termination + +0.0.3 / 2013-08-04 +================== + + * bump level version + +0.0.2 / 2013-07-30 +================== + + * removed log + +0.0.1 / 2013-07-23 +================== + + * Initial commit \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..b407198 --- /dev/null +++ b/readme.md @@ -0,0 +1,79 @@ +# level-modella + +[![NPM version](https://badge.fury.io/js/level-modella.png)](http://badge.fury.io/js/level-modella) +[![Build Status](https://secure.travis-ci.org/ramitos/level-modella.png)](http://travis-ci.org/ramitos/level-modella) +[![Dependency Status](https://gemnasium.com/ramitos/level-modella.png)](https://gemnasium.com/ramitos/level-modella) +[![Coverage Status](https://coveralls.io/repos/ramitos/level-modella/badge.png?branch=master)](https://coveralls.io/r/ramitos/level-modella?branch=master) +[![Code Climate](https://codeclimate.com/github/ramitos/level-modella.png)](https://codeclimate.com/github/ramitos/level-modella) + +[Level](https://github.com/level/level) plugin for [modella](https://github.com/modella/modella). + +## install + +```bash +npm install [--save/--save-dev] level-modella +``` + +## example + +```js +var model = require('modella'); +var store = require('level-modella'); +var level = require('level')('/tmp/level'); +var sublevel = require('sublevel'); +var uid = require('uid'); + +var users_store = sublevel(level, 'users'); + +var User = model('user'); + +User.attr('id'); +User.attr('name'); +User.attr('email'); +User.attr('password'); + +User.use(store(users_store)); + +/** + * Initialize + */ + +var user = new User; + +user.id(uid(6)) + .name('matt') + .email('mattmuelle@gmail.com') + .password('test'); + +user.save(function(err) { + console.log(user.toJSON()); +}); +``` + +## api + +### store(db) + +Use the plugin. + +### model.save([options,] fn) +### model.put([options,] fn) + +Save a model. + +### model.del([options,] fn) +### model.remove([options,] fn) + +Remove a model. + +### Model.get(key, [options,] fn) + +Get a model. The object passes to the callback is a `Model` instance. + +### Model.db + +`level` instance + +## license + +MIT \ No newline at end of file From cb60d039332a762bbcaf32aff89c9fd20e1d3493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 20:02:38 -0800 Subject: [PATCH 04/20] boilerplate tests --- .coveralls | 2 +- Makefile | 2 +- package.json | 3 ++- src/level-modella.js | 8 ++++---- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.coveralls b/.coveralls index a957864..ad493c9 100644 --- a/.coveralls +++ b/.coveralls @@ -1,2 +1,2 @@ service_name: travis-ci -repo_token: \ No newline at end of file +repo_token: nzlZHxRa4UAvp2QBBovUOS82u9nR5tPTT \ No newline at end of file diff --git a/Makefile b/Makefile index 5a2e073..d5dd8af 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ REPORTER = spec -UI = qunit +UI = bdd test: @NODE_ENV=test ./node_modules/.bin/mocha -u $(UI) -R $(REPORTER) -c -G -b diff --git a/package.json b/package.json index 7841152..90e0ebd 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "mocha": "1.10.x", "modella": "*", "pwd": "0.0.x", - "uid": "0.0.x" + "uid": "0.0.x", + "level": "0.18.x" }, "engines": { "node": ">=0.8" diff --git a/src/level-modella.js b/src/level-modella.js index 47de8ce..39a0abf 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -3,7 +3,7 @@ */ var debug = require('debug')('modella:level'), type = require('type-component'), - xtend = require('xtend') + xtend = require('xtend'); // holds all the dbs, so that it can close them on process SIGTERM var dbs = []; @@ -11,7 +11,7 @@ var dbs = []; var default_options = { valueEncoding: 'json', keyEncoding: 'utf8' -} +}; /* Parses options/fn so that it handles situations where no options * are passed to the function @@ -118,7 +118,7 @@ level_modella.get = function(key, options, fn) { options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('get() requires key and callback arguments')) + return dispatch_error(this, new Error('get() requires key and callback arguments')); debug('get: %s', key); var self = this; @@ -146,7 +146,7 @@ level_modella.remove = level_modella.del = function(options, fn) { options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('remove() requires a callback arguments')) + return dispatch_error(this, new Error('remove() requires a callback arguments')); var key = this.primary(); debug('remove: %s', key); From ebd77d175a8ec07fe059f138802b0c0126431c55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 21:24:28 -0800 Subject: [PATCH 05/20] add tests --- package.json | 8 +- src/level-modella.js | 8 +- test/test.js | 180 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 154 insertions(+), 42 deletions(-) diff --git a/package.json b/package.json index 90e0ebd..16bb525 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "contributors": [ "Sérgio Ramos (http://sergioramos.me/)" ], - "main": "src/vlevel-modella.js", + "main": "src/level-modella.js", "directories": { "lib": "src" }, @@ -37,9 +37,11 @@ "modella": "*", "pwd": "0.0.x", "uid": "0.0.x", - "level": "0.18.x" + "level": "0.18.x", + "leveldown": "0.10.x", + "mkdirp": "0.3.x" }, "engines": { "node": ">=0.8" } -} +} \ No newline at end of file diff --git a/src/level-modella.js b/src/level-modella.js index 39a0abf..713aa78 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -67,6 +67,8 @@ var level_modella = module.exports = function(db) { dbs.push(db); return function(model) { + model.db = db; + Object.keys(level_modella).forEach(function(proto) { model[proto] = level_modella[proto]; }); @@ -88,7 +90,7 @@ level_modella.put = level_modella.save = level_modella.update = function(options options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('put() requires a callback arguments')) + return dispatch_error(this, new Error('put() requires a callback argument')) var value = this.toJSON(); var key = this.primary(); @@ -146,12 +148,12 @@ level_modella.remove = level_modella.del = function(options, fn) { options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('remove() requires a callback arguments')); + return dispatch_error(this, new Error('remove() requires a callback argument')); var key = this.primary(); debug('remove: %s', key); - this.db.del(key, options, function(err) { + this.model.db.del(key, options, function(err) { if (err) return fn(err); debug('success remove: %s', key); diff --git a/test/test.js b/test/test.js index 7dc3825..d11ed36 100644 --- a/test/test.js +++ b/test/test.js @@ -1,47 +1,155 @@ -/** - * Module Dependencies - */ - +var store = process.env.LEVEL_COV ? require('../lib-cov/level_modella') : require('../'); var model = require('modella'); -var level = require('../')(__dirname + '/mydb'); +var level = require('level'); var uid = require('uid'); +var mkdirp = require('mkdirp'); +var type = require('type-component'); +var leveldown = require('leveldown'); +var assert = require('assert'); +var path = require('path'); + +var User, location = path.join(__dirname, 'db'), user = { + id: uid(), + name: 'seth cohen' +}; + +var close = function(done) { + if(type(User.db) === 'undefined') return done(); + + User.db.close(function() { + leveldown.destroy(location, done); + }); +}; + +var use = function(done) { + User.use(store(level(location, done))); +}; + +beforeEach(function(done) { + mkdirp(location, done); +}); + +beforeEach(function() { + User = model('User'); + User.attr('id'); + User.attr('name'); +}); + +afterEach(close); + +describe('store', function() { + afterEach(close); + + it('store() should return a fn', function() { + var db = level(location); + var adapter = store(db); + assert(type(adapter) === 'function'); + User = {db: db} // make sure it's cleaned + }); + + it('should fill static methods', function() { + User.use(store(level(location))); + assert(type(User.get) === 'function'); + assert(type(User.save) === 'function'); + assert(type(User.remove) === 'function'); + }); +}); + +describe('put', function() { + beforeEach(use); + afterEach(close); + + it('should save', function(done) { + var model = User(user); -var User = model('user') - .attr('id') - .attr('name') - .attr('email') - .attr('password'); + model.save(function(err, model) { + if(err) return done(err); -User.use(level); + model.model.db.get(model.id(), { + valueEncoding: 'json' + }, function(err, value) { + if(err) return done(err); -/** - * Initialize - */ + assert(value.id === model.id()); + assert(value.name === model.name()); -var user = new User; + done() + }); + }); + }); -user.id(uid(6)) - .name('matt') - .email('mattmuelle@gmail.com') - .password('test'); + it('should emit when no callback is passed', function(done) { + var model = User(user); -// user.save(function(err, user) { -// console.log(user); -// }); + model.once('error', function(err) { + assert(err && err.message === 'put() requires a callback argument'); + done(); + }); -User.all(function(err, users) { - console.log(users); + store.save.call(model); + }); }); -// User.find('ewcbix', function(err, user) { -// if (err) throw err; -// console.log(user); -// }); - -// User.find('ewcbix', function(err, user) { -// if (err) throw err; -// user.remove(function(err) { -// if (err) throw err; -// console.log('removed'); -// }); -// }); +describe('remove', function() { + beforeEach(use); + afterEach(close); + + it('should remove', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + + model.remove(function(err) { + if(err) return done(err); + + model.model.db.get(model.id(), function(err) { + assert(err && err.type === 'NotFoundError') + done(); + }); + }); + }); + }); + + it('should emit when no callback is passed', function(done) { + var model = User(user); + + model.once('error', function(err) { + assert(err && err.message === 'remove() requires a callback argument'); + done(); + }); + + store.remove.call(model); + }); +}); + +describe('get', function() { + beforeEach(use); + afterEach(close); + + it('should get', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + + User.get(model.id(), function(err, value) { + if(err) return done(err); + + assert(value.id() === model.id()); + assert(value.name() === model.name()); + + done(); + }); + }); + }); + + it('should emit when no callback/key is passed', function(done) { + User.once('error', function(err) { + assert(err && err.message === 'get() requires key and callback arguments'); + done(); + }); + + User.get(); + }); +}); \ No newline at end of file From 869d07857255d5a262024b108336a34419e52a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 21:25:48 -0800 Subject: [PATCH 06/20] add .travis.yml --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index e69de29..2ca91f2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: node_js +node_js: + - "0.10" + - "0.8" \ No newline at end of file From 39a4b884608bb44656e48b92078e9de5c016170d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 21:29:14 -0800 Subject: [PATCH 07/20] add test-coveralls to npm test --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 16bb525..85b39e9 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "url": "git://github.com/modella/level-modella.git" }, "scripts": { - "test": "make test" + "test": "make test test-coveralls" }, "dependencies": { "debug": "0.7.x", From 7b2363bfb4eaa3a5b4f514015c4996216a02a9e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 21:34:28 -0800 Subject: [PATCH 08/20] fix cov require --- test/test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.js b/test/test.js index d11ed36..826874e 100644 --- a/test/test.js +++ b/test/test.js @@ -1,4 +1,4 @@ -var store = process.env.LEVEL_COV ? require('../lib-cov/level_modella') : require('../'); +var store = process.env.LEVEL_COV ? require('../lib-cov/level-modella') : require('../'); var model = require('modella'); var level = require('level'); var uid = require('uid'); From fb39929f6b5deb378e98a902af4fb6e174690b4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 1 Dec 2013 21:51:25 -0800 Subject: [PATCH 09/20] increase coverage --- package.json | 5 +++-- src/level-modella.js | 42 +++++++++++++++++++++--------------------- test/test.js | 5 +++++ 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index 85b39e9..fd1287f 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,8 @@ "dependencies": { "debug": "0.7.x", "type-component": "0.0.1", - "xtend": "2.1.x" + "xtend": "2.1.x", + "map-series": "0.0.x" }, "devDependencies": { "mocha-lcov-reporter": "0.0.x", @@ -44,4 +45,4 @@ "engines": { "node": ">=0.8" } -} \ No newline at end of file +} diff --git a/src/level-modella.js b/src/level-modella.js index 713aa78..78af3ca 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -3,7 +3,8 @@ */ var debug = require('debug')('modella:level'), type = require('type-component'), - xtend = require('xtend'); + xtend = require('xtend'), + series = require('map-series'); // holds all the dbs, so that it can close them on process SIGTERM var dbs = []; @@ -25,26 +26,19 @@ function get_callback(options, fn) { return type(options) === 'function' ? options : fn; } -/* if a function is passed, then it sends the error through that - * if not, it emits the error through the model - * - * @param {object} model - * @param {error} err - * @param {function} [fn] - * @api private - */ -function dispatch_error(model, err, fn) { - type(fn) === 'function' ? fn(err) : model.emit('error', err); -} - // automatically cleanup on termination -process.on('SIGTERM', function() { - dbs.forEach(function(db) { - db.close(function (err) { +function close_all(done) { + series(dbs, function(db, fn) { + db.close(function(err) { if(err) console.error(err); + fn(); }); + }, function() { + if(done) done(); }); -}); +} + +process.on('SIGTERM', close_all); /* exports a function to be passed to `Model.use` @@ -90,7 +84,7 @@ level_modella.put = level_modella.save = level_modella.update = function(options options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('put() requires a callback argument')) + return this.emit('error', new Error('put() requires a callback argument')); var value = this.toJSON(); var key = this.primary(); @@ -120,7 +114,7 @@ level_modella.get = function(key, options, fn) { options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('get() requires key and callback arguments')); + return this.emit('error', new Error('get() requires key and callback arguments')); debug('get: %s', key); var self = this; @@ -148,7 +142,7 @@ level_modella.remove = level_modella.del = function(options, fn) { options = xtend(default_options, options); if (type(fn) !== 'function') - return dispatch_error(this, new Error('remove() requires a callback argument')); + return this.emit('error', new Error('remove() requires a callback argument')); var key = this.primary(); debug('remove: %s', key); @@ -159,4 +153,10 @@ level_modella.remove = level_modella.del = function(options, fn) { debug('success remove: %s', key); fn(err); }); -}; \ No newline at end of file +}; + +/* closes all db instances + * + * @api private + */ +module.exports.__close_all = close_all; \ No newline at end of file diff --git a/test/test.js b/test/test.js index 826874e..29c3ee9 100644 --- a/test/test.js +++ b/test/test.js @@ -53,6 +53,11 @@ describe('store', function() { assert(type(User.save) === 'function'); assert(type(User.remove) === 'function'); }); + + it('close all', function(done) { + User.use(store(level(location))); + User.__close_all(done); + }); }); describe('put', function() { From c42de78d5b35972b34c5f0e4c8328ba2fde0c01c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Mon, 2 Dec 2013 17:09:16 -0800 Subject: [PATCH 10/20] 0.2.0 * also accept a string and create a level instance in that case * add a streaming `.all` --- history.md | 7 +++++++ package.json | 9 ++++++--- readme.md | 4 ++++ src/level-modella.js | 29 ++++++++++++++++++++++++++++- test/test.js | 29 +++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 4 deletions(-) diff --git a/history.md b/history.md index c94a68e..7ba489d 100644 --- a/history.md +++ b/history.md @@ -1,3 +1,10 @@ +0.2.0 / 2013-12-02 +================== + + * also accept a string and create a level instance in that case + * add a streaming `.all` + + 0.1.0 / 2013-12-01 ================== diff --git a/package.json b/package.json index fd1287f..7f20cce 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.1.0", + "version": "0.2.0", "description": "modella plugin for level", "keywords": [ "level", @@ -28,7 +28,9 @@ "debug": "0.7.x", "type-component": "0.0.1", "xtend": "2.1.x", - "map-series": "0.0.x" + "map-series": "0.0.x", + "ordered-through": "0.0.x", + "level": "0.18.x" }, "devDependencies": { "mocha-lcov-reporter": "0.0.x", @@ -40,7 +42,8 @@ "uid": "0.0.x", "level": "0.18.x", "leveldown": "0.10.x", - "mkdirp": "0.3.x" + "mkdirp": "0.3.x", + "level-cursor": "0.5.x", }, "engines": { "node": ">=0.8" diff --git a/readme.md b/readme.md index b407198..941e673 100644 --- a/readme.md +++ b/readme.md @@ -70,6 +70,10 @@ Remove a model. Get a model. The object passes to the callback is a `Model` instance. +### Model.all([options]) + +Returns a stream that will emit a model instance on each `data` event. Accepted options are the [same](https://github.com/rvagg/node-levelup/#dbcreatereadstreamoptions) that levelup accepts. + ### Model.db `level` instance diff --git a/src/level-modella.js b/src/level-modella.js index 78af3ca..c6a8d35 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -4,7 +4,9 @@ var debug = require('debug')('modella:level'), type = require('type-component'), xtend = require('xtend'), - series = require('map-series'); + through = require('ordered-through'), + series = require('map-series'), + level = require('level'); // holds all the dbs, so that it can close them on process SIGTERM var dbs = []; @@ -58,6 +60,9 @@ process.on('SIGTERM', close_all); * @api public */ var level_modella = module.exports = function(db) { + if(type(db) === 'string') + db = level(db) + dbs.push(db); return function(model) { @@ -155,6 +160,28 @@ level_modella.remove = level_modella.del = function(options, fn) { }); }; +/* get all models from the store + * + * ```javascript + * var cursor = require('level-cursor') + * cursor(user.all()).each(function (user) {}, function (err) {}) + * ``` + * + * @param {object} [options] + * @api public + */ +level_modella.all = function(options) { + options = xtend(default_options, options); + var self = this; + + debug('all'); + + return this.db.createReadStream(options).pipe(through(function(data, fn) { + debug('success get: %s -> %j', data.key, data.value); + fn(null, self(data.value)); + })); +}; + /* closes all db instances * * @api private diff --git a/test/test.js b/test/test.js index 29c3ee9..ebd7bac 100644 --- a/test/test.js +++ b/test/test.js @@ -6,6 +6,7 @@ var mkdirp = require('mkdirp'); var type = require('type-component'); var leveldown = require('leveldown'); var assert = require('assert'); +var cursor = require('level-cursor'); var path = require('path'); var User, location = path.join(__dirname, 'db'), user = { @@ -40,6 +41,12 @@ afterEach(close); describe('store', function() { afterEach(close); + it('store() accept a string', function() { + User.use(store(location)); + assert(User.db); + assert(User.db.location === location); + }); + it('store() should return a fn', function() { var db = level(location); var adapter = store(db); @@ -157,4 +164,26 @@ describe('get', function() { User.get(); }); +}); + +describe('all', function() { + beforeEach(use); + afterEach(close); + + it('should get all', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + var called = false; + + cursor(User.all()).each(function (user) { + called = true; + assert(user.primary() === model.primary()); + }, function (err) { + assert(called); + done(err); + }); + }); + }); }); \ No newline at end of file From b47ab6108d6dcec61c003c8acfa0b5365795ead3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Mon, 2 Dec 2013 17:39:12 -0800 Subject: [PATCH 11/20] fix package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 7f20cce..05480c9 100644 --- a/package.json +++ b/package.json @@ -43,9 +43,9 @@ "level": "0.18.x", "leveldown": "0.10.x", "mkdirp": "0.3.x", - "level-cursor": "0.5.x", + "level-cursor": "0.5.x" }, "engines": { "node": ">=0.8" } -} +} \ No newline at end of file From d09bea58cd3109989979b70bbaeab9d283e36a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Tue, 3 Dec 2013 00:47:05 -0800 Subject: [PATCH 12/20] 0.3.0 * add `Model.remove.all` * rename `Model.all` to `Model.get.all` --- history.md | 6 +++++ package.json | 8 +++---- readme.md | 6 ++++- src/level-modella.js | 54 +++++++++++++++++++++++++++++++++----------- test/test.js | 31 ++++++++++++++++--------- 5 files changed, 76 insertions(+), 29 deletions(-) diff --git a/history.md b/history.md index 7ba489d..b3f1b53 100644 --- a/history.md +++ b/history.md @@ -1,3 +1,9 @@ +0.3.0 / 2013-12-02 +================== + + * add `Model.remove.all` + * rename `Model.all` to `Model.get.all` + 0.2.0 / 2013-12-02 ================== diff --git a/package.json b/package.json index 05480c9..febd5a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.2.0", + "version": "0.3.0", "description": "modella plugin for level", "keywords": [ "level", @@ -30,7 +30,8 @@ "xtend": "2.1.x", "map-series": "0.0.x", "ordered-through": "0.0.x", - "level": "0.18.x" + "level": "0.18.x", + "level-cursor": "0.5.x" }, "devDependencies": { "mocha-lcov-reporter": "0.0.x", @@ -42,8 +43,7 @@ "uid": "0.0.x", "level": "0.18.x", "leveldown": "0.10.x", - "mkdirp": "0.3.x", - "level-cursor": "0.5.x" + "mkdirp": "0.3.x" }, "engines": { "node": ">=0.8" diff --git a/readme.md b/readme.md index 941e673..8b60799 100644 --- a/readme.md +++ b/readme.md @@ -70,10 +70,14 @@ Remove a model. Get a model. The object passes to the callback is a `Model` instance. -### Model.all([options]) +### Model.get.all([options]) Returns a stream that will emit a model instance on each `data` event. Accepted options are the [same](https://github.com/rvagg/node-levelup/#dbcreatereadstreamoptions) that levelup accepts. +### Model.remove.all([options,] fn) + +Removes all models. + ### Model.db `level` instance diff --git a/src/level-modella.js b/src/level-modella.js index c6a8d35..b8771df 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -6,6 +6,7 @@ var debug = require('debug')('modella:level'), xtend = require('xtend'), through = require('ordered-through'), series = require('map-series'), + cursor = require('level-cursor'), level = require('level'); // holds all the dbs, so that it can close them on process SIGTERM @@ -71,6 +72,9 @@ var level_modella = module.exports = function(db) { Object.keys(level_modella).forEach(function(proto) { model[proto] = level_modella[proto]; }); + + model.get.all = level_modella.getAll(model); + model.remove.all = level_modella.removeAll(model); }; }; @@ -117,14 +121,14 @@ level_modella.put = level_modella.save = level_modella.update = function(options level_modella.get = function(key, options, fn) { fn = get_callback(options, fn); options = xtend(default_options, options); + var self = this; if (type(fn) !== 'function') - return this.emit('error', new Error('get() requires key and callback arguments')); + return self.emit('error', new Error('get() requires key and callback arguments')); debug('get: %s', key); - var self = this; - this.db.get(key, options, function(err, value) { + self.db.get(key, options, function(err, value) { if (err) return fn(err); debug('success get: %s -> %j', key, value); @@ -132,6 +136,30 @@ level_modella.get = function(key, options, fn) { }); }; +/* get all models from the store + * + * ```javascript + * var cursor = require('level-cursor') + * cursor(User.get.all()).each(function (user) {}, function (err) {}) + * ``` + * + * @param {object} [options] + * @api public + */ +level_modella.getAll = function(self) { + return function(options) { + options = xtend(default_options, options); + + debug('all'); + var stream = self.db.createReadStream(options); + + return stream.pipe(through(function(data, fn) { + debug('success get: %s -> %j', data.key, data.value); + fn(null, self(data.value)); + })); + }; +}; + /* removes a model from the store * * ```javascript @@ -163,23 +191,23 @@ level_modella.remove = level_modella.del = function(options, fn) { /* get all models from the store * * ```javascript - * var cursor = require('level-cursor') - * cursor(user.all()).each(function (user) {}, function (err) {}) + * User.remove.all(function (err) {}) * ``` * * @param {object} [options] * @api public */ -level_modella.all = function(options) { - options = xtend(default_options, options); - var self = this; +level_modella.removeAll = function(self) { + return function(options, fn) { + fn = get_callback(options, fn); + options = xtend(default_options, options); - debug('all'); + debug('remove.all'); - return this.db.createReadStream(options).pipe(through(function(data, fn) { - debug('success get: %s -> %j', data.key, data.value); - fn(null, self(data.value)); - })); + cursor(self.db.createKeyStream(options).pipe(through(function(key, fn) { + self.db.del(key, options, fn); + }))).all(fn); + }; }; /* closes all db instances diff --git a/test/test.js b/test/test.js index ebd7bac..3a26edf 100644 --- a/test/test.js +++ b/test/test.js @@ -133,6 +133,24 @@ describe('remove', function() { store.remove.call(model); }); + + it('should remove all', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + + User.remove.all(function(err){ + if(err) return done(err); + + cursor(User.get.all()).all(function(err, users){ + if(err) return done(err); + assert(users.length === 0); + done(); + }); + }); + }); + }); }); describe('get', function() { @@ -164,24 +182,15 @@ describe('get', function() { User.get(); }); -}); - -describe('all', function() { - beforeEach(use); - afterEach(close); it('should get all', function(done) { var model = User(user); model.save(function(err, model) { if(err) return done(err); - var called = false; - cursor(User.all()).each(function (user) { - called = true; - assert(user.primary() === model.primary()); - }, function (err) { - assert(called); + cursor(User.get.all()).all(function(err, users){ + assert(users[0].primary() === model.primary()); done(err); }); }); From c89d567ebbc826dfe6cac04a427a960d9f94a92f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Tue, 3 Dec 2013 00:51:58 -0800 Subject: [PATCH 13/20] update dependencies --- history.md | 29 ++++++++++++----------------- package.json | 7 +++---- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/history.md b/history.md index b3f1b53..5d7ee3e 100644 --- a/history.md +++ b/history.md @@ -1,43 +1,38 @@ -0.3.0 / 2013-12-02 -================== +# 0.3.1 / 2013-12-03 + + * update dependencies + +# 0.3.0 / 2013-12-03 * add `Model.remove.all` * rename `Model.all` to `Model.get.all` -0.2.0 / 2013-12-02 -================== +# 0.2.0 / 2013-12-02 * also accept a string and create a level instance in that case * add a streaming `.all` - -0.1.0 / 2013-12-01 -================== +# 0.1.0 / 2013-12-01 * receive a level instance instead of creating it -0.0.5 / 2013-11-15 -================== +# 0.0.5 / 2013-11-15 * updated to work with modella 0.2.0 * updated level to work with node 0.11.8 -0.0.4 / 2013-09-14 -================== +# 0.0.4 / 2013-09-14 * automatically close on termination -0.0.3 / 2013-08-04 -================== +# 0.0.3 / 2013-08-04 * bump level version -0.0.2 / 2013-07-30 -================== +# 0.0.2 / 2013-07-30 * removed log -0.0.1 / 2013-07-23 -================== +# 0.0.1 / 2013-07-23 * Initial commit \ No newline at end of file diff --git a/package.json b/package.json index febd5a8..c137c4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.3.0", + "version": "0.3.1", "description": "modella plugin for level", "keywords": [ "level", @@ -36,12 +36,11 @@ "devDependencies": { "mocha-lcov-reporter": "0.0.x", "jscoverage": "0.3.x", - "coveralls": "2.0.x", - "mocha": "1.10.x", + "coveralls": "2.5.x", + "mocha": "1.15.x", "modella": "*", "pwd": "0.0.x", "uid": "0.0.x", - "level": "0.18.x", "leveldown": "0.10.x", "mkdirp": "0.3.x" }, From 480eb17ea33d4752011c4e9eead677b8afe0534f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Tue, 3 Dec 2013 00:55:08 -0800 Subject: [PATCH 14/20] use modella in the badges --- readme.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 8b60799..2e89a2c 100644 --- a/readme.md +++ b/readme.md @@ -1,10 +1,10 @@ # level-modella [![NPM version](https://badge.fury.io/js/level-modella.png)](http://badge.fury.io/js/level-modella) -[![Build Status](https://secure.travis-ci.org/ramitos/level-modella.png)](http://travis-ci.org/ramitos/level-modella) -[![Dependency Status](https://gemnasium.com/ramitos/level-modella.png)](https://gemnasium.com/ramitos/level-modella) -[![Coverage Status](https://coveralls.io/repos/ramitos/level-modella/badge.png?branch=master)](https://coveralls.io/r/ramitos/level-modella?branch=master) -[![Code Climate](https://codeclimate.com/github/ramitos/level-modella.png)](https://codeclimate.com/github/ramitos/level-modella) +[![Build Status](https://secure.travis-ci.org/modella/level-modella.png)](http://travis-ci.org/modella/level-modella) +[![Dependency Status](https://gemnasium.com/modella/level-modella.png)](https://gemnasium.com/modella/level-modella) +[![Coverage Status](https://coveralls.io/repos/modella/level-modella/badge.png?branch=master)](https://coveralls.io/r/modella/level-modella?branch=master) +[![Code Climate](https://codeclimate.com/github/modella/level-modella.png)](https://codeclimate.com/github/modella/level-modella) [Level](https://github.com/level/level) plugin for [modella](https://github.com/modella/modella). From df7628525b183e42bae1b7a4448f97579f2dfdff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Fri, 6 Dec 2013 14:10:10 -0800 Subject: [PATCH 15/20] use a prototype to properly handle `this` --- package.json | 2 +- src/level-modella.js | 110 +++++++++++++++++++++++-------------------- test/test.js | 6 +-- 3 files changed, 63 insertions(+), 55 deletions(-) diff --git a/package.json b/package.json index c137c4b..8cf74c6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.3.1", + "version": "0.4.0", "description": "modella plugin for level", "keywords": [ "level", diff --git a/src/level-modella.js b/src/level-modella.js index b8771df..705fff7 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -43,39 +43,20 @@ function close_all(done) { process.on('SIGTERM', close_all); - -/* exports a function to be passed to `Model.use` - * - * ```javascript - * var level_modella = require('level-modella') - * var modella = require('modella') - * var level = require('level') - * - * User = modella('User'); - * - * User.use(level_modella(level)) - * ``` +/* level_modella costructor * + * @param {object} model * @param {object} db - * @return {fn} - * @api public + * @api private */ -var level_modella = module.exports = function(db) { - if(type(db) === 'string') - db = level(db) - - dbs.push(db); - - return function(model) { - model.db = db; - - Object.keys(level_modella).forEach(function(proto) { - model[proto] = level_modella[proto]; - }); - - model.get.all = level_modella.getAll(model); - model.remove.all = level_modella.removeAll(model); - }; +var level_modella = function (model) { + if(!(this instanceof level_modella)) return new level_modella(model); + + model.get = this.get; + model.put = model.save = model.update = this.put; + model.del = model.remove = this.del; + model.get.all = this.getAll.bind(model); + model.remove.all = model.del.all = this.delAll.bind(model); }; /* save a model into the store @@ -88,7 +69,7 @@ var level_modella = module.exports = function(db) { * @param {function} fn * @api public */ -level_modella.put = level_modella.save = level_modella.update = function(options, fn) { +level_modella.prototype.put = function(options, fn) { fn = get_callback(options, fn); options = xtend(default_options, options); @@ -118,7 +99,7 @@ level_modella.put = level_modella.save = level_modella.update = function(options * @param {function} fn * @api public */ -level_modella.get = function(key, options, fn) { +level_modella.prototype.get = function(key, options, fn) { fn = get_callback(options, fn); options = xtend(default_options, options); var self = this; @@ -146,18 +127,17 @@ level_modella.get = function(key, options, fn) { * @param {object} [options] * @api public */ -level_modella.getAll = function(self) { - return function(options) { - options = xtend(default_options, options); +level_modella.prototype.getAll = function(options) { + options = xtend(default_options, options); + var self = this; - debug('all'); - var stream = self.db.createReadStream(options); + debug('all'); + var stream = self.db.createReadStream(options); - return stream.pipe(through(function(data, fn) { - debug('success get: %s -> %j', data.key, data.value); - fn(null, self(data.value)); - })); - }; + return stream.pipe(through(function(data, fn) { + debug('success get: %s -> %j', data.key, data.value); + fn(null, self(data.value)); + })); }; /* removes a model from the store @@ -170,7 +150,7 @@ level_modella.getAll = function(self) { * @param {function} fn * @api public */ -level_modella.remove = level_modella.del = function(options, fn) { +level_modella.prototype.del = function(options, fn) { fn = get_callback(options, fn); options = xtend(default_options, options); @@ -197,16 +177,44 @@ level_modella.remove = level_modella.del = function(options, fn) { * @param {object} [options] * @api public */ -level_modella.removeAll = function(self) { - return function(options, fn) { - fn = get_callback(options, fn); - options = xtend(default_options, options); +level_modella.prototype.delAll = function(options, fn) { + fn = get_callback(options, fn); + options = xtend(default_options, options); + var self = this; - debug('remove.all'); + debug('remove.all'); - cursor(self.db.createKeyStream(options).pipe(through(function(key, fn) { - self.db.del(key, options, fn); - }))).all(fn); + cursor(self.db.createKeyStream(options).pipe(through(function(key, fn) { + self.db.del(key, options, fn); + }))).all(fn); +}; + +/* exports a function to be passed to `Model.use` + * + * ```javascript + * var level_modella = require('level-modella') + * var modella = require('modella') + * var level = require('level') + * + * User = modella('User'); + * + * User.use(level_modella(level)) + * ``` + * + * @param {object} db + * @return {fn} + * @api public + */ +module.exports = function(db){ + if(type(db) === 'string') + db = level(db); + + dbs.push(db); + + return function(model) { + model.db = db; + level_modella(model); + return model; }; }; diff --git a/test/test.js b/test/test.js index 3a26edf..93f463d 100644 --- a/test/test.js +++ b/test/test.js @@ -63,7 +63,7 @@ describe('store', function() { it('close all', function(done) { User.use(store(level(location))); - User.__close_all(done); + store.__close_all(done); }); }); @@ -98,7 +98,7 @@ describe('put', function() { done(); }); - store.save.call(model); + store(model.model.db)(User).save.call(model); }); }); @@ -131,7 +131,7 @@ describe('remove', function() { done(); }); - store.remove.call(model); + store(model.model.db)(User).remove.call(model); }); it('should remove all', function(done) { From 036b9a8c45e6cc60ed3ca587ce943d2f4418b04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Fri, 6 Dec 2013 14:34:58 -0800 Subject: [PATCH 16/20] fix `this` in get.all & del.all --- package.json | 2 +- src/level-modella.js | 34 +++++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index 8cf74c6..86c5c8a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.4.0", + "version": "0.4.1", "description": "modella plugin for level", "keywords": [ "level", diff --git a/src/level-modella.js b/src/level-modella.js index 705fff7..11a29de 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -51,12 +51,26 @@ process.on('SIGTERM', close_all); */ var level_modella = function (model) { if(!(this instanceof level_modella)) return new level_modella(model); + var self = this - model.get = this.get; - model.put = model.save = model.update = this.put; - model.del = model.remove = this.del; - model.get.all = this.getAll.bind(model); - model.remove.all = model.del.all = this.delAll.bind(model); + model.get = function () { + return self.get.apply(this, arguments); + }; + + model.get.all = function () { + return self.getAll.apply(self, arguments); + }; + + model.del = model.remove = function () { + return self.del.apply(this, arguments); + }; + + model.del.all = model.remove.all = function () { + return self.delAll.apply(self, arguments); + }; + + model.put = model.save = model.update = self.put; + self.model = model; }; /* save a model into the store @@ -132,11 +146,13 @@ level_modella.prototype.getAll = function(options) { var self = this; debug('all'); - var stream = self.db.createReadStream(options); + + var stream = self.model.db.createReadStream(options); + //console.log(stream) return stream.pipe(through(function(data, fn) { debug('success get: %s -> %j', data.key, data.value); - fn(null, self(data.value)); + fn(null, self.model(data.value)); })); }; @@ -184,8 +200,8 @@ level_modella.prototype.delAll = function(options, fn) { debug('remove.all'); - cursor(self.db.createKeyStream(options).pipe(through(function(key, fn) { - self.db.del(key, options, fn); + cursor(self.model.db.createKeyStream(options).pipe(through(function(key, fn) { + self.model.db.del(key, options, fn); }))).all(fn); }; From bcf690857d3d7519074073e778451b422367bdc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Fri, 6 Dec 2013 14:37:15 -0800 Subject: [PATCH 17/20] link `model.all` with `model.get.all` --- src/level-modella.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/level-modella.js b/src/level-modella.js index 11a29de..6ee936f 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -69,6 +69,7 @@ var level_modella = function (model) { return self.delAll.apply(self, arguments); }; + model.all = model.get.all model.put = model.save = model.update = self.put; self.model = model; }; From 60962336742b97210a7d529dc33fe3c9b53e4311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Sun, 8 Dec 2013 20:12:18 -0800 Subject: [PATCH 18/20] add `raw` option --- package.json | 2 +- src/level-modella.js | 7 +++++-- test/test.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 86c5c8a..c555c2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.4.1", + "version": "0.5.1", "description": "modella plugin for level", "keywords": [ "level", diff --git a/src/level-modella.js b/src/level-modella.js index 6ee936f..d26c8f1 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -126,6 +126,7 @@ level_modella.prototype.get = function(key, options, fn) { self.db.get(key, options, function(err, value) { if (err) return fn(err); + if (options.raw) return fn(err, value); debug('success get: %s -> %j', key, value); fn(null, self(value)); @@ -145,11 +146,13 @@ level_modella.prototype.get = function(key, options, fn) { level_modella.prototype.getAll = function(options) { options = xtend(default_options, options); var self = this; + var db = self.model.db; debug('all'); - var stream = self.model.db.createReadStream(options); - //console.log(stream) + var stream = options.raw ? db.createValueStream(options) : db.createReadStream(options); + + if (options.raw) return stream; return stream.pipe(through(function(data, fn) { debug('success get: %s -> %j', data.key, data.value); diff --git a/test/test.js b/test/test.js index 93f463d..9a4fd3c 100644 --- a/test/test.js +++ b/test/test.js @@ -153,6 +153,42 @@ describe('remove', function() { }); }); +describe('raw', function() { + beforeEach(use); + afterEach(close); + + it('get', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + + User.get(model.id(), {raw: true}, function(err, value) { + if(err) return done(err); + + assert(value.id === model.id()); + assert(value.name === model.name()); + + done(); + }); + }); + }); + + it('get all', function(done) { + var model = User(user); + + model.save(function(err, model) { + if(err) return done(err); + + cursor(User.get.all({raw: true})).all(function(err, users){ + assert(users[0].id === model.primary()); + done(err); + }); + }); + }); +}); + + describe('get', function() { beforeEach(use); afterEach(close); From abd26a171528268746267ac409803e2def43f2d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Mon, 16 Dec 2013 22:35:24 -0800 Subject: [PATCH 19/20] add option to keys in read .raw --- src/level-modella.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/level-modella.js b/src/level-modella.js index d26c8f1..2bc77e1 100644 --- a/src/level-modella.js +++ b/src/level-modella.js @@ -150,11 +150,15 @@ level_modella.prototype.getAll = function(options) { debug('all'); - var stream = options.raw ? db.createValueStream(options) : db.createReadStream(options); + if (options.raw && !options.keys) { + return db.createValueStream(options); + } - if (options.raw) return stream; + if (options.raw && options.keys) { + return db.createKeyStream(options); + } - return stream.pipe(through(function(data, fn) { + return db.createReadStream(options).pipe(through(function(data, fn) { debug('success get: %s -> %j', data.key, data.value); fn(null, self.model(data.value)); })); From 45dab8ba19c01fc1da83fdc73f312d15fc3fe074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Se=CC=81rgio=20Ramos?= Date: Mon, 16 Dec 2013 22:38:11 -0800 Subject: [PATCH 20/20] version update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c555c2d..8fb513c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "level-modella", - "version": "0.5.1", + "version": "0.6.0", "description": "modella plugin for level", "keywords": [ "level",