New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

mongorito

Package Overview
Dependencies
Maintainers
1
Versions
50
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mongorito - npm Package Compare versions

Comparing version 0.5.1 to 0.6.0

.travis.yml

4

index.js

@@ -0,1 +1,5 @@

require('6to5/register')({
blacklist: ['generators']
});
module.exports = require('./lib/mongorito');

722

lib/mongorito.js
/**
* Dependencies
*/
* Dependencies
*/

@@ -17,54 +17,50 @@ var Class = require('class-extend');

/**
* Mongorito
*
* Main class, manages mongodb connection and collections
*/
* Mongorito
*
* Main class, manages mongodb connection and collections
*/
var Mongorito = {
connect: function () {
var urls = Array.prototype.slice.call(arguments);
// convert mongo:// urls to monk-supported ones
urls = urls.map(function (url) {
return url.replace(/^mongo\:\/\//, '');
});
var db = monk.apply(null, urls);
// if there is already a connection
// don't overwrite it with a new one
if (!this.db) this.db = db;
return db;
},
disconnect: function () {
this.db.close();
},
close: function () {
return this.disconnect.apply(this, arguments);
},
collections: {},
collection: function (db, name) {
var url = db.driver._connect_args[0];
var collections = this.collections[url];
if (!collections) {
collections = this.collections[url] = {};
}
if (collections[name]) return collections[name];
var collection = db.get(name);
return collections[name] = wrap(collection);
}
};
class Mongorito {
static connect (...urls) {
// convert mongo:// urls to monk-supported ones
urls = urls.map(url => url.replace(/^mongo\:\/\//, ''));
let db = monk.apply(null, urls);
// if there is already a connection
// don't overwrite it with a new one
if (!this.db) this.db = db;
return db;
}
static disconnect () {
this.db.close();
}
static close () {
return this.disconnect.apply(this, arguments);
}
static collection (db, name) {
let url = db.driver._connect_args[0];
let collections = this.collections[url];
if (!collections) {
collections = this.collections[url] = {};
}
if (collections[name]) return collections[name];
let collection = db.get(name);
return collections[name] = wrap(collection);
}
}
Mongorito.collections = {};
/**
* Expose `Mongorito`
*/
* Expose `Mongorito`
*/

@@ -75,4 +71,4 @@ var exports = module.exports = Mongorito;

/**
* Query
*/
* Query
*/

@@ -83,290 +79,290 @@ var Query = require('./query');

/**
* Model
*/
* Model
*/
var Model;
class Model {
constructor (attrs = {}, options = {}) {
this.attributes = attrs;
this.changed = {};
this.previous = {};
this.options = options;
var InstanceMethods = {
constructor: function (attrs, options) {
this.attributes = attrs || {};
this.changed = {};
this.previous = {};
this.options = options || {};
// support for multiple connections
// if model has a custom database assigned
// use it, otherwise use the default
var db = this.db || Mongorito.db;
this.collection = Mongorito.collection(db, this.collection);
// reset hooks
this.hooks = {
before: {
create: [],
update: [],
remove: [],
save: []
},
after: {
create: [],
update: [],
remove: [],
save: []
}
};
// run custom per-model configuration
this.configure();
},
get: function (key) {
var attrs = this.attributes;
return key ? attrs[key] : attrs;
},
set: function (key, value) {
// if object passed instead of key-value pair
// iterate and call set on each item
if (isObject(key)) {
var attrs = key;
Object.keys(attrs).forEach(function (key) {
this.set(key, attrs[key]);
}, this);
return;
}
this.previous[key] = this.get(key);
this.attributes[key] = value;
this.changed[key] = value;
return value;
},
setDefaults: function () {
var defaults = this.defaults || {};
Object.keys(defaults).forEach(function (key) {
var defaultValue = defaults[key];
var actualValue = this.get(key);
if (undefined == actualValue) {
this.set(key, defaultValue);
}
}, this);
},
toJSON: function () {
return this.attributes;
},
configure: function () {
},
hook: function (when, action, method) {
if (isObject(when)) {
var hooks = when;
Object.keys(hooks).forEach(function (key) {
var parts = key.split(':');
var when = parts[0];
var action = parts[1];
var method = hooks[key];
this.hook(when, action, method);
}, this);
return;
}
// reset hooks
Object.defineProperty(this, '_hooks', {
value: {
before: {
create: [],
update: [],
remove: [],
save: []
},
after: {
create: [],
update: [],
remove: [],
save: []
}
},
enumerable: false
});
if (isArray(method)) {
var methods = method;
methods.forEach(function (method) {
this.hook(when, action, method);
}, this);
return;
}
if (false === isFunction(method)) method = this[method];
if ('around' === when) {
this.hooks.before[action].push(method);
this.hooks.after[action].unshift(method);
} else {
this.hooks[when][action].push(method);
}
},
before: function (action, method) {
this.hook('before', action, method);
},
after: function (action, method) {
this.hook('after', action, method);
},
around: function (action, method) {
this.hook('around', action, method);
},
runHooks: function *(when, action) {
yield compose(this.hooks[when][action]).call(this);
},
save: function *() {
// set default values if needed
this.setDefaults();
var id = this.get('_id');
var fn = id ? this.update : this.create;
// revert populated documents to _id's
var populate = this.options.populate || emptyObject;
Object.keys(populate).forEach(function (key) {
var value = this.get(key);
if (isArray(value)) {
value = value.map(function (doc) {
return doc.get('_id');
});
} else {
value = value.get('_id');
}
this.set(key, value);
}, this);
yield this.runHooks('before', 'save');
var result = yield fn.call(this);
yield this.runHooks('after', 'save');
return result;
},
create: function *() {
var collection = this.collection;
var attrs = this.attributes;
var timestamp = Math.round(new Date().getTime() / 1000);
this.set({
created_at: timestamp,
updated_at: timestamp
});
yield this.runHooks('before', 'create');
var doc = yield collection.insert(attrs);
this.set('_id', doc._id);
yield this.runHooks('after', 'create');
return this;
},
update: function *() {
var collection = this.collection;
var attrs = this.attributes;
var timestamp = Math.round(new Date().getTime() / 1000);
this.set('updated_at', timestamp);
yield this.runHooks('before', 'update');
yield collection.updateById(attrs._id, attrs);
yield this.runHooks('after', 'update');
return this;
},
remove: function *() {
var collection = this.collection;
yield this.runHooks('before', 'remove');
yield collection.remove({
_id: this.get('_id')
});
yield this.runHooks('after', 'remove');
return this;
}
};
// run custom per-model configuration
this.configure();
}
get _collection () {
return Mongorito.collection(this._db, this.collection);
}
get _db () {
return this.db || Mongorito.db
}
var StaticMethods = {
collection: function () {
var name = this.prototype.collection;
// support for multiple connections
// if model has a custom database assigned
// use it, otherwise use the default
var db = this.prototype.db || Mongorito.db;
return Mongorito.collection(db, name);
},
find: function *(query) {
var collection = this.collection();
var model = this;
var query = new Query(collection, model).find(query);
return yield query;
},
count: function *(query) {
var collection = this.collection();
var model = this;
var count = new Query(collection, model).count(query);
return yield count;
},
all: function *() {
return yield this.find();
},
findOne: function *(query) {
var docs = yield this.find(query);
return docs[0];
},
findById: function *(id) {
var doc = yield this.findOne({ _id: id });
return doc;
},
remove: function *(query) {
var collection = this.collection();
var model = this;
var query = new Query(collection, model).remove(query);
return yield query;
},
index: function *(fields) {
var collection = this.collection();
return yield collection.index(fields);
},
indexes: function *() {
var collection = this.collection();
return yield collection.indexes();
},
id: function () {
var collection = this.collection();
return collection.id.apply(collection, arguments);
}
};
get (key) {
let attrs = this.attributes;
return key ? attrs[key] : attrs;
}
set (key, value) {
// if object passed instead of key-value pair
// iterate and call set on each item
if (isObject(key)) {
let attrs = key;
let keys = Object.keys(attrs);
keys.forEach(key => this.set(key, attrs[key]));
return;
}
this.previous[key] = this.get(key);
this.attributes[key] = value;
this.changed[key] = value;
return value;
}
setDefaults () {
let defaults = this.defaults || {};
let keys = Object.keys(defaults);
keys.forEach(key => {
let defaultValue = defaults[key];
let actualValue = this.get(key);
if (undefined == actualValue) {
this.set(key, defaultValue);
}
});
}
toJSON () {
return this.attributes;
}
configure () {
}
hook (when, action, method) {
if (isObject(when)) {
let hooks = when;
let keys = Object.keys(hooks);
keys.forEach(key => {
let [when, action] = key.split(':');
let method = hooks[key];
this.hook(when, action, method);
});
return;
}
if (isArray(method)) {
let methods = method;
methods.forEach(method => this.hook(when, action, method));
return;
}
if (false === isFunction(method)) method = this[method];
if ('around' === when) {
this._hooks.before[action].push(method);
this._hooks.after[action].unshift(method);
} else {
this._hooks[when][action].push(method);
}
}
hooks () {
return this.hook.apply(this, arguments);
}
before (action, method) {
this.hook('before', action, method);
}
after (action, method) {
this.hook('after', action, method);
}
around (action, method) {
this.hook('around', action, method);
}
* runHooks (when, action) {
let hooks = this._hooks[when][action];
yield compose(hooks).call(this);
}
* save () {
// set default values if needed
this.setDefaults();
let id = this.get('_id');
let fn = id ? this.update : this.create;
// revert populated documents to _id's
let populate = this.options.populate || emptyObject;
let keys = Object.keys(populate);
keys.forEach(key => {
let value = this.get(key);
if (isArray(value)) {
value = value.map(doc => doc.get('_id'));
} else {
value = value.get('_id');
}
this.set(key, value);
});
yield this.runHooks('before', 'save');
let result = yield fn.call(this);
yield this.runHooks('after', 'save');
return result;
}
* create () {
let collection = this._collection;
let attrs = this.attributes;
let timestamp = Math.round(new Date().getTime() / 1000);
this.set({
created_at: timestamp,
updated_at: timestamp
});
yield this.runHooks('before', 'create');
let doc = yield collection.insert(attrs);
this.set('_id', doc._id);
yield this.runHooks('after', 'create');
return this;
}
* update () {
let collection = this._collection;
let attrs = this.attributes;
let timestamp = Math.round(new Date().getTime() / 1000);
this.set('updated_at', timestamp);
yield this.runHooks('before', 'update');
yield collection.updateById(attrs._id, attrs);
yield this.runHooks('after', 'update');
return this;
}
* remove () {
let collection = this._collection;
yield this.runHooks('before', 'remove');
yield collection.remove({ _id: this.get('_id') });
yield this.runHooks('after', 'remove');
return this;
}
static collection () {
let name = this.prototype.collection;
// support for multiple connections
// if model has a custom database assigned
// use it, otherwise use the default
let db = this.prototype.db || Mongorito.db;
return Mongorito.collection(db, name);
}
static * find (query) {
let collection = this.collection();
let model = this;
let q = new Query(collection, model).find(query);
return yield q;
}
static * count (query) {
let collection = this.collection();
let model = this;
let count = new Query(collection, model).count(query);
return yield count;
}
static * all () {
return yield this.find();
}
static * findOne (query) {
let docs = yield this.find(query);
return docs[0];
}
static * findById (id) {
return yield this.findOne({ _id: id });
}
static * remove (query) {
let collection = this.collection();
let model = this;
let query = new Query(collection, model).remove(query);
return yield query;
}
static * index (fields) {
let collection = this.collection();
return yield collection.index(fields);
}
static * indexes () {
let collection = this.collection();
return yield collection.indexes();
}
static id () {
let collection = this.collection();
return collection.id.apply(collection, arguments);
}
}
// Setting up functions that have

@@ -376,34 +372,36 @@ // the same implementation

var methods = [
'where',
'limit',
'skip',
'sort',
'exists',
'lt',
'lte',
'gt',
'gte',
'in',
'nin',
'and',
'or',
'ne',
'nor',
'populate'
'where',
'limit',
'skip',
'sort',
'exists',
'lt',
'lte',
'gt',
'gte',
'in',
'nin',
'and',
'or',
'ne',
'nor',
'populate'
];
methods.forEach(function (method) {
StaticMethods[method] = function () {
var collection = this.collection();
var model = this;
var query = new Query(collection, model);
query[method].apply(query, arguments);
return query;
};
methods.forEach(method => {
Model[method] = function () {
let collection = this.collection();
let model = this;
let query = new Query(collection, model);
query[method].apply(query, arguments);
return query;
};
});
exports.Model = Model = Class.extend(InstanceMethods, StaticMethods);
Model.extend = Class.extend;
exports.Model = Model;
var emptyObject = {};
/**
* Module dependencies
*/
* Module dependencies
*/
var Class = require('class-extend');
var util = require('./util');

@@ -13,206 +11,207 @@

var isString = util.isString;
var isArray = util.isArray;
/**
* Query
*/
* Query
*/
var Query = module.exports = Class.extend({
constructor: function (collection, model, key) {
this.collection = collection;
this.model = model;
this.query = {};
this.options = { populate: {} };
this.lastKey = key;
},
where: function (key, value) {
// if object was passed instead of key-value pair
// iterate over that object and call .where(key, value)
if (isObject(key)) {
var conditions = key;
Object.keys(conditions).forEach(function (key) {
this.where(key, conditions[key]);
}, this);
}
if (isString(key)) {
// if only one argument was supplied
// save the key in this.lastKey
// for future methods, like .equals()
if (undefined == value) {
this.lastKey = key;
return this;
}
// 1. if regular expression
// 2. if object and not ObjectID
if (isRegExp(value)) {
value = { $regex: value };
} else if (isObject(value) && false === isObjectID(value)) {
value = { $elemMatch: value };
}
this.query[key] = value;
}
return this;
},
limit: function (limit) {
this.options.limit = limit;
return this;
},
skip: function (skip) {
this.options.skip = skip;
return this;
},
sort: function (sort) {
this.options.sort = sort;
return this;
},
equals: function (value) {
var key = this.lastKey;
delete this.lastKey;
this.query[key] = value;
return this;
},
exists: function (key, exists) {
if (this.lastKey) {
exists = key;
key = this.lastKey;
delete this.lastKey;
}
this.query[key] = { $exists: exists || true };
return this;
},
populate: function (key, model) {
this.options.populate[key] = model;
return this;
},
count: function *(query) {
this.where(query);
var collection = this.collection;
var model = this.model;
var count = collection.count(this.query);
return yield count;
},
find: function *(query) {
this.where(query);
var collection = this.collection;
var model = this.model;
var options = this.options;
// fields to populate
var populate = Object.keys(options.populate);
var docs = yield collection.find(this.query, options);
var index = 0;
var doc;
while (doc = docs[index++]) {
// options.populate is a key-model pair object
var j = 0;
var key;
while (key = populate[j++]) {
// model to use when populating the field
var model = options.populate[key];
var value = doc[key];
// if value is an array of IDs, loop through it
if (value instanceof Array) {
// convert each _id to String
// and then convert it to
// findById function
var subdocs = value.map(String).map(model.findById, model);
// find sub documents
value = yield subdocs;
} else {
value = yield model.findById(value);
}
// replace previous ID with actual documents
doc[key] = value;
}
// index - 1, because index here is already an index of the next document
docs[index - 1] = new model(doc, {
populate: options.populate
});
}
return docs;
},
findOne: function *(query) {
var docs = yield this.find(query);
return docs[0];
},
remove: function *(query) {
this.where(query);
var collection = this.collection;
var model = this.model;
return yield collection.remove(this.query, this.options);
}
});
class Query {
constructor (collection, model, key) {
this.collection = collection;
this.model = model;
this.query = {};
this.options = { populate: {} };
this.lastKey = key;
}
where (key, value) {
// if object was passed instead of key-value pair
// iterate over that object and call .where(key, value)
if (isObject(key)) {
let conditions = key;
let keys = Object.keys(conditions);
keys.forEach(key => this.where(key, conditions[key]));
}
if (isString(key)) {
// if only one argument was supplied
// save the key in this.lastKey
// for future methods, like .equals()
if (undefined == value) {
this.lastKey = key;
return this;
}
// 1. if regular expression
// 2. if object and not ObjectID
if (isRegExp(value)) {
value = { $regex: value };
} else if (isObject(value) && false === isObjectID(value)) {
value = { $elemMatch: value };
}
this.query[key] = value;
}
return this;
}
limit (limit) {
this.options.limit = limit;
return this;
}
skip (skip) {
this.options.skip = skip;
return this;
}
sort (sort) {
this.options.sort = sort;
return this;
}
equals (value) {
let key = this.lastKey;
this.lastKey = null;
this.query[key] = value;
return this;
}
exists (key, exists) {
if (this.lastKey) {
exists = key;
key = this.lastKey;
this.lastKey = null;
}
this.query[key] = { $exists: exists || true };
return this;
}
populate (key, model) {
this.options.populate[key] = model;
return this;
}
* count (query) {
this.where(query);
let collection = this.collection;
let model = this.model;
let count = collection.count(this.query);
return yield count;
}
* find (query) {
this.where(query);
let collection = this.collection;
let model = this.model;
let options = this.options;
// fields to populate
let populate = Object.keys(options.populate);
let docs = yield collection.find(this.query, options);
let i = 0;
let doc;
while (doc = docs[i++]) {
// options.populate is a key-model pair object
let j = 0;
let key;
while (key = populate[j++]) {
// model to use when populating the field
let model = options.populate[key];
let value = doc[key];
// if value is an array of IDs, loop through it
if (isArray(value)) {
// convert each _id
// to findById op
let subdocs = value.map(model.findById, model);
// find sub documents
value = yield subdocs;
} else {
value = yield model.findById(value);
}
// replace previous ID with actual documents
doc[key] = value;
}
// index - 1, because index here is already an index of the next document
docs[i - 1] = new model(doc, {
populate: options.populate
});
}
return docs;
}
* findOne (query) {
let docs = yield this.find(query);
return docs[0];
}
* remove (query) {
this.where(query);
let collection = this.collection;
let model = this.model;
return yield collection.remove(this.query, this.options);
}
}
// Setting up functions that
// have the same implementation
var methods = [
'lt',
'lte',
'gt',
'gte',
'in',
'nin',
'and',
'or',
'ne',
'nor'
'lt',
'lte',
'gt',
'gte',
'in',
'nin',
'and',
'or',
'ne',
'nor'
];
methods.forEach(function (method) {
Query.prototype[method] = function (key, value) {
// if .where() was called with one argument
// key was already set in this.lastKey
if (this.lastKey) {
value = key;
key = this.lastKey;
delete this.lastKey;
}
this.query[key] = {};
this.query[key]['$' + method] = value;
return this;
}
});
methods.forEach(method => {
Query.prototype[method] = function (key, value) {
// if .where() was called with one argument
// key was already set in this.lastKey
if (this.lastKey) {
value = key;
key = this.lastKey;
this.lastKey = null;
}
this.query[key] = {
['$' + method]: value
};
return this;
}
});
module.exports = Query;

@@ -12,4 +12,2 @@ /**

var exports = module.exports;
exports.isFunction = isFunction;

@@ -16,0 +14,0 @@ exports.isObjectID = isObjectID;

{
"name": "mongorito",
"version": "0.5.1",
"version": "0.6.0",
"description": "ES6 generator-based MongoDB ODM. It rocks.",
"author": "Vadim Demedes <vdemedes@gmail.com>",
"dependencies": {
"6to5": "^2.2.0",
"class-extend": "^0.1.1",
"co-monk": "^1.0.0",
"koa-compose": "^2.3.0",
"monk": "^0.9.0"
"monk": "^0.9.1"
},

@@ -20,3 +21,3 @@ "devDependencies": {

"scripts": {
"test": "./node_modules/.bin/mocha --harmony"
"test": "./node_modules/.bin/mocha --harmony test/test.js"
},

@@ -23,0 +24,0 @@ "repository": {

@@ -7,3 +7,3 @@ # Mongorito

![NPM stats](https://nodei.co/npm/mongorito.png?downloads=true)
[![Build Status](https://travis-ci.org/vdemedes/mongorito.svg)](https://travis-ci.org/vdemedes/mongorito)

@@ -30,3 +30,4 @@ ## Features

**Note**: In order for the following examples to work, you need use something like [co](https://github.com/tj/co).
**Note**: In order for the following examples to work, you need use something like [co](https://github.com/tj/co) to run generators.
**Another note**: If you want to use ES6 classes (like in the following examples), use [6to5](https://github.com/6to5/6to5). If not, there is an alternative API left from previous versions of Mongorito.

@@ -44,5 +45,5 @@ ## Overview

// define model
var Post = Model.extend({
collection: 'posts'
});
class Post extends Model {
get collection () { return 'posts'; }
}

@@ -49,0 +50,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc