diff --git a/chapter25/01_package.json b/chapter25/01_package.json
new file mode 100644
index 0000000..f191c0d
--- /dev/null
+++ b/chapter25/01_package.json
@@ -0,0 +1,10 @@
+{
+ "name": "application-name"
+ , "version": "0.0.1"
+ , "private": true
+ , "dependencies": {
+ "express": "2.5.11"
+ , "jade": ">= 0.0.1"
+ , "mongoose": ">=2.7.0"
+ }
+}
\ No newline at end of file
diff --git a/chapter25/02_user_schema.js b/chapter25/02_user_schema.js
new file mode 100644
index 0000000..c0f536a
--- /dev/null
+++ b/chapter25/02_user_schema.js
@@ -0,0 +1,9 @@
+var mongoose = require('mongoose');
+
+var UserSchema = new mongoose.Schema({
+ username: String,
+ name: String,
+ password: String
+});
+
+module.exports = UserSchema;
\ No newline at end of file
diff --git a/chapter25/03_user_model.js b/chapter25/03_user_model.js
new file mode 100644
index 0000000..e93cb61
--- /dev/null
+++ b/chapter25/03_user_model.js
@@ -0,0 +1,6 @@
+var mongoose = require('mongoose');
+var UserSchema = require('../schemas/user');
+
+var User = mongoose.model('User', UserSchema);
+
+module.exports = User;
\ No newline at end of file
diff --git a/chapter25/04_load_user_route_middleware_new_version.js b/chapter25/04_load_user_route_middleware_new_version.js
new file mode 100644
index 0000000..74e75cf
--- /dev/null
+++ b/chapter25/04_load_user_route_middleware_new_version.js
@@ -0,0 +1,16 @@
+var User = require('../../data/models/user');
+
+function loadUser(req, res, next) {
+ User.findOne({username: req.params.name}, function(err, user) {
+ if (err) {
+ return next(err);
+ }
+ if (! user) {
+ return res.send('Not found', 404);
+ }
+ req.user = user;
+ next();
+ });
+}
+
+module.exports = loadUser;
\ No newline at end of file
diff --git a/chapter25/05_user_routes_new_version.js b/chapter25/05_user_routes_new_version.js
new file mode 100644
index 0000000..fde5058
--- /dev/null
+++ b/chapter25/05_user_routes_new_version.js
@@ -0,0 +1,56 @@
+/*
+ * User Routes
+ */
+
+var User = require('../data/models/user');
+var notLoggedIn = require('./middleware/not_logged_in');
+var loadUser = require('./middleware/load_user');
+var restrictUserToSelf = require('./middleware/restrict_user_to_self');
+
+
+module.exports = function(app) {
+
+ app.get('/users', function(req, res,next){
+ User.find({}, function(err, users) {
+ if (err) {
+ return next(err);
+ }
+ res.render('users/index', {title: 'Users', users: users});
+ });
+ });
+
+ app.get('/users/new', notLoggedIn, function(req, res) {
+ res.render('users/new', {title: "New User"});
+ });
+
+ app.get('/users/:name', loadUser, function(req, res, next){
+ res.render('users/profile', {title: 'User profile', user: req.user});
+ });
+
+ app.post('/users', notLoggedIn, function(req, res, next) {
+ User.findOne({username: req.body.username}, function(err, user) {
+ if (err) {
+ return next(err);
+ }
+ if (user) {
+ return res.send('Conflict', 409);
+ }
+ User.create(req.body, function(err) {
+ if (err) {
+ return next(err);
+ }
+ res.redirect('/users');
+ });
+ });
+ });
+
+ app.del('/users/:name', loadUser, restrictUserToSelf,
+ function(req, res, next) {
+ req.user.remove(function(err) {
+ if (err) { return next(err); }
+ res.redirect('/users');
+ });
+
+ });
+
+};
\ No newline at end of file
diff --git a/chapter25/06_user_list_with_paging.jade b/chapter25/06_user_list_with_paging.jade
new file mode 100644
index 0000000..833b49e
--- /dev/null
+++ b/chapter25/06_user_list_with_paging.jade
@@ -0,0 +1,21 @@
+h1 Users
+
+p
+ a(href="/users/new") Create new profile
+
+
+
+
+
+ul
+ - for(var username in users) {
+ li
+ a(href="/users/" + encodeURIComponent(username))= users[username].name
+ - };
+
+- if (page > 0) {
+ a(href="?page=" + (page - 1)) Previous
+
+- }
+
+a(href="?page=" + (page + 1)) Next
\ No newline at end of file
diff --git a/chapter25/07_user_list_with_paging_new_version.js b/chapter25/07_user_list_with_paging_new_version.js
new file mode 100644
index 0000000..baa33a6
--- /dev/null
+++ b/chapter25/07_user_list_with_paging_new_version.js
@@ -0,0 +1,19 @@
+h1 Users
+
+p
+ a(href="/users/new") Create new profile
+
+ul
+ - users.forEach(function(user) {
+ li
+ a(href="/users/" + encodeURIComponent(user.username))= user.name
+ - });
+
+- if (page > 0) {
+ a(href="?page=" + (page - 1)) Previous
+
+- }
+
+- if (! lastPage) {
+ a(href="?page=" + (page + 1)) Next
+- }
\ No newline at end of file
diff --git a/chapter25/08_package_new_version.json b/chapter25/08_package_new_version.json
new file mode 100644
index 0000000..1376aad
--- /dev/null
+++ b/chapter25/08_package_new_version.json
@@ -0,0 +1,11 @@
+{
+ "name": "application-name"
+ , "version": "0.0.1"
+ , "private": true
+ , "dependencies": {
+ "express": "2.5.11"
+ , "jade": ">= 0.0.1"
+ , "mongoose": ">=2.7.0"
+ , "async": "0.1.22"
+ }
+}
\ No newline at end of file
diff --git a/chapter25/09_user_schema_unique_index.js b/chapter25/09_user_schema_unique_index.js
new file mode 100644
index 0000000..e518172
--- /dev/null
+++ b/chapter25/09_user_schema_unique_index.js
@@ -0,0 +1,9 @@
+var mongoose = require('mongoose');
+
+var UserSchema = new mongoose.Schema({
+ username: {type: String, unique: true},
+ name: String,
+ password: String
+});
+
+module.exports = UserSchema;
\ No newline at end of file
diff --git a/chapter25/10_user_schema_with_validated_email.js b/chapter25/10_user_schema_with_validated_email.js
new file mode 100644
index 0000000..b8cb0e5
--- /dev/null
+++ b/chapter25/10_user_schema_with_validated_email.js
@@ -0,0 +1,18 @@
+var mongoose = require('mongoose');
+
+// simple but incomplete email regexp:
+var emailRegexp = /.+\@.+\..+/;
+
+var UserSchema = new mongoose.Schema({
+ username: {type: String, unique: true},
+ name: String,
+ password: String,
+ email: {
+ type: String,
+ required: true,
+ match: emailRegexp
+
+ }
+});
+
+module.exports = UserSchema;
\ No newline at end of file
diff --git a/chapter25/11_user_schema_with_enumerated_field.js b/chapter25/11_user_schema_with_enumerated_field.js
new file mode 100644
index 0000000..2b03517
--- /dev/null
+++ b/chapter25/11_user_schema_with_enumerated_field.js
@@ -0,0 +1,22 @@
+var mongoose = require('mongoose');
+
+var emailRegexp = /.+\@.+\..+/;
+
+var UserSchema = new mongoose.Schema({
+ username: {type: String, unique: true},
+ name: String,
+ password: String,
+ email: {
+ type: String,
+ required: true,
+ match: emailRegexp
+ },
+ gender: {
+ type: String,
+ required: true,
+ uppercase: true,
+ 'enum': ['M', 'F']
+ }
+});
+
+module.exports = UserSchema;
\ No newline at end of file
diff --git a/chapter25/12_user_form_with_gender_field.jade b/chapter25/12_user_form_with_gender_field.jade
new file mode 100644
index 0000000..c48f724
--- /dev/null
+++ b/chapter25/12_user_form_with_gender_field.jade
@@ -0,0 +1,23 @@
+h1 New User
+
+form(method="POST", action="/users")
+ p
+ label(for="username") Username Welcome to <%= title %> some html ' + http.STATUS_CODES[status] + '. Redirecting to ' + url + ' views: ' + sess.views + ' expires in: ' + (sess.cookie.maxAge / 1000) + 's Hello ' + escape((interp = name) == null ? '' : interp) + '\n Hello ' + escape((interp = name) == null ? '' : interp) + '\n wahoo! foo bar baz rawr..... #{something} foo asdf
+asdf
+ asdfasdfaf
+ asdf
+asd.
+ . foo\bar foo bar foo bar foo bar baz foo bar baz foo bar baz Woah! jade and markdown, very cool we can even link to stuff Welcome to my super lame site. Ferret ');
+ buf.push('Just an example');
+ buf.push(' ');
+ buf.push('Just an example');
+ buf.push(' Hello ' + escape((interp = name) == null ? '' : interp) + '\n Hello ' + escape((interp = name) == null ? '' : interp) + '\n wahoo! foo bar baz rawr..... #{something} foo asdf
+ asdf
+ asdfasdfaf
+ asdf
+ asd
+ .
+ .
+ input#username(name="username")
+ p
+ label(for="name") Name
+ input#name(name="name")
+ p
+ label(for="email") Email
+ input#email(name="email")
+ p
+ label(for="password") Password
+ input#password(type="password", name="password")
+ p
+ label(for="gender") Gender
+ input#gender(name="gender")
+ p
+ label(for="bio") Bio
+ textarea#bio(name="bio")
+ p
+ input(type="submit", value="Create")
\ No newline at end of file
diff --git a/chapter25/13_user_form_with_birthday.jade b/chapter25/13_user_form_with_birthday.jade
new file mode 100644
index 0000000..d49c670
--- /dev/null
+++ b/chapter25/13_user_form_with_birthday.jade
@@ -0,0 +1,26 @@
+h1 New User
+
+form(method="POST", action="/users")
+ p
+ label(for="username") Username
+ input#username(name="username")
+ p
+ label(for="name") Name
+ input#name(name="name")
+ p
+ label(for="email") Email
+ input#email(name="email")
+ p
+ label(for="password") Password
+ input#password(type="password", name="password")
+ p
+ label(for="gender") Gender
+ input#gender(name="gender")
+ p
+ label(for="birthday") Birthday
+ input#birthday(name="birthday")
+ p
+ label(for="bio") Bio
+ textarea#bio(name="bio")
+ p
+ input(type="submit", value="Create")
\ No newline at end of file
diff --git a/chapter25/14_package_with_request.json b/chapter25/14_package_with_request.json
new file mode 100644
index 0000000..8000eee
--- /dev/null
+++ b/chapter25/14_package_with_request.json
@@ -0,0 +1,12 @@
+{
+ "name": "application-name"
+ , "version": "0.0.1"
+ , "private": true
+ , "dependencies": {
+ "express": "2.5.11"
+ , "jade": ">= 0.0.1"
+ , "mongoose": ">=2.7.0"
+ , "async": "0.1.22"
+ , "request": "2.10.0"
+ }
+}
\ No newline at end of file
diff --git a/chapter25/15_user_profile_with_virtual_attribute.jade b/chapter25/15_user_profile_with_virtual_attribute.jade
new file mode 100644
index 0000000..cf838c0
--- /dev/null
+++ b/chapter25/15_user_profile_with_virtual_attribute.jade
@@ -0,0 +1,24 @@
+h1= user.name
+
+h2 Bio
+p= user.bio
+
+h2 Email
+p= user.email
+
+h2 Gender
+p= user.gender
+
+h2 Birthday
+p= user.birthday
+
+- if (user.twitter) {
+ h2 Twitter
+ p
+ a(href= user.twitter_url)="@" + user.twitter
+- }
+
+
+form(action="/users/" + encodeURIComponent(user.username), method="POST")
+ input(name="_method", type="hidden", value="DELETE")
+ input(type="submit", value="Delete")
\ No newline at end of file
diff --git a/chapter25/16_user_form_with_virtual_attribute.jade b/chapter25/16_user_form_with_virtual_attribute.jade
new file mode 100644
index 0000000..72f0f65
--- /dev/null
+++ b/chapter25/16_user_form_with_virtual_attribute.jade
@@ -0,0 +1,29 @@
+h1 New User
+
+form(method="POST", action="/users")
+ p
+ label(for="username") Username
+ input#username(name="username")
+ p
+ label(for="full_name") Full name (first and last)
+ input#full_name(name="full_name")
+ p
+ label(for="email") Email
+ input#email(name="email")
+ p
+ label(for="password") Password
+ input#password(type="password", name="password")
+ p
+ label(for="gender") Gender
+ input#gender(name="gender")
+ p
+ label(for="birthday") Birthday
+ input#birthday(name="birthday")
+ p
+ label(for="twitter") Twitter Handle
+ input#twitter(name="twitter")
+ p
+ label(for="bio") Bio
+ textarea#bio(name="bio")
+ p
+ input(type="submit", value="Create")
\ No newline at end of file
diff --git a/chapter25/17_user_profile_with_virtual_attribute.jade b/chapter25/17_user_profile_with_virtual_attribute.jade
new file mode 100644
index 0000000..0548af3
--- /dev/null
+++ b/chapter25/17_user_profile_with_virtual_attribute.jade
@@ -0,0 +1,24 @@
+h1= user.full_name
+
+h2 Bio
+p= user.bio
+
+h2 Email
+p= user.email
+
+h2 Gender
+p= user.gender
+
+h2 Birthday
+p= user.birthday
+
+- if (user.twitter) {
+ h2 Twitter
+ p
+ a(href= user.twitter_url)="@" + user.twitter
+- }
+
+
+form(action="/users/" + encodeURIComponent(user.username), method="POST")
+ input(name="_method", type="hidden", value="DELETE")
+ input(type="submit", value="Delete")
\ No newline at end of file
diff --git a/chapter25/18_user_list_with_virtual_attribute.jade b/chapter25/18_user_list_with_virtual_attribute.jade
new file mode 100644
index 0000000..b880402
--- /dev/null
+++ b/chapter25/18_user_list_with_virtual_attribute.jade
@@ -0,0 +1,19 @@
+h1 Users
+
+p
+ a(href="/users/new") Create new profile
+
+ul
+ - users.forEach(function(user) {
+ li
+ a(href="/users/" + encodeURIComponent(user.username))= user.full_name
+ - });
+
+- if (page > 0) {
+ a(href="?page=" + (page - 1)) Previous
+
+- }
+
+- if (! lastPage) {
+ a(href="?page=" + (page + 1)) Next
+- }
\ No newline at end of file
diff --git a/chapter25/19_article_schema.js b/chapter25/19_article_schema.js
new file mode 100644
index 0000000..3d01bb4
--- /dev/null
+++ b/chapter25/19_article_schema.js
@@ -0,0 +1,20 @@
+var Schema = require('mongoose').Schema;
+
+var ArticleSchema = new Schema({
+ title: {
+ type: String,
+ unique: true
+ },
+ body: String,
+ author: {
+ type: Schema.ObjectId,
+ ref: 'User',
+ required: true
+ },
+ created_at: {
+ type: Date,
+ 'default': Date.now
+ }
+});
+
+module.exports = ArticleSchema;
\ No newline at end of file
diff --git a/chapter25/20_article_model.js b/chapter25/20_article_model.js
new file mode 100644
index 0000000..36701ab
--- /dev/null
+++ b/chapter25/20_article_model.js
@@ -0,0 +1,6 @@
+var mongoose = require('mongoose');
+var ArticleSchema = require('../schemas/article');
+
+var Article = mongoose.model('Article', ArticleSchema);
+
+module.exports = Article;
\ No newline at end of file
diff --git a/chapter25/21_article_routes.js b/chapter25/21_article_routes.js
new file mode 100644
index 0000000..8ba70b0
--- /dev/null
+++ b/chapter25/21_article_routes.js
@@ -0,0 +1,96 @@
+/*
+ * Article Routes
+ */
+
+var async = require('async');
+
+var Article = require('../data/models/article');
+var notLoggedIn = require('./middleware/not_logged_in');
+var loadArticle = require('./middleware/load_article');
+var loggedIn = require('./middleware/logged_in');
+
+var maxArticlesPerPage = 5;
+
+module.exports = function(app) {
+
+ app.get('/articles', function(req, res, next){
+ var page = req.query.page && parseInt(req.query.page, 10) || 0;
+ async.parallel([
+
+ function(next) {
+ Article.count(next);
+ },
+
+ function(next) {
+ Article.find({})
+ .sort('title', 1)
+ .skip(page * maxArticlesPerPage)
+ .limit(maxArticlesPerPage)
+ .exec(next);
+ }
+ ],
+
+ // final callback
+ function(err, results) {
+
+ if (err) {
+ return next(err);
+ }
+
+ var count = results[0];
+ var articles = results[1];
+
+ var lastPage = (page + 1) * maxArticlesPerPage >= count;
+
+ res.render('articles/index', {
+ title: 'Articles',
+ articles: articles,
+ page: page,
+ lastPage: lastPage
+ });
+
+ }
+ );
+ });
+
+ app.get('/articles/new', loggedIn, function(req, res) {
+ res.render('Articles/new', {title: "New Article"});
+ });
+
+ app.get('/articles/:title', loadArticle, function(req, res, next){
+ res.render('articles/article', {title: req.article.title,
+ article: req.article});
+ });
+
+ app.post('/articles', loggedIn, function(req, res, next) {
+ var article = req.body;
+ article.author = req.session.user._id;
+ Article.create(article, function(err) {
+ if (err) {
+ if (err.code === 11000) {
+ res.send('Conflict', 409);
+ } else {
+ if (err.name === 'ValidationError') {
+ return res.send(Object.keys(err.errors).map(function(errField) {
+ return err.errors[errField].message;
+ }).join('. '), 406);
+ } else {
+ next(err);
+ }
+
+ }
+ return;
+ }
+ res.redirect('/articles');
+ });
+ });
+
+ app.del('/articles/:title', loggedIn, loadArticle, function(req, res, next) {
+ req.article.remove(function(err) {
+ if (err) { return next(err); }
+ res.redirect('/articles');
+ });
+
+ });
+
+};
\ No newline at end of file
diff --git a/chapter25/22_load_article_middleware.js b/chapter25/22_load_article_middleware.js
new file mode 100644
index 0000000..631039b
--- /dev/null
+++ b/chapter25/22_load_article_middleware.js
@@ -0,0 +1,18 @@
+var Article = require('../../data/models/article');
+
+function loadArticle(req, res, next) {
+ Article.findOne({title: req.params.title})
+ .populate('author')
+ .exec(function(err, article) {
+ if (err) {
+ return next(err);
+ }
+ if (! article) {
+ return res.send('Not found', 404);
+ }
+ req.article = article;
+ next();
+ });
+}
+
+module.exports = loadArticle;
\ No newline at end of file
diff --git a/chapter25/23_article_detail.jade b/chapter25/23_article_detail.jade
new file mode 100644
index 0000000..b3c8112
--- /dev/null
+++ b/chapter25/23_article_detail.jade
@@ -0,0 +1,13 @@
+h1= article.title
+
+div!= article.body
+
+hr
+
+p
+ span Author:
+
+ a(href="/users/" + encodeURIComponent(article.author.username))= article.author.full_name
+
+p
+ a(href="/articles") Back to all articles
\ No newline at end of file
diff --git a/chapter25/24_logged_in_middleware.js b/chapter25/24_logged_in_middleware.js
new file mode 100644
index 0000000..f726997
--- /dev/null
+++ b/chapter25/24_logged_in_middleware.js
@@ -0,0 +1,9 @@
+function loggedIn(req, res, next) {
+ if (! req.session.user) {
+ res.send('Forbidden. Please log in first.', 403);
+ } else {
+ next();
+ }
+}
+
+module.exports = loggedIn;
\ No newline at end of file
diff --git a/chapter25/25_article_list.jade b/chapter25/25_article_list.jade
new file mode 100644
index 0000000..515318a
--- /dev/null
+++ b/chapter25/25_article_list.jade
@@ -0,0 +1,19 @@
+h1 Articles
+
+p
+ a(href="/articles/new") Create new article
+
+ul
+ - articles.forEach(function(article) {
+ li
+ a(href="/articles/" + encodeURIComponent(article.title))= article.title
+ - });
+
+- if (page > 0) {
+ a(href="?page=" + (page - 1)) Previous
+
+- }
+
+- if (! lastPage) {
+ a(href="?page=" + (page + 1)) Next
+- }
diff --git a/chapter25/26_article_creation_form.jade b/chapter25/26_article_creation_form.jade
new file mode 100644
index 0000000..322cc73
--- /dev/null
+++ b/chapter25/26_article_creation_form.jade
@@ -0,0 +1,11 @@
+h1 New Article
+
+form(method="POST", action="/articles")
+ p
+ label(for="title") Title
+ input#title(name="title")
+ p
+ label(for="body") Body
+ textarea#body(name="body")
+ p
+ input(type="submit", value="Create")
diff --git a/chapter25/27_article_list_partial.jade b/chapter25/27_article_list_partial.jade
new file mode 100644
index 0000000..df95420
--- /dev/null
+++ b/chapter25/27_article_list_partial.jade
@@ -0,0 +1,5 @@
+ul
+ - articles.forEach(function(article) {
+ li
+ a(href="/articles/" + encodeURIComponent(article.title))= article.title
+ - });
\ No newline at end of file
diff --git a/chapter25/28_article_list_new_version.jade b/chapter25/28_article_list_new_version.jade
new file mode 100644
index 0000000..d04e0ea
--- /dev/null
+++ b/chapter25/28_article_list_new_version.jade
@@ -0,0 +1,15 @@
+h1 Articles
+
+p
+ a(href="/articles/new") Create new article
+
+p!= partial('articles/list', {articles: articles})
+
+- if (page > 0) {
+ a(href="?page=" + (page - 1)) Previous
+
+- }
+
+- if (! lastPage) {
+ a(href="?page=" + (page + 1)) Next
+- }
\ No newline at end of file
diff --git a/test/app.js b/test/app.js
new file mode 100644
index 0000000..52923be
--- /dev/null
+++ b/test/app.js
@@ -0,0 +1,44 @@
+
+/**
+ * Module dependencies.
+ */
+
+var express = require('express')
+ , routes = require('./routes');
+var async = require('async');
+var app = module.exports = express.createServer();
+
+// Configuration
+
+app.configure(function(){
+ app.set('views', __dirname + '/views');
+ app.set('view engine', 'jade');
+ app.use(express.bodyParser());
+ app.use(express.methodOverride());
+ app.use(express.cookieParser('my secret string'));
+ app.use(express.session({
+ secret: 'my secret string',
+ maxAge: 3600000
+ }));
+ app.use(app.router);
+ app.use(express.static(__dirname + '/public'));
+});
+
+app.configure('development', function(){
+ app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
+});
+
+app.configure('production', function(){
+ app.use(express.errorHandler());
+});
+
+// Routes
+
+require('./routes/index')(app);
+require('./routes/users')(app);
+require('./routes/session')(app);
+
+
+app.listen(3000, function(){
+ console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
+});
diff --git a/test/data/models/user.js b/test/data/models/user.js
new file mode 100644
index 0000000..e93cb61
--- /dev/null
+++ b/test/data/models/user.js
@@ -0,0 +1,6 @@
+var mongoose = require('mongoose');
+var UserSchema = require('../schemas/user');
+
+var User = mongoose.model('User', UserSchema);
+
+module.exports = User;
\ No newline at end of file
diff --git a/test/data/users.json b/test/data/users.json
new file mode 100644
index 0000000..a9d0ffd
--- /dev/null
+++ b/test/data/users.json
@@ -0,0 +1,24 @@
+{
+
+ "frank": {
+ "username": "frank",
+ "name": "Frank Sinatra",
+ "bio": "Singer",
+ "password": "password"
+ },
+
+ "jobim": {
+ "username": "jobim",
+ "name": "Antonio Carlos Jobim",
+ "bio": "Composer",
+ "password": "password"
+ },
+
+ "fred": {
+ "username": "fred",
+ "name": "Fred Astaire",
+ "bio": "Dancer and Actor",
+ "password": "password"
+ }
+
+}
\ No newline at end of file
diff --git a/test/node_modules/.bin/express b/test/node_modules/.bin/express
new file mode 100644
index 0000000..cad5a1e
--- /dev/null
+++ b/test/node_modules/.bin/express
@@ -0,0 +1,15 @@
+#!/bin/sh
+basedir=`dirname "$0"`
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+ "$basedir/node" "$basedir/../express/bin/express" "$@"
+ ret=$?
+else
+ node "$basedir/../express/bin/express" "$@"
+ ret=$?
+fi
+exit $ret
diff --git a/test/node_modules/.bin/express.cmd b/test/node_modules/.bin/express.cmd
new file mode 100644
index 0000000..54cebb3
--- /dev/null
+++ b/test/node_modules/.bin/express.cmd
@@ -0,0 +1,6 @@
+:: Created by npm, please don't edit manually.
+@IF EXIST "%~dp0\node.exe" (
+ "%~dp0\node.exe" "%~dp0\..\express\bin\express" %*
+) ELSE (
+ node "%~dp0\..\express\bin\express" %*
+)
\ No newline at end of file
diff --git a/test/node_modules/.bin/jade b/test/node_modules/.bin/jade
new file mode 100644
index 0000000..7de066b
--- /dev/null
+++ b/test/node_modules/.bin/jade
@@ -0,0 +1,15 @@
+#!/bin/sh
+basedir=`dirname "$0"`
+
+case `uname` in
+ *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
+esac
+
+if [ -x "$basedir/node" ]; then
+ "$basedir/node" "$basedir/../jade/bin/jade" "$@"
+ ret=$?
+else
+ node "$basedir/../jade/bin/jade" "$@"
+ ret=$?
+fi
+exit $ret
diff --git a/test/node_modules/.bin/jade.cmd b/test/node_modules/.bin/jade.cmd
new file mode 100644
index 0000000..2d85713
--- /dev/null
+++ b/test/node_modules/.bin/jade.cmd
@@ -0,0 +1,6 @@
+:: Created by npm, please don't edit manually.
+@IF EXIST "%~dp0\node.exe" (
+ "%~dp0\node.exe" "%~dp0\..\jade\bin\jade" %*
+) ELSE (
+ node "%~dp0\..\jade\bin\jade" %*
+)
\ No newline at end of file
diff --git a/test/node_modules/async/.gitmodules b/test/node_modules/async/.gitmodules
new file mode 100644
index 0000000..a9aae98
--- /dev/null
+++ b/test/node_modules/async/.gitmodules
@@ -0,0 +1,9 @@
+[submodule "deps/nodeunit"]
+ path = deps/nodeunit
+ url = git://github.com/caolan/nodeunit.git
+[submodule "deps/UglifyJS"]
+ path = deps/UglifyJS
+ url = https://github.com/mishoo/UglifyJS.git
+[submodule "deps/nodelint"]
+ path = deps/nodelint
+ url = https://github.com/tav/nodelint.git
diff --git a/test/node_modules/async/.npmignore b/test/node_modules/async/.npmignore
new file mode 100644
index 0000000..9bdfc97
--- /dev/null
+++ b/test/node_modules/async/.npmignore
@@ -0,0 +1,4 @@
+deps
+dist
+test
+nodelint.cfg
\ No newline at end of file
diff --git a/test/node_modules/async/LICENSE b/test/node_modules/async/LICENSE
new file mode 100644
index 0000000..b7f9d50
--- /dev/null
+++ b/test/node_modules/async/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Caolan McMahon
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/test/node_modules/async/Makefile b/test/node_modules/async/Makefile
new file mode 100644
index 0000000..bad647c
--- /dev/null
+++ b/test/node_modules/async/Makefile
@@ -0,0 +1,25 @@
+PACKAGE = asyncjs
+NODEJS = $(if $(shell test -f /usr/bin/nodejs && echo "true"),nodejs,node)
+CWD := $(shell pwd)
+NODEUNIT = $(CWD)/node_modules/nodeunit/bin/nodeunit
+UGLIFY = $(CWD)/node_modules/uglify-js/bin/uglifyjs
+NODELINT = $(CWD)/node_modules/nodelint/nodelint
+
+BUILDDIR = dist
+
+all: clean test build
+
+build: $(wildcard lib/*.js)
+ mkdir -p $(BUILDDIR)
+ $(UGLIFY) lib/async.js > $(BUILDDIR)/async.min.js
+
+test:
+ $(NODEUNIT) test
+
+clean:
+ rm -rf $(BUILDDIR)
+
+lint:
+ $(NODELINT) --config nodelint.cfg lib/async.js
+
+.PHONY: test build all
diff --git a/test/node_modules/async/README.md b/test/node_modules/async/README.md
new file mode 100644
index 0000000..1bbbc47
--- /dev/null
+++ b/test/node_modules/async/README.md
@@ -0,0 +1,1021 @@
+# Async.js
+
+Async is a utility module which provides straight-forward, powerful functions
+for working with asynchronous JavaScript. Although originally designed for
+use with [node.js](http://nodejs.org), it can also be used directly in the
+browser.
+
+Async provides around 20 functions that include the usual 'functional'
+suspects (map, reduce, filter, forEach…) as well as some common patterns
+for asynchronous control flow (parallel, series, waterfall…). All these
+functions assume you follow the node.js convention of providing a single
+callback as the last argument of your async function.
+
+
+## Quick Examples
+
+ async.map(['file1','file2','file3'], fs.stat, function(err, results){
+ // results is now an array of stats for each file
+ });
+
+ async.filter(['file1','file2','file3'], path.exists, function(results){
+ // results now equals an array of the existing files
+ });
+
+ async.parallel([
+ function(){ ... },
+ function(){ ... }
+ ], callback);
+
+ async.series([
+ function(){ ... },
+ function(){ ... }
+ ]);
+
+There are many more functions available so take a look at the docs below for a
+full list. This module aims to be comprehensive, so if you feel anything is
+missing please create a GitHub issue for it.
+
+
+## Download
+
+Releases are available for download from
+[GitHub](http://github.com/caolan/async/downloads).
+Alternatively, you can install using Node Package Manager (npm):
+
+ npm install async
+
+
+__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed
+
+__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped
+
+
+## In the Browser
+
+So far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:
+
+
+
+
+
+## Documentation
+
+### Collections
+
+* [forEach](#forEach)
+* [map](#map)
+* [filter](#filter)
+* [reject](#reject)
+* [reduce](#reduce)
+* [detect](#detect)
+* [sortBy](#sortBy)
+* [some](#some)
+* [every](#every)
+* [concat](#concat)
+
+### Control Flow
+
+* [series](#series)
+* [parallel](#parallel)
+* [whilst](#whilst)
+* [until](#until)
+* [waterfall](#waterfall)
+* [queue](#queue)
+* [auto](#auto)
+* [iterator](#iterator)
+* [apply](#apply)
+* [nextTick](#nextTick)
+
+### Utils
+
+* [memoize](#memoize)
+* [unmemoize](#unmemoize)
+* [log](#log)
+* [dir](#dir)
+* [noConflict](#noConflict)
+
+
+## Collections
+
+
+### forEach(arr, iterator, callback)
+
+Applies an iterator function to each item in an array, in parallel.
+The iterator is called with an item from the list and a callback for when it
+has finished. If the iterator passes an error to this callback, the main
+callback for the forEach function is immediately called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(err) - A callback which is called after all the iterator functions
+ have finished, or an error has occurred.
+
+__Example__
+
+ // assuming openFiles is an array of file names and saveFile is a function
+ // to save the modified contents of that file:
+
+ async.forEach(openFiles, saveFile, function(err){
+ // if any of the saves produced an error, err would equal that error
+ });
+
+---------------------------------------
+
+
+### forEachSeries(arr, iterator, callback)
+
+The same as forEach only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. This means the iterator functions will complete in order.
+
+
+---------------------------------------
+
+
+### forEachLimit(arr, limit, iterator, callback)
+
+The same as forEach only the iterator is applied to batches of items in the
+array, in series. The next batch of iterators is only called once the current
+one has completed processing.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* limit - How many items should be in each batch.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(err) - A callback which is called after all the iterator functions
+ have finished, or an error has occurred.
+
+__Example__
+
+ // Assume documents is an array of JSON objects and requestApi is a
+ // function that interacts with a rate-limited REST api.
+
+ async.forEachLimit(documents, 20, requestApi, function(err){
+ // if any of the saves produced an error, err would equal that error
+ });
+---------------------------------------
+
+
+### map(arr, iterator, callback)
+
+Produces a new array of values by mapping each value in the given array through
+the iterator function. The iterator is called with an item from the array and a
+callback for when it has finished processing. The callback takes 2 arguments,
+an error and the transformed item from the array. If the iterator passes an
+error to this callback, the main callback for the map function is immediately
+called with the error.
+
+Note, that since this function applies the iterator to each item in parallel
+there is no guarantee that the iterator functions will complete in order, however
+the results array will be in the same order as the original array.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and a transformed item.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is an array of the
+ transformed items from the original array.
+
+__Example__
+
+ async.map(['file1','file2','file3'], fs.stat, function(err, results){
+ // results is now an array of stats for each file
+ });
+
+---------------------------------------
+
+
+### mapSeries(arr, iterator, callback)
+
+The same as map only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+
+---------------------------------------
+
+
+### filter(arr, iterator, callback)
+
+__Alias:__ select
+
+Returns a new array of all the values which pass an async truth test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists. This operation is
+performed in parallel, but the results array will be in the same order as the
+original.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(results) - A callback which is called after all the iterator
+ functions have finished.
+
+__Example__
+
+ async.filter(['file1','file2','file3'], path.exists, function(results){
+ // results now equals an array of the existing files
+ });
+
+---------------------------------------
+
+
+### filterSeries(arr, iterator, callback)
+
+__alias:__ selectSeries
+
+The same as filter only the iterator is applied to each item in the array in
+series. The next iterator is only called once the current one has completed
+processing. The results array will be in the same order as the original.
+
+---------------------------------------
+
+
+### reject(arr, iterator, callback)
+
+The opposite of filter. Removes values that pass an async truth test.
+
+---------------------------------------
+
+
+### rejectSeries(arr, iterator, callback)
+
+The same as filter, only the iterator is applied to each item in the array
+in series.
+
+
+---------------------------------------
+
+
+### reduce(arr, memo, iterator, callback)
+
+__aliases:__ inject, foldl
+
+Reduces a list of values into a single value using an async iterator to return
+each successive step. Memo is the initial state of the reduction. This
+function only operates in series. For performance reasons, it may make sense to
+split a call to this function into a parallel map, then use the normal
+Array.prototype.reduce on the results. This function is for situations where
+each step in the reduction needs to be async, if you can get the data before
+reducing it then its probably a good idea to do so.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* memo - The initial state of the reduction.
+* iterator(memo, item, callback) - A function applied to each item in the
+ array to produce the next step in the reduction. The iterator is passed a
+ callback which accepts an optional error as its first argument, and the state
+ of the reduction as the second. If an error is passed to the callback, the
+ reduction is stopped and the main callback is immediately called with the
+ error.
+* callback(err, result) - A callback which is called after all the iterator
+ functions have finished. Result is the reduced value.
+
+__Example__
+
+ async.reduce([1,2,3], 0, function(memo, item, callback){
+ // pointless async:
+ process.nextTick(function(){
+ callback(null, memo + item)
+ });
+ }, function(err, result){
+ // result is now equal to the last value of memo, which is 6
+ });
+
+---------------------------------------
+
+
+### reduceRight(arr, memo, iterator, callback)
+
+__Alias:__ foldr
+
+Same as reduce, only operates on the items in the array in reverse order.
+
+
+---------------------------------------
+
+
+### detect(arr, iterator, callback)
+
+Returns the first value in a list that passes an async truth test. The
+iterator is applied in parallel, meaning the first iterator to return true will
+fire the detect callback with that result. That means the result might not be
+the first item in the original array (in terms of order) that passes the test.
+
+If order within the original array is important then look at detectSeries.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+ true, or after all the iterator functions have finished. Result will be
+ the first item in the array that passes the truth test (iterator) or the
+ value undefined if none passed.
+
+__Example__
+
+ async.detect(['file1','file2','file3'], path.exists, function(result){
+ // result now equals the first file in the list that exists
+ });
+
+---------------------------------------
+
+
+### detectSeries(arr, iterator, callback)
+
+The same as detect, only the iterator is applied to each item in the array
+in series. This means the result is always the first in the original array (in
+terms of array order) that passes the truth test.
+
+
+---------------------------------------
+
+
+### sortBy(arr, iterator, callback)
+
+Sorts a list by the results of running each value through an async iterator.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and a value to use as the sort criteria.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is the items from
+ the original array sorted by the values returned by the iterator calls.
+
+__Example__
+
+ async.sortBy(['file1','file2','file3'], function(file, callback){
+ fs.stat(file, function(err, stats){
+ callback(err, stats.mtime);
+ });
+ }, function(err, results){
+ // results is now the original array of files sorted by
+ // modified date
+ });
+
+
+---------------------------------------
+
+
+### some(arr, iterator, callback)
+
+__Alias:__ any
+
+Returns true if at least one element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists. Once any iterator
+call returns true, the main callback is immediately called.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called as soon as any iterator returns
+ true, or after all the iterator functions have finished. Result will be
+ either true or false depending on the values of the async tests.
+
+__Example__
+
+ async.some(['file1','file2','file3'], path.exists, function(result){
+ // if result is true then at least one of the files exists
+ });
+
+---------------------------------------
+
+
+### every(arr, iterator, callback)
+
+__Alias:__ all
+
+Returns true if every element in the array satisfies an async test.
+_The callback for each iterator call only accepts a single argument of true or
+false, it does not accept an error argument first!_ This is in-line with the
+way node libraries work with truth tests like path.exists.
+
+__Arguments__
+
+* arr - An array to iterate over.
+* iterator(item, callback) - A truth test to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed.
+* callback(result) - A callback which is called after all the iterator
+ functions have finished. Result will be either true or false depending on
+ the values of the async tests.
+
+__Example__
+
+ async.every(['file1','file2','file3'], path.exists, function(result){
+ // if result is true then every file exists
+ });
+
+---------------------------------------
+
+
+### concat(arr, iterator, callback)
+
+Applies an iterator to each item in a list, concatenating the results. Returns the
+concatenated list. The iterators are called in parallel, and the results are
+concatenated as they return. There is no guarantee that the results array will
+be returned in the original order of the arguments passed to the iterator function.
+
+__Arguments__
+
+* arr - An array to iterate over
+* iterator(item, callback) - A function to apply to each item in the array.
+ The iterator is passed a callback which must be called once it has completed
+ with an error (which can be null) and an array of results.
+* callback(err, results) - A callback which is called after all the iterator
+ functions have finished, or an error has occurred. Results is an array containing
+ the concatenated results of the iterator function.
+
+__Example__
+
+ async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){
+ // files is now a list of filenames that exist in the 3 directories
+ });
+
+---------------------------------------
+
+
+### concatSeries(arr, iterator, callback)
+
+Same as async.concat, but executes in series instead of parallel.
+
+
+## Control Flow
+
+
+### series(tasks, [callback])
+
+Run an array of functions in series, each one running once the previous
+function has completed. If any functions in the series pass an error to its
+callback, no more functions are run and the callback for the series is
+immediately called with the value of the error. Once the tasks have completed,
+the results are passed to the final callback as an array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.series.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed
+ a callback it must call on completion.
+* callback(err, results) - An optional callback to run once all the functions
+ have completed. This function gets an array of all the arguments passed to
+ the callbacks used in the array.
+
+__Example__
+
+ async.series([
+ function(callback){
+ // do some stuff ...
+ callback(null, 'one');
+ },
+ function(callback){
+ // do some more stuff ...
+ callback(null, 'two');
+ },
+ ],
+ // optional callback
+ function(err, results){
+ // results is now equal to ['one', 'two']
+ });
+
+
+ // an example using an object instead of an array
+ async.series({
+ one: function(callback){
+ setTimeout(function(){
+ callback(null, 1);
+ }, 200);
+ },
+ two: function(callback){
+ setTimeout(function(){
+ callback(null, 2);
+ }, 100);
+ },
+ },
+ function(err, results) {
+ // results is now equal to: {one: 1, two: 2}
+ });
+
+
+---------------------------------------
+
+
+### parallel(tasks, [callback])
+
+Run an array of functions in parallel, without waiting until the previous
+function has completed. If any of the functions pass an error to its
+callback, the main callback is immediately called with the value of the error.
+Once the tasks have completed, the results are passed to the final callback as an
+array.
+
+It is also possible to use an object instead of an array. Each property will be
+run as a function and the results will be passed to the final callback as an object
+instead of an array. This can be a more readable way of handling results from
+async.parallel.
+
+
+__Arguments__
+
+* tasks - An array or object containing functions to run, each function is passed a
+ callback it must call on completion.
+* callback(err, results) - An optional callback to run once all the functions
+ have completed. This function gets an array of all the arguments passed to
+ the callbacks used in the array.
+
+__Example__
+
+ async.parallel([
+ function(callback){
+ setTimeout(function(){
+ callback(null, 'one');
+ }, 200);
+ },
+ function(callback){
+ setTimeout(function(){
+ callback(null, 'two');
+ }, 100);
+ },
+ ],
+ // optional callback
+ function(err, results){
+ // the results array will equal ['one','two'] even though
+ // the second function had a shorter timeout.
+ });
+
+
+ // an example using an object instead of an array
+ async.parallel({
+ one: function(callback){
+ setTimeout(function(){
+ callback(null, 1);
+ }, 200);
+ },
+ two: function(callback){
+ setTimeout(function(){
+ callback(null, 2);
+ }, 100);
+ },
+ },
+ function(err, results) {
+ // results is now equals to: {one: 1, two: 2}
+ });
+
+
+---------------------------------------
+
+
+### whilst(test, fn, callback)
+
+Repeatedly call fn, while test returns true. Calls the callback when stopped,
+or an error occurs.
+
+__Arguments__
+
+* test() - synchronous truth test to perform before each execution of fn.
+* fn(callback) - A function to call each time the test passes. The function is
+ passed a callback which must be called once it has completed with an optional
+ error as the first argument.
+* callback(err) - A callback which is called after the test fails and repeated
+ execution of fn has stopped.
+
+__Example__
+
+ var count = 0;
+
+ async.whilst(
+ function () { return count < 5; },
+ function (callback) {
+ count++;
+ setTimeout(callback, 1000);
+ },
+ function (err) {
+ // 5 seconds have passed
+ }
+ );
+
+
+---------------------------------------
+
+
+### until(test, fn, callback)
+
+Repeatedly call fn, until test returns true. Calls the callback when stopped,
+or an error occurs.
+
+The inverse of async.whilst.
+
+
+---------------------------------------
+
+
+### waterfall(tasks, [callback])
+
+Runs an array of functions in series, each passing their results to the next in
+the array. However, if any of the functions pass an error to the callback, the
+next function is not executed and the main callback is immediately called with
+the error.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a callback it
+ must call on completion.
+* callback(err, [results]) - An optional callback to run once all the functions
+ have completed. This will be passed the results of the last task's callback.
+
+
+
+__Example__
+
+ async.waterfall([
+ function(callback){
+ callback(null, 'one', 'two');
+ },
+ function(arg1, arg2, callback){
+ callback(null, 'three');
+ },
+ function(arg1, callback){
+ // arg1 now equals 'three'
+ callback(null, 'done');
+ }
+ ], function (err, result) {
+ // result now equals 'done'
+ });
+
+
+---------------------------------------
+
+
+### queue(worker, concurrency)
+
+Creates a queue object with the specified concurrency. Tasks added to the
+queue will be processed in parallel (up to the concurrency limit). If all
+workers are in progress, the task is queued until one is available. Once
+a worker has completed a task, the task's callback is called.
+
+__Arguments__
+
+* worker(task, callback) - An asynchronous function for processing a queued
+ task.
+* concurrency - An integer for determining how many worker functions should be
+ run in parallel.
+
+__Queue objects__
+
+The queue object returned by this function has the following properties and
+methods:
+
+* length() - a function returning the number of items waiting to be processed.
+* concurrency - an integer for determining how many worker functions should be
+ run in parallel. This property can be changed after a queue is created to
+ alter the concurrency on-the-fly.
+* push(task, [callback]) - add a new task to the queue, the callback is called
+ once the worker has finished processing the task.
+ instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.
+* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued
+* empty - a callback that is called when the last item from the queue is given to a worker
+* drain - a callback that is called when the last item from the queue has returned from the worker
+
+__Example__
+
+ // create a queue object with concurrency 2
+
+ var q = async.queue(function (task, callback) {
+ console.log('hello ' + task.name);
+ callback();
+ }, 2);
+
+
+ // assign a callback
+ q.drain = function() {
+ console.log('all items have been processed');
+ }
+
+ // add some items to the queue
+
+ q.push({name: 'foo'}, function (err) {
+ console.log('finished processing foo');
+ });
+ q.push({name: 'bar'}, function (err) {
+ console.log('finished processing bar');
+ });
+
+ // add some items to the queue (batch-wise)
+
+ q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {
+ console.log('finished processing bar');
+ });
+
+
+---------------------------------------
+
+
+### auto(tasks, [callback])
+
+Determines the best order for running functions based on their requirements.
+Each function can optionally depend on other functions being completed first,
+and each function is run as soon as its requirements are satisfied. If any of
+the functions pass an error to their callback, that function will not complete
+(so any other functions depending on it will not run) and the main callback
+will be called immediately with the error. Functions also receive an object
+containing the results of functions which have completed so far.
+
+__Arguments__
+
+* tasks - An object literal containing named functions or an array of
+ requirements, with the function itself the last item in the array. The key
+ used for each function or array is used when specifying requirements. The
+ syntax is easier to understand by looking at the example.
+* callback(err, results) - An optional callback which is called when all the
+ tasks have been completed. The callback will receive an error as an argument
+ if any tasks pass an error to their callback. If all tasks complete
+ successfully, it will receive an object containing their results.
+
+__Example__
+
+ async.auto({
+ get_data: function(callback){
+ // async code to get some data
+ },
+ make_folder: function(callback){
+ // async code to create a directory to store a file in
+ // this is run at the same time as getting the data
+ },
+ write_file: ['get_data', 'make_folder', function(callback){
+ // once there is some data and the directory exists,
+ // write the data to a file in the directory
+ callback(null, filename);
+ }],
+ email_link: ['write_file', function(callback, results){
+ // once the file is written let's email a link to it...
+ // results.write_file contains the filename returned by write_file.
+ }]
+ });
+
+This is a fairly trivial example, but to do this using the basic parallel and
+series functions would look like this:
+
+ async.parallel([
+ function(callback){
+ // async code to get some data
+ },
+ function(callback){
+ // async code to create a directory to store a file in
+ // this is run at the same time as getting the data
+ }
+ ],
+ function(results){
+ async.series([
+ function(callback){
+ // once there is some data and the directory exists,
+ // write the data to a file in the directory
+ },
+ email_link: function(callback){
+ // once the file is written let's email a link to it...
+ }
+ ]);
+ });
+
+For a complicated series of async tasks using the auto function makes adding
+new tasks much easier and makes the code more readable.
+
+
+---------------------------------------
+
+
+### iterator(tasks)
+
+Creates an iterator function which calls the next function in the array,
+returning a continuation to call the next one after that. Its also possible to
+'peek' the next iterator by doing iterator.next().
+
+This function is used internally by the async module but can be useful when
+you want to manually control the flow of functions in series.
+
+__Arguments__
+
+* tasks - An array of functions to run, each function is passed a callback it
+ must call on completion.
+
+__Example__
+
+ var iterator = async.iterator([
+ function(){ sys.p('one'); },
+ function(){ sys.p('two'); },
+ function(){ sys.p('three'); }
+ ]);
+
+ node> var iterator2 = iterator();
+ 'one'
+ node> var iterator3 = iterator2();
+ 'two'
+ node> iterator3();
+ 'three'
+ node> var nextfn = iterator2.next();
+ node> nextfn();
+ 'three'
+
+
+---------------------------------------
+
+
+### apply(function, arguments..)
+
+Creates a continuation function with some arguments already applied, a useful
+shorthand when combined with other control flow functions. Any arguments
+passed to the returned function are added to the arguments originally passed
+to apply.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to automatically apply when the
+ continuation is called.
+
+__Example__
+
+ // using apply
+
+ async.parallel([
+ async.apply(fs.writeFile, 'testfile1', 'test1'),
+ async.apply(fs.writeFile, 'testfile2', 'test2'),
+ ]);
+
+
+ // the same process without using apply
+
+ async.parallel([
+ function(callback){
+ fs.writeFile('testfile1', 'test1', callback);
+ },
+ function(callback){
+ fs.writeFile('testfile2', 'test2', callback);
+ },
+ ]);
+
+It's possible to pass any number of additional arguments when calling the
+continuation:
+
+ node> var fn = async.apply(sys.puts, 'one');
+ node> fn('two', 'three');
+ one
+ two
+ three
+
+---------------------------------------
+
+
+### nextTick(callback)
+
+Calls the callback on a later loop around the event loop. In node.js this just
+calls process.nextTick, in the browser it falls back to setTimeout(callback, 0),
+which means other higher priority events may precede the execution of the callback.
+
+This is used internally for browser-compatibility purposes.
+
+__Arguments__
+
+* callback - The function to call on a later loop around the event loop.
+
+__Example__
+
+ var call_order = [];
+ async.nextTick(function(){
+ call_order.push('two');
+ // call_order now equals ['one','two]
+ });
+ call_order.push('one')
+
+
+## Utils
+
+
+### memoize(fn, [hasher])
+
+Caches the results of an async function. When creating a hash to store function
+results against, the callback is omitted from the hash and an optional hash
+function can be used.
+
+__Arguments__
+
+* fn - the function you to proxy and cache results from.
+* hasher - an optional function for generating a custom hash for storing
+ results, it has all the arguments applied to it apart from the callback, and
+ must be synchronous.
+
+__Example__
+
+ var slow_fn = function (name, callback) {
+ // do something
+ callback(null, result);
+ };
+ var fn = async.memoize(slow_fn);
+
+ // fn can now be used as if it were slow_fn
+ fn('some name', function () {
+ // callback
+ });
+
+
+### unmemoize(fn)
+
+Undoes a memoized function, reverting it to the original, unmemoized
+form. Comes handy in tests.
+
+__Arguments__
+
+* fn - the memoized function
+
+
+### log(function, arguments)
+
+Logs the result of an async function to the console. Only works in node.js or
+in browsers that support console.log and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.log is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+ var hello = function(name, callback){
+ setTimeout(function(){
+ callback(null, 'hello ' + name);
+ }, 1000);
+ };
+
+ node> async.log(hello, 'world');
+ 'hello world'
+
+
+---------------------------------------
+
+
+### dir(function, arguments)
+
+Logs the result of an async function to the console using console.dir to
+display the properties of the resulting object. Only works in node.js or
+in browsers that support console.dir and console.error (such as FF and Chrome).
+If multiple arguments are returned from the async function, console.dir is
+called on each argument in order.
+
+__Arguments__
+
+* function - The function you want to eventually apply all arguments to.
+* arguments... - Any number of arguments to apply to the function.
+
+__Example__
+
+ var hello = function(name, callback){
+ setTimeout(function(){
+ callback(null, {hello: name});
+ }, 1000);
+ };
+
+ node> async.dir(hello, 'world');
+ {hello: 'world'}
+
+
+---------------------------------------
+
+
+### noConflict()
+
+Changes the value of async back to its original value, returning a reference to the
+async object.
diff --git a/test/node_modules/async/index.js b/test/node_modules/async/index.js
new file mode 100644
index 0000000..8e23845
--- /dev/null
+++ b/test/node_modules/async/index.js
@@ -0,0 +1,3 @@
+// This file is just added for convenience so this repository can be
+// directly checked out into a project's deps folder
+module.exports = require('./lib/async');
diff --git a/test/node_modules/async/lib/async.js b/test/node_modules/async/lib/async.js
new file mode 100644
index 0000000..7cc4f5e
--- /dev/null
+++ b/test/node_modules/async/lib/async.js
@@ -0,0 +1,692 @@
+/*global setTimeout: false, console: false */
+(function () {
+
+ var async = {};
+
+ // global on the server, window in the browser
+ var root = this,
+ previous_async = root.async;
+
+ if (typeof module !== 'undefined' && module.exports) {
+ module.exports = async;
+ }
+ else {
+ root.async = async;
+ }
+
+ async.noConflict = function () {
+ root.async = previous_async;
+ return async;
+ };
+
+ //// cross-browser compatiblity functions ////
+
+ var _forEach = function (arr, iterator) {
+ if (arr.forEach) {
+ return arr.forEach(iterator);
+ }
+ for (var i = 0; i < arr.length; i += 1) {
+ iterator(arr[i], i, arr);
+ }
+ };
+
+ var _map = function (arr, iterator) {
+ if (arr.map) {
+ return arr.map(iterator);
+ }
+ var results = [];
+ _forEach(arr, function (x, i, a) {
+ results.push(iterator(x, i, a));
+ });
+ return results;
+ };
+
+ var _reduce = function (arr, iterator, memo) {
+ if (arr.reduce) {
+ return arr.reduce(iterator, memo);
+ }
+ _forEach(arr, function (x, i, a) {
+ memo = iterator(memo, x, i, a);
+ });
+ return memo;
+ };
+
+ var _keys = function (obj) {
+ if (Object.keys) {
+ return Object.keys(obj);
+ }
+ var keys = [];
+ for (var k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ keys.push(k);
+ }
+ }
+ return keys;
+ };
+
+ //// exported async module functions ////
+
+ //// nextTick implementation with browser-compatible fallback ////
+ if (typeof process === 'undefined' || !(process.nextTick)) {
+ async.nextTick = function (fn) {
+ setTimeout(fn, 0);
+ };
+ }
+ else {
+ async.nextTick = process.nextTick;
+ }
+
+ async.forEach = function (arr, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length) {
+ return callback();
+ }
+ var completed = 0;
+ _forEach(arr, function (x) {
+ iterator(x, function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ if (completed === arr.length) {
+ callback(null);
+ }
+ }
+ });
+ });
+ };
+
+ async.forEachSeries = function (arr, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length) {
+ return callback();
+ }
+ var completed = 0;
+ var iterate = function () {
+ iterator(arr[completed], function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ if (completed === arr.length) {
+ callback(null);
+ }
+ else {
+ iterate();
+ }
+ }
+ });
+ };
+ iterate();
+ };
+
+ async.forEachLimit = function (arr, limit, iterator, callback) {
+ callback = callback || function () {};
+ if (!arr.length || limit <= 0) {
+ return callback();
+ }
+ var completed = 0;
+ var started = 0;
+ var running = 0;
+
+ (function replenish () {
+ if (completed === arr.length) {
+ return callback();
+ }
+
+ while (running < limit && started < arr.length) {
+ started += 1;
+ running += 1;
+ iterator(arr[started - 1], function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ completed += 1;
+ running -= 1;
+ if (completed === arr.length) {
+ callback();
+ }
+ else {
+ replenish();
+ }
+ }
+ });
+ }
+ })();
+ };
+
+
+ var doParallel = function (fn) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [async.forEach].concat(args));
+ };
+ };
+ var doSeries = function (fn) {
+ return function () {
+ var args = Array.prototype.slice.call(arguments);
+ return fn.apply(null, [async.forEachSeries].concat(args));
+ };
+ };
+
+
+ var _asyncMap = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (err, v) {
+ results[x.index] = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ };
+ async.map = doParallel(_asyncMap);
+ async.mapSeries = doSeries(_asyncMap);
+
+
+ // reduce only has a series version, as doing reduce in parallel won't
+ // work in many situations.
+ async.reduce = function (arr, memo, iterator, callback) {
+ async.forEachSeries(arr, function (x, callback) {
+ iterator(memo, x, function (err, v) {
+ memo = v;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, memo);
+ });
+ };
+ // inject alias
+ async.inject = async.reduce;
+ // foldl alias
+ async.foldl = async.reduce;
+
+ async.reduceRight = function (arr, memo, iterator, callback) {
+ var reversed = _map(arr, function (x) {
+ return x;
+ }).reverse();
+ async.reduce(reversed, memo, iterator, callback);
+ };
+ // foldr alias
+ async.foldr = async.reduceRight;
+
+ var _filter = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (v) {
+ if (v) {
+ results.push(x);
+ }
+ callback();
+ });
+ }, function (err) {
+ callback(_map(results.sort(function (a, b) {
+ return a.index - b.index;
+ }), function (x) {
+ return x.value;
+ }));
+ });
+ };
+ async.filter = doParallel(_filter);
+ async.filterSeries = doSeries(_filter);
+ // select alias
+ async.select = async.filter;
+ async.selectSeries = async.filterSeries;
+
+ var _reject = function (eachfn, arr, iterator, callback) {
+ var results = [];
+ arr = _map(arr, function (x, i) {
+ return {index: i, value: x};
+ });
+ eachfn(arr, function (x, callback) {
+ iterator(x.value, function (v) {
+ if (!v) {
+ results.push(x);
+ }
+ callback();
+ });
+ }, function (err) {
+ callback(_map(results.sort(function (a, b) {
+ return a.index - b.index;
+ }), function (x) {
+ return x.value;
+ }));
+ });
+ };
+ async.reject = doParallel(_reject);
+ async.rejectSeries = doSeries(_reject);
+
+ var _detect = function (eachfn, arr, iterator, main_callback) {
+ eachfn(arr, function (x, callback) {
+ iterator(x, function (result) {
+ if (result) {
+ main_callback(x);
+ main_callback = function () {};
+ }
+ else {
+ callback();
+ }
+ });
+ }, function (err) {
+ main_callback();
+ });
+ };
+ async.detect = doParallel(_detect);
+ async.detectSeries = doSeries(_detect);
+
+ async.some = function (arr, iterator, main_callback) {
+ async.forEach(arr, function (x, callback) {
+ iterator(x, function (v) {
+ if (v) {
+ main_callback(true);
+ main_callback = function () {};
+ }
+ callback();
+ });
+ }, function (err) {
+ main_callback(false);
+ });
+ };
+ // any alias
+ async.any = async.some;
+
+ async.every = function (arr, iterator, main_callback) {
+ async.forEach(arr, function (x, callback) {
+ iterator(x, function (v) {
+ if (!v) {
+ main_callback(false);
+ main_callback = function () {};
+ }
+ callback();
+ });
+ }, function (err) {
+ main_callback(true);
+ });
+ };
+ // all alias
+ async.all = async.every;
+
+ async.sortBy = function (arr, iterator, callback) {
+ async.map(arr, function (x, callback) {
+ iterator(x, function (err, criteria) {
+ if (err) {
+ callback(err);
+ }
+ else {
+ callback(null, {value: x, criteria: criteria});
+ }
+ });
+ }, function (err, results) {
+ if (err) {
+ return callback(err);
+ }
+ else {
+ var fn = function (left, right) {
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
+ };
+ callback(null, _map(results.sort(fn), function (x) {
+ return x.value;
+ }));
+ }
+ });
+ };
+
+ async.auto = function (tasks, callback) {
+ callback = callback || function () {};
+ var keys = _keys(tasks);
+ if (!keys.length) {
+ return callback(null);
+ }
+
+ var results = {};
+
+ var listeners = [];
+ var addListener = function (fn) {
+ listeners.unshift(fn);
+ };
+ var removeListener = function (fn) {
+ for (var i = 0; i < listeners.length; i += 1) {
+ if (listeners[i] === fn) {
+ listeners.splice(i, 1);
+ return;
+ }
+ }
+ };
+ var taskComplete = function () {
+ _forEach(listeners.slice(0), function (fn) {
+ fn();
+ });
+ };
+
+ addListener(function () {
+ if (_keys(results).length === keys.length) {
+ callback(null, results);
+ callback = function () {};
+ }
+ });
+
+ _forEach(keys, function (k) {
+ var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
+ var taskCallback = function (err) {
+ if (err) {
+ callback(err);
+ // stop subsequent errors hitting callback multiple times
+ callback = function () {};
+ }
+ else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ taskComplete();
+ }
+ };
+ var requires = task.slice(0, Math.abs(task.length - 1)) || [];
+ var ready = function () {
+ return _reduce(requires, function (a, x) {
+ return (a && results.hasOwnProperty(x));
+ }, true) && !results.hasOwnProperty(k);
+ };
+ if (ready()) {
+ task[task.length - 1](taskCallback, results);
+ }
+ else {
+ var listener = function () {
+ if (ready()) {
+ removeListener(listener);
+ task[task.length - 1](taskCallback, results);
+ }
+ };
+ addListener(listener);
+ }
+ });
+ };
+
+ async.waterfall = function (tasks, callback) {
+ callback = callback || function () {};
+ if (!tasks.length) {
+ return callback();
+ }
+ var wrapIterator = function (iterator) {
+ return function (err) {
+ if (err) {
+ callback(err);
+ callback = function () {};
+ }
+ else {
+ var args = Array.prototype.slice.call(arguments, 1);
+ var next = iterator.next();
+ if (next) {
+ args.push(wrapIterator(next));
+ }
+ else {
+ args.push(callback);
+ }
+ async.nextTick(function () {
+ iterator.apply(null, args);
+ });
+ }
+ };
+ };
+ wrapIterator(async.iterator(tasks))();
+ };
+
+ async.parallel = function (tasks, callback) {
+ callback = callback || function () {};
+ if (tasks.constructor === Array) {
+ async.map(tasks, function (fn, callback) {
+ if (fn) {
+ fn(function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ callback.call(null, err, args);
+ });
+ }
+ }, callback);
+ }
+ else {
+ var results = {};
+ async.forEach(_keys(tasks), function (k, callback) {
+ tasks[k](function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ }
+ };
+
+ async.series = function (tasks, callback) {
+ callback = callback || function () {};
+ if (tasks.constructor === Array) {
+ async.mapSeries(tasks, function (fn, callback) {
+ if (fn) {
+ fn(function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ callback.call(null, err, args);
+ });
+ }
+ }, callback);
+ }
+ else {
+ var results = {};
+ async.forEachSeries(_keys(tasks), function (k, callback) {
+ tasks[k](function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (args.length <= 1) {
+ args = args[0];
+ }
+ results[k] = args;
+ callback(err);
+ });
+ }, function (err) {
+ callback(err, results);
+ });
+ }
+ };
+
+ async.iterator = function (tasks) {
+ var makeCallback = function (index) {
+ var fn = function () {
+ if (tasks.length) {
+ tasks[index].apply(null, arguments);
+ }
+ return fn.next();
+ };
+ fn.next = function () {
+ return (index < tasks.length - 1) ? makeCallback(index + 1): null;
+ };
+ return fn;
+ };
+ return makeCallback(0);
+ };
+
+ async.apply = function (fn) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ return function () {
+ return fn.apply(
+ null, args.concat(Array.prototype.slice.call(arguments))
+ );
+ };
+ };
+
+ var _concat = function (eachfn, arr, fn, callback) {
+ var r = [];
+ eachfn(arr, function (x, cb) {
+ fn(x, function (err, y) {
+ r = r.concat(y || []);
+ cb(err);
+ });
+ }, function (err) {
+ callback(err, r);
+ });
+ };
+ async.concat = doParallel(_concat);
+ async.concatSeries = doSeries(_concat);
+
+ async.whilst = function (test, iterator, callback) {
+ if (test()) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ async.whilst(test, iterator, callback);
+ });
+ }
+ else {
+ callback();
+ }
+ };
+
+ async.until = function (test, iterator, callback) {
+ if (!test()) {
+ iterator(function (err) {
+ if (err) {
+ return callback(err);
+ }
+ async.until(test, iterator, callback);
+ });
+ }
+ else {
+ callback();
+ }
+ };
+
+ async.queue = function (worker, concurrency) {
+ var workers = 0;
+ var q = {
+ tasks: [],
+ concurrency: concurrency,
+ saturated: null,
+ empty: null,
+ drain: null,
+ push: function (data, callback) {
+ if(data.constructor !== Array) {
+ data = [data];
+ }
+ _forEach(data, function(task) {
+ q.tasks.push({
+ data: task,
+ callback: typeof callback === 'function' ? callback : null
+ });
+ if (q.saturated && q.tasks.length == concurrency) {
+ q.saturated();
+ }
+ async.nextTick(q.process);
+ });
+ },
+ process: function () {
+ if (workers < q.concurrency && q.tasks.length) {
+ var task = q.tasks.shift();
+ if(q.empty && q.tasks.length == 0) q.empty();
+ workers += 1;
+ worker(task.data, function () {
+ workers -= 1;
+ if (task.callback) {
+ task.callback.apply(task, arguments);
+ }
+ if(q.drain && q.tasks.length + workers == 0) q.drain();
+ q.process();
+ });
+ }
+ },
+ length: function () {
+ return q.tasks.length;
+ },
+ running: function () {
+ return workers;
+ }
+ };
+ return q;
+ };
+
+ var _console_fn = function (name) {
+ return function (fn) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ fn.apply(null, args.concat([function (err) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ if (typeof console !== 'undefined') {
+ if (err) {
+ if (console.error) {
+ console.error(err);
+ }
+ }
+ else if (console[name]) {
+ _forEach(args, function (x) {
+ console[name](x);
+ });
+ }
+ }
+ }]));
+ };
+ };
+ async.log = _console_fn('log');
+ async.dir = _console_fn('dir');
+ /*async.info = _console_fn('info');
+ async.warn = _console_fn('warn');
+ async.error = _console_fn('error');*/
+
+ async.memoize = function (fn, hasher) {
+ var memo = {};
+ var queues = {};
+ hasher = hasher || function (x) {
+ return x;
+ };
+ var memoized = function () {
+ var args = Array.prototype.slice.call(arguments);
+ var callback = args.pop();
+ var key = hasher.apply(null, args);
+ if (key in memo) {
+ callback.apply(null, memo[key]);
+ }
+ else if (key in queues) {
+ queues[key].push(callback);
+ }
+ else {
+ queues[key] = [callback];
+ fn.apply(null, args.concat([function () {
+ memo[key] = arguments;
+ var q = queues[key];
+ delete queues[key];
+ for (var i = 0, l = q.length; i < l; i++) {
+ q[i].apply(null, arguments);
+ }
+ }]));
+ }
+ };
+ memoized.unmemoized = fn;
+ return memoized;
+ };
+
+ async.unmemoize = function (fn) {
+ return function () {
+ return (fn.unmemoized || fn).apply(null, arguments);
+ };
+ };
+
+}());
diff --git a/test/node_modules/async/package.json b/test/node_modules/async/package.json
new file mode 100644
index 0000000..6c13362
--- /dev/null
+++ b/test/node_modules/async/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "async",
+ "description": "Higher-order functions and common patterns for asynchronous code",
+ "main": "./index",
+ "author": {
+ "name": "Caolan McMahon"
+ },
+ "version": "0.1.22",
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/caolan/async.git"
+ },
+ "bugs": {
+ "url": "http://github.com/caolan/async/issues"
+ },
+ "licenses": [
+ {
+ "type": "MIT",
+ "url": "http://github.com/caolan/async/raw/master/LICENSE"
+ }
+ ],
+ "devDependencies": {
+ "nodeunit": ">0.0.0",
+ "uglify-js": "1.2.x",
+ "nodelint": ">0.0.0"
+ },
+ "readme": "# Async.js\n\nAsync is a utility module which provides straight-forward, powerful functions\nfor working with asynchronous JavaScript. Although originally designed for\nuse with [node.js](http://nodejs.org), it can also be used directly in the\nbrowser.\n\nAsync provides around 20 functions that include the usual 'functional'\nsuspects (map, reduce, filter, forEach…) as well as some common patterns\nfor asynchronous control flow (parallel, series, waterfall…). All these\nfunctions assume you follow the node.js convention of providing a single\ncallback as the last argument of your async function.\n\n\n## Quick Examples\n\n async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n async.parallel([\n function(){ ... },\n function(){ ... }\n ], callback);\n\n async.series([\n function(){ ... },\n function(){ ... }\n ]);\n\nThere are many more functions available so take a look at the docs below for a\nfull list. This module aims to be comprehensive, so if you feel anything is\nmissing please create a GitHub issue for it.\n\n\n## Download\n\nReleases are available for download from\n[GitHub](http://github.com/caolan/async/downloads).\nAlternatively, you can install using Node Package Manager (npm):\n\n npm install async\n\n\n__Development:__ [async.js](https://github.com/caolan/async/raw/master/lib/async.js) - 17.5kb Uncompressed\n\n__Production:__ [async.min.js](https://github.com/caolan/async/raw/master/dist/async.min.js) - 1.7kb Packed and Gzipped\n\n\n## In the Browser\n\nSo far its been tested in IE6, IE7, IE8, FF3.6 and Chrome 5. Usage:\n\n \n \n\n\n## Documentation\n\n### Collections\n\n* [forEach](#forEach)\n* [map](#map)\n* [filter](#filter)\n* [reject](#reject)\n* [reduce](#reduce)\n* [detect](#detect)\n* [sortBy](#sortBy)\n* [some](#some)\n* [every](#every)\n* [concat](#concat)\n\n### Control Flow\n\n* [series](#series)\n* [parallel](#parallel)\n* [whilst](#whilst)\n* [until](#until)\n* [waterfall](#waterfall)\n* [queue](#queue)\n* [auto](#auto)\n* [iterator](#iterator)\n* [apply](#apply)\n* [nextTick](#nextTick)\n\n### Utils\n\n* [memoize](#memoize)\n* [unmemoize](#unmemoize)\n* [log](#log)\n* [dir](#dir)\n* [noConflict](#noConflict)\n\n\n## Collections\n\n\n### forEach(arr, iterator, callback)\n\nApplies an iterator function to each item in an array, in parallel.\nThe iterator is called with an item from the list and a callback for when it\nhas finished. If the iterator passes an error to this callback, the main\ncallback for the forEach function is immediately called with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // assuming openFiles is an array of file names and saveFile is a function\n // to save the modified contents of that file:\n\n async.forEach(openFiles, saveFile, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n\n---------------------------------------\n\n\n### forEachSeries(arr, iterator, callback)\n\nThe same as forEach only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. This means the iterator functions will complete in order.\n\n\n---------------------------------------\n\n\n### forEachLimit(arr, limit, iterator, callback)\n\nThe same as forEach only the iterator is applied to batches of items in the\narray, in series. The next batch of iterators is only called once the current\none has completed processing.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* limit - How many items should be in each batch.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(err) - A callback which is called after all the iterator functions\n have finished, or an error has occurred.\n\n__Example__\n\n // Assume documents is an array of JSON objects and requestApi is a\n // function that interacts with a rate-limited REST api.\n\n async.forEachLimit(documents, 20, requestApi, function(err){\n // if any of the saves produced an error, err would equal that error\n });\n---------------------------------------\n\n\n### map(arr, iterator, callback)\n\nProduces a new array of values by mapping each value in the given array through\nthe iterator function. The iterator is called with an item from the array and a\ncallback for when it has finished processing. The callback takes 2 arguments, \nan error and the transformed item from the array. If the iterator passes an\nerror to this callback, the main callback for the map function is immediately\ncalled with the error.\n\nNote, that since this function applies the iterator to each item in parallel\nthere is no guarantee that the iterator functions will complete in order, however\nthe results array will be in the same order as the original array.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a transformed item.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array of the\n transformed items from the original array.\n\n__Example__\n\n async.map(['file1','file2','file3'], fs.stat, function(err, results){\n // results is now an array of stats for each file\n });\n\n---------------------------------------\n\n\n### mapSeries(arr, iterator, callback)\n\nThe same as map only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n\n---------------------------------------\n\n\n### filter(arr, iterator, callback)\n\n__Alias:__ select\n\nReturns a new array of all the values which pass an async truth test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. This operation is\nperformed in parallel, but the results array will be in the same order as the\noriginal.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(results) - A callback which is called after all the iterator\n functions have finished.\n\n__Example__\n\n async.filter(['file1','file2','file3'], path.exists, function(results){\n // results now equals an array of the existing files\n });\n\n---------------------------------------\n\n\n### filterSeries(arr, iterator, callback)\n\n__alias:__ selectSeries\n\nThe same as filter only the iterator is applied to each item in the array in\nseries. The next iterator is only called once the current one has completed\nprocessing. The results array will be in the same order as the original.\n\n---------------------------------------\n\n\n### reject(arr, iterator, callback)\n\nThe opposite of filter. Removes values that pass an async truth test.\n\n---------------------------------------\n\n\n### rejectSeries(arr, iterator, callback)\n\nThe same as filter, only the iterator is applied to each item in the array\nin series.\n\n\n---------------------------------------\n\n\n### reduce(arr, memo, iterator, callback)\n\n__aliases:__ inject, foldl\n\nReduces a list of values into a single value using an async iterator to return\neach successive step. Memo is the initial state of the reduction. This\nfunction only operates in series. For performance reasons, it may make sense to\nsplit a call to this function into a parallel map, then use the normal\nArray.prototype.reduce on the results. This function is for situations where\neach step in the reduction needs to be async, if you can get the data before\nreducing it then its probably a good idea to do so.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* memo - The initial state of the reduction.\n* iterator(memo, item, callback) - A function applied to each item in the\n array to produce the next step in the reduction. The iterator is passed a\n callback which accepts an optional error as its first argument, and the state\n of the reduction as the second. If an error is passed to the callback, the\n reduction is stopped and the main callback is immediately called with the\n error.\n* callback(err, result) - A callback which is called after all the iterator\n functions have finished. Result is the reduced value.\n\n__Example__\n\n async.reduce([1,2,3], 0, function(memo, item, callback){\n // pointless async:\n process.nextTick(function(){\n callback(null, memo + item)\n });\n }, function(err, result){\n // result is now equal to the last value of memo, which is 6\n });\n\n---------------------------------------\n\n\n### reduceRight(arr, memo, iterator, callback)\n\n__Alias:__ foldr\n\nSame as reduce, only operates on the items in the array in reverse order.\n\n\n---------------------------------------\n\n\n### detect(arr, iterator, callback)\n\nReturns the first value in a list that passes an async truth test. The\niterator is applied in parallel, meaning the first iterator to return true will\nfire the detect callback with that result. That means the result might not be\nthe first item in the original array (in terms of order) that passes the test.\n\nIf order within the original array is important then look at detectSeries.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n the first item in the array that passes the truth test (iterator) or the\n value undefined if none passed.\n\n__Example__\n\n async.detect(['file1','file2','file3'], path.exists, function(result){\n // result now equals the first file in the list that exists\n });\n\n---------------------------------------\n\n\n### detectSeries(arr, iterator, callback)\n\nThe same as detect, only the iterator is applied to each item in the array\nin series. This means the result is always the first in the original array (in\nterms of array order) that passes the truth test.\n\n\n---------------------------------------\n\n\n### sortBy(arr, iterator, callback)\n\nSorts a list by the results of running each value through an async iterator.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and a value to use as the sort criteria.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is the items from\n the original array sorted by the values returned by the iterator calls.\n\n__Example__\n\n async.sortBy(['file1','file2','file3'], function(file, callback){\n fs.stat(file, function(err, stats){\n callback(err, stats.mtime);\n });\n }, function(err, results){\n // results is now the original array of files sorted by\n // modified date\n });\n\n\n---------------------------------------\n\n\n### some(arr, iterator, callback)\n\n__Alias:__ any\n\nReturns true if at least one element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists. Once any iterator\ncall returns true, the main callback is immediately called.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called as soon as any iterator returns\n true, or after all the iterator functions have finished. Result will be\n either true or false depending on the values of the async tests.\n\n__Example__\n\n async.some(['file1','file2','file3'], path.exists, function(result){\n // if result is true then at least one of the files exists\n });\n\n---------------------------------------\n\n\n### every(arr, iterator, callback)\n\n__Alias:__ all\n\nReturns true if every element in the array satisfies an async test.\n_The callback for each iterator call only accepts a single argument of true or\nfalse, it does not accept an error argument first!_ This is in-line with the\nway node libraries work with truth tests like path.exists.\n\n__Arguments__\n\n* arr - An array to iterate over.\n* iterator(item, callback) - A truth test to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed.\n* callback(result) - A callback which is called after all the iterator\n functions have finished. Result will be either true or false depending on\n the values of the async tests.\n\n__Example__\n\n async.every(['file1','file2','file3'], path.exists, function(result){\n // if result is true then every file exists\n });\n\n---------------------------------------\n\n\n### concat(arr, iterator, callback)\n\nApplies an iterator to each item in a list, concatenating the results. Returns the\nconcatenated list. The iterators are called in parallel, and the results are\nconcatenated as they return. There is no guarantee that the results array will\nbe returned in the original order of the arguments passed to the iterator function.\n\n__Arguments__\n\n* arr - An array to iterate over\n* iterator(item, callback) - A function to apply to each item in the array.\n The iterator is passed a callback which must be called once it has completed\n with an error (which can be null) and an array of results.\n* callback(err, results) - A callback which is called after all the iterator\n functions have finished, or an error has occurred. Results is an array containing\n the concatenated results of the iterator function.\n\n__Example__\n\n async.concat(['dir1','dir2','dir3'], fs.readdir, function(err, files){\n // files is now a list of filenames that exist in the 3 directories\n });\n\n---------------------------------------\n\n\n### concatSeries(arr, iterator, callback)\n\nSame as async.concat, but executes in series instead of parallel.\n\n\n## Control Flow\n\n\n### series(tasks, [callback])\n\nRun an array of functions in series, each one running once the previous\nfunction has completed. If any functions in the series pass an error to its\ncallback, no more functions are run and the callback for the series is\nimmediately called with the value of the error. Once the tasks have completed,\nthe results are passed to the final callback as an array.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.series.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed\n a callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.series([\n function(callback){\n // do some stuff ...\n callback(null, 'one');\n },\n function(callback){\n // do some more stuff ...\n callback(null, 'two');\n },\n ],\n // optional callback\n function(err, results){\n // results is now equal to ['one', 'two']\n });\n\n\n // an example using an object instead of an array\n async.series({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equal to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### parallel(tasks, [callback])\n\nRun an array of functions in parallel, without waiting until the previous\nfunction has completed. If any of the functions pass an error to its\ncallback, the main callback is immediately called with the value of the error.\nOnce the tasks have completed, the results are passed to the final callback as an\narray.\n\nIt is also possible to use an object instead of an array. Each property will be\nrun as a function and the results will be passed to the final callback as an object\ninstead of an array. This can be a more readable way of handling results from\nasync.parallel.\n\n\n__Arguments__\n\n* tasks - An array or object containing functions to run, each function is passed a\n callback it must call on completion.\n* callback(err, results) - An optional callback to run once all the functions\n have completed. This function gets an array of all the arguments passed to\n the callbacks used in the array.\n\n__Example__\n\n async.parallel([\n function(callback){\n setTimeout(function(){\n callback(null, 'one');\n }, 200);\n },\n function(callback){\n setTimeout(function(){\n callback(null, 'two');\n }, 100);\n },\n ],\n // optional callback\n function(err, results){\n // the results array will equal ['one','two'] even though\n // the second function had a shorter timeout.\n });\n\n\n // an example using an object instead of an array\n async.parallel({\n one: function(callback){\n setTimeout(function(){\n callback(null, 1);\n }, 200);\n },\n two: function(callback){\n setTimeout(function(){\n callback(null, 2);\n }, 100);\n },\n },\n function(err, results) {\n // results is now equals to: {one: 1, two: 2}\n });\n\n\n---------------------------------------\n\n\n### whilst(test, fn, callback)\n\nRepeatedly call fn, while test returns true. Calls the callback when stopped,\nor an error occurs.\n\n__Arguments__\n\n* test() - synchronous truth test to perform before each execution of fn.\n* fn(callback) - A function to call each time the test passes. The function is\n passed a callback which must be called once it has completed with an optional\n error as the first argument.\n* callback(err) - A callback which is called after the test fails and repeated\n execution of fn has stopped.\n\n__Example__\n\n var count = 0;\n\n async.whilst(\n function () { return count < 5; },\n function (callback) {\n count++;\n setTimeout(callback, 1000);\n },\n function (err) {\n // 5 seconds have passed\n }\n );\n\n\n---------------------------------------\n\n\n### until(test, fn, callback)\n\nRepeatedly call fn, until test returns true. Calls the callback when stopped,\nor an error occurs.\n\nThe inverse of async.whilst.\n\n\n---------------------------------------\n\n\n### waterfall(tasks, [callback])\n\nRuns an array of functions in series, each passing their results to the next in\nthe array. However, if any of the functions pass an error to the callback, the\nnext function is not executed and the main callback is immediately called with\nthe error.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n* callback(err, [results]) - An optional callback to run once all the functions\n have completed. This will be passed the results of the last task's callback.\n\n\n\n__Example__\n\n async.waterfall([\n function(callback){\n callback(null, 'one', 'two');\n },\n function(arg1, arg2, callback){\n callback(null, 'three');\n },\n function(arg1, callback){\n // arg1 now equals 'three'\n callback(null, 'done');\n }\n ], function (err, result) {\n // result now equals 'done' \n });\n\n\n---------------------------------------\n\n\n### queue(worker, concurrency)\n\nCreates a queue object with the specified concurrency. Tasks added to the\nqueue will be processed in parallel (up to the concurrency limit). If all\nworkers are in progress, the task is queued until one is available. Once\na worker has completed a task, the task's callback is called.\n\n__Arguments__\n\n* worker(task, callback) - An asynchronous function for processing a queued\n task.\n* concurrency - An integer for determining how many worker functions should be\n run in parallel.\n\n__Queue objects__\n\nThe queue object returned by this function has the following properties and\nmethods:\n\n* length() - a function returning the number of items waiting to be processed.\n* concurrency - an integer for determining how many worker functions should be\n run in parallel. This property can be changed after a queue is created to\n alter the concurrency on-the-fly.\n* push(task, [callback]) - add a new task to the queue, the callback is called\n once the worker has finished processing the task.\n instead of a single task, an array of tasks can be submitted. the respective callback is used for every task in the list.\n* saturated - a callback that is called when the queue length hits the concurrency and further tasks will be queued\n* empty - a callback that is called when the last item from the queue is given to a worker\n* drain - a callback that is called when the last item from the queue has returned from the worker\n\n__Example__\n\n // create a queue object with concurrency 2\n\n var q = async.queue(function (task, callback) {\n console.log('hello ' + task.name);\n callback();\n }, 2);\n\n\n // assign a callback\n q.drain = function() {\n console.log('all items have been processed');\n }\n\n // add some items to the queue\n\n q.push({name: 'foo'}, function (err) {\n console.log('finished processing foo');\n });\n q.push({name: 'bar'}, function (err) {\n console.log('finished processing bar');\n });\n\n // add some items to the queue (batch-wise)\n\n q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function (err) {\n console.log('finished processing bar');\n });\n\n\n---------------------------------------\n\n\n### auto(tasks, [callback])\n\nDetermines the best order for running functions based on their requirements.\nEach function can optionally depend on other functions being completed first,\nand each function is run as soon as its requirements are satisfied. If any of\nthe functions pass an error to their callback, that function will not complete\n(so any other functions depending on it will not run) and the main callback\nwill be called immediately with the error. Functions also receive an object\ncontaining the results of functions which have completed so far.\n\n__Arguments__\n\n* tasks - An object literal containing named functions or an array of\n requirements, with the function itself the last item in the array. The key\n used for each function or array is used when specifying requirements. The\n syntax is easier to understand by looking at the example.\n* callback(err, results) - An optional callback which is called when all the\n tasks have been completed. The callback will receive an error as an argument\n if any tasks pass an error to their callback. If all tasks complete\n successfully, it will receive an object containing their results.\n\n__Example__\n\n async.auto({\n get_data: function(callback){\n // async code to get some data\n },\n make_folder: function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n },\n write_file: ['get_data', 'make_folder', function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n callback(null, filename);\n }],\n email_link: ['write_file', function(callback, results){\n // once the file is written let's email a link to it...\n // results.write_file contains the filename returned by write_file.\n }]\n });\n\nThis is a fairly trivial example, but to do this using the basic parallel and\nseries functions would look like this:\n\n async.parallel([\n function(callback){\n // async code to get some data\n },\n function(callback){\n // async code to create a directory to store a file in\n // this is run at the same time as getting the data\n }\n ],\n function(results){\n async.series([\n function(callback){\n // once there is some data and the directory exists,\n // write the data to a file in the directory\n },\n email_link: function(callback){\n // once the file is written let's email a link to it...\n }\n ]);\n });\n\nFor a complicated series of async tasks using the auto function makes adding\nnew tasks much easier and makes the code more readable.\n\n\n---------------------------------------\n\n\n### iterator(tasks)\n\nCreates an iterator function which calls the next function in the array,\nreturning a continuation to call the next one after that. Its also possible to\n'peek' the next iterator by doing iterator.next().\n\nThis function is used internally by the async module but can be useful when\nyou want to manually control the flow of functions in series.\n\n__Arguments__\n\n* tasks - An array of functions to run, each function is passed a callback it\n must call on completion.\n\n__Example__\n\n var iterator = async.iterator([\n function(){ sys.p('one'); },\n function(){ sys.p('two'); },\n function(){ sys.p('three'); }\n ]);\n\n node> var iterator2 = iterator();\n 'one'\n node> var iterator3 = iterator2();\n 'two'\n node> iterator3();\n 'three'\n node> var nextfn = iterator2.next();\n node> nextfn();\n 'three'\n\n\n---------------------------------------\n\n\n### apply(function, arguments..)\n\nCreates a continuation function with some arguments already applied, a useful\nshorthand when combined with other control flow functions. Any arguments\npassed to the returned function are added to the arguments originally passed\nto apply.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to automatically apply when the\n continuation is called.\n\n__Example__\n\n // using apply\n\n async.parallel([\n async.apply(fs.writeFile, 'testfile1', 'test1'),\n async.apply(fs.writeFile, 'testfile2', 'test2'),\n ]);\n\n\n // the same process without using apply\n\n async.parallel([\n function(callback){\n fs.writeFile('testfile1', 'test1', callback);\n },\n function(callback){\n fs.writeFile('testfile2', 'test2', callback);\n },\n ]);\n\nIt's possible to pass any number of additional arguments when calling the\ncontinuation:\n\n node> var fn = async.apply(sys.puts, 'one');\n node> fn('two', 'three');\n one\n two\n three\n\n---------------------------------------\n\n\n### nextTick(callback)\n\nCalls the callback on a later loop around the event loop. In node.js this just\ncalls process.nextTick, in the browser it falls back to setTimeout(callback, 0),\nwhich means other higher priority events may precede the execution of the callback.\n\nThis is used internally for browser-compatibility purposes.\n\n__Arguments__\n\n* callback - The function to call on a later loop around the event loop.\n\n__Example__\n\n var call_order = [];\n async.nextTick(function(){\n call_order.push('two');\n // call_order now equals ['one','two]\n });\n call_order.push('one')\n\n\n## Utils\n\n\n### memoize(fn, [hasher])\n\nCaches the results of an async function. When creating a hash to store function\nresults against, the callback is omitted from the hash and an optional hash\nfunction can be used.\n\n__Arguments__\n\n* fn - the function you to proxy and cache results from.\n* hasher - an optional function for generating a custom hash for storing\n results, it has all the arguments applied to it apart from the callback, and\n must be synchronous.\n\n__Example__\n\n var slow_fn = function (name, callback) {\n // do something\n callback(null, result);\n };\n var fn = async.memoize(slow_fn);\n\n // fn can now be used as if it were slow_fn\n fn('some name', function () {\n // callback\n });\n\n\n### unmemoize(fn)\n\nUndoes a memoized function, reverting it to the original, unmemoized\nform. Comes handy in tests.\n\n__Arguments__\n\n* fn - the memoized function\n\n\n### log(function, arguments)\n\nLogs the result of an async function to the console. Only works in node.js or\nin browsers that support console.log and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.log is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, 'hello ' + name);\n }, 1000);\n };\n\n node> async.log(hello, 'world');\n 'hello world'\n\n\n---------------------------------------\n\n\n### dir(function, arguments)\n\nLogs the result of an async function to the console using console.dir to\ndisplay the properties of the resulting object. Only works in node.js or\nin browsers that support console.dir and console.error (such as FF and Chrome).\nIf multiple arguments are returned from the async function, console.dir is\ncalled on each argument in order.\n\n__Arguments__\n\n* function - The function you want to eventually apply all arguments to.\n* arguments... - Any number of arguments to apply to the function.\n\n__Example__\n\n var hello = function(name, callback){\n setTimeout(function(){\n callback(null, {hello: name});\n }, 1000);\n };\n\n node> async.dir(hello, 'world');\n {hello: 'world'}\n\n\n---------------------------------------\n\n\n### noConflict()\n\nChanges the value of async back to its original value, returning a reference to the\nasync object.\n",
+ "readmeFilename": "README.md",
+ "_id": "async@0.1.22",
+ "dist": {
+ "shasum": "79440029ca3d7d81f698478a2a6a2aa52f0cda22"
+ },
+ "_from": "async@0.1.22"
+}
diff --git a/test/node_modules/express/.npmignore b/test/node_modules/express/.npmignore
new file mode 100644
index 0000000..74bd365
--- /dev/null
+++ b/test/node_modules/express/.npmignore
@@ -0,0 +1,7 @@
+.git*
+docs/
+examples/
+support/
+test/
+testing.js
+.DS_Store
diff --git a/test/node_modules/express/History.md b/test/node_modules/express/History.md
new file mode 100644
index 0000000..95ea466
--- /dev/null
+++ b/test/node_modules/express/History.md
@@ -0,0 +1,823 @@
+
+2.5.11 / 2012-06-29
+==================
+
+ * Fixed backport of req.protocol
+
+2.5.10 / 2012-06-15
+==================
+
+ * Remove annoying engines field from package.json
+ * Backport support for trusting X-Forwarded-Proto
+ * use version of `package.json` for `express` command
+
+2.5.9/ 2012-04-02
+==================
+
+ * Added support for PURGE request method [pbuyle]
+ * Fixed `express(1)` generated app `app.address()` before `listening` [mmalecki]
+
+2.5.8 / 2012-02-08
+==================
+
+ * Update mkdirp dep. Closes #991
+
+2.5.7 / 2012-02-06
+==================
+
+ * Fixed `app.all` duplicate DELETE requests [mscdex]
+
+2.5.6 / 2012-01-13
+==================
+
+ * Updated hamljs dev dep. Closes #953
+
+2.5.5 / 2012-01-08
+==================
+
+ * Fixed: set `filename` on cached templates [matthewleon]
+
+2.5.4 / 2012-01-02
+==================
+
+ * Fixed `express(1)` eol on 0.4.x. Closes #947
+
+2.5.3 / 2011-12-30
+==================
+
+ * Fixed `req.is()` when a charset is present
+
+2.5.2 / 2011-12-10
+==================
+
+ * Fixed: express(1) LF -> CRLF for windows
+
+2.5.1 / 2011-11-17
+==================
+
+ * Changed: updated connect to 1.8.x
+ * Removed sass.js support from express(1)
+
+2.5.0 / 2011-10-24
+==================
+
+ * Added ./routes dir for generated app by default
+ * Added npm install reminder to express(1) app gen
+ * Added 0.5.x support
+ * Removed `make test-cov` since it wont work with node 0.5.x
+ * Fixed express(1) public dir for windows. Closes #866
+
+2.4.7 / 2011-10-05
+==================
+
+ * Added mkdirp to express(1). Closes #795
+ * Added simple _json-config_ example
+ * Added shorthand for the parsed request's pathname via `req.path`
+ * Changed connect dep to 1.7.x to fix npm issue...
+ * Fixed `res.redirect()` __HEAD__ support. [reported by xerox]
+ * Fixed `req.flash()`, only escape args
+ * Fixed absolute path checking on windows. Closes #829 [reported by andrewpmckenzie]
+
+2.4.6 / 2011-08-22
+==================
+
+ * Fixed multiple param callback regression. Closes #824 [reported by TroyGoode]
+
+2.4.5 / 2011-08-19
+==================
+
+ * Added support for routes to handle errors. Closes #809
+ * Added `app.routes.all()`. Closes #803
+ * Added "basepath" setting to work in conjunction with reverse proxies etc.
+ * Refactored `Route` to use a single array of callbacks
+ * Added support for multiple callbacks for `app.param()`. Closes #801
+Closes #805
+ * Changed: removed .call(self) for route callbacks
+ * Dependency: `qs >= 0.3.1`
+ * Fixed `res.redirect()` on windows due to `join()` usage. Closes #808
+
+2.4.4 / 2011-08-05
+==================
+
+ * Fixed `res.header()` intention of a set, even when `undefined`
+ * Fixed `*`, value no longer required
+ * Fixed `res.send(204)` support. Closes #771
+
+2.4.3 / 2011-07-14
+==================
+
+ * Added docs for `status` option special-case. Closes #739
+ * Fixed `options.filename`, exposing the view path to template engines
+
+2.4.2. / 2011-07-06
+==================
+
+ * Revert "removed jsonp stripping" for XSS
+
+2.4.1 / 2011-07-06
+==================
+
+ * Added `res.json()` JSONP support. Closes #737
+ * Added _extending-templates_ example. Closes #730
+ * Added "strict routing" setting for trailing slashes
+ * Added support for multiple envs in `app.configure()` calls. Closes #735
+ * Changed: `res.send()` using `res.json()`
+ * Changed: when cookie `path === null` don't default it
+ * Changed; default cookie path to "home" setting. Closes #731
+ * Removed _pids/logs_ creation from express(1)
+
+2.4.0 / 2011-06-28
+==================
+
+ * Added chainable `res.status(code)`
+ * Added `res.json()`, an explicit version of `res.send(obj)`
+ * Added simple web-service example
+
+2.3.12 / 2011-06-22
+==================
+
+ * \#express is now on freenode! come join!
+ * Added `req.get(field, param)`
+ * Added links to Japanese documentation, thanks @hideyukisaito!
+ * Added; the `express(1)` generated app outputs the env
+ * Added `content-negotiation` example
+ * Dependency: connect >= 1.5.1 < 2.0.0
+ * Fixed view layout bug. Closes #720
+ * Fixed; ignore body on 304. Closes #701
+
+2.3.11 / 2011-06-04
+==================
+
+ * Added `npm test`
+ * Removed generation of dummy test file from `express(1)`
+ * Fixed; `express(1)` adds express as a dep
+ * Fixed; prune on `prepublish`
+
+2.3.10 / 2011-05-27
+==================
+
+ * Added `req.route`, exposing the current route
+ * Added _package.json_ generation support to `express(1)`
+ * Fixed call to `app.param()` function for optional params. Closes #682
+
+2.3.9 / 2011-05-25
+==================
+
+ * Fixed bug-ish with `../' in `res.partial()` calls
+
+2.3.8 / 2011-05-24
+==================
+
+ * Fixed `app.options()`
+
+2.3.7 / 2011-05-23
+==================
+
+ * Added route `Collection`, ex: `app.get('/user/:id').remove();`
+ * Added support for `app.param(fn)` to define param logic
+ * Removed `app.param()` support for callback with return value
+ * Removed module.parent check from express(1) generated app. Closes #670
+ * Refactored router. Closes #639
+
+2.3.6 / 2011-05-20
+==================
+
+ * Changed; using devDependencies instead of git submodules
+ * Fixed redis session example
+ * Fixed markdown example
+ * Fixed view caching, should not be enabled in development
+
+2.3.5 / 2011-05-20
+==================
+
+ * Added export `.view` as alias for `.View`
+
+2.3.4 / 2011-05-08
+==================
+
+ * Added `./examples/say`
+ * Fixed `res.sendfile()` bug preventing the transfer of files with spaces
+
+2.3.3 / 2011-05-03
+==================
+
+ * Added "case sensitive routes" option.
+ * Changed; split methods supported per rfc [slaskis]
+ * Fixed route-specific middleware when using the same callback function several times
+
+2.3.2 / 2011-04-27
+==================
+
+ * Fixed view hints
+
+2.3.1 / 2011-04-26
+==================
+
+ * Added `app.match()` as `app.match.all()`
+ * Added `app.lookup()` as `app.lookup.all()`
+ * Added `app.remove()` for `app.remove.all()`
+ * Added `app.remove.VERB()`
+ * Fixed template caching collision issue. Closes #644
+ * Moved router over from connect and started refactor
+
+2.3.0 / 2011-04-25
+==================
+
+ * Added options support to `res.clearCookie()`
+ * Added `res.helpers()` as alias of `res.locals()`
+ * Added; json defaults to UTF-8 with `res.send()`. Closes #632. [Daniel * Dependency `connect >= 1.4.0`
+ * Changed; auto set Content-Type in res.attachement [Aaron Heckmann]
+ * Renamed "cache views" to "view cache". Closes #628
+ * Fixed caching of views when using several apps. Closes #637
+ * Fixed gotcha invoking `app.param()` callbacks once per route middleware.
+Closes #638
+ * Fixed partial lookup precedence. Closes #631
+Shaw]
+
+2.2.2 / 2011-04-12
+==================
+
+ * Added second callback support for `res.download()` connection errors
+ * Fixed `filename` option passing to template engine
+
+2.2.1 / 2011-04-04
+==================
+
+ * Added `layout(path)` helper to change the layout within a view. Closes #610
+ * Fixed `partial()` collection object support.
+ Previously only anything with `.length` would work.
+ When `.length` is present one must still be aware of holes,
+ however now `{ collection: {foo: 'bar'}}` is valid, exposes
+ `keyInCollection` and `keysInCollection`.
+
+ * Performance improved with better view caching
+ * Removed `request` and `response` locals
+ * Changed; errorHandler page title is now `Express` instead of `Connect`
+
+2.2.0 / 2011-03-30
+==================
+
+ * Added `app.lookup.VERB()`, ex `app.lookup.put('/user/:id')`. Closes #606
+ * Added `app.match.VERB()`, ex `app.match.put('/user/12')`. Closes #606
+ * Added `app.VERB(path)` as alias of `app.lookup.VERB()`.
+ * Dependency `connect >= 1.2.0`
+
+2.1.1 / 2011-03-29
+==================
+
+ * Added; expose `err.view` object when failing to locate a view
+ * Fixed `res.partial()` call `next(err)` when no callback is given [reported by aheckmann]
+ * Fixed; `res.send(undefined)` responds with 204 [aheckmann]
+
+2.1.0 / 2011-03-24
+==================
+
+ * Added `<%= title %>
'
+ , '' + files.map(function(file){
+ var icon = ''
+ , classes = [];
+
+ if (useIcons && '..' != file) {
+ icon = icons[extname(file)] || icons.default;
+ icon = '
';
+}
+
+/**
+ * Load and cache the given `icon`.
+ *
+ * @param {String} icon
+ * @return {String}
+ * @api private
+ */
+
+function load(icon) {
+ if (cache[icon]) return cache[icon];
+ return cache[icon] = fs.readFileSync(__dirname + '/../public/icons/' + icon, 'base64');
+}
+
+/**
+ * Filter "hidden" `files`, aka files
+ * beginning with a `.`.
+ *
+ * @param {Array} files
+ * @return {Array}
+ * @api private
+ */
+
+function removeHidden(files) {
+ return files.filter(function(file){
+ return '.' != file[0];
+ });
+}
+
+/**
+ * Icon map.
+ */
+
+var icons = {
+ '.js': 'page_white_code_red.png'
+ , '.c': 'page_white_c.png'
+ , '.h': 'page_white_h.png'
+ , '.cc': 'page_white_cplusplus.png'
+ , '.php': 'page_white_php.png'
+ , '.rb': 'page_white_ruby.png'
+ , '.cpp': 'page_white_cplusplus.png'
+ , '.swf': 'page_white_flash.png'
+ , '.pdf': 'page_white_acrobat.png'
+ , 'default': 'page_white.png'
+};
diff --git a/test/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js b/test/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
new file mode 100644
index 0000000..f2fc44f
--- /dev/null
+++ b/test/node_modules/express/node_modules/connect/lib/middleware/errorHandler.js
@@ -0,0 +1,100 @@
+/*!
+ * Connect - errorHandler
+ * Copyright(c) 2010 Sencha Inc.
+ * Copyright(c) 2011 TJ Holowaychuk
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var utils = require('../utils')
+ , url = require('url')
+ , fs = require('fs');
+
+/**
+ * Flexible error handler, providing (_optional_) stack traces
+ * and error message responses for requests accepting text, html,
+ * or json.
+ *
+ * Options:
+ *
+ * - `showStack`, `stack` respond with both the error message and stack trace. Defaults to `false`
+ * - `showMessage`, `message`, respond with the exception message only. Defaults to `false`
+ * - `dumpExceptions`, `dump`, dump exceptions to stderr (without terminating the process). Defaults to `false`
+ *
+ * Text:
+ *
+ * By default, and when _text/plain_ is accepted a simple stack trace
+ * or error message will be returned.
+ *
+ * JSON:
+ *
+ * When _application/json_ is accepted, connect will respond with
+ * an object in the form of `{ "error": error }`.
+ *
+ * HTML:
+ *
+ * When accepted connect will output a nice html stack trace.
+ *
+ * @param {Object} options
+ * @return {Function}
+ * @api public
+ */
+
+exports = module.exports = function errorHandler(options){
+ options = options || {};
+
+ // defaults
+ var showStack = options.showStack || options.stack
+ , showMessage = options.showMessage || options.message
+ , dumpExceptions = options.dumpExceptions || options.dump
+ , formatUrl = options.formatUrl;
+
+ return function errorHandler(err, req, res, next){
+ res.statusCode = 500;
+ if (dumpExceptions) console.error(err.stack);
+ if (showStack) {
+ var accept = req.headers.accept || '';
+ // html
+ if (~accept.indexOf('html')) {
+ fs.readFile(__dirname + '/../public/style.css', 'utf8', function(e, style){
+ fs.readFile(__dirname + '/../public/error.html', 'utf8', function(e, html){
+ var stack = (err.stack || '')
+ .split('\n').slice(1)
+ .map(function(v){ return '';
+ classes.push('icon');
+ }
+
+ return '
{linked-path}
+ {files}
+ {title}
+ 500 {error}
+ {stack}
+ Title
+ | Title
+ Title
+bar
`. Code buffered by `=` is escaped
+by default for security, however to output unescaped return values
+you may use `!=`:
+
+```jade
+p!= aVarContainingMoreHTML
+```
+
+ Jade also has designer-friendly variants, making the literal JavaScript
+ more expressive and declarative. For example the following assignments
+ are equivalent, and the expression is still regular javascript:
+
+```jade
+- var foo = 'foo ' + 'bar'
+foo = 'foo ' + 'bar'
+```
+
+ Likewise Jade has first-class `if`, `else if`, `else`, `until`, `while`, `unless` among others, however you must remember that the expressions are still regular javascript:
+
+```jade
+if foo == 'bar'
+ ul
+ li yay
+ li foo
+ li worked
+else
+ p oh no! didnt work
+```
+
+
+## Iteration
+
+ Along with vanilla JavaScript Jade also supports a subset of
+ constructs that allow you to create more designer-friendly templates,
+ one of these constructs is `each`, taking the form:
+
+```jade
+each VAL[, KEY] in OBJ
+```
+
+An example iterating over an array:
+
+```jade
+- var items = ["one", "two", "three"]
+each item in items
+ li= item
+```
+
+outputs:
+
+```html
+My Site
+ Tobi
+ tj
+
+
+');
+ buf.push('' + escape((interp = title) == null ? '' : interp) + '');
+ buf.push('
');
+ __.lineno = 3;
+ buf.push('');
+ buf.push('' + escape((interp = title) == null ? '' : interp) + '');
+ buf.push('
');
+ buf.push('
foo
+bar
+ +Jade 同样支持不输出的注释,加一个短横线就行了: + + //- will not output within markup + p foo + p bar + +渲染为: + +foo
+bar
+ +### 块注释 + + 块注释也是支持的: + + body + // + #content + h1 Example + +渲染为: + + + + + +Jade 同样很好的支持了条件注释: + + body + //if IE + a(href='http://www.mozilla.com/en-US/firefox/') Get Firefox + + +渲染为: + + + + + +### 内联 + + Jade 支持以自然的方式定义标签嵌套: + + ul + li.first + a(href='#') foo + li + a(href='#') bar + li.last + a(href='#') baz + +### 块展开 + + 块展开可以帮助你在一行内创建嵌套的标签,下面的例子和上面的是一样的: + + ul + li.first: a(href='#') foo + li: a(href='#') bar + li.last: a(href='#') baz + + +### 属性 + +Jade 现在支持使用'(' 和 ')' 作为属性分隔符 + + a(href='/login', title='View login page') Login + +当一个值是 `undefined` 或者 `null` 属性_不_会被加上, +所以呢,它不会编译出 'something="null"'. + + div(something=null) + +Boolean 属性也是支持的: + + input(type="checkbox", checked) + +使用代码的Boolean 属性只有当属性为`true`时才会输出: + + input(type="checkbox", checked=someValue) + +多行同样也是可用的: + + input(type='checkbox', + name='agreement', + checked) + +多行的时候可以不加逗号: + + input(type='checkbox' + name='agreement' + checked) + +加点空格,格式好看一点?同样支持 + + input( + type='checkbox' + name='agreement' + checked) + +冒号也是支持的: + + rss(xmlns:atom="atom") + +假如我有一个`user` 对象 `{ id: 12, name: 'tobi' }` +我们希望创建一个指向"/user/12"的链接 `href`, 我们可以使用普通的javascript字符串连接,如下: + + a(href='/user/' + user.id)= user.name + +或者我们使用jade的修改方式,这个我想很多使用Ruby或者 CoffeeScript的人会看起来像普通的js..: + + a(href='/user/#{user.id}')= user.name + +`class`属性是一个特殊的属性,你可以直接传递一个数组,比如`bodyClasses = ['user', 'authenticated']` : + + body(class=bodyClasses) + +### HTML + + 内联的html是可以的,我们可以使用管道定义一段文本 : + +``` +html + body + |foo bar baz
+``` + + 或者我们可以使用`.` 来告诉Jade我们需要一段文本: + +``` +html + body. +foo bar baz
+``` + + 上面的两个例子都会渲染成相同的结果: + +``` +foo bar baz
+ +``` + + 这条规则适应于在jade里的任何文本: + +``` +html + body + h1 User #{name} +``` + +### Doctypes + +添加文档类型只需要简单的使用 `!!!`, 或者 `doctype` 跟上下面的可选项: + + !!! + +会渲染出 _transitional_ 文档类型, 或者: + + !!! 5 + +or + + !!! html + +or + + doctype html + +doctypes 是大小写不敏感的, 所以下面两个是一样的: + + doctype Basic + doctype basic + +当然也是可以直接传递一段文档类型的文本: + + doctype html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN + +渲染后: + + ', + 'default': '', + 'transitional': '', + 'strict': '', + 'frameset': '', + '1.1': '', + 'basic': '', + 'mobile': '' + }; +``` + +通过下面的代码可以很简单的改变默认的文档类型: + +```javascript + jade.doctypes.default = 'whatever you want'; +``` + +## 过滤器 + +过滤器前缀 `:`, 比如 `:markdown` 会把下面块里的文本交给专门的函数进行处理。查看顶部 _特性_ 里有哪些可用的过滤器。 + + body + :markdown + Woah! jade _and_ markdown, very **cool** + we can even link to [stuff](http://google.com) + +渲染为: + +Woah! jade and markdown, very cool we can even link to stuff
+ +## 代码 + +Jade目前支持三种类型的可执行代码。第一种是前缀`-`, 这是不会被输出的: + + - var foo = 'bar'; + +这可以用在条件语句或者循环中: + + - for (var key in obj) + p= obj[key] + +由于Jade的缓存技术,下面的代码也是可以的: + + - if (foo) + ul + li yay + li foo + li worked + - else + p oh no! didnt work + +哈哈,甚至是很长的循环也是可以的: + + - if (items.length) + ul + - items.forEach(function(item){ + li= item + - }) + +所以你想要的! + +下一步我们要_转义_输出的代码,比如我们返回一个值,只要前缀一个`=`: + + - var foo = 'bar' + = foo + h1= foo + +它会渲染为`barWelcome to my super lame site.
+ + + +``` + + 前面已经提到,`include` 可以包含比如html或者css这样的内容。给定一个扩展名后,Jade不会把这个文件当作一个Jade源代码,并且会把它当作一个普通文本包含进来: + +``` +html + body + include content.html +``` + + Include 也可以接受块内容,给定的块将会附加到包含文件 _最后_ 的块里。 举个例子,`head.jade` 包含下面的内容: + + + ``` +head + script(src='/jquery.js') +``` + + 我们可以像下面给`include head`添加内容, 这里是添加两个脚本. + +``` +html + include head + script(src='/foo.js') + script(src='/bar.js') + body + h1 test +``` + + +## Mixins + + Mixins在编译的模板里会被Jade转换为普通的JavaScript函数。 Mixins 可以还参数,但不是必需的: + + mixin list + ul + li foo + li bar + li baz + + 使用不带参数的mixin看上去非常简单,在一个块外: + + h2 Groceries + mixin list + + Mixins 也可以带一个或者多个参数,参数就是普通的javascripts表达式,比如下面的例子: + + mixin pets(pets) + ul.pets + - each pet in pets + li= pet + + mixin profile(user) + .user + h2= user.name + mixin pets(user.pets) + + 会输出像下面的html: + +```html +'); + buf.push('Just an example'); + buf.push('
'); + } + return buf.join(""); + } catch (err) { + rethrow(err, __.input, __.filename, __.lineno); + } +} +``` + +当`compileDebug` 参数是`false`, 这个参数会被去掉,这样对于轻量级的浏览器端模板是非常有用的。结合Jade的参数和当前源码库里的 `./runtime.js` 文件,你可以通过toString()来编译模板而不需要在浏览器端运行整个Jade库,这样可以提高性能,也可以减少载入的JavaScript数量。 + +```js +function anonymous(locals) { + var attrs = jade.attrs, escape = jade.escape; + var buf = []; + with (locals || {}) { + var interp; + var title = 'yay' + buf.push(''); + buf.push('Just an example'); + buf.push('
'); + } + return buf.join(""); +} +``` + +## Makefile的一个例子 + + 通过执行`make`, 下面的Makefile例子可以把 _pages/*.jade_ 编译为 _pages/*.html_ 。 + +```make +JADE = $(shell find pages/*.jade) +HTML = $(JADE:.jade=.html) + +all: $(HTML) + +%.html: %.jade + jade < $< --path $< > $@ + +clean: + rm -f $(HTML) + +.PHONY: clean +``` + +这个可以和`watch(1)` 命令起来产生像下面的行为: + + $ watch make + +## 命令行的jade(1) + +``` + +使用: jade [options] [dir|file ...] + +选项: + + -h, --help 输出帮助信息 + -v, --version 输出版本号 + -o, --objWelcome to my site
+ +## Pipe text + + Another form of text is "pipe" text. Pipes act + as the text margin for large bodies of text. + + p + | This is a large + | body of text for + | this tag. + | + | Nothing too + | exciting. + + yields: + +This is a large + body of text for + this tag. + + Nothing too + exciting. +
+ + Using pipes we can also specify regular Jade tags + within the text: + + p + | Click to visit + a(href='http://google.com') Google + | if you want. + +## Text only tags + + As an alternative to pipe text you may add + a trailing "." to indicate that the block + contains nothing but plain-text, no tags: + + p. + This is a large + body of text for + this tag. + + Nothing too + exciting. + + Some tags are text-only by default, for example + _script_, _textarea_, and _style_ tags do not + contain nested HTML so Jade implies the trailing ".": + + script + if (foo) { + bar(); + } + + style + body { + padding: 50px; + font: 14px Helvetica; + } + +## Template script tags + + Sometimes it's useful to define HTML in script + tags using Jade, typically for client-side templates. + + To do this simply give the _script_ tag an arbitrary + _type_ attribute such as _text/x-template_: + + script(type='text/template') + h1 Look! + p Jade still works in here! + +## Interpolation + + Both plain-text and piped-text support interpolation, + which comes in two forms, escapes and non-escaped. The + following will output the _user.name_ in the paragraph + but HTML within it will be escaped to prevent XSS attacks: + + p Welcome #{user.name} + + The following syntax is identical however it will _not_ escape + HTML, and should only be used with strings that you trust: + + p Welcome !{user.name} + +## Inline HTML + + Sometimes constructing small inline snippets of HTML + in Jade can be annoying, luckily we can add plain + HTML as well: + + p Welcome #{user.name} + +## Code + + To buffer output with Jade simply use _=_ at the beginning + of a line or after a tag. This method escapes any HTML + present in the string. + + p= user.description + + To buffer output unescaped use the _!=_ variant, but again + be careful of XSS. + + p!= user.description + + The final way to mess with JavaScript code in Jade is the unbuffered + _-_, which can be used for conditionals, defining variables etc: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) { + h2 Description + p.description= user.description + - } + + When compiled blocks are wrapped in anonymous functions, so the + following is also valid, without braces: + + - var user = { description: 'foo bar baz' } + #user + - if (user.description) + h2 Description + p.description= user.description + + If you really want you could even use `.forEach()` and others: + + - users.forEach(function(user){ + .user + h2= user.name + p User #{user.name} is #{user.age} years old + - }) + + Taking this further Jade provides some syntax for conditionals, + iteration, switch statements etc. Let's look at those next! + +## Assignment + + Jade's first-class assignment is simple, simply use the _=_ + operator and Jade will _var_ it for you. The following are equivalent: + + - var user = { name: 'tobi' } + user = { name: 'tobi' } + +## Conditionals + + Jade's first-class conditional syntax allows for optional + parenthesis, and you may now omit the leading _-_ otherwise + it's identical, still just regular javascript: + + user = { description: 'foo bar baz' } + #user + if user.description + h2 Description + p.description= user.description + + Jade provides the negated version, _unless_ as well, the following + are equivalent: + + - if (!(user.isAnonymous)) + p You're logged in as #{user.name} + + unless user.isAnonymous + p You're logged in as #{user.name} + +## Iteration + + JavaScript's _for_ loops don't look very declarative, so Jade + also provides its own _for_ loop construct, aliased as _each_: + + for user in users + .user + h2= user.name + p user #{user.name} is #{user.age} year old + + As mentioned _each_ is identical: + + each user in users + .user + h2= user.name + + If necessary the index is available as well: + + for user, i in users + .user(class='user-#{i}') + h2= user.name + + Remember, it's just JavaScript: + + ul#letters + for letter in ['a', 'b', 'c'] + li= letter + +## Mixins + + Mixins provide a way to define jade "functions" which "mix in" + their contents when called. This is useful for abstracting + out large fragments of Jade. + + The simplest possible mixin which accepts no arguments might + look like this: + + mixin hello + p Hello + + You use a mixin by placing `+` before the name: + + +hello + + For something a little more dynamic, mixins can take + arguments, the mixin itself is converted to a javascript + function internally: + + mixin hello(user) + p Hello #{user} + + +hello('Tobi') + + Yields: + +Hello Tobi
+ + Mixins may optionally take blocks, when a block is passed + its contents becomes the implicit `block` argument. For + example here is a mixin passed a block, and also invoked + without passing a block: + + mixin article(title) + .article + .article-wrapper + h1= title + if block + block + else + p No content provided + + +article('Hello world') + + +article('Hello world') + p This is my + p Amazing article + + yields: + +No content provided
+This is my
+Amazing article
+This is my
+Amazing article
+Hello ' + escape((interp = name) == null ? '' : interp) + '\\n
');\n }\n return buf.join(\"\");\n}\n```\n\n Through the use of Jade's `./runtime.js` you may utilize these pre-compiled templates on the client-side _without_ Jade itself, all you need is the associated utility functions (in runtime.js), which are then available as `jade.attrs`, `jade.escape` etc. To enable this you should pass `{ client: true }` to `jade.compile()` to tell Jade to reference the helper functions\n via `jade.attrs`, `jade.escape` etc.\n\n```js\nfunction anonymous(locals, attrs, escape, rethrow) {\n var attrs = jade.attrs, escape = jade.escape, rethrow = jade.rethrow;\n var buf = [];\n with (locals || {}) {\n var interp;\n buf.push('\\nHello ' + escape((interp = name) == null ? '' : interp) + '\\n
');\n }\n return buf.join(\"\");\n}\n```\n\n\n## Public API\n\n```js\nvar jade = require('jade');\n\n// Compile a function\nvar fn = jade.compile('string of jade', options);\nfn(locals);\n```\n\n### Options\n\n - `self` Use a `self` namespace to hold the locals _(false by default)_\n - `locals` Local variable object\n - `filename` Used in exceptions, and required when using includes\n - `debug` Outputs tokens and function body generated\n - `compiler` Compiler to replace jade's default\n - `compileDebug` When `false` no debug instrumentation is compiled\n - `pretty` Add pretty-indentation whitespace to output _(false by default)_\n\n\n## Syntax\n\n\n### Line Endings\n\n**CRLF** and **CR** are converted to **LF** before parsing.\n\n\n### Tags\n\nA tag is simply a leading word:\n\n```jade\nhtml\n```\n\nfor example is converted to ``\n\ntags can also have ids:\n\n```jade\ndiv#container\n```\n\nwhich would render ``\n\nhow about some classes?\n\n```jade\ndiv.user-details\n```\n\nrenders ``\n\nmultiple classes? _and_ an id? sure:\n\n```jade\ndiv#foo.bar.baz\n```\n\nrenders ``\n\ndiv div div sure is annoying, how about:\n\n```jade\n#foo\n.bar\n```\n\nwhich is syntactic sugar for what we have already been doing, and outputs:\n\n```html\n\n```\n\n\n### Tag Text\n\nSimply place some content after the tag:\n\n```jade\np wahoo!\n```\n\nrenders `wahoo!
`.\n\nwell cool, but how about large bodies of text:\n\n```jade\np\n | foo bar baz\n | rawr rawr\n | super cool\n | go jade go\n```\n\nrenders `foo bar baz rawr.....
`\n\ninterpolation? yup! both types of text can utilize interpolation,\nif we passed `{ name: 'tj', email: 'tj@vision-media.ca' }` to the compiled function we can do the following:\n\n```jade\n#user #{name} <#{email}>\n```\n\noutputs `#{something}
`\n\nWe can also utilize the unescaped variant `!{html}`, so the following\nwill result in a literal script tag:\n\n```jade\n- var html = \"\"\n| !{html}\n```\n\nNested tags that also contain text can optionally use a text block:\n\n```jade\nlabel\n | Username:\n input(name='user[name]')\n```\n\nor immediate tag text:\n\n```jade\nlabel Username:\n input(name='user[name]')\n```\n\nTags that accept _only_ text such as `script` and `style` do not\nneed the leading `|` character, for example:\n\n```jade\nhtml\n head\n title Example\n script\n if (foo) {\n bar();\n } else {\n baz();\n }\n```\n\nOnce again as an alternative, we may use a trailing `.` to indicate a text block, for example:\n\n```jade\np.\n foo asdf\n asdf\n asdfasdfaf\n asdf\n asd.\n```\n\noutputs:\n\n```html\nfoo asdf\nasdf\n asdfasdfaf\n asdf\nasd.\n
\n```\n\nThis however differs from a trailing `.` followed by a space, which although is ignored by the Jade parser, tells Jade that this period is a literal:\n\n```jade\np .\n```\n\noutputs:\n\n```html\n.
\n```\n\nIt should be noted that text blocks should be doubled escaped. For example if you desire the following output.\n\n```html\nfoo\\bar
\n```\n\nuse:\n\n```jade\np.\n foo\\\\bar\n```\n\n\n### Comments\n\nSingle line comments currently look the same as JavaScript comments,\naka `//` and must be placed on their own line:\n\n```jade\n// just some paragraphs\np foo\np bar\n```\n\nwould output\n\n```html\n\nfoo
\nbar
\n```\n\nJade also supports unbuffered comments, by simply adding a hyphen:\n\n```jade\n//- will not output within markup\np foo\np bar\n```\n\noutputting\n\n```html\nfoo
\nbar
\n```\n\n\n### Block Comments\n\n A block comment is legal as well:\n\n```jade\nbody\n //\n #content\n h1 Example\n```\n\noutputting\n\n```html\n\n \n\n```\n\nJade supports conditional-comments as well, for example:\n\n```jade\nhead\n //if lt IE 8\n script(src='/ie-sucks.js')\n```\n\noutputs:\n\n```html\n\n \n\n```\n\n\n### Nesting\n\n Jade supports nesting to define the tags in a natural way:\n\n```jade\nul\n li.first\n a(href='#') foo\n li\n a(href='#') bar\n li.last\n a(href='#') baz\n```\n\n\n### Block Expansion\n\n Block expansion allows you to create terse single-line nested tags,\n the following example is equivalent to the nesting example above.\n\n```jade\nul\n li.first: a(href='#') foo\n li: a(href='#') bar\n li.last: a(href='#') baz\n```\n\n\n### Case\n\n The case statement takes the following form:\n\n```jade\nhtml\n body\n friends = 10\n case friends\n when 0\n p you have no friends\n when 1\n p you have a friend\n default\n p you have #{friends} friends\n```\n\n Block expansion may also be used:\n\n```jade\nfriends = 5\n\nhtml\n body\n case friends\n when 0: p you have no friends\n when 1: p you have a friend\n default: p you have #{friends} friends\n```\n\n\n### Attributes\n\nJade currently supports `(` and `)` as attribute delimiters.\n\n```jade\na(href='/login', title='View login page') Login\n```\n\nWhen a value is `undefined` or `null` the attribute is _not_ added,\nso this is fine, it will not compile `something=\"null\"`.\n\n```jade\ndiv(something=null)\n```\n\nBoolean attributes are also supported:\n\n```jade\ninput(type=\"checkbox\", checked)\n```\n\nBoolean attributes with code will only output the attribute when `true`:\n\n```jade\ninput(type=\"checkbox\", checked=someValue)\n```\n\nMultiple lines work too:\n\n```jade\ninput(type='checkbox',\n name='agreement',\n checked)\n```\n\nMultiple lines without the comma work fine:\n\n```jade\ninput(type='checkbox'\n name='agreement'\n checked)\n```\n\nFunky whitespace? fine:\n\n```jade\ninput(\n type='checkbox'\n name='agreement'\n checked)\n```\n\nColons work:\n\n```jade\nrss(xmlns:atom=\"atom\")\n```\n\nSuppose we have the `user` local `{ id: 12, name: 'tobi' }`\nand we wish to create an anchor tag with `href` pointing to \"/user/12\"\nwe could use regular javascript concatenation:\n\n```jade\na(href='/user/' + user.id)= user.name\n```\n\nor we could use jade's interpolation, which I added because everyone\nusing Ruby or CoffeeScript seems to think this is legal js..:\n\n```jade\na(href='/user/#{user.id}')= user.name\n```\n\nThe `class` attribute is special-cased when an array is given,\nallowing you to pass an array such as `bodyClasses = ['user', 'authenticated']` directly:\n\n```jade\nbody(class=bodyClasses)\n```\n\n\n### HTML\n\n Inline html is fine, we can use the pipe syntax to\n write arbitrary text, in this case some html:\n\n```jade\nhtml\n body\n |foo bar baz
\n```\n\n Or we can use the trailing `.` to indicate to Jade that we\n only want text in this block, allowing us to omit the pipes:\n\n```jade\nhtml\n body.\nfoo bar baz
\n```\n\n Both of these examples yield the same result:\n\n```html\nfoo bar baz
\n\n```\n\n The same rule applies for anywhere you can have text\n in jade, raw html is fine:\n\n```jade\nhtml\n body\n h1 User #{name}\n```\n\n\n### Doctypes\n\nTo add a doctype simply use `!!!`, or `doctype` followed by an optional value:\n\n```jade\n!!!\n```\n\nor\n\n```jade\ndoctype\n```\n\nWill output the _html 5_ doctype, however:\n\n```jade\n!!! transitional\n```\n\nWill output the _transitional_ doctype.\n\nDoctypes are case-insensitive, so the following are equivalent:\n\n```jade\ndoctype Basic\ndoctype basic\n```\n\nit's also possible to simply pass a doctype literal:\n\n```jade\ndoctype html PUBLIC \"-//W3C//DTD XHTML Basic 1.1//EN\n```\n\nyielding:\n\n```html\n\n```\n\nBelow are the doctypes defined by default, which can easily be extended:\n\n```js\nvar doctypes = exports.doctypes = {\n '5': '',\n 'default': '',\n 'xml': '',\n 'transitional': '',\n 'strict': '',\n 'frameset': '',\n '1.1': '',\n 'basic': '',\n 'mobile': ''\n};\n```\n\nTo alter the default simply change:\n\n```js\njade.doctypes.default = 'whatever you want';\n```\n\n\n## Filters\n\nFilters are prefixed with `:`, for example `:markdown` and\npass the following block of text to an arbitrary function for processing. View the _features_\nat the top of this document for available filters.\n\n```jade\nbody\n :markdown\n Woah! jade _and_ markdown, very **cool**\n we can even link to [stuff](http://google.com)\n```\n\nRenders:\n\n```html\nWoah! jade and markdown, very cool we can even link to stuff
\n```\n\n\n## Code\n\nJade currently supports three classifications of executable code. The first\nis prefixed by `-`, and is not buffered:\n\n```jade\n- var foo = 'bar';\n```\n\nThis can be used for conditionals, or iteration:\n\n```jade\n- for (var key in obj)\n p= obj[key]\n```\n\nDue to Jade's buffering techniques the following is valid as well:\n\n```jade\n- if (foo)\n ul\n li yay\n li foo\n li worked\n- else\n p oh no! didnt work\n```\n\nHell, even verbose iteration:\n\n```jade\n- if (items.length)\n ul\n - items.forEach(function(item){\n li= item\n - })\n```\n\nAnything you want!\n\nNext up we have _escaped_ buffered code, which is used to\nbuffer a return value, which is prefixed by `=`:\n\n```jade\n- var foo = 'bar'\n= foo\nh1= foo\n```\n\nWhich outputs `barWelcome to my super lame site.
\n \n \n\n```\n\n As mentioned `include` can be used to include other content\n such as html or css. By providing an extension Jade will not\n assume that the file is Jade source and will include it as\n a literal:\n\n```jade\nhtml\n body\n include content.html\n```\n\n Include directives may also accept a block, in which case the\n the given block will be appended to the _last_ block defined\n in the file. For example if `head.jade` contains:\n\n```jade\nhead\n script(src='/jquery.js')\n```\n\n We may append values by providing a block to `include head`\n as shown below, adding the two scripts.\n\n```jade\nhtml\n include head\n script(src='/foo.js')\n script(src='/bar.js')\n body\n h1 test\n```\n\n You may also `yield` within an included template, allowing you to explicitly mark where the block given to `include` will be placed. Suppose for example you wish to prepend scripts rather than append, you might do the following:\n\n```jade\nhead\n yield\n script(src='/jquery.js')\n script(src='/jquery.ui.js')\n```\n\n Since included Jade is parsed and literally merges the AST, lexically scoped variables function as if the included Jade was written right in the same file. This means `include` may be used as sort of partial, for example suppose we have `user.jade` which utilizes a `user` variable.\n\n```jade\nh1= user.name\np= user.occupation\n```\n\nWe could then simply `include user` while iterating users, and since the `user` variable is already defined within the loop the included template will have access to it.\n\n```jade\nusers = [{ name: 'Tobi', occupation: 'Ferret' }]\n\neach user in users\n .user\n include user\n```\n\nyielding:\n\n```html\nFerret
\n');\n buf.push('Just an example');\n buf.push('
');\n }\n return buf.join(\"\");\n } catch (err) {\n rethrow(err, __.input, __.filename, __.lineno);\n }\n}\n```\n\nWhen the `compileDebug` option _is_ explicitly `false`, this instrumentation\nis stripped, which is very helpful for light-weight client-side templates. Combining Jade's options with the `./runtime.js` file in this repo allows you\nto toString() compiled templates and avoid running the entire Jade library on\nthe client, increasing performance, and decreasing the amount of JavaScript\nrequired.\n\n```js\nfunction anonymous(locals) {\n var attrs = jade.attrs, escape = jade.escape;\n var buf = [];\n with (locals || {}) {\n var interp;\n var title = 'yay'\n buf.push('');\n buf.push('Just an example');\n buf.push('
');\n }\n return buf.join(\"\");\n}\n```\n\n\n## Example Makefile\n\n Below is an example Makefile used to compile _pages/*.jade_\n into _pages/*.html_ files by simply executing `make`.\n\n```make\nJADE = $(shell find pages/*.jade)\nHTML = $(JADE:.jade=.html)\n\nall: $(HTML)\n\n%.html: %.jade\n jade < $< --path $< > $@\n\nclean:\n rm -f $(HTML)\n\n.PHONY: clean\n```\n\nthis can be combined with the `watch(1)` command to produce\na watcher-like behaviour:\n\n```bash\n$ watch make\n```\n\n\n## jade(1)\n\n```\n\nUsage: jade [options] [dir|file ...]\n\nOptions:\n\n -h, --help output usage information\n -V, --version output the version number\n -o, --objout
\ No newline at end of file diff --git a/test/node_modules/jade/testing/nested/something.jade b/test/node_modules/jade/testing/nested/something.jade new file mode 100644 index 0000000..552c797 --- /dev/null +++ b/test/node_modules/jade/testing/nested/something.jade @@ -0,0 +1 @@ +p out \ No newline at end of file diff --git a/test/node_modules/jade/testing/some.js b/test/node_modules/jade/testing/some.js new file mode 100644 index 0000000..3104e71 --- /dev/null +++ b/test/node_modules/jade/testing/some.js @@ -0,0 +1,4 @@ + +if (something) { + something('hey'); +} diff --git a/test/node_modules/jade/testing/test.md b/test/node_modules/jade/testing/test.md new file mode 100644 index 0000000..9af1bb2 --- /dev/null +++ b/test/node_modules/jade/testing/test.md @@ -0,0 +1,5 @@ +Just a _test_ of some **markdown**: + + - foo + - bar + - baz diff --git a/test/node_modules/mongoose/.npmignore b/test/node_modules/mongoose/.npmignore new file mode 100644 index 0000000..df5ea94 --- /dev/null +++ b/test/node_modules/mongoose/.npmignore @@ -0,0 +1,13 @@ +lib-cov +**.swp +*.sw* +*.orig +.DS_Store +node_modules/ +benchmarks/ +docs/ +test/ +Makefile +CNAME +index.html +index.jade diff --git a/test/node_modules/mongoose/.travis.yml b/test/node_modules/mongoose/.travis.yml new file mode 100644 index 0000000..c663337 --- /dev/null +++ b/test/node_modules/mongoose/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - 0.4 + - 0.6 + - 0.8 +services: + - mongodb diff --git a/test/node_modules/mongoose/CONTRIBUTING.md b/test/node_modules/mongoose/CONTRIBUTING.md new file mode 100644 index 0000000..05349a4 --- /dev/null +++ b/test/node_modules/mongoose/CONTRIBUTING.md @@ -0,0 +1,35 @@ +## Contributing to Mongoose + +### Reporting bugs + +- Before opening a new issue, look for existing [issues](https://github.com/learnboost/mongoose/issues) to avoid duplication. If the issue does not yet exist, [create one](https://github.com/learnboost/mongoose/issues/new). + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. + +### Fixing bugs / Adding features + +- Before starting to write code, look for existing [issues](https://github.com/learnboost/mongoose/issues). That way you avoid working on something that might not be of interest or that has been addressed already in a different branch. You can create a new issue [here](https://github.com/learnboost/mongoose/issues/new). + - _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_. +- Fork the [repo](https://github.com/learnboost/mongoose) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. +- Follow the general coding style of the rest of the project: + - 2 space tabs + - no trailing whitespace + - comma first + - inline documentation for new methods, class members, etc + - 1 space between conditionals/functions, and their parenthesis and curly braces + - `if (..) {` + - `for (..) {` + - `while (..) {` + - `function (err) {` +- Write tests and make sure they pass (execute `make test` from the command line to run the test suite). + +### Documentation + +To contribute to the [API documentation](http://mongoosejs.com/docs/api.html) just make your changes to the inline documentation of the appropriate [source code](https://github.com/LearnBoost/mongoose/tree/master/lib) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button. + +To contribute to the [guide](http://mongoosejs.com/docs/guide.html) or [quick start](http://mongoosejs.com/docs/index.html) docs, make your changes to the appropriate `.jade` files in the [docs](https://github.com/LearnBoost/mongoose/tree/master/docs) directory of the master branch and submit a pull request. Again, the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button might work for you here. + +If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make docs` from the project root, which switches to the gh-pages branch, merges from master, and builds all the static pages for you. Now execute `node server.js` from the project root which will launch a local webserver where you can browse the documentation site locally. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes. + +### Plugins website + +The [plugins](http://plugins.mongoosejs.com/) site is also an [open source project](https://github.com/aheckmann/mongooseplugins) that you can get involved with. Feel free to fork and improve it as well! diff --git a/test/node_modules/mongoose/History.md b/test/node_modules/mongoose/History.md new file mode 100644 index 0000000..a9919b0 --- /dev/null +++ b/test/node_modules/mongoose/History.md @@ -0,0 +1,1264 @@ + +3.5.4 / 2013-01-07 +================== + + * changed; "_pres" & "_posts" are now reserved pathnames #1261 + * updated; driver to 1.2.8 + * fixed; exception when reopening a replica set. #1263 [ethankan](https://github.com/ethankan) + * website; updated + +3.5.3 / 2012-12-26 +================== + + * added; support for geo object notation #1257 + * fixed; $within query casting with arrays + * fixed; unix domain socket support #1254 + * updated; driver to 1.2.7 + * updated; muri to 0.0.5 + +3.5.2 / 2012-12-17 +================== + + * fixed; using auth with replica sets #1253 + +3.5.1 / 2012-12-12 +================== + + * fixed; regression when using subdoc with `path` as pathname #1245 [daeq](https://github.com/daeq) + * fixed; safer db option checks + * updated; driver to 1.2.5 + * website; add more examples + * website; clean up old docs + * website; fix prev release urls + * docs; clarify streaming with HTTP responses + +3.5.0 / 2012-12-10 +================== + + * added; paths to CastErrors #1239 + * added; support for mongodb connection string spec #1187 + * added; post validate event + * added; Schema#get (to retrieve schema options) + * added; VersionError #1071 + * added; npmignore [hidekiy](https://github.com/hidekiy) + * update; driver to 1.2.3 + * fixed; stackoverflow in setter #1234 + * fixed; utils.isObject() + * fixed; do not clobber user specified driver writeConcern #1227 + * fixed; always pass current document to post hooks + * fixed; throw error when user attempts to overwrite a model + * fixed; connection.model only caches on connection #1209 + * fixed; respect conn.model() creation when matching global model exists #1209 + * fixed; passing model name + collection name now always honors collection name + * fixed; setting virtual field to an empty object #1154 + * fixed; subclassed MongooseErrors exposure, now available in mongoose.Error.xxxx + * fixed; model.remove() ignoring callback when executed twice [daeq](https://github.com/daeq) #1210 + * docs; add collection option to schema api docs #1222 + * docs; NOTE about db safe options + * docs; add post hooks docs + * docs; connection string options + * docs; middleware is not executed with Model.remove #1241 + * docs; {g,s}etter introspection #777 + * docs; update validation docs + * docs; add link to plugins page + * docs; clarify error returned by unique indexes #1225 + * docs; more detail about disabling autoIndex behavior + * docs; add homepage section to package (npm docs mongoose) + * docs; more detail around collection name pluralization #1193 + * website; add .important css + * website; update models page + * website; update getting started + * website; update quick start + +3.4.0 / 2012-11-10 +================== + + * added; support for generic toJSON/toObject transforms #1160 #1020 #1197 + * added; doc.set() merge support #1148 [NuORDER](https://github.com/NuORDER) + * added; query#add support #1188 [aleclofabbro](https://github.com/aleclofabbro) + * changed; adding invalid nested paths to non-objects throws 4216f14 + * changed; fixed; stop invalid function cloning (internal fix) + * fixed; add query $and casting support #1180 [anotheri](https://github.com/anotheri) + * fixed; overwriting of query arguments #1176 + * docs; fix expires examples + * docs; transforms + * docs; schema `collection` option docs [hermanjunge](https://github.com/hermanjunge) + * website; updated + * tests; added + +3.3.1 / 2012-10-11 +================== + + * fixed; allow goose.connect(uris, dbname, opts) #1144 + * docs; persist API private checked state across page loads + +3.3.0 / 2012-10-10 +================== + + * fixed; passing options as 2nd arg to connect() #1144 + * fixed; race condition after no-op save #1139 + * fixed; schema field selection application in findAndModify #1150 + * fixed; directly setting arrays #1126 + * updated; driver to 1.1.11 + * updated; collection pluralization rules [mrickard](https://github.com/mrickard) + * tests; added + * docs; updated + +3.2.2 / 2012-10-08 +================== + + * updated; driver to 1.1.10 #1143 + * updated; use sliced 0.0.3 + * fixed; do not recast embedded docs unnecessarily + * fixed; expires schema option helper #1132 + * fixed; built in string setters #1131 + * fixed; debug output for Dates/ObjectId properties #1129 + * docs; fixed Javascript syntax error in example [olalonde](https://github.com/olalonde) + * docs; fix toJSON example #1137 + * docs; add ensureIndex production notes + * docs; fix spelling + * docs; add blogposts about v3 + * website; updated + * removed; undocumented inGroupsOf util + * tests; added + +3.2.1 / 2012-09-28 +================== + + * fixed; remove query batchSize option default of 1000 https://github.com/learnboost/mongoose/commit/3edaa8651 + * docs; updated + * website; updated + +3.2.0 / 2012-09-27 +================== + + * added; direct array index assignment with casting support `doc.array.set(index, value)` + * fixed; QueryStream#resume within same tick as pause() #1116 + * fixed; default value validatation #1109 + * fixed; array splice() not casting #1123 + * fixed; default array construction edge case #1108 + * fixed; query casting for inequalities in arrays #1101 [dpatti](https://github.com/dpatti) + * tests; added + * website; more documentation + * website; fixed layout issue #1111 [SlashmanX](https://github.com/SlashmanX) + * website; refactored [guille](https://github.com/guille) + +3.1.2 / 2012-09-10 +================== + + * added; ReadPreferrence schema option #1097 + * updated; driver to 1.1.7 + * updated; default query batchSize to 1000 + * fixed; we now cast the mapReduce query option #1095 + * fixed; $elemMatch+$in with field selection #1091 + * fixed; properly cast $elemMatch+$in conditions #1100 + * fixed; default field application of subdocs #1027 + * fixed; querystream prematurely dying #1092 + * fixed; querystream never resumes when paused at getMore boundries #1092 + * fixed; querystream occasionally emits data events after destroy #1092 + * fixed; remove unnecessary ObjectId creation in querystream + * fixed; allow ne(boolean) again #1093 + * docs; add populate/field selection syntax notes + * docs; add toObject/toJSON options detail + * docs; `read` schema option + +3.1.1 / 2012-08-31 +================== + + * updated; driver to 1.1.6 + +3.1.0 / 2012-08-29 +================== + + * changed; fixed; directly setting nested objects now overwrites entire object (previously incorrectly merged them) + * added; read pref support (mongodb 2.2) 205a709c + * added; aggregate support (mongodb 2.2) f3a5bd3d + * added; virtual {g,s}etter introspection (#1070) + * updated; docs [brettz9](https://github.com/brettz9) + * updated; driver to 1.1.5 + * fixed; retain virtual setter return values (#1069) + +3.0.3 / 2012-08-23 +================== + + * fixed; use of nested paths beginning w/ numbers #1062 + * fixed; query population edge case #1053 #1055 [jfremy](https://github.com/jfremy) + * fixed; simultaneous top and sub level array modifications #1073 + * added; id and _id schema option aliases + tests + * improve debug formatting to allow copy/paste logged queries into mongo shell [eknkc](https://github.com/eknkc) + * docs + +3.0.2 / 2012-08-17 +================== + + * added; missing support for v3 sort/select syntax to findAndModify helpers (#1058) + * fixed; replset fullsetup event emission + * fixed; reconnected event for replsets + * fixed; server reconnection setting discovery + * fixed; compat with non-schema path props using positional notation (#1048) + * fixed; setter/casting order (#665) + * docs; updated + +3.0.1 / 2012-08-11 +================== + + * fixed; throw Error on bad validators (1044) + * fixed; typo in EmbeddedDocument#parentArray [lackac] + * fixed; repair mongoose.SchemaTypes alias + * updated; docs + +3.0.0 / 2012-08-07 +================== + + * removed; old subdocument#commit method + * fixed; setting arrays of matching docs [6924cbc2] + * fixed; doc!remove event now emits in save order as save for consistency + * fixed; pre-save hooks no longer fire on subdocuments when validation fails + * added; subdoc#parent() and subdoc#parentArray() to access subdocument parent objects + * added; query#lean() helper + +3.0.0rc0 / 2012-08-01 +===================== + + * fixed; allow subdoc literal declarations containing "type" pathname (#993) + * fixed; unsetting a default array (#758) + * fixed; boolean $in queries (#998) + * fixed; allow use of `options` as a pathname (#529) + * fixed; `model` is again a permitted schema path name + * fixed; field selection option on subdocs (#1022) + * fixed; handle another edge case with subdoc saving (#975) + * added; emit save err on model if listening + * added; MongoDB TTL collection support (#1006) + * added; $center options support + * added; $nearSphere and $polygon support + * updated; driver version to 1.1.2 + +3.0.0alpha2 / 2012-07-18 +========================= + + * changed; index errors are now emitted on their model and passed to an optional callback (#984) + * fixed; specifying index along with sparse/unique option no longer overwrites (#1004) + * fixed; never swallow connection errors (#618) + * fixed; creating object from model with emded object no longer overwrites defaults [achurkin] (#859) + * fixed; stop needless validation of unchanged/unselected fields (#891) + * fixed; document#equals behavior of objectids (#974) + * fixed; honor the minimize schema option (#978) + * fixed; provide helpful error msgs when reserved schema path is used (#928) + * fixed; callback to conn#disconnect is optional (#875) + * fixed; handle missing protocols in connection urls (#987) + * fixed; validate args to query#where (#969) + * fixed; saving modified/removed subdocs (#975) + * fixed; update with $pull from Mixed array (#735) + * fixed; error with null shard key value + * fixed; allow unsetting enums (#967) + * added; support for manual index creation (#984) + * added; support for disabled auto-indexing (#984) + * added; support for preserving MongooseArray#sort changes (#752) + * added; emit state change events on connection + * added; support for specifying BSON subtype in MongooseBuffer#toObject [jcrugzz] + * added; support for disabled versioning (#977) + * added; implicit "new" support for models and Schemas + +3.0.0alpha1 / 2012-06-15 +========================= + + * removed; doc#commit (use doc#markModified) + * removed; doc.modified getter (#950) + * removed; mongoose{connectSet,createSetConnection}. use connect,createConnection instead + * removed; query alias methods 1149804c + * removed; MongooseNumber + * changed; now creating indexes in background by default + * changed; strict mode now enabled by default (#952) + * changed; doc#modifiedPaths is now a method (#950) + * changed; getters no longer cast (#820); casting happens during set + * fixed; no need to pass updateArg to findOneAndUpdate (#931) + * fixed: utils.merge bug when merging nested non-objects. [treygriffith] + * fixed; strict:throw should produce errors in findAndModify (#963) + * fixed; findAndUpdate no longer overwrites document (#962) + * fixed; setting default DocumentArrays (#953) + * fixed; selection of _id with schema deselection (#954) + * fixed; ensure promise#error emits instanceof Error + * fixed; CursorStream: No stack overflow on any size result (#929) + * fixed; doc#remove now passes safe options + * fixed; invalid use of $set during $pop + * fixed; array#{$pop,$shift} mirror MongoDB behavior + * fixed; no longer test non-required vals in string match (#934) + * fixed; edge case with doc#inspect + * fixed; setter order (#665) + * fixed; setting invalid paths in strict mode (#916) + * fixed; handle docs without id in DocumentArray#id method (#897) + * fixed; do not save virtuals during model.update (#894) + * fixed; sub doc toObject virtuals application (#889) + * fixed; MongooseArray#pull of ObjectId (#881) + * fixed; handle passing db name with any repl set string + * fixed; default application of selected fields (#870) + * fixed; subdoc paths reported in validation errors (#725) + * fixed; incorrect reported num of affected docs in update ops (#862) + * fixed; connection assignment in Model#model (#853) + * fixed; stringifying arrays of docs (#852) + * fixed; modifying subdoc and parent array works (#842) + * fixed; passing undefined to next hook (#785) + * fixed; Query#{update,remove}() works without callbacks (#788) + * fixed; set/updating nested objects by parent pathname (#843) + * fixed; allow null in number arrays (#840) + * fixed; isNew on sub doc after insertion error (#837) + * fixed; if an insert fails, set isNew back to false [boutell] + * fixed; isSelected when only _id is selected (#730) + * fixed; setting an unset default value (#742) + * fixed; query#sort error messaging (#671) + * fixed; support for passing $options with $regex + * added; array of object literal notation in schema creates DocumentArrays + * added; gt,gte,lt,lte query support for arrays (#902) + * added; capped collection support (#938) + * added; document versioning support + * added; inclusion of deselected schema path (#786) + * added; non-atomic array#pop + * added; EmbeddedDocument constructor is now exposed in DocArray#create 7cf8beec + * added; mapReduce support (#678) + * added; support for a configurable minimize option #to{Object,JSON}(option) (#848) + * added; support for strict: `throws` [regality] + * added; support for named schema types (#795) + * added; to{Object,JSON} schema options (#805) + * added; findByIdAnd{Update,Remove}() + * added; findOneAnd{Update,Remove}() + * added; query.setOptions() + * added; instance.update() (#794) + * added; support specifying model in populate() [DanielBaulig] + * added; `lean` query option [gitfy] + * added; multi-atomic support to MongooseArray#nonAtomicPush + * added; support for $set + other $atomic ops on single array + * added; tests + * updated; driver to 1.0.2 + * updated; query.sort() syntax to mirror query.select() + * updated; clearer cast error msg for array numbers + * updated; docs + * updated; doc.clone 3x faster (#950) + * updated; only create _id if necessary (#950) + +2.7.3 / 2012-08-01 +================== + + * fixed; boolean $in queries (#998) + * fixed field selection option on subdocs (#1022) + +2.7.2 / 2012-07-18 +================== + + * fixed; callback to conn#disconnect is optional (#875) + * fixed; handle missing protocols in connection urls (#987) + * fixed; saving modified/removed subdocs (#975) + * updated; tests + +2.7.1 / 2012-06-26 +=================== + + * fixed; sharding: when a document holds a null as a value of the shard key + * fixed; update() using $pull on an array of Mixed (gh-735) + * deprecated; MongooseNumber#{inc, increment, decrement} methods + * tests; now using mocha + +2.7.0 / 2012-06-14 +=================== + + * added; deprecation warnings to methods being removed in 3.x + +2.6.8 / 2012-06-14 +=================== + + * fixed; edge case when using 'options' as a path name (#961) + +2.6.7 / 2012-06-08 +=================== + + * fixed; ensure promise#error always emits instanceof Error + * fixed; selection of _id w/ another excluded path (#954) + * fixed; setting default DocumentArrays (#953) + +2.6.6 / 2012-06-06 +=================== + + * fixed; stack overflow in query stream with large result sets (#929) + * added; $gt, $gte, $lt, $lte support to arrays (#902) + * fixed; pass option `safe` along to doc#remove() calls + +2.6.5 / 2012-05-24 +=================== + + * fixed; do not save virtuals in Model.update (#894) + * added; missing $ prefixed query aliases (going away in 3.x) (#884) [timoxley] + * fixed; setting invalid paths in strict mode (#916) + * fixed; resetting isNew after insert failure (#837) [boutell] + +2.6.4 / 2012-05-15 +=================== + + * updated; backport string regex $options to 2.x + * updated; use driver 1.0.2 (performance improvements) (#914) + * fixed; calling MongooseDocumentArray#id when the doc has no _id (#897) + +2.6.3 / 2012-05-03 +=================== + + * fixed; repl-set connectivity issues during failover on MongoDB 2.0.1 + * updated; driver to 1.0.0 + * fixed; virtuals application of subdocs when using toObject({ virtuals: true }) (#889) + * fixed; MongooseArray#pull of ObjectId correctly updates the array itself (#881) + +2.6.2 / 2012-04-30 +=================== + + * fixed; default field application of selected fields (#870) + +2.6.1 / 2012-04-30 +=================== + + * fixed; connection assignment in mongoose#model (#853, #877) + * fixed; incorrect reported num of affected docs in update ops (#862) + +2.6.0 / 2012-04-19 +=================== + + * updated; hooks.js to 0.2.1 + * fixed; issue with passing undefined to a hook callback. thanks to [chrisleishman] for reporting. + * fixed; updating/setting nested objects in strict schemas (#843) as reported by [kof] + * fixed; Query#{update,remove}() work without callbacks again (#788) + * fixed; modifying subdoc along with parent array $atomic op (#842) + +2.5.14 / 2012-04-13 +=================== + + * fixed; setting an unset default value (#742) + * fixed; doc.isSelected(otherpath) when only _id is selected (#730) + * updated; docs + +2.5.13 / 2012-03-22 +=================== + + * fixed; failing validation of unselected required paths (#730,#713) + * fixed; emitting connection error when only one listener (#759) + * fixed; MongooseArray#splice was not returning values (#784) [chrisleishman] + +2.5.12 / 2012-03-21 +=================== + + * fixed; honor the `safe` option in all ensureIndex calls + * updated; node-mongodb-native driver to 0.9.9-7 + +2.5.11 / 2012-03-15 +=================== + + * added; introspection for getters/setters (#745) + * updated; node-mongodb-driver to 0.9.9-5 + * added; tailable method to Query (#769) [holic] + * fixed; Number min/max validation of null (#764) [btamas] + * added; more flexible user/password connection options (#738) [KarneAsada] + +2.5.10 / 2012-03-06 +=================== + + * updated; node-mongodb-native driver to 0.9.9-4 + * added; Query#comment() + * fixed; allow unsetting arrays + * fixed; hooking the set method of subdocuments (#746) + * fixed; edge case in hooks + * fixed; allow $id and $ref in queries (fixes compatibility with mongoose-dbref) (#749) [richtera] + * added; default path selection to SchemaTypes + +2.5.9 / 2012-02-22 +=================== + + * fixed; properly cast nested atomic update operators for sub-documents + +2.5.8 / 2012-02-21 +=================== + + * added; post 'remove' middleware includes model that was removed (#729) [timoxley] + +2.5.7 / 2012-02-09 +=================== + + * fixed; RegExp validators on node >= v0.6.x + +2.5.6 / 2012-02-09 +=================== + + * fixed; emit errors returned from db.collection() on the connection (were being swallowed) + * added; can add multiple validators in your schema at once (#718) [diogogmt] + * fixed; strict embedded documents (#717) + * updated; docs [niemyjski] + * added; pass number of affected docs back in model.update/save + +2.5.5 / 2012-02-03 +=================== + + * fixed; RangeError: maximum call stack exceed error when removing docs with Number _id (#714) + +2.5.4 / 2012-02-03 +=================== + + * fixed; RangeError: maximum call stack exceed error (#714) + +2.5.3 / 2012-02-02 +=================== + + * added; doc#isSelected(path) + * added; query#equals() + * added; beta sharding support + * added; more descript error msgs (#700) [obeleh] + * added; document.modifiedPaths (#709) [ljharb] + * fixed; only functions can be added as getters/setters (#707,704) [ljharb] + +2.5.2 / 2012-01-30 +=================== + + * fixed; rollback -native driver to 0.9.7-3-5 (was causing timeouts and other replica set weirdness) + * deprecated; MongooseNumber (will be moved to a separate repo for 3.x) + * added; init event is emitted on schemas + +2.5.1 / 2012-01-27 +=================== + + * fixed; honor strict schemas in Model.update (#699) + +2.5.0 / 2012-01-26 +=================== + + * added; doc.toJSON calls toJSON on embedded docs when exists [jerem] + * added; populate support for refs of type Buffer (#686) [jerem] + * added; $all support for ObjectIds and Dates (#690) + * fixed; virtual setter calling on instantiation when strict: true (#682) [hunterloftis] + * fixed; doc construction triggering getters (#685) + * fixed; MongooseBuffer check in deepEquals (#688) + * fixed; range error when using Number _ids with `instance.save()` (#691) + * fixed; isNew on embedded docs edge case (#680) + * updated; driver to 0.9.8-3 + * updated; expose `model()` method within static methods + +2.4.10 / 2012-01-10 +=================== + + * added; optional getter application in .toObject()/.toJSON() (#412) + * fixed; nested $operators in $all queries (#670) + * added; $nor support (#674) + * fixed; bug when adding nested schema (#662) [paulwe] + +2.4.9 / 2012-01-04 +=================== + + * updated; driver to 0.9.7-3-5 to fix Linux performance degradation on some boxes + +2.4.8 / 2011-12-22 +=================== + + * updated; bump -native to 0.9.7.2-5 + * fixed; compatibility with date.js (#646) [chrisleishman] + * changed; undocumented schema "lax" option to "strict" + * fixed; default value population for strict schemas + * updated; the nextTick helper for small performance gain. 1bee2a2 + +2.4.7 / 2011-12-16 +=================== + + * fixed; bug in 2.4.6 with path setting + * updated; bump -native to 0.9.7.2-1 + * added; strict schema option [nw] + +2.4.6 / 2011-12-16 +=================== + + * fixed; conflicting mods on update bug [sirlantis] + * improved; doc.id getter performance + +2.4.5 / 2011-12-14 +=================== + + * fixed; bad MongooseArray behavior in 2.4.2 - 2.4.4 + +2.4.4 / 2011-12-14 +=================== + + * fixed; MongooseArray#doAtomics throwing after sliced + +2.4.3 / 2011-12-14 +=================== + + * updated; system.profile schema for MongoDB 2x + +2.4.2 / 2011-12-12 +=================== + + * fixed; partially populating multiple children of subdocs (#639) [kenpratt] + * fixed; allow Update of numbers to null (#640) [jerem] + +2.4.1 / 2011-12-02 +=================== + + * added; options support for populate() queries + * updated; -native driver to 0.9.7-1.4 + +2.4.0 / 2011-11-29 +=================== + + * added; QueryStreams (#614) + * added; debug print mode for development + * added; $within support to Array queries (#586) [ggoodale] + * added; $centerSphere query support + * fixed; $within support + * added; $unset is now used when setting a path to undefined (#519) + * added; query#batchSize support + * updated; docs + * updated; -native driver to 0.9.7-1.3 (provides Windows support) + +2.3.13 / 2011-11-15 +=================== + + * fixed; required validation for Refs (#612) [ded] + * added; $nearSphere support for Arrays (#610) + +2.3.12 / 2011-11-09 +=================== + + * fixed; regression, objects passed to Model.update should not be changed (#605) + * fixed; regression, empty Model.update should not be executed + +2.3.11 / 2011-11-08 +=================== + + * fixed; using $elemMatch on arrays of Mixed types (#591) + * fixed; allow using $regex when querying Arrays (#599) + * fixed; calling Model.update with no atomic keys (#602) + +2.3.10 / 2011-11-05 +=================== + + * fixed; model.update casting for nested paths works (#542) + +2.3.9 / 2011-11-04 +================== + + * fixed; deepEquals check for MongooseArray returned false + * fixed; reset modified flags of embedded docs after save [gitfy] + * fixed; setting embedded doc with identical values no longer marks modified [gitfy] + * updated; -native driver to 0.9.6.23 [mlazarov] + * fixed; Model.update casting (#542, #545, #479) + * fixed; populated refs no longer fail required validators (#577) + * fixed; populating refs of objects with custom ids works + * fixed; $pop & $unset work with Model.update (#574) + * added; more helpful debugging message for Schema#add (#578) + * fixed; accessing .id when no _id exists now returns null (#590) + +2.3.8 / 2011-10-26 +================== + + * added; callback to query#findOne is now optional (#581) + +2.3.7 / 2011-10-24 +================== + + * fixed; wrapped save/remove callbacks in nextTick to mitigate -native swallowing thrown errors + +2.3.6 / 2011-10-21 +================== + + * fixed; exclusion of embedded doc _id from query results (#541) + +2.3.5 / 2011-10-19 +================== + + * fixed; calling queries without passing a callback works (#569) + * fixed; populate() works with String and Number _ids too (#568) + +2.3.4 / 2011-10-18 +================== + + * added; Model.create now accepts an array as a first arg + * fixed; calling toObject on a DocumentArray with nulls no longer throws + * fixed; calling inspect on a DocumentArray with nulls no longer throws + * added; MongooseArray#unshift support + * fixed; save hooks now fire on embedded documents [gitfy] (#456) + * updated; -native driver to 0.9.6-22 + * fixed; correctly pass $addToSet op instead of $push + * fixed; $addToSet properly detects dates + * fixed; $addToSet with multiple items works + * updated; better node 0.6 Buffer support + +2.3.3 / 2011-10-12 +================== + + * fixed; population conditions in multi-query settings [vedmalex] (#563) + * fixed; now compatible with Node v0.5.x + +2.3.2 / 2011-10-11 +================== + + * fixed; population of null subdoc properties no longer hangs (#561) + +2.3.1 / 2011-10-10 +================== + + * added; support for Query filters to populate() [eneko] + * fixed; querying with number no longer crashes mongodb (#555) [jlbyrey] + * updated; version of -native driver to 0.9.6-21 + * fixed; prevent query callbacks that throw errors from corrupting -native connection state + +2.3.0 / 2011-10-04 +================== + + * fixed; nulls as default values for Boolean now works as expected + * updated; version of -native driver to 0.9.6-20 + +2.2.4 / 2011-10-03 +================== + + * fixed; populate() works when returned array contains undefined/nulls + +2.2.3 / 2011-09-29 +================== + + * updated; version of -native driver to 0.9.6-19 + +2.2.2 / 2011-09-28 +================== + + * added; $regex support to String [davidandrewcope] + * added; support for other contexts like repl etc (#535) + * fixed; clear modified state properly after saving + * added; $addToSet support to Array + +2.2.1 / 2011-09-22 +================== + + * more descript error when casting undefined to string + * updated; version of -native driver to 0.9.6-18 + +2.2.0 / 2011-09-22 +================== + + * fixed; maxListeners warning on schemas with many arrays (#530) + * changed; return / apply defaults based on fields selected in query (#423) + * fixed; correctly detect Mixed types within schema arrays (#532) + +2.1.4 / 2011-09-20 +================== + + * fixed; new private methods that stomped on users code + * changed; finished removing old "compat" support which did nothing + +2.1.3 / 2011-09-16 +================== + + * updated; version of -native driver to 0.9.6-15 + * added; emit `error` on connection when open fails [edwardhotchkiss] + * added; index support to Buffers (thanks justmoon for helping track this down) + * fixed; passing collection name via schema in conn.model() now works (thanks vedmalex for reporting) + +2.1.2 / 2011-09-07 +================== + + * fixed; Query#find with no args no longer throws + +2.1.1 / 2011-09-07 +================== + + * added; support Model.count(fn) + * fixed; compatibility with node >=0.4.0 < 0.4.3 + * added; pass model.options.safe through with .save() so w:2, wtimeout:5000 options work [andrewjstone] + * added; support for $type queries + * added; support for Query#or + * added; more tests + * optimized populate queries + +2.1.0 / 2011-09-01 +================== + + * changed; document#validate is a public method + * fixed; setting number to same value no longer marks modified (#476) [gitfy] + * fixed; Buffers shouldn't have default vals + * added; allow specifying collection name in schema (#470) [ixti] + * fixed; reset modified paths and atomics after saved (#459) + * fixed; set isNew on embedded docs to false after save + * fixed; use self to ensure proper scope of options in doOpenSet (#483) [andrewjstone] + +2.0.4 / 2011-08-29 +================== + + * Fixed; Only send the depopulated ObjectId instead of the entire doc on save (DBRefs) + * Fixed; Properly cast nested array values in Model.update (the data was stored in Mongo incorrectly but recast on document fetch was "fixing" it) + +2.0.3 / 2011-08-28 +================== + + * Fixed; manipulating a populated array no longer causes infinite loop in BSON serializer during save (#477) + * Fixed; populating an empty array no longer hangs foreeeeeeeever (#481) + +2.0.2 / 2011-08-25 +================== + + * Fixed; Maintain query option key order (fixes 'bad hint' error from compound query hints) + +2.0.1 / 2011-08-25 +================== + + * Fixed; do not over-write the doc when no valide props exist in Model.update (#473) + +2.0.0 / 2011-08-24 +=================== + + * Added; support for Buffers [justmoon] + * Changed; improved error handling [maelstrom] + * Removed: unused utils.erase + * Fixed; support for passing other context object into Schemas (#234) [Sija] + * Fixed; getters are no longer circular refs to themselves (#366) + * Removed; unused compat.js + * Fixed; getter/setter scopes are set properly + * Changed; made several private properties more obvious by prefixing _ + * Added; DBRef support [guille] + * Changed; removed support for multiple collection names per model + * Fixed; no longer applying setters when document returned from db + * Changed; default auto_reconnect to true + * Changed; Query#bind no longer clones the query + * Fixed; Model.update now accepts $pull, $inc and friends (#404) + * Added; virtual type option support [nw] + +1.8.4 / 2011-08-21 +=================== + + * Fixed; validation bug when instantiated with non-schema properties (#464) [jmreidy] + +1.8.3 / 2011-08-19 +=================== + + * Fixed; regression in connection#open [jshaw86] + +1.8.2 / 2011-08-17 +=================== + + * fixed; reset connection.readyState after failure [tomseago] + * fixed; can now query positionally for non-embedded docs (arrays of numbers/strings etc) + * fixed; embedded document query casting + * added; support for passing options to node-mongo-native db, server, and replsetserver [tomseago] + +1.8.1 / 2011-08-10 +=================== + + * fixed; ObjectIds were always marked modified + * fixed; can now query using document instances + * fixed; can now query/update using documents with subdocs + +1.8.0 / 2011-08-04 +=================== + + * fixed; can now use $all with String and Number + * fixed; can query subdoc array with $ne: null + * fixed; instance.subdocs#id now works with custom _ids + * fixed; do not apply setters when doc returned from db (change in bad behavior) + +1.7.4 / 2011-07-25 +=================== + + * fixed; sparse now a valid seperate schema option + * fixed; now catching cast errors in queries + * fixed; calling new Schema with object created in vm.runInNewContext now works (#384) [Sija] + * fixed; String enum was disallowing null + * fixed; Find by nested document _id now works (#389) + +1.7.3 / 2011-07-16 +=================== + + * fixed; MongooseArray#indexOf now works with ObjectIds + * fixed; validation scope now set properly (#418) + * fixed; added missing colors dependency (#398) + +1.7.2 / 2011-07-13 +=================== + + * changed; node-mongodb-native driver to v0.9.6.7 + +1.7.1 / 2011-07-12 +=================== + + * changed; roll back node-mongodb-native driver to v0.9.6.4 + +1.7.0 / 2011-07-12 +=================== + + * fixed; collection name misspelling [mathrawka] + * fixed; 2nd param is required for ReplSetServers [kevinmarvin] + * fixed; MongooseArray behaves properly with Object.keys + * changed; node-mongodb-native driver to v0.9.6.6 + * fixed/changed; Mongodb segfault when passed invalid ObjectId (#407) + - This means invalid data passed to the ObjectId constructor will now error + +1.6.0 / 2011-07-07 +=================== + + * changed; .save() errors are now emitted on the instances db instead of the instance 9782463fc + * fixed; errors occurring when creating indexes now properly emit on db + * added; $maxDistance support to MongooseArrays + * fixed; RegExps now work with $all + * changed; node-mongodb-native driver to v0.9.6.4 + * fixed; model names are now accessible via .modelName + * added; Query#slaveOk support + +1.5.0 / 2011-06-27 +=================== + + * changed; saving without a callback no longer ignores the error (@bnoguchi) + * changed; hook-js version bump to 0.1.9 + * changed; node-mongodb-native version bumped to 0.9.6.1 - When .remove() doesn't + return an error, null is no longer passed. + * fixed; two memory leaks (@justmoon) + * added; sparse index support + * added; more ObjectId conditionals (gt, lt, gte, lte) (@phillyqueso) + * added; options are now passed in model#remote (@JerryLuke) + +1.4.0 / 2011-06-10 +=================== + + * bumped hooks-js dependency (fixes issue passing null as first arg to next()) + * fixed; document#inspect now works properly with nested docs + * fixed; 'set' now works as a schema attribute (GH-365) + * fixed; _id is now set properly within pre-init hooks (GH-289) + * added; Query#distinct / Model#distinct support (GH-155) + * fixed; embedded docs now can use instance methods (GH-249) + * fixed; can now overwrite strings conflicting with schema type + +1.3.7 / 2011-06-03 +=================== + + * added MongooseArray#splice support + * fixed; 'path' is now a valid Schema pathname + * improved hooks (utilizing https://github.com/bnoguchi/hooks-js) + * fixed; MongooseArray#$shift now works (never did) + * fixed; Document.modified no longer throws + * fixed; modifying subdoc property sets modified paths for subdoc and parent doc + * fixed; marking subdoc path as modified properly persists the value to the db + * fixed; RexExps can again be saved ( #357 ) + +1.3.6 / 2011-05-18 +=================== + + * fixed; corrected casting for queries against array types + * added; Document#set now accepts Document instances + +1.3.5 / 2011-05-17 +=================== + + * fixed; $ne queries work properly with single vals + * added; #inspect() methods to improve console.log output + +1.3.4 / 2011-05-17 +=================== + + * fixed; find by Date works as expected (#336) + * added; geospatial 2d index support + * added; support for $near (#309) + * updated; node-mongodb-native driver + * fixed; updating numbers work (#342) + * added; better error msg when try to remove an embedded doc without an _id (#307) + * added; support for 'on-the-fly' schemas (#227) + * changed; virtual id getters can now be skipped + * fixed; .index() called on subdoc schema now works as expected + * fixed; db.setProfile() now buffers until the db is open (#340) + +1.3.3 / 2011-04-27 +=================== + + * fixed; corrected query casting on nested mixed types + +1.3.2 / 2011-04-27 +=================== + + * fixed; query hints now retain key order + +1.3.1 / 2011-04-27 +=================== + + * fixed; setting a property on an embedded array no longer overwrites entire array (GH-310) + * fixed; setting nested properties works when sibling prop is named "type" + * fixed; isModified is now much finer grained when .set() is used (GH-323) + * fixed; mongoose.model() and connection.model() now return the Model (GH-308, GH-305) + * fixed; can now use $gt, $lt, $gte, $lte with String schema types (GH-317) + * fixed; .lowercase() -> .toLowerCase() in pluralize() + * fixed; updating an embedded document by index works (GH-334) + * changed; .save() now passes the instance to the callback (GH-294, GH-264) + * added; can now query system.profile and system.indexes collections + * added; db.model('system.profile') is now included as a default Schema + * added; db.setProfiling(level, ms, callback) + * added; Query#hint() support + * added; more tests + * updated node-mongodb-native to 0.9.3 + +1.3.0 / 2011-04-19 +=================== + + * changed; save() callbacks now fire only once on failed validation + * changed; Errors returned from save() callbacks now instances of ValidationError + * fixed; MongooseArray#indexOf now works properly + +1.2.0 / 2011-04-11 +=================== + + * changed; MongooseNumber now casts empty string to null + +1.1.25 / 2011-04-08 +=================== + + * fixed; post init now fires at proper time + +1.1.24 / 2011-04-03 +=================== + + * fixed; pushing an array onto an Array works on existing docs + +1.1.23 / 2011-04-01 +=================== + + * Added Model#model + +1.1.22 / 2011-03-31 +=================== + + * Fixed; $in queries on mixed types now work + +1.1.21 / 2011-03-31 +=================== + + * Fixed; setting object root to null/undefined works + +1.1.20 / 2011-03-31 +=================== + + * Fixed; setting multiple props on null field works + +1.1.19 / 2011-03-31 +=================== + + * Fixed; no longer using $set on paths to an unexisting fields + +1.1.18 / 2011-03-30 +=================== + + * Fixed; non-mixed type object setters work after initd from null + +1.1.17 / 2011-03-30 +=================== + + * Fixed; nested object property access works when root initd with null value + +1.1.16 / 2011-03-28 +=================== + + * Fixed; empty arrays are now saved + +1.1.15 / 2011-03-28 +=================== + + * Fixed; `null` and `undefined` are set atomically. + +1.1.14 / 2011-03-28 +=================== + + * Changed; more forgiving date casting, accepting '' as null. + +1.1.13 / 2011-03-26 +=================== + + * Fixed setting values as `undefined`. + +1.1.12 / 2011-03-26 +=================== + + * Fixed; nested objects now convert to JSON properly + * Fixed; setting nested objects directly now works + * Update node-mongodb-native + +1.1.11 / 2011-03-25 +=================== + + * Fixed for use of `type` as a key. + +1.1.10 / 2011-03-23 +=================== + + * Changed; Make sure to only ensure indexes while connected + +1.1.9 / 2011-03-2 +================== + + * Fixed; Mixed can now default to empty arrays + * Fixed; keys by the name 'type' are now valid + * Fixed; null values retrieved from the database are hydrated as null values. + * Fixed repeated atomic operations when saving a same document twice. + +1.1.8 / 2011-03-23 +================== + + * Fixed 'id' overriding. [bnoguchi] + +1.1.7 / 2011-03-22 +================== + + * Fixed RegExp query casting when querying against an Array of Strings [bnoguchi] + * Fixed getters/setters for nested virtualsl. [bnoguchi] + +1.1.6 / 2011-03-22 +================== + + * Only doValidate when path exists in Schema [aheckmann] + * Allow function defaults for Array types [aheckmann] + * Fix validation hang [aheckmann] + * Fix setting of isRequired of SchemaType [aheckmann] + * Fix SchemaType#required(false) filter [aheckmann] + * More backwards compatibility [aheckmann] + * More tests [aheckmann] + +1.1.5 / 2011-03-14 +================== + + * Added support for `uri, db, fn` and `uri, fn` signatures for replica sets. + * Improved/extended replica set tests. + +1.1.4 / 2011-03-09 +================== + + * Fixed; running an empty Query doesn't throw. [aheckmann] + * Changed; Promise#addBack returns promise. [aheckmann] + * Added streaming cursor support. [aheckmann] + * Changed; Query#update defaults to use$SetOnSave now. [brian] + * Added more docs. + +1.1.3 / 2011-03-04 +================== + + * Added Promise#resolve [aheckmann] + * Fixed backward compatibility with nulls [aheckmann] + * Changed; Query#{run,exec} return promises [aheckmann] + +1.1.2 / 2011-03-03 +================== + + * Restored Query#exec and added notion of default operation [brian] + * Fixed ValidatorError messages [brian] + +1.1.1 / 2011-03-01 +================== + + * Added SchemaType String `lowercase`, `uppercase`, `trim`. + * Public exports (`Model`, `Document`) and tests. + * Added ObjectId casting support for `Document`s. + +1.1.0 / 2011-02-25 +================== + + * Added support for replica sets. + +1.0.16 / 2011-02-18 +=================== + + * Added $nin as another whitelisted $conditional for SchemaArray [brian] + * Changed #with to #where [brian] + * Added ability to use $in conditional with Array types [brian] + +1.0.15 / 2011-02-18 +=================== + + * Added `id` virtual getter for documents to easily access the hexString of + the `_id`. + +1.0.14 / 2011-02-17 +=================== + + * Fix for arrays within subdocuments [brian] + +1.0.13 / 2011-02-16 +=================== + + * Fixed embedded documents saving. + +1.0.12 / 2011-02-14 +=================== + + * Minor refactorings [brian] + +1.0.11 / 2011-02-14 +=================== + + * Query refactor and $ne, $slice, $or, $size, $elemMatch, $nin, $exists support [brian] + * Named scopes sugar [brian] + +1.0.10 / 2011-02-11 +=================== + + * Updated node-mongodb-native driver [thanks John Allen] + +1.0.9 / 2011-02-09 +================== + + * Fixed single member arrays as defaults [brian] + +1.0.8 / 2011-02-09 +================== + + * Fixed for collection-level buffering of commands [gitfy] + * Fixed `Document#toJSON` [dalejefferson] + * Fixed `Connection` authentication [robrighter] + * Fixed clash of accessors in getters/setters [eirikurn] + * Improved `Model#save` promise handling + +1.0.7 / 2011-02-05 +================== + + * Fixed memory leak warnings for test suite on 0.3 + * Fixed querying documents that have an array that contain at least one + specified member. [brian] + * Fixed default value for Array types (fixes GH-210). [brian] + * Fixed example code. + +1.0.6 / 2011-02-03 +================== + + * Fixed `post` middleware + * Fixed; it's now possible to instantiate a model even when one of the paths maps + to an undefined value [brian] + +1.0.5 / 2011-02-02 +================== + + * Fixed; combo $push and $pushAll auto-converts into a $pushAll [brian] + * Fixed; combo $pull and $pullAll auto-converts to a single $pullAll [brian] + * Fixed; $pullAll now removes said members from array before save (so it acts just + like pushAll) [brian] + * Fixed; multiple $pulls and $pushes become a single $pullAll and $pushAll. + Moreover, $pull now modifies the array before save to reflect the immediate + change [brian] + * Added tests for nested shortcut getters [brian] + * Added tests that show that Schemas with nested Arrays don't apply defaults + [brian] + +1.0.4 / 2011-02-02 +================== + + * Added MongooseNumber#toString + * Added MongooseNumber unit tests + +1.0.3 / 2011-02-02 +================== + + * Make sure safe mode works with Model#save + * Changed Schema options: safe mode is now the default + * Updated node-mongodb-native to HEAD + +1.0.2 / 2011-02-02 +================== + + * Added a Model.create shortcut for creating documents. [brian] + * Fixed; we can now instantiate models with hashes that map to at least one + null value. [brian] + * Fixed Schema with more than 2 nested levels. [brian] + +1.0.1 / 2011-02-02 +================== + + * Improved `MongooseNumber`, works almost like the native except for `typeof` + not being `'number'`. diff --git a/test/node_modules/mongoose/README.md b/test/node_modules/mongoose/README.md new file mode 100644 index 0000000..06db9dc --- /dev/null +++ b/test/node_modules/mongoose/README.md @@ -0,0 +1,346 @@ +## What's Mongoose? + +Mongoose is a [MongoDB](http://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. + +Defining a model is as easy as: + + var Comment = new Schema({ + title : String + , body : String + , date : Date + }); + + var BlogPost = new Schema({ + author : ObjectId + , title : String + , body : String + , buf : Buffer + , date : Date + , comments : [Comment] + , meta : { + votes : Number + , favs : Number + } + }); + + var Post = mongoose.model('BlogPost', BlogPost); + +## Documentation + +[mongoosejs.com](http://mongoosejs.com/) + +## Try it live +
+## Installation
+
+The recommended way is through the excellent [NPM](http://www.npmjs.org/):
+
+ $ npm install mongoose
+
+Otherwise, you can check it in your repository and then expose it:
+
+ $ git clone git://github.com/LearnBoost/mongoose.git node_modules/mongoose/
+
+And install dependency modules written on `package.json`.
+
+Then you can `require` it:
+
+ require('mongoose')
+
+## Connecting to MongoDB
+
+First, we need to define a connection. If your app uses only one database, you should use `mongose.connect`. If you need to create additional connections, use `mongoose.createConnection`.
+
+Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`.
+
+ var mongoose = require('mongoose');
+
+ mongoose.connect('mongodb://localhost/my_database');
+
+Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`.
+
+**Important!** Mongoose buffers all the commands until it's connected to the database. This means that you don't have to wait until it connects to MongoDB in order to define models, run queries, etc.
+
+## Defining a Model
+
+Models are defined through the `Schema` interface.
+
+ var Schema = mongoose.Schema
+ , ObjectId = Schema.ObjectId;
+
+ var BlogPost = new Schema({
+ author : ObjectId
+ , title : String
+ , body : String
+ , date : Date
+ });
+
+Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of:
+
+* [Validators](http://mongoosejs.com/docs/validation.html) (async and sync)
+* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default)
+* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get)
+* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set)
+* [Indexes](http://mongoosejs.com/docs/guide.html#indexes)
+* [Middleware](http://mongoosejs.com/docs/middleware.html)
+* [Methods](http://mongoosejs.com/docs/guide.html#methods) definition
+* [Statics](http://mongoosejs.com/docs/guide.html#statics) definition
+* [Plugins](http://mongoosejs.com/docs/plugins.html)
+* [psuedo-JOINs](http://mongoosejs.com/docs/populate.html)
+
+The following example shows some of these features:
+
+ var Comment = new Schema({
+ name : { type: String, default: 'hahaha' }
+ , age : { type: Number, min: 18, index: true }
+ , bio : { type: String, match: /[a-z]/ }
+ , date : { type: Date, default: Date.now }
+ , buff : Buffer
+ });
+
+ // a setter
+ Comment.path('name').set(function (v) {
+ return capitalize(v);
+ });
+
+ // middleware
+ Comment.pre('save', function (next) {
+ notify(this.get('email'));
+ next();
+ });
+
+Take a look at the example in `examples/schema.js` for an end-to-end example of a typical setup.
+
+## Accessing a Model
+
+Once we define a model through `mongoose.model('ModelName', mySchema)`, we can access it through the same function
+
+ var myModel = mongoose.model('ModelName');
+
+Or just do it all at once
+
+ var MyModel = mongoose.model('ModelName', mySchema);
+
+We can then instantiate it, and save it:
+
+ var instance = new MyModel();
+ instance.my.key = 'hello';
+ instance.save(function (err) {
+ //
+ });
+
+Or we can find documents from the same collection
+
+ MyModel.find({}, function (err, docs) {
+ // docs.forEach
+ });
+
+You can also `findOne`, `findById`, `update`, etc. For more details check out [this link](http://mongoosejs.com/docs/queries.html).
+
+**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created:
+
+ var conn = mongoose.createConnection('your connection string');
+ var MyModel = conn.model('ModelName', schema);
+ var m = new MyModel;
+ m.save() // works
+
+ vs
+
+ var conn = mongoose.createConnection('your connection string');
+ var MyModel = mongoose.model('ModelName', schema);
+ var m = new MyModel;
+ m.save() // does not work b/c the default connection object was never connected
+
+## Embedded Documents
+
+In the first example snippet, we defined a key in the Schema that looks like:
+
+ comments: [Comments]
+
+Where `Comments` is a `Schema` we created. This means that creating embedded documents is as simple as:
+
+ // retrieve my model
+ var BlogPost = mongoose.model('BlogPost');
+
+ // create a blog post
+ var post = new BlogPost();
+
+ // create a comment
+ post.comments.push({ title: 'My comment' });
+
+ post.save(function (err) {
+ if (!err) console.log('Success!');
+ });
+
+The same goes for removing them:
+
+ BlogPost.findById(myId, function (err, post) {
+ if (!err) {
+ post.comments[0].remove();
+ post.save(function (err) {
+ // do something
+ });
+ }
+ });
+
+Embedded documents enjoy all the same features as your models. Defaults, validators, middleware. Whenever an error occurs, it's bubbled to the `save()` error callback, so error handling is a snap!
+
+Mongoose interacts with your embedded documents in arrays _atomically_, out of the box.
+
+## Middleware
+
+Middleware is one of the most exciting features about Mongoose. Middleware takes away all the pain of nested callbacks.
+
+Middleware are defined at the Schema level and are applied for the methods `init` (when a document is initialized with data from MongoDB), `save` (when a document or embedded document is saved).
+
+There's two types of middleware:
+
+- Serial
+ Serial middleware are defined like:
+
+ .pre(method, function (next, methodArg1, methodArg2, ...) {
+ // ...
+ })
+
+ They're executed one after the other, when each middleware calls `next`.
+
+ You can also intercept the `method`'s incoming arguments via your middleware -- notice `methodArg1`, `methodArg2`, etc in the `pre` definition above. See section "Intercepting and mutating method arguments" below.
+
+
+- Parallel
+ Parallel middleware offer more fine-grained flow control, and are defined like:
+
+ .pre(method, true, function (next, done, methodArg1, methodArg2) {
+ // ...
+ })
+
+ Parallel middleware can `next()` immediately, but the final argument will be called when all the parallel middleware have called `done()`.
+
+### Error handling
+
+If any middleware calls `next` or `done` with an `Error` instance, the flow is interrupted, and the error is passed to the function passed as an argument.
+
+For example:
+
+ schema.pre('save', function (next) {
+ // something goes wrong
+ next(new Error('something went wrong'));
+ });
+
+ // later...
+
+ myModel.save(function (err) {
+ // err can come from a middleware
+ });
+
+### Intercepting and mutating method arguments
+
+You can intercept method arguments via middleware.
+
+For example, this would allow you to broadcast changes about your Documents every time someone `set`s a path in your Document to a new value:
+
+ schema.pre('set', function (next, path, val, typel) {
+ // `this` is the current Document
+ this.emit('set', path, val);
+
+ // Pass control to the next pre
+ next();
+ });
+
+Moreover, you can mutate the incoming `method` arguments so that subsequent middleware see different values for those arguments. To do so, just pass the new values to `next`:
+
+ .pre(method, function firstPre (next, methodArg1, methodArg2) {
+ // Mutate methodArg1
+ next("altered-" + methodArg1.toString(), methodArg2);
+ })
+
+ // pre declaration is chainable
+ .pre(method, function secondPre (next, methodArg1, methodArg2) {
+ console.log(methodArg1);
+ // => 'altered-originalValOfMethodArg1'
+
+ console.log(methodArg2);
+ // => 'originalValOfMethodArg2'
+
+ // Passing no arguments to `next` automatically passes along the current argument values
+ // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)`
+ // and also equivalent to, with the example method arg
+ // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')`
+ next();
+ })
+
+### Schema gotcha
+
+`type`, when used in a schema has special meaning within Mongoose. If your schema requires using `type` as a nested property you must use object notation:
+
+ new Schema({
+ broken: { type: Boolean }
+ , asset : {
+ name: String
+ , type: String // uh oh, it broke. asset will be interpreted as String
+ }
+ });
+
+ new Schema({
+ works: { type: Boolean }
+ , asset : {
+ name: String
+ , type: { type: String } // works. asset is an object with a type property
+ }
+ });
+
+## API docs
+
+You can find the [Dox](http://github.com/visionmedia/dox) generated API docs [here](http://mongoosejs.com/docs/api.html).
+
+## Getting support
+
+- Google Groups [mailing list](http://groups.google.com/group/mongoose-orm)
+- (irc) #mongoosejs on freenode
+- reporting [issues](https://github.com/learnboost/mongoose/issues/)
+- [10gen](http://www.mongodb.org/display/DOCS/Technical+Support)
+
+## Driver access
+
+The driver being used defaults to [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) and is directly accessible through `YourModel.collection`. **Note**: using the driver directly bypasses all Mongoose power-tools like validation, getters, setters, hooks, etc.
+
+## Mongoose Plugins
+
+Take a peek at the [plugins search site](http://plugins.mongoosejs.com/) to see related modules from the community.
+
+## Contributing to Mongoose
+
+### Cloning the repository
+
+ git clone git://github.com/LearnBoost/mongoose.git
+
+### Guidelines
+
+See [contributing](http://mongoosejs.com/docs/contributing.html).
+
+## Credits
+
+[contributors](https://github.com/learnboost/mongoose/graphs/contributors)
+
+## License
+
+Copyright (c) 2010-2012 LearnBoost <dev@learnboost.com>
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/test/node_modules/mongoose/examples/schema.js b/test/node_modules/mongoose/examples/schema.js
new file mode 100644
index 0000000..d108d05
--- /dev/null
+++ b/test/node_modules/mongoose/examples/schema.js
@@ -0,0 +1,102 @@
+
+/**
+ * Module dependencies.
+ */
+
+var mongoose = require('mongoose')
+ , Schema = mongoose.Schema;
+
+/**
+ * Schema definition
+ */
+
+// recursive embedded-document schema
+
+var Comment = new Schema();
+
+Comment.add({
+ title : { type: String, index: true }
+ , date : Date
+ , body : String
+ , comments : [Comment]
+});
+
+var BlogPost = new Schema({
+ title : { type: String, index: true }
+ , slug : { type: String, lowercase: true, trim: true }
+ , date : Date
+ , buf : Buffer
+ , comments : [Comment]
+ , creator : Schema.ObjectId
+});
+
+var Person = new Schema({
+ name: {
+ first: String
+ , last : String
+ }
+ , email: { type: String, required: true, index: { unique: true, sparse: true } }
+ , alive: Boolean
+});
+
+/**
+ * Accessing a specific schema type by key
+ */
+
+BlogPost.path('date')
+.default(function(){
+ return new Date()
+ })
+.set(function(v){
+ return v == 'now' ? new Date() : v;
+ });
+
+/**
+ * Pre hook.
+ */
+
+BlogPost.pre('save', function(next, done){
+ emailAuthor(done); // some async function
+ next();
+});
+
+/**
+ * Methods
+ */
+
+BlogPost.methods.findCreator = function (callback) {
+ return this.db.model('Person').findById(this.creator, callback);
+}
+
+BlogPost.statics.findByTitle = function (title, callback) {
+ return this.find({ title: title }, callback);
+}
+
+BlogPost.methods.expressiveQuery = function (creator, date, callback) {
+ return this.find('creator', creator).where('date').gte(date).run(callback);
+}
+
+/**
+ * Plugins
+ */
+
+function slugGenerator (options){
+ options = options || {};
+ var key = options.key || 'title';
+
+ return function slugGenerator(schema){
+ schema.path(key).set(function(v){
+ this.slug = v.toLowerCase().replace(/[^a-z0-9]/g, '').replace(/-+/g, '');
+ return v;
+ });
+ };
+};
+
+BlogPost.plugin(slugGenerator());
+
+/**
+ * Define model.
+ */
+
+mongoose.model('BlogPost', BlogPost);
+mongoose.model('Person', Person);
diff --git a/test/node_modules/mongoose/index.js b/test/node_modules/mongoose/index.js
new file mode 100644
index 0000000..e7e6278
--- /dev/null
+++ b/test/node_modules/mongoose/index.js
@@ -0,0 +1,7 @@
+
+/**
+ * Export lib/mongoose
+ *
+ */
+
+module.exports = require('./lib/');
diff --git a/test/node_modules/mongoose/lib/collection.js b/test/node_modules/mongoose/lib/collection.js
new file mode 100644
index 0000000..1c2ab7d
--- /dev/null
+++ b/test/node_modules/mongoose/lib/collection.js
@@ -0,0 +1,177 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var STATES = require('./connectionstate')
+
+/**
+ * Abstract Collection constructor
+ *
+ * This is the base class that drivers inherit from and implement.
+ *
+ * @param {String} name name of the collection
+ * @param {Connection} conn A MongooseConnection instance
+ * @param {Object} opts optional collection options
+ * @api public
+ */
+
+function Collection (name, conn, opts) {
+ this.name = name;
+ this.conn = conn;
+ this.buffer = true;
+ this.queue = [];
+
+ if ('number' == typeof opts) opts = { size: opts };
+ this.opts = opts || {};
+
+ if (STATES.connected == this.conn.readyState) {
+ this.onOpen();
+ }
+};
+
+/**
+ * The collection name
+ *
+ * @api public
+ * @property name
+ */
+
+Collection.prototype.name;
+
+/**
+ * The Connection instance
+ *
+ * @api public
+ * @property conn
+ */
+
+Collection.prototype.conn;
+
+/**
+ * Called when the database connects
+ *
+ * @api private
+ */
+
+Collection.prototype.onOpen = function () {
+ var self = this;
+ this.buffer = false;
+ self.doQueue();
+};
+
+/**
+ * Called when the database disconnects
+ *
+ * @api private
+ */
+
+Collection.prototype.onClose = function () {
+ this.buffer = true;
+};
+
+/**
+ * Queues a method for later execution when its
+ * database connection opens.
+ *
+ * @param {String} name name of the method to queue
+ * @param {Array} args arguments to pass to the method when executed
+ * @api private
+ */
+
+Collection.prototype.addQueue = function (name, args) {
+ this.queue.push([name, args]);
+ return this;
+};
+
+/**
+ * Executes all queued methods and clears the queue.
+ *
+ * @api private
+ */
+
+Collection.prototype.doQueue = function () {
+ for (var i = 0, l = this.queue.length; i < l; i++){
+ this[this.queue[i][0]].apply(this, this.queue[i][1]);
+ }
+ this.queue = [];
+ return this;
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.ensureIndex = function(){
+ throw new Error('Collection#ensureIndex unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findAndModify = function(){
+ throw new Error('Collection#findAndModify unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findOne = function(){
+ throw new Error('Collection#findOne unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.find = function(){
+ throw new Error('Collection#find unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.insert = function(){
+ throw new Error('Collection#insert unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.save = function(){
+ throw new Error('Collection#save unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.update = function(){
+ throw new Error('Collection#update unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.getIndexes = function(){
+ throw new Error('Collection#getIndexes unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.mapReduce = function(){
+ throw new Error('Collection#mapReduce unimplemented by driver');
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Collection;
diff --git a/test/node_modules/mongoose/lib/connection.js b/test/node_modules/mongoose/lib/connection.js
new file mode 100644
index 0000000..dc48644
--- /dev/null
+++ b/test/node_modules/mongoose/lib/connection.js
@@ -0,0 +1,680 @@
+/*!
+ * Module dependencies.
+ */
+
+var url = require('url')
+ , utils = require('./utils')
+ , EventEmitter = utils.EventEmitter
+ , driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native'
+ , Model = require('./model')
+ , Schema = require('./schema')
+ , Collection = require(driver + '/collection')
+ , STATES = require('./connectionstate')
+ , MongooseError = require('./error')
+ , assert =require('assert')
+ , muri = require('muri')
+
+/*!
+ * Protocol prefix regexp.
+ *
+ * @api private
+ */
+
+var rgxProtocol = /^(?:.)+:\/\//;
+
+/**
+ * Connection constructor
+ *
+ * For practical reasons, a Connection equals a Db.
+ *
+ * @param {Mongoose} base a mongoose instance
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `connecting`: Emitted when `connection.{open,openSet}()` is executed on this connection.
+ * @event `connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios.
+ * @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models.
+ * @event `disconnecting`: Emitted when `connection.close()` was executed.
+ * @event `disconnected`: Emitted after getting disconnected from the db.
+ * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models.
+ * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successfull connection.
+ * @event `error`: Emitted when an error occurs on this connection.
+ * @event `fullsetup`: Emitted in a replica-set scenario, when all nodes specified in the connection string are connected.
+ * @api public
+ */
+
+function Connection (base) {
+ this.base = base;
+ this.collections = {};
+ this.models = {};
+ this.replica = false;
+ this.hosts = null;
+ this.host = null;
+ this.port = null;
+ this.user = null;
+ this.pass = null;
+ this.name = null;
+ this.options = null;
+ this._readyState = STATES.disconnected;
+ this._closeCalled = false;
+ this._hasOpened = false;
+};
+
+/*!
+ * Inherit from EventEmitter
+ */
+
+Connection.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Connection ready state
+ *
+ * - 0 = disconnected
+ * - 1 = connected
+ * - 2 = connecting
+ * - 3 = disconnecting
+ *
+ * Each state change emits its associated event name.
+ *
+ * ####Example
+ *
+ * conn.on('connected', callback);
+ * conn.on('disconnected', callback);
+ *
+ * @property readyState
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'readyState', {
+ get: function(){ return this._readyState; }
+ , set: function (val) {
+ if (!(val in STATES)) {
+ throw new Error('Invalid connection state: ' + val);
+ }
+
+ if (this._readyState !== val) {
+ this._readyState = val;
+
+ if (STATES.connected === val)
+ this._hasOpened = true;
+
+ this.emit(STATES[val]);
+ }
+ }
+});
+
+/**
+ * A hash of the collections associated with this connection
+ *
+ * @property collections
+ */
+
+Connection.prototype.collections;
+
+/**
+ * The mongodb.Db instance, set when the connection is opened
+ *
+ * @property db
+ */
+
+Connection.prototype.db;
+
+/**
+ * Opens the connection to MongoDB.
+ *
+ * `options` is a hash with the following possible properties:
+ *
+ * db - passed to the connection db instance
+ * server - passed to the connection server instance(s)
+ * replset - passed to the connection ReplSet instance
+ * user - username for authentication
+ * pass - password for authentication
+ *
+ * ####Notes:
+ *
+ * Mongoose forces the db option `forceServerObjectId` false and cannot be overridden.
+ * Mongoose defaults the server `auto_reconnect` options to true which can be overridden.
+ * See the node-mongodb-native driver instance for options that it understands.
+ *
+ * _Options passed take precedence over options included in connection strings._
+ *
+ * @param {String} connection_string mongodb://uri or the host to which you are connecting
+ * @param {String} [database] database name
+ * @param {Number} [port] database port
+ * @param {Object} [options] options
+ * @param {Function} [callback]
+ * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native
+ * @api public
+ */
+
+Connection.prototype.open = function (host, database, port, options, callback) {
+ var self = this
+ , parsed
+ , uri;
+
+ if ('string' === typeof database) {
+ switch (arguments.length) {
+ case 2:
+ port = 27017;
+ case 3:
+ switch (typeof port) {
+ case 'function':
+ callback = port, port = 27017;
+ break;
+ case 'object':
+ options = port, port = 27017;
+ break;
+ }
+ break;
+ case 4:
+ if ('function' === typeof options)
+ callback = options, options = {};
+ }
+ } else {
+ switch (typeof database) {
+ case 'function':
+ callback = database, database = undefined;
+ break;
+ case 'object':
+ options = database;
+ database = undefined;
+ callback = port;
+ break;
+ }
+
+ if (!rgxProtocol.test(host)) {
+ host = 'mongodb://' + host;
+ }
+
+ try {
+ parsed = muri(host);
+ } catch (err) {
+ this.error(err, callback);
+ return this;
+ }
+
+ database = parsed.db;
+ host = parsed.hosts[0].host || parsed.hosts[0].ipc;
+ port = parsed.hosts[0].port || 27017;
+ }
+
+ this.options = this.parseOptions(options, parsed && parsed.options);
+
+ // make sure we can open
+ if (STATES.disconnected !== this.readyState) {
+ var err = new Error('Trying to open unclosed connection.');
+ err.state = this.readyState;
+ this.error(err, callback);
+ return this;
+ }
+
+ if (!host) {
+ this.error(new Error('Missing hostname.'), callback);
+ return this;
+ }
+
+ if (!database) {
+ this.error(new Error('Missing database name.'), callback);
+ return this;
+ }
+
+ // authentication
+ if (options && options.user && options.pass) {
+ this.user = options.user;
+ this.pass = options.pass;
+
+ } else if (parsed && parsed.auth) {
+ this.user = parsed.auth.user;
+ this.pass = parsed.auth.pass;
+
+ // Check hostname for user/pass
+ } else if (/@/.test(host) && /:/.test(host.split('@')[0])) {
+ host = host.split('@');
+ var auth = host.shift().split(':');
+ host = host.pop();
+ this.user = auth[0];
+ this.pass = auth[1];
+
+ } else {
+ this.user = this.pass = undefined;
+ }
+
+ this.name = database;
+ this.host = host;
+ this.port = port;
+
+ this._open(callback);
+ return this;
+};
+
+/**
+ * Connects to a replica set.
+ *
+ * ####Example:
+ *
+ * var db = mongoose.createConnection();
+ * db.openSet("mongodb://user:pwd@localhost:27020/testing,mongodb://example.com:27020,mongodb://localhost:27019");
+ *
+ * The database name and/or auth need only be included in one URI.
+ * The `options` is a hash which is passed to the internal driver connection object.
+ *
+ * Valid `options`
+ *
+ * db - passed to the connection db instance
+ * server - passed to the connection server instance(s)
+ * replset - passed to the connection ReplSetServer instance
+ * user - username for authentication
+ * pass - password for authentication
+ *
+ * _Options passed take precedence over options included in connection strings._
+ *
+ * @param {String} uris comma-separated mongodb:// `URI`s
+ * @param {String} [database] database name if not included in `uris`
+ * @param {Object} [options] passed to the internal driver
+ * @param {Function} [callback]
+ * @see node-mongodb-native https://github.com/mongodb/node-mongodb-native
+ * @api public
+ */
+
+Connection.prototype.openSet = function (uris, database, options, callback) {
+ if (!rgxProtocol.test(uris)) {
+ uris = 'mongodb://' + uris;
+ }
+
+ var self = this;
+
+ switch (arguments.length) {
+ case 3:
+ switch (typeof database) {
+ case 'string':
+ this.name = database;
+ break;
+ case 'object':
+ callback = options;
+ options = database;
+ database = null;
+ break;
+ }
+
+ if ('function' === typeof options) {
+ callback = options;
+ options = {};
+ }
+ break;
+ case 2:
+ switch (typeof database) {
+ case 'string':
+ this.name = database;
+ break;
+ case 'function':
+ callback = database, database = null;
+ break;
+ case 'object':
+ options = database, database = null;
+ break;
+ }
+ }
+
+ var parsed;
+ try {
+ parsed = muri(uris);
+ } catch (err) {
+ this.error(err, callback);
+ return this;
+ }
+
+ if (!this.name) {
+ this.name = parsed.db;
+ }
+
+ this.hosts = parsed.hosts;
+ this.options = this.parseOptions(options, parsed && parsed.options);
+ this.replica = true;
+
+ if (!this.name) {
+ this.error(new Error('No database name provided for replica set'), callback);
+ return this;
+ }
+
+ // authentication
+ if (options && options.user && options.pass) {
+ this.user = options.user;
+ this.pass = options.pass;
+
+ } else if (parsed && parsed.auth) {
+ this.user = parsed.auth.user;
+ this.pass = parsed.auth.pass;
+
+ } else {
+ this.user = this.pass = undefined;
+ }
+
+ this._open(callback);
+ return this;
+};
+
+/**
+ * error
+ *
+ * Graceful error handling, passes error to callback
+ * if available, else emits error on the connection.
+ *
+ * @param {Error} err
+ * @param {Function} callback optional
+ * @api private
+ */
+
+Connection.prototype.error = function (err, callback) {
+ if (callback) return callback(err);
+ this.emit('error', err);
+}
+
+/**
+ * Handles opening the connection with the appropriate method based on connection type.
+ *
+ * @param {Function} callback
+ * @api private
+ */
+
+Connection.prototype._open = function (callback) {
+ this.readyState = STATES.connecting;
+ this._closeCalled = false;
+
+ var self = this;
+
+ var method = this.replica
+ ? 'doOpenSet'
+ : 'doOpen';
+
+ // open connection
+ this[method](function (err) {
+ if (err) {
+ self.readyState = STATES.disconnected;
+ if (self._hasOpened) {
+ if (callback) callback(err);
+ } else {
+ self.error(err, callback);
+ }
+ return;
+ }
+
+ self.onOpen(callback);
+ });
+}
+
+/**
+ * Called when the connection is opened
+ *
+ * @api private
+ */
+
+Connection.prototype.onOpen = function (callback) {
+ var self = this;
+
+ function open (err) {
+ if (err) {
+ self.readyState = STATES.disconnected;
+ if (self._hasOpened) {
+ if (callback) callback(err);
+ } else {
+ self.error(err, callback);
+ }
+ return;
+ }
+
+ self.readyState = STATES.connected;
+
+ // avoid having the collection subscribe to our event emitter
+ // to prevent 0.3 warning
+ for (var i in self.collections)
+ self.collections[i].onOpen();
+
+ callback && callback();
+ self.emit('open');
+ };
+
+ // re-authenticate
+ if (self.user && self.pass) {
+ self.db.authenticate(self.user, self.pass, open);
+ }
+ else
+ open();
+};
+
+/**
+ * Closes the connection
+ *
+ * @param {Function} [callback] optional
+ * @return {Connection} self
+ * @api public
+ */
+
+Connection.prototype.close = function (callback) {
+ var self = this;
+ this._closeCalled = true;
+
+ switch (this.readyState){
+ case 0: // disconnected
+ callback && callback();
+ break;
+
+ case 1: // connected
+ this.readyState = STATES.disconnecting;
+ this.doClose(function(err){
+ if (err){
+ self.error(err, callback);
+ } else {
+ self.onClose();
+ callback && callback();
+ }
+ });
+ break;
+
+ case 2: // connecting
+ this.once('open', function(){
+ self.close(callback);
+ });
+ break;
+
+ case 3: // disconnecting
+ if (!callback) break;
+ this.once('close', function () {
+ callback();
+ });
+ break;
+ }
+
+ return this;
+};
+
+/**
+ * Called when the connection closes
+ *
+ * @api private
+ */
+
+Connection.prototype.onClose = function () {
+ this.readyState = STATES.disconnected;
+
+ // avoid having the collection subscribe to our event emitter
+ // to prevent 0.3 warning
+ for (var i in this.collections)
+ this.collections[i].onClose();
+
+ this.emit('close');
+};
+
+/**
+ * Retrieves a collection, creating it if not cached.
+ *
+ * @param {String} name of the collection
+ * @param {Object} [options] optional collection options
+ * @return {Collection} collection instance
+ * @api public
+ */
+
+Connection.prototype.collection = function (name, options) {
+ if (!(name in this.collections))
+ this.collections[name] = new Collection(name, this, options);
+ return this.collections[name];
+};
+
+/**
+ * Defines or retrieves a model.
+ *
+ * var mongoose = require('mongoose');
+ * var db = mongoose.createConnection(..);
+ * db.model('Venue', new Schema(..));
+ * var Ticket = db.model('Ticket', new Schema(..));
+ * var Venue = db.model('Venue');
+ *
+ * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._
+ *
+ * ####Example:
+ *
+ * var schema = new Schema({ name: String }, { collection: 'actor' });
+ *
+ * // or
+ *
+ * schema.set('collection', 'actor');
+ *
+ * // or
+ *
+ * var collectionName = 'actor'
+ * var M = conn.model('Actor', schema, collectionName)
+ *
+ * @param {String} name the model name
+ * @param {Schema} [schema] a schema. necessary when defining a model
+ * @param {String} [collection] name of mongodb collection (optional) if not given it will be induced from model name
+ * @see Mongoose#model #index_Mongoose-model
+ * @return {Model} The compiled model
+ * @api public
+ */
+
+Connection.prototype.model = function (name, schema, collection) {
+ // collection name discovery
+ if ('string' == typeof schema) {
+ collection = schema;
+ schema = false;
+ }
+
+ if (this.models[name] && !collection) {
+ // model exists but we are not subclassing with custom collection
+ if (schema instanceof Schema && schema != this.models[name].schema) {
+ throw new MongooseError.OverwriteModelError(name);
+ }
+ return this.models[name];
+ }
+
+ var opts = { cache: false, connection: this }
+ var model;
+
+ if (schema instanceof Schema) {
+ // compile a model
+ model = this.base.model(name, schema, collection, opts)
+
+ // only the first model with this name is cached to allow
+ // for one-offs with custom collection names etc.
+ if (!this.models[name]) {
+ this.models[name] = model;
+ }
+
+ model.init();
+ return model;
+ }
+
+ if (this.models[name] && collection) {
+ // subclassing current model with alternate collection
+ model = this.models[name];
+ schema = model.prototype.schema;
+ var sub = model.__subclass(this, schema, collection);
+ // do not cache the sub model
+ return sub;
+ }
+
+ // lookup model in mongoose module
+ model = this.base.models[name];
+
+ if (!model) {
+ throw new MongooseError.MissingSchemaError(name);
+ }
+
+ if (this == model.prototype.db
+ && (!collection || collection == model.collection.name)) {
+ // model already uses this connection.
+
+ // only the first model with this name is cached to allow
+ // for one-offs with custom collection names etc.
+ if (!this.models[name]) {
+ this.models[name] = model;
+ }
+
+ return model;
+ }
+
+ return this.models[name] = model.__subclass(this, schema, collection);
+}
+
+/**
+ * Set profiling level.
+ *
+ * @param {Number|String} level either off (0), slow (1), or all (2)
+ * @param {Number} [ms] the threshold in milliseconds above which queries will be logged when in `slow` mode. defaults to 100.
+ * @param {Function} callback
+ * @api public
+ */
+
+Connection.prototype.setProfiling = function (level, ms, callback) {
+ if (STATES.connected !== this.readyState) {
+ return this.on('open', this.setProfiling.bind(this, level, ms, callback));
+ }
+
+ if (!callback) callback = ms, ms = 100;
+
+ var cmd = {};
+
+ switch (level) {
+ case 0:
+ case 'off':
+ cmd.profile = 0;
+ break;
+ case 1:
+ case 'slow':
+ cmd.profile = 1;
+ if ('number' !== typeof ms) {
+ ms = parseInt(ms, 10);
+ if (isNaN(ms)) ms = 100;
+ }
+ cmd.slowms = ms;
+ break;
+ case 2:
+ case 'all':
+ cmd.profile = 2;
+ break;
+ default:
+ return callback(new Error('Invalid profiling level: '+ level));
+ }
+
+ this.db.executeDbCommand(cmd, function (err, resp) {
+ if (err) return callback(err);
+
+ var doc = resp.documents[0];
+
+ err = 1 === doc.ok
+ ? null
+ : new Error('Could not set profiling level to: '+ level)
+
+ callback(err, doc);
+ });
+};
+
+/*!
+ * Noop.
+ */
+
+function noop () {}
+
+/*!
+ * Module exports.
+ */
+
+Connection.STATES = STATES;
+module.exports = Connection;
diff --git a/test/node_modules/mongoose/lib/connectionstate.js b/test/node_modules/mongoose/lib/connectionstate.js
new file mode 100644
index 0000000..2d05ab0
--- /dev/null
+++ b/test/node_modules/mongoose/lib/connectionstate.js
@@ -0,0 +1,24 @@
+
+/*!
+ * Connection states
+ */
+
+var STATES = module.exports = exports = Object.create(null);
+
+var disconnected = 'disconnected';
+var connected = 'connected';
+var connecting = 'connecting';
+var disconnecting = 'disconnecting';
+var uninitialized = 'uninitialized';
+
+STATES[0] = disconnected;
+STATES[1] = connected;
+STATES[2] = connecting;
+STATES[3] = disconnecting;
+STATES[99] = uninitialized;
+
+STATES[disconnected] = 0;
+STATES[connected] = 1;
+STATES[connecting] = 2;
+STATES[disconnecting] = 3;
+STATES[uninitialized] = 99;
diff --git a/test/node_modules/mongoose/lib/document.js b/test/node_modules/mongoose/lib/document.js
new file mode 100644
index 0000000..3e4e9d6
--- /dev/null
+++ b/test/node_modules/mongoose/lib/document.js
@@ -0,0 +1,1520 @@
+/*!
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+ , MongooseError = require('./error')
+ , MixedSchema = require('./schema/mixed')
+ , Schema = require('./schema')
+ , ValidatorError = require('./schematype').ValidatorError
+ , utils = require('./utils')
+ , clone = utils.clone
+ , isMongooseObject = utils.isMongooseObject
+ , inspect = require('util').inspect
+ , StateMachine = require('./statemachine')
+ , ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')
+ , ValidationError = require('./errors/validation')
+ , DocumentError = require('./errors/document')
+ , deepEqual = utils.deepEqual
+ , hooks = require('hooks')
+ , DocumentArray
+ , MongooseArray
+
+/**
+ * Document constructor.
+ *
+ * @param {Object} obj the values to set
+ * @param {Object} [fields] the fields which were selected in the query returning this document
+ * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `init`: Emitted on a document after it has was retreived from the db and fully hydrated by Mongoose.
+ * @event `save`: Emitted when the document is successfully saved
+ * @api private
+ */
+
+function Document (obj, fields, skipId) {
+ // node <0.4.3 bug
+ if (!this._events) this._events = {};
+ this.setMaxListeners(0);
+
+ if ('boolean' === typeof fields) {
+ this._strictMode = fields;
+ this._selected = fields = undefined;
+ } else {
+ this._strictMode = this.schema.options && this.schema.options.strict;
+ this._selected = fields;
+ }
+
+ this.isNew = true;
+ this.errors = undefined;
+ this._shardval = undefined;
+ this._saveError = undefined;
+ this._validationError = undefined;
+ this._adhocPaths = undefined;
+ this._removing = undefined;
+ this._inserting = undefined;
+ this.__version = undefined;
+ this.__getters = {};
+ this.__id = undefined;
+
+ this._activePaths = new ActiveRoster;
+
+ var required = this.schema.requiredPaths();
+ for (var i = 0; i < required.length; ++i) {
+ this._activePaths.require(required[i]);
+ }
+
+ this._doc = this._buildDoc(obj, fields, skipId);
+ if (obj) this.set(obj, undefined, true);
+ this._registerHooks();
+};
+
+/*!
+ * Inherit from EventEmitter.
+ */
+
+Document.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * The documents schema.
+ *
+ * @api public
+ * @property schema
+ */
+
+Document.prototype.schema;
+
+/**
+ * Boolean flag specifying if the document is new.
+ *
+ * @api public
+ * @property isNew
+ */
+
+Document.prototype.isNew;
+
+/**
+ * The string version of this documents _id.
+ *
+ * ####Note:
+ *
+ * This getter exists on all documents by default. The getter can be disabled by setting the `id` [option](/docs/guide.html#id) of its `Schema` to false at construction time.
+ *
+ * new Schema({ name: String }, { id: false });
+ *
+ * @api public
+ * @see Schema options /docs/guide.html#options
+ * @property id
+ */
+
+Document.prototype.id;
+
+/**
+ * Hash containing current validation errors.
+ *
+ * @api public
+ * @property errors
+ */
+
+Document.prototype.errors;
+
+/**
+ * Builds the default doc structure
+ *
+ * @param {Object} obj
+ * @param {Object} [fields]
+ * @param {Boolean} [skipId]
+ * @return {Object}
+ * @api private
+ */
+
+Document.prototype._buildDoc = function (obj, fields, skipId) {
+ var doc = {}
+ , self = this
+ , exclude
+ , keys
+ , key
+ , ki
+
+ // determine if this doc is a result of a query with
+ // excluded fields
+ if (fields && 'Object' === fields.constructor.name) {
+ keys = Object.keys(fields);
+ ki = keys.length;
+
+ while (ki--) {
+ if ('_id' !== keys[ki]) {
+ exclude = 0 === fields[keys[ki]];
+ break;
+ }
+ }
+ }
+
+ var paths = Object.keys(this.schema.paths)
+ , plen = paths.length
+ , ii = 0
+
+ for (; ii < plen; ++ii) {
+ var p = paths[ii];
+
+ if ('_id' == p) {
+ if (skipId) continue;
+ if (obj && '_id' in obj) continue;
+ }
+
+ var type = this.schema.paths[p]
+ , path = p.split('.')
+ , len = path.length
+ , last = len-1
+ , doc_ = doc
+ , i = 0
+
+ for (; i < len; ++i) {
+ var piece = path[i]
+ , def
+
+ if (i === last) {
+ if (fields) {
+ if (exclude) {
+ // apply defaults to all non-excluded fields
+ if (p in fields) continue;
+
+ def = type.getDefault(self, true);
+ if ('undefined' !== typeof def) {
+ doc_[piece] = def;
+ self._activePaths.default(p);
+ }
+
+ } else if (p in fields) {
+ // selected field
+ def = type.getDefault(self, true);
+ if ('undefined' !== typeof def) {
+ doc_[piece] = def;
+ self._activePaths.default(p);
+ }
+ }
+ } else {
+ def = type.getDefault(self, true);
+ if ('undefined' !== typeof def) {
+ doc_[piece] = def;
+ self._activePaths.default(p);
+ }
+ }
+ } else {
+ doc_ = doc_[piece] || (doc_[piece] = {});
+ }
+ }
+ };
+
+ return doc;
+};
+
+/**
+ * Initializes the document without setters or marking anything modified.
+ *
+ * Called internally after a document is returned from mongodb.
+ *
+ * @param {Object} doc document returned by mongo
+ * @param {Function} fn callback
+ * @api private
+ */
+
+Document.prototype.init = function (doc, fn) {
+ this.isNew = false;
+
+ init(this, doc, this._doc);
+ this._storeShard();
+
+ this.emit('init', this);
+ if (fn) fn(null);
+ return this;
+};
+
+/*!
+ * Init helper.
+ *
+ * @param {Object} self document instance
+ * @param {Object} obj raw mongodb doc
+ * @param {Object} doc object we are initializing
+ * @api private
+ */
+
+function init (self, obj, doc, prefix) {
+ prefix = prefix || '';
+
+ var keys = Object.keys(obj)
+ , len = keys.length
+ , schema
+ , path
+ , i;
+
+ while (len--) {
+ i = keys[len];
+ path = prefix + i;
+ schema = self.schema.path(path);
+
+ if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
+ // assume nested object
+ if (!doc[i]) {
+ doc[i] = {};
+ }
+ init(self, obj[i], doc[i], path + '.');
+ } else {
+ if (obj[i] === null) {
+ doc[i] = null;
+ } else if (obj[i] !== undefined) {
+ if (schema) {
+ self.try(function(){
+ doc[i] = schema.cast(obj[i], self, true);
+ });
+ } else {
+ doc[i] = obj[i];
+ }
+ }
+ // mark as hydrated
+ self._activePaths.init(path);
+ }
+ }
+};
+
+/**
+ * Stores the current values of the shard keys.
+ *
+ * ####Note:
+ *
+ * _Shard key values do not / are not allowed to change._
+ *
+ * @api private
+ */
+
+Document.prototype._storeShard = function _storeShard () {
+ // backwards compat
+ var key = this.schema.options.shardKey || this.schema.options.shardkey;
+ if (!(key && 'Object' == key.constructor.name)) return;
+
+ var orig = this._shardval = {}
+ , paths = Object.keys(key)
+ , len = paths.length
+ , val
+
+ for (var i = 0; i < len; ++i) {
+ val = this.getValue(paths[i]);
+ if (isMongooseObject(val)) {
+ orig[paths[i]] = val.toObject({ depopulate: true })
+ } else if (null != val && val.valueOf) {
+ orig[paths[i]] = val.valueOf();
+ } else {
+ orig[paths[i]] = val;
+ }
+ }
+}
+
+/*!
+ * Set up middleware support
+ */
+
+for (var k in hooks) {
+ Document.prototype[k] = Document[k] = hooks[k];
+}
+
+/**
+ * Sends an update command with this document `_id` as the query selector.
+ *
+ * ####Example:
+ *
+ * weirdCar.update({$inc: {wheels:1}}, { safe: true }, callback);
+ *
+ * ####Valid options:
+ *
+ * - `safe` safe mode (defaults to value set in schema (true))
+ * - `upsert` (boolean) whether to create the doc if it doesn't match (false)
+ *
+ * @param {Object} doc
+ * @param {Object} options
+ * @param {Function} callback
+ * @return {Query}
+ * @api public
+ */
+
+Document.prototype.update = function update () {
+ var args = utils.args(arguments);
+ args.unshift({_id: this._id});
+ this.constructor.update.apply(this.constructor, args);
+}
+
+/**
+ * Sets the value of a path, or many paths.
+ *
+ * ####Example:
+ *
+ * // path, value
+ * doc.set(path, value)
+ *
+ * // object
+ * doc.set({
+ * path : value
+ * , path2 : {
+ * path : value
+ * }
+ * })
+ *
+ * // only-the-fly cast to number
+ * doc.set(path, value, Number)
+ *
+ * // only-the-fly cast to string
+ * doc.set(path, value, String)
+ *
+ * @param {String|Object} path path or object of key/vals to set
+ * @param {Any} val the value to set
+ * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for "on-the-fly" attributes
+ * @param {Object} [options] optionally specify options that modify the behavior of the set
+ * @api public
+ */
+
+Document.prototype.set = function (path, val, type, options) {
+ if (type && 'Object' == type.constructor.name) {
+ options = type;
+ type = undefined;
+ }
+
+ var merge = options && options.merge
+ , adhoc = type && true !== type
+ , constructing = true === type
+ , adhocs
+
+ if (adhoc) {
+ adhocs = this._adhocPaths || (this._adhocPaths = {});
+ adhocs[path] = Schema.interpretAsType(path, type);
+ }
+
+ if ('string' !== typeof path) {
+ // new Document({ key: val })
+
+ if (null === path || undefined === path) {
+ var _ = path;
+ path = val;
+ val = _;
+
+ } else {
+ var prefix = val
+ ? val + '.'
+ : '';
+
+ if (path instanceof Document) path = path._doc;
+
+ var keys = Object.keys(path)
+ , i = keys.length
+ , pathtype
+ , key
+
+ while (i--) {
+ key = keys[i];
+ pathtype = this.schema.pathType(prefix + key);
+ if (null != path[key]
+ && 'Object' == path[key].constructor.name
+ && 'virtual' != pathtype
+ && !(this._path(prefix + key) instanceof MixedSchema)) {
+ this.set(path[key], prefix + key, constructing);
+ } else if (this._strictMode) {
+ if ('real' === pathtype || 'virtual' === pathtype) {
+ this.set(prefix + key, path[key], constructing);
+ } else if ('throw' == this._strictMode) {
+ throw new Error("Field `" + key + "` is not in schema.");
+ }
+ } else if (undefined !== path[key]) {
+ this.set(prefix + key, path[key], constructing);
+ }
+ }
+
+ return this;
+ }
+ }
+
+ // ensure _strict is honored for obj props
+ // docschema = new Schema({ path: { nest: 'string' }})
+ // doc.set('path', obj);
+ var pathType = this.schema.pathType(path);
+ if ('nested' == pathType && val && 'Object' == val.constructor.name) {
+ if (!merge) this.setValue(path, null);
+ this.set(val, path, constructing);
+ return this;
+ }
+
+ var schema;
+ if ('adhocOrUndefined' == pathType && this._strictMode) {
+ return this;
+ } else if ('virtual' == pathType) {
+ schema = this.schema.virtualpath(path);
+ schema.applySetters(val, this);
+ return this;
+ } else {
+ schema = this._path(path);
+ }
+
+ var parts = path.split('.')
+ , pathToMark
+
+ // When using the $set operator the path to the field must already exist.
+ // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
+
+ if (parts.length <= 1) {
+ pathToMark = path;
+ } else {
+ for (var i = 0; i < parts.length; ++i) {
+ var part = parts[i];
+ var subpath = parts.slice(0, i).concat(part).join('.');
+ if (this.isDirectModified(subpath) // earlier prefixes that are already
+ // marked as dirty have precedence
+ || this.get(subpath) === null) {
+ pathToMark = subpath;
+ break;
+ }
+ }
+
+ if (!pathToMark) pathToMark = path;
+ }
+
+ if (!schema || null === val || undefined === val) {
+ this._set(pathToMark, path, constructing, parts, schema, val);
+ return this;
+ }
+
+ var self = this;
+
+ // if this doc is being constructed we should not
+ // trigger getters.
+ var priorVal = constructing
+ ? undefined
+ : this.get(path);
+
+ var shouldSet = this.try(function(){
+ val = schema.applySetters(val, self, false, priorVal);
+ });
+
+ if (shouldSet) {
+ this._set(pathToMark, path, constructing, parts, schema, val, priorVal);
+ }
+
+ return this;
+}
+
+/**
+ * Determine if we should mark this change as modified.
+ *
+ * @return {Boolean}
+ * @api private
+ */
+
+Document.prototype._shouldModify = function (
+ pathToMark, path, constructing, parts, schema, val, priorVal) {
+
+ if (this.isNew) return true;
+ if (this.isDirectModified(pathToMark)) return false;
+
+ if (undefined === val && !this.isSelected(path)) {
+ // when a path is not selected in a query, its initial
+ // value will be undefined.
+ return true;
+ }
+
+ if (undefined === val && path in this._activePaths.states.default) {
+ // we're just unsetting the default value which was never saved
+ return false;
+ }
+
+ if (!deepEqual(val, priorVal || this.get(path))) {
+ return true;
+ }
+
+ if (!constructing &&
+ null != val &&
+ path in this._activePaths.states.default &&
+ deepEqual(val, schema.getDefault(this, constructing))) {
+ // a path with a default was $unset on the server
+ // and the user is setting it to the same value again
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * Handles the actual setting of the value and marking the path modified if appropriate.
+ *
+ * @api private
+ */
+
+Document.prototype._set = function (
+ pathToMark, path, constructing, parts, schema, val, priorVal) {
+
+ var shouldModify = this._shouldModify.apply(this, arguments);
+
+ if (shouldModify) {
+ this.markModified(pathToMark, val);
+
+ // handle directly setting arrays (gh-1126)
+ MongooseArray || (MongooseArray = require('./types/array'));
+ if (val instanceof MongooseArray) {
+ val._registerAtomic('$set', val);
+ }
+ }
+
+ var obj = this._doc
+ , i = 0
+ , l = parts.length
+
+ for (; i < l; i++) {
+ var next = i + 1
+ , last = next === l;
+
+ if (last) {
+ obj[parts[i]] = val;
+ } else {
+ if (obj[parts[i]] && 'Object' === obj[parts[i]].constructor.name) {
+ obj = obj[parts[i]];
+ } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
+ obj = obj[parts[i]];
+ } else {
+ obj = obj[parts[i]] = {};
+ }
+ }
+ }
+}
+
+/**
+ * Gets a raw value from a path (no getters)
+ *
+ * @param {String} path
+ * @api private
+ */
+
+Document.prototype.getValue = function (path) {
+ var parts = path.split('.')
+ , obj = this._doc
+ , part;
+
+ for (var i = 0, l = parts.length; i < l; i++) {
+ part = parts[i];
+ obj = obj.getValue
+ ? obj.getValue(part) // If we have an embedded array document member
+ : obj[part];
+ if (!obj) return obj;
+ }
+
+ return obj;
+}
+
+/**
+ * Sets a raw value for a path (no casting, setters, transformations)
+ *
+ * @param {String} path
+ * @param {Object} value
+ * @api private
+ */
+
+Document.prototype.setValue = function (path, val) {
+ var parts = path.split('.')
+ , obj = this._doc;
+
+ for (var i = 0, len = parts.length-1; i < len; i++) {
+ obj = obj[parts[i]];
+ }
+
+ obj[parts[len]] = val;
+ return this;
+};
+
+/**
+ * Returns the value of a path.
+ *
+ * ####Example
+ *
+ * // path
+ * doc.get('age') // 47
+ *
+ * // dynamic casting to a string
+ * doc.get('age', String) // "47"
+ *
+ * @param {String} path
+ * @param {Schema|String|Number|Buffer|etc..} [type] optionally specify a type for on-the-fly attributes
+ * @api public
+ */
+
+Document.prototype.get = function (path, type) {
+ var adhocs;
+ if (type) {
+ adhocs = this._adhocPaths || (this._adhocPaths = {});
+ adhocs[path] = Schema.interpretAsType(path, type);
+ }
+
+ var schema = this._path(path) || this.schema.virtualpath(path)
+ , pieces = path.split('.')
+ , obj = this._doc;
+
+ for (var i = 0, l = pieces.length; i < l; i++) {
+ obj = null == obj ? null : obj[pieces[i]];
+ }
+
+ if (schema) {
+ obj = schema.applyGetters(obj, this);
+ }
+
+ return obj;
+};
+
+/**
+ * Returns the schematype for the given `path`.
+ *
+ * @param {String} path
+ * @api private
+ */
+
+Document.prototype._path = function (path) {
+ var adhocs = this._adhocPaths
+ , adhocType = adhocs && adhocs[path];
+
+ if (adhocType) {
+ return adhocType;
+ } else {
+ return this.schema.path(path);
+ }
+};
+
+/**
+ * Marks the path as having pending changes to write to the db.
+ *
+ * _Very helpful when using [Mixed](./schematypes.html#mixed) types._
+ *
+ * ####Example:
+ *
+ * doc.mixed.type = 'changed';
+ * doc.markModified('mixed.type');
+ * doc.save() // changes to mixed.type are now persisted
+ *
+ * @param {String} path the path to mark modified
+ * @api public
+ */
+
+Document.prototype.markModified = function (path) {
+ this._activePaths.modify(path);
+}
+
+/**
+ * Catches errors that occur during execution of `fn` and stores them to later be passed when `save()` is executed.
+ *
+ * @param {Function} fn function to execute
+ * @param {Object} scope the scope with which to call fn
+ * @api private
+ */
+
+Document.prototype.try = function (fn, scope) {
+ var res;
+ try {
+ fn.call(scope);
+ res = true;
+ } catch (e) {
+ this._error(e);
+ res = false;
+ }
+ return res;
+};
+
+/**
+ * Returns the list of paths that have been modified.
+ *
+ * @return {Array}
+ * @api public
+ */
+
+Document.prototype.modifiedPaths = function () {
+ var directModifiedPaths = Object.keys(this._activePaths.states.modify);
+
+ return directModifiedPaths.reduce(function (list, path) {
+ var parts = path.split('.');
+ return list.concat(parts.reduce(function (chains, part, i) {
+ return chains.concat(parts.slice(0, i).concat(part).join('.'));
+ }, []));
+ }, []);
+};
+
+/**
+ * Returns true if this document was modified, else false.
+ *
+ * If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified.
+ *
+ * ####Example
+ *
+ * doc.set('documents.0.title', 'changed');
+ * doc.isModified() // true
+ * doc.isModified('documents') // true
+ * doc.isModified('documents.0.title') // true
+ * doc.isDirectModified('documents') // false
+ *
+ * @param {String} [path] optional
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isModified = function (path) {
+ return path
+ ? !!~this.modifiedPaths().indexOf(path)
+ : this._activePaths.some('modify');
+};
+
+/**
+ * Returns true if `path` was directly set and modified, else false.
+ *
+ * ####Example
+ *
+ * doc.set('documents.0.title', 'changed');
+ * doc.isDirectModified('documents.0.title') // true
+ * doc.isDirectModified('documents') // false
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isDirectModified = function (path) {
+ return (path in this._activePaths.states.modify);
+};
+
+/**
+ * Checks if `path` was initialized.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isInit = function (path) {
+ return (path in this._activePaths.states.init);
+};
+
+/**
+ * Checks if `path` was selected in the source query which initialized this document.
+ *
+ * ####Example
+ *
+ * Thing.findOne().select('name').exec(function (err, doc) {
+ * doc.isSelected('name') // true
+ * doc.isSelected('age') // false
+ * })
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isSelected = function isSelected (path) {
+ if (this._selected) {
+
+ if ('_id' === path) {
+ return 0 !== this._selected._id;
+ }
+
+ var paths = Object.keys(this._selected)
+ , i = paths.length
+ , inclusive = false
+ , cur
+
+ if (1 === i && '_id' === paths[0]) {
+ // only _id was selected.
+ return 0 === this._selected._id;
+ }
+
+ while (i--) {
+ cur = paths[i];
+ if ('_id' == cur) continue;
+ inclusive = !! this._selected[cur];
+ break;
+ }
+
+ if (path in this._selected) {
+ return inclusive;
+ }
+
+ i = paths.length;
+ var pathDot = path + '.';
+
+ while (i--) {
+ cur = paths[i];
+ if ('_id' == cur) continue;
+
+ if (0 === cur.indexOf(pathDot)) {
+ return inclusive;
+ }
+
+ if (0 === pathDot.indexOf(cur)) {
+ return inclusive;
+ }
+ }
+
+ return ! inclusive;
+ }
+
+ return true;
+}
+
+/**
+ * Executes registered validation rules for this document.
+ *
+ * ####Note:
+ *
+ * This method is called `pre` save and if a validation rule is violated, [save](#model_Model-save) is aborted and the error is returned to your `callback`.
+ *
+ * ####Example:
+ *
+ * doc.validate(function (err) {
+ * if (err) handleError(err);
+ * else // validation passed
+ * });
+ *
+ * @param {Function} cb called after validation completes, passing an error if one occurred
+ * @api public
+ */
+
+Document.prototype.validate = function (cb) {
+ var self = this
+
+ // only validate required fields when necessary
+ var paths = Object.keys(this._activePaths.states.require).filter(function (path) {
+ if (!self.isSelected(path) && !self.isModified(path)) return false;
+ return true;
+ });
+
+ paths = paths.concat(Object.keys(this._activePaths.states.init));
+ paths = paths.concat(Object.keys(this._activePaths.states.modify));
+ paths = paths.concat(Object.keys(this._activePaths.states.default));
+
+ if (0 === paths.length) {
+ complete();
+ return this;
+ }
+
+ var validating = {}
+ , total = 0;
+
+ paths.forEach(validatePath);
+ return this;
+
+ function validatePath (path) {
+ if (validating[path]) return;
+
+ validating[path] = true;
+ total++;
+
+ process.nextTick(function(){
+ var p = self.schema.path(path);
+ if (!p) return --total || complete();
+
+ p.doValidate(self.getValue(path), function (err) {
+ if (err) self.invalidate(path, err, true);
+ --total || complete();
+ }, self);
+ });
+ }
+
+ function complete () {
+ var err = self._validationError;
+ self._validationError = undefined;
+ self.emit('validate', self);
+ cb(err);
+ }
+};
+
+/**
+ * Marks a path as invalid, causing validation to fail.
+ *
+ * @param {String} path the field to invalidate
+ * @param {String|Error} err the error which states the reason `path` was invalid
+ * @api public
+ */
+
+Document.prototype.invalidate = function (path, err) {
+ if (!this._validationError) {
+ this._validationError = new ValidationError(this);
+ }
+
+ if (!err || 'string' === typeof err) {
+ err = new ValidatorError(path, err);
+ }
+
+ this._validationError.errors[path] = err;
+}
+
+/**
+ * Resets the internal modified state of this document.
+ *
+ * @api private
+ * @return {Document}
+ */
+
+Document.prototype._reset = function reset () {
+ var self = this;
+ DocumentArray || (DocumentArray = require('./types/documentarray'));
+
+ this._activePaths
+ .map('init', 'modify', function (i) {
+ return self.getValue(i);
+ })
+ .filter(function (val) {
+ return val && val instanceof DocumentArray && val.length;
+ })
+ .forEach(function (array) {
+ var i = array.length;
+ while (i--) {
+ var doc = array[i];
+ if (!doc) continue;
+ doc._reset();
+ }
+ });
+
+ // clear atomics
+ this._dirty().forEach(function (dirt) {
+ var type = dirt.value;
+ if (type && type._atomics) {
+ type._atomics = {};
+ }
+ });
+
+ // Clear 'modify'('dirty') cache
+ this._activePaths.clear('modify');
+ this._validationError = undefined;
+ this.errors = undefined;
+ var self = this;
+ this.schema.requiredPaths().forEach(function (path) {
+ self._activePaths.require(path);
+ });
+
+ return this;
+}
+
+/**
+ * Returns this documents dirty paths / vals.
+ *
+ * @api private
+ */
+
+Document.prototype._dirty = function _dirty () {
+ var self = this;
+
+ var all = this._activePaths.map('modify', function (path) {
+ return { path: path
+ , value: self.getValue(path)
+ , schema: self._path(path) };
+ });
+
+ // Sort dirty paths in a flat hierarchy.
+ all.sort(function (a, b) {
+ return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
+ });
+
+ // Ignore "foo.a" if "foo" is dirty already.
+ var minimal = []
+ , lastPath
+ , top;
+
+ all.forEach(function (item, i) {
+ if (item.path.indexOf(lastPath) !== 0) {
+ lastPath = item.path + '.';
+ minimal.push(item);
+ top = item;
+ } else {
+ if (!(item.value && top.value)) return;
+
+ // special case for top level MongooseArrays
+ if (top.value._atomics && top.value.hasAtomics()) {
+ // the `top` array itself and a sub path of `top` are being modified.
+ // the only way to honor all of both modifications is through a $set
+ // of entire array.
+ top.value._atomics = {};
+ top.value._atomics.$set = top.value;
+ }
+ }
+ });
+
+ top = lastPath = null;
+ return minimal;
+}
+
+/*!
+ * Compiles schemas.
+ */
+
+function compile (tree, proto, prefix) {
+ var keys = Object.keys(tree)
+ , i = keys.length
+ , limb
+ , key;
+
+ while (i--) {
+ key = keys[i];
+ limb = tree[key];
+
+ define(key
+ , (('Object' === limb.constructor.name
+ && Object.keys(limb).length)
+ && (!limb.type || limb.type.type)
+ ? limb
+ : null)
+ , proto
+ , prefix
+ , keys);
+ }
+};
+
+/*!
+ * Defines the accessor named prop on the incoming prototype.
+ */
+
+function define (prop, subprops, prototype, prefix, keys) {
+ var prefix = prefix || ''
+ , path = (prefix ? prefix + '.' : '') + prop;
+
+ if (subprops) {
+
+ Object.defineProperty(prototype, prop, {
+ enumerable: true
+ , get: function () {
+ if (!this.__getters)
+ this.__getters = {};
+
+ if (!this.__getters[path]) {
+ var nested = Object.create(this);
+
+ // save scope for nested getters/setters
+ if (!prefix) nested._scope = this;
+
+ // shadow inherited getters from sub-objects so
+ // thing.nested.nested.nested... doesn't occur (gh-366)
+ var i = 0
+ , len = keys.length;
+
+ for (; i < len; ++i) {
+ // over-write the parents getter without triggering it
+ Object.defineProperty(nested, keys[i], {
+ enumerable: false // It doesn't show up.
+ , writable: true // We can set it later.
+ , configurable: true // We can Object.defineProperty again.
+ , value: undefined // It shadows its parent.
+ });
+ }
+
+ nested.toObject = function () {
+ return this.get(path);
+ };
+
+ compile(subprops, nested, path);
+ this.__getters[path] = nested;
+ }
+
+ return this.__getters[path];
+ }
+ , set: function (v) {
+ if (v instanceof Document) v = v.toObject();
+ return this.set(path, v);
+ }
+ });
+
+ } else {
+
+ Object.defineProperty(prototype, prop, {
+ enumerable: true
+ , get: function ( ) { return this.get.call(this._scope || this, path); }
+ , set: function (v) { return this.set.call(this._scope || this, path, v); }
+ });
+ }
+};
+
+/**
+ * Assigns/compiles `schema` into this documents prototype.
+ *
+ * @param {Schema} schema
+ * @api private
+ */
+
+Document.prototype._setSchema = function (schema) {
+ compile(schema.tree, this);
+ this.schema = schema;
+}
+
+/**
+ * Register default hooks
+ *
+ * @api private
+ */
+
+Document.prototype._registerHooks = function _registerHooks () {
+ if (!this.save) return;
+
+ DocumentArray || (DocumentArray = require('./types/documentarray'));
+
+ this.pre('save', function (next) {
+ // we keep the error semaphore to make sure we don't
+ // call `save` unnecessarily (we only need 1 error)
+ var subdocs = 0
+ , error = false
+ , self = this;
+
+ // check for DocumentArrays
+ var arrays = this._activePaths
+ .map('init', 'modify', function (i) {
+ return self.getValue(i);
+ })
+ .filter(function (val) {
+ return val && val instanceof DocumentArray && val.length;
+ });
+
+ if (!arrays.length)
+ return next();
+
+ arrays.forEach(function (array) {
+ if (error) return;
+
+ // handle sparse arrays by using for loop vs array.forEach
+ // which skips the sparse elements
+
+ var len = array.length
+ subdocs += len;
+
+ for (var i = 0; i < len; ++i) {
+ if (error) break;
+
+ var doc = array[i];
+ if (!doc) {
+ --subdocs || next();
+ continue;
+ }
+
+ doc.save(handleSave);
+ }
+ });
+
+ function handleSave (err) {
+ if (error) return;
+
+ if (err) {
+ self._validationError = undefined;
+ return next(error = err);
+ }
+
+ --subdocs || next();
+ }
+
+ }, function (err) {
+ // emit on the Model if listening
+ if (this.constructor.listeners('error').length) {
+ this.constructor.emit('error', err);
+ } else {
+ // emit on the connection
+ if (!this.db.listeners('error').length) {
+ err.stack = 'No listeners detected, throwing. '
+ + 'Consider adding an error listener to your connection.\n'
+ + err.stack
+ }
+ this.db.emit('error', err);
+ }
+ }).pre('save', function checkForExistingErrors (next) {
+ // if any doc.set() calls failed
+ if (this._saveError) {
+ next(this._saveError);
+ this._saveError = null;
+ } else {
+ next();
+ }
+ }).pre('save', function validation (next) {
+ return this.validate(next);
+ });
+
+ // add user defined queues
+ this._doQueue();
+};
+
+/**
+ * Registers an error
+ *
+ * @param {Error} err
+ * @api private
+ */
+
+Document.prototype._error = function (err) {
+ this._saveError = err;
+ return this;
+};
+
+/**
+ * Executes methods queued from the Schema definition
+ *
+ * @api private
+ */
+
+Document.prototype._doQueue = function () {
+ var q = this.schema && this.schema.callQueue;
+ if (q) {
+ for (var i = 0, l = q.length; i < l; i++) {
+ this[q[i][0]].apply(this, q[i][1]);
+ }
+ }
+ return this;
+};
+
+/**
+ * Converts this document into a plain javascript object
+ *
+ * ####Options:
+ *
+ * - `getters` apply all getters (path and virtual getters)
+ * - `virtuals` apply virtual getters (can override `getters` option)
+ * - `minimize` remove empty objects (defaults to true)
+ * - `transform` a transform function to apply to the resulting document before returning
+ *
+ * ####Getters/Virtuals
+ *
+ * Example of only applying path getters
+ *
+ * doc.toObject({ getters: true, virtuals: false })
+ *
+ * Example of only applying virtual getters
+ *
+ * doc.toObject({ virtuals: true })
+ *
+ * Example of applying both path and virtual getters
+ *
+ * doc.toObject({ getters: true })
+ *
+ * To apply these options to every document of your schema by default, set your [schemas](#schema_Schema) `toObject` option to the same argument.
+ *
+ * schema.set('toObject', { virtuals: true })
+ *
+ * ####Transform
+ *
+ * We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional `transform` function.
+ *
+ * Transform functions receive three arguments
+ *
+ * function (doc, ret, options) {}
+ *
+ * - `doc` The mongoose document which is being converted
+ * - `ret` The plain object representation which has been converted
+ * - `options` The options in use (either schema options or the options passed inline)
+ *
+ * ####Example
+ *
+ * // specify the transform schema option
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * // remove the _id of every document before returning the result
+ * delete ret._id;
+ * }
+ *
+ * // without the transformation in the schema
+ * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
+ *
+ * // with the transformation
+ * doc.toObject(); // { name: 'Wreck-it Ralph' }
+ *
+ * With transformations we can do a lot more than remove properties. We can even return completely new customized objects:
+ *
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * return { movie: ret.name }
+ * }
+ *
+ * // without the transformation in the schema
+ * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
+ *
+ * // with the transformation
+ * doc.toObject(); // { movie: 'Wreck-it Ralph' }
+ *
+ * _Note: if a transform function returns `undefined`, the return value will be ignored._
+ *
+ * Transformations may also be applied inline, overridding any transform set in the options:
+ *
+ * function xform (doc, ret, options) {
+ * return { inline: ret.name, custom: true }
+ * }
+ *
+ * // pass the transform as an inline option
+ * doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
+ *
+ * _Note: if you call `toObject` and pass any options, the transform declared in your schema options will __not__ be applied. To force its application pass `transform: true`_
+ *
+ * schema.options.toObject.hide = '_id';
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * if (options.hide) {
+ * options.hide.split(' ').forEach(function (prop) {
+ * delete ret[prop];
+ * });
+ * }
+ * }
+ *
+ * var doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
+ * doc.toObject(); // { secret: 47, name: 'Wreck-it Ralph' }
+ * doc.toObject({ hide: 'secret _id' }); // { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
+ * doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
+ *
+ * Transforms are applied to the document _and each of its sub-documents_. To determine whether or not you are currently operating on a sub-document you might use the following guard:
+ *
+ * if ('function' == typeof doc.ownerDocument) {
+ * // working with a sub doc
+ * }
+ *
+ * Transforms, like all of these options, are also available for `toJSON`.
+ *
+ * See [schema options](/docs/guide.html#toObject) for some more details.
+ *
+ * @param {Object} [options]
+ * @return {Object} js object
+ * @api public
+ */
+
+Document.prototype.toObject = function (options) {
+ // When internally saving this document we always pass options,
+ // bypassing the custom schema options.
+ if (!(options && 'Object' == options.constructor.name)) {
+ options = this.schema.options.toObject
+ ? clone(this.schema.options.toObject)
+ : {};
+ }
+
+ ;('minimize' in options) || (options.minimize = this.schema.options.minimize);
+
+ var ret = clone(this._doc, options);
+
+ if (options.virtuals || options.getters && false !== options.virtuals) {
+ applyGetters(this, ret, 'virtuals', options);
+ }
+
+ if (options.getters) {
+ applyGetters(this, ret, 'paths', options);
+ }
+
+ if (true === options.transform) {
+ var opts = options.json
+ ? this.schema.options.toJSON
+ : this.schema.options.toObject;
+ if (opts) {
+ options.transform = opts.transform;
+ }
+ }
+
+ if ('function' == typeof options.transform) {
+ var xformed = options.transform(this, ret, options);
+ if ('undefined' != typeof xformed) ret = xformed;
+ }
+
+ return ret;
+};
+
+/*!
+ * Applies virtuals properties to `json`.
+ *
+ * @param {Document} self
+ * @param {Object} json
+ * @param {String} type either `virtuals` or `paths`
+ * @return {Object} `json`
+ */
+
+function applyGetters (self, json, type, options) {
+ var schema = self.schema
+ , paths = Object.keys(schema[type])
+ , i = paths.length
+ , path
+
+ while (i--) {
+ path = paths[i];
+
+ var parts = path.split('.')
+ , plen = parts.length
+ , last = plen - 1
+ , branch = json
+ , part
+
+ for (var ii = 0; ii < plen; ++ii) {
+ part = parts[ii];
+ if (ii === last) {
+ branch[part] = clone(self.get(path), options);
+ } else {
+ branch = branch[part] || (branch[part] = {});
+ }
+ }
+ }
+
+ return json;
+}
+
+/**
+ * The return value of this method is used in calls to JSON.stringify(doc).
+ *
+ * This method accepts the same options as [Document#toObject](#document_Document-toObject). To apply the options to every document of your schema by default, set your [schemas](#schema_Schema) `toJSON` option to the same argument.
+ *
+ * schema.set('toJSON', { virtuals: true })
+ *
+ * See [schema options](/docs/guide.html#toJSON) for details.
+ *
+ * @param {Object} options same options as [Document#toObject](#document_Document-toObject)
+ * @return {Object}
+ * @see Document#toObject #document_Document-toObject
+
+ * @api public
+ */
+
+Document.prototype.toJSON = function (options) {
+ // check for object type since an array of documents
+ // being stringified passes array indexes instead
+ // of options objects. JSON.stringify([doc, doc])
+ if (!(options && 'Object' == options.constructor.name)) {
+ options = this.schema.options.toJSON
+ ? clone(this.schema.options.toJSON)
+ : {};
+ }
+ options.json = true;
+ return this.toObject(options);
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ */
+
+Document.prototype.inspect = function (options) {
+ var opts = options && 'Object' == options.constructor.name
+ ? options
+ : undefined
+ return inspect(this.toObject(opts));
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ * @method toString
+ */
+
+Document.prototype.toString = Document.prototype.inspect;
+
+/**
+ * Returns true if the Document stores the same data as doc.
+ *
+ * Documents are considered equal when they have matching `_id`s.
+ *
+ * @param {Document} doc a document to compare
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.equals = function (doc) {
+ var tid = this.get('_id');
+ var docid = doc.get('_id');
+ return tid.equals
+ ? tid.equals(docid)
+ : tid === docid;
+};
+
+/*!
+ * Module exports.
+ */
+
+Document.ValidationError = ValidationError;
+module.exports = exports = Document;
+exports.Error = DocumentError;
diff --git a/test/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
new file mode 100644
index 0000000..0480d31
--- /dev/null
+++ b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
@@ -0,0 +1,8 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var Binary = require('mongodb').BSONPure.Binary;
+
+module.exports = exports = Binary;
diff --git a/test/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
new file mode 100644
index 0000000..a53857f
--- /dev/null
+++ b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
@@ -0,0 +1,212 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var MongooseCollection = require('../../collection')
+ , Collection = require('mongodb').Collection
+ , STATES = require('../../connectionstate')
+ , utils = require('../../utils')
+
+/**
+ * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
+ *
+ * All methods methods from the [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver are copied and wrapped in queue management.
+ *
+ * @inherits Collection
+ * @api private
+ */
+
+function NativeCollection () {
+ this.collection = null;
+ MongooseCollection.apply(this, arguments);
+}
+
+/*!
+ * Inherit from abstract Collection.
+ */
+
+NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
+
+/**
+ * Called when the connection opens.
+ *
+ * @api private
+ */
+
+NativeCollection.prototype.onOpen = function () {
+ var self = this;
+
+ if (this.collection) {
+ return MongooseCollection.prototype.onOpen.call(self);
+ }
+
+ if (!self.opts.size) {
+ // non-capped
+ return self.conn.db.collection(self.name, callback);
+ }
+
+ // capped
+ return self.conn.db.collection(self.name, function (err, c) {
+ if (err) return callback(err);
+
+ // discover if this collection exists and if it is capped
+ c.options(function (err, exists) {
+ if (err) return callback(err);
+
+ if (exists) {
+ if (exists.capped) {
+ callback(null, c);
+ } else {
+ var msg = 'A non-capped collection exists with this name.\n\n'
+ + ' To use this collection as a capped collection, please '
+ + 'first convert it.\n'
+ + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped'
+ err = new Error(msg);
+ callback(err);
+ }
+ } else {
+ // create
+ var opts = utils.clone(self.opts);
+ opts.capped = true;
+ self.conn.db.createCollection(self.name, opts, callback);
+ }
+ });
+ });
+
+ function callback (err, collection) {
+ if (err) {
+ // likely a strict mode error
+ self.conn.emit('error', err);
+ } else {
+ self.collection = collection;
+ MongooseCollection.prototype.onOpen.call(self);
+ }
+ };
+};
+
+/**
+ * Called when the connection closes
+ *
+ * @api private
+ */
+
+NativeCollection.prototype.onClose = function () {
+ MongooseCollection.prototype.onClose.call(this);
+};
+
+/*!
+ * Copy the collection methods and make them subject to queues
+ */
+
+for (var i in Collection.prototype) {
+ (function(i){
+ NativeCollection.prototype[i] = function () {
+ if (this.buffer) {
+ this.addQueue(i, arguments);
+ return;
+ }
+
+ var collection = this.collection
+ , args = arguments
+ , self = this
+ , debug = self.conn.base.options.debug;
+
+ if (debug) {
+ if ('function' === typeof debug) {
+ debug.apply(debug
+ , [self.name, i].concat(utils.args(args, 0, args.length-1)));
+ } else {
+ console.error('\x1B[0;36mMongoose:\x1B[0m %s.%s(%s) %s %s %s'
+ , self.name
+ , i
+ , print(args[0])
+ , print(args[1])
+ , print(args[2])
+ , print(args[3]))
+ }
+ }
+
+ collection[i].apply(collection, args);
+ };
+ })(i);
+}
+
+/*!
+ * Debug print helper
+ */
+
+function print (arg) {
+ var type = typeof arg;
+ if ('function' === type || 'undefined' === type) return '';
+ return format(arg);
+}
+
+/*!
+ * Debug print helper
+ */
+
+function format (obj, sub) {
+ var x = utils.clone(obj);
+ if (x) {
+ if ('Binary' === x.constructor.name) {
+ x = '[object Buffer]';
+ } else if ('ObjectID' === x.constructor.name) {
+ var representation = 'ObjectId("' + x.toHexString() + '")';
+ x = { inspect: function() { return representation; } };
+ } else if ('Date' === x.constructor.name) {
+ var representation = 'new Date("' + x.toUTCString() + '")';
+ x = { inspect: function() { return representation; } };
+ } else if ('Object' === x.constructor.name) {
+ var keys = Object.keys(x)
+ , i = keys.length
+ , key
+ while (i--) {
+ key = keys[i];
+ if (x[key]) {
+ if ('Binary' === x[key].constructor.name) {
+ x[key] = '[object Buffer]';
+ } else if ('Object' === x[key].constructor.name) {
+ x[key] = format(x[key], true);
+ } else if ('ObjectID' === x[key].constructor.name) {
+ ;(function(x){
+ var representation = 'ObjectId("' + x[key].toHexString() + '")';
+ x[key] = { inspect: function() { return representation; } };
+ })(x)
+ } else if ('Date' === x[key].constructor.name) {
+ ;(function(x){
+ var representation = 'new Date("' + x[key].toUTCString() + '")';
+ x[key] = { inspect: function() { return representation; } };
+ })(x)
+ } else if (Array.isArray(x[key])) {
+ x[key] = x[key].map(function (o) {
+ return format(o, true)
+ });
+ }
+ }
+ }
+ }
+ if (sub) return x;
+ }
+
+ return require('util')
+ .inspect(x, false, 10, true)
+ .replace(/\n/g, '')
+ .replace(/\s{2,}/g, ' ')
+}
+
+/**
+ * Retreives information about this collections indexes.
+ *
+ * @param {Function} callback
+ * @method getIndexes
+ * @api public
+ */
+
+NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = NativeCollection;
diff --git a/test/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
new file mode 100644
index 0000000..551e68f
--- /dev/null
+++ b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
@@ -0,0 +1,267 @@
+/*!
+ * Module dependencies.
+ */
+
+var MongooseConnection = require('../../connection')
+ , mongo = require('mongodb')
+ , Server = mongo.Server
+ , STATES = require('../../connectionstate')
+ , ReplSetServers = mongo.ReplSetServers;
+
+/**
+ * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation.
+ *
+ * @inherits Connection
+ * @api private
+ */
+
+function NativeConnection() {
+ MongooseConnection.apply(this, arguments);
+};
+
+/*!
+ * Inherits from Connection.
+ */
+
+NativeConnection.prototype.__proto__ = MongooseConnection.prototype;
+
+/**
+ * Opens the connection to MongoDB.
+ *
+ * @param {Function} fn
+ * @return {Connection} this
+ * @api private
+ */
+
+NativeConnection.prototype.doOpen = function (fn) {
+ var server
+ , self = this;
+
+ if (!this.db) {
+ server = new mongo.Server(this.host, this.port, this.options.server);
+ this.db = new mongo.Db(this.name, server, this.options.db);
+ }
+
+ this.db.open(function (err) {
+ if (err) return fn(err);
+ fn();
+ listen(self);
+ });
+
+ return this;
+};
+
+function listen (conn) {
+ if (conn._listening) return;
+ conn._listening = true;
+
+ conn.db.on('close', function(){
+ if (conn._closeCalled) return;
+
+ // the driver never emits an `open` event. auto_reconnect still
+ // emits a `close` event but since we never get another
+ // `open` we can't emit close
+ if (conn.db.serverConfig.autoReconnect) {
+ conn.readyState = STATES.disconnected;
+ conn.emit('close');
+ return;
+ }
+ conn.onClose();
+ });
+ conn.db.on('error', function(err){
+ conn.emit('error', err);
+ });
+ conn.db.on('timeout', function(err){
+ var error = new Error(err && err.err || 'connection timeout');
+ conn.emit('error', error);
+ });
+ conn.db.on('open', function (err, db) {
+ if (STATES.disconnected === conn.readyState && db && db.databaseName) {
+ conn.readyState = STATES.connected;
+ conn.emit('reconnected')
+ }
+ })
+}
+
+/**
+ * Opens a connection to a MongoDB ReplicaSet.
+ *
+ * See description of [doOpen](#NativeConnection-doOpen) for server options. In this case `options.replset` is also passed to ReplSetServers.
+ *
+ * @param {Function} fn
+ * @api private
+ * @return {Connection} this
+ */
+
+NativeConnection.prototype.doOpenSet = function (fn) {
+ var servers = []
+ , self = this;
+
+ if (!this.db) {
+ this.hosts.forEach(function (server) {
+ var host = server.host || server.ipc;
+ var port = server.port || 27017;
+ servers.push(new mongo.Server(host, port, self.options.server));
+ })
+
+ var server = new ReplSetServers(servers, this.options.replset);
+ this.db = new mongo.Db(this.name, server, this.options.db);
+
+ this.db.on('fullsetup', function () {
+ self.emit('fullsetup')
+ });
+ }
+
+ this.db.open(function (err) {
+ if (err) return fn(err);
+ fn();
+ listen(self);
+ });
+
+ return this;
+};
+
+/**
+ * Closes the connection
+ *
+ * @param {Function} fn
+ * @return {Connection} this
+ * @api private
+ */
+
+NativeConnection.prototype.doClose = function (fn) {
+ this.db.close();
+ if (fn) fn();
+ return this;
+}
+
+/**
+ * Prepares default connection options for the node-mongodb-native driver.
+ *
+ * _NOTE: `passed` options take precedence over connection string options._
+ *
+ * @param {Object} passed options that were passed directly during connection
+ * @param {Object} [connStrOptions] options that were passed in the connection string
+ * @api private
+ */
+
+NativeConnection.prototype.parseOptions = function (passed, connStrOpts) {
+ var o = passed || {};
+ o.db || (o.db = {});
+ o.server || (o.server = {});
+ o.replset || (o.replset = {});
+ o.server.socketOptions || (o.server.socketOptions = {});
+ o.replset.socketOptions || (o.replset.socketOptions = {});
+
+ var opts = connStrOpts || {};
+ Object.keys(opts).forEach(function (name) {
+ switch (name) {
+ case 'poolSize':
+ if ('undefined' == typeof o.server.poolSize) {
+ o.server.poolSize = o.replset.poolSize = opts[name];
+ }
+ break;
+ case 'slaveOk':
+ if ('undefined' == typeof o.server.slave_ok) {
+ o.server.slave_ok = opts[name];
+ }
+ break;
+ case 'autoReconnect':
+ if ('undefined' == typeof o.server.auto_reconnect) {
+ o.server.auto_reconnect = opts[name];
+ }
+ break;
+ case 'ssl':
+ case 'socketTimeoutMS':
+ case 'connectTimeoutMS':
+ if ('undefined' == typeof o.server.socketOptions[name]) {
+ o.server.socketOptions[name] = o.replset.socketOptions[name] = opts[name];
+ }
+ break;
+ case 'retries':
+ case 'reconnectWait':
+ case 'rs_name':
+ if ('undefined' == typeof o.replset[name]) {
+ o.replset[name] = opts[name];
+ }
+ break;
+ case 'replicaSet':
+ if ('undefined' == typeof o.replset.rs_name) {
+ o.replset.rs_name = opts[name];
+ }
+ break;
+ case 'readSecondary':
+ if ('undefined' == typeof o.replset.read_secondary) {
+ o.replset.read_secondary = opts[name];
+ }
+ break;
+ case 'nativeParser':
+ if ('undefined' == typeof o.db.native_parser) {
+ o.db.native_parser = opts[name];
+ }
+ break;
+ case 'w':
+ case 'safe':
+ case 'fsync':
+ case 'journal':
+ case 'wtimeoutMS':
+ if ('undefined' == typeof o.db[name]) {
+ o.db[name] = opts[name];
+ }
+ break;
+ case 'readPreference':
+ if ('undefined' == typeof o.db.read_preference) {
+ o.db.read_preference = opts[name];
+ }
+ break;
+ case 'readPreferenceTags':
+ if ('undefined' == typeof o.db.read_preference_tags) {
+ o.db.read_preference_tags = opts[name];
+ }
+ break;
+ }
+ })
+
+ if (!('auto_reconnect' in o.server)) {
+ o.server.auto_reconnect = true;
+ }
+
+ if (!o.db.read_preference) {
+ // read from primaries by default
+ o.db.read_preference = 'primary';
+ }
+
+ // mongoose creates its own ObjectIds
+ o.db.forceServerObjectId = false;
+
+ // default safe using new nomenclature
+ if (!('journal' in o.db || 'j' in o.db ||
+ 'fsync' in o.db || 'safe' in o.db || 'w' in o.db)) {
+ o.db.w = 1;
+ }
+
+ validate(o);
+ return o;
+}
+
+/*!
+ * Validates the driver db options.
+ *
+ * @param {Object} o
+ */
+
+function validate (o) {
+ if (-1 === o.db.w || 0 === o.db.w) {
+ if (o.db.journal || o.db.fsync || o.db.safe) {
+ throw new Error(
+ 'Invalid writeConcern: '
+ + 'w set to -1 or 0 cannot be combined with safe|fsync|journal');
+ }
+ }
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = NativeConnection;
diff --git a/test/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
new file mode 100644
index 0000000..3c46c93
--- /dev/null
+++ b/test/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
@@ -0,0 +1,29 @@
+
+/*!
+ * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId
+ * @constructor NodeMongoDbObjectId
+ * @see ObjectId
+ */
+
+var ObjectId = require('mongodb').BSONPure.ObjectID;
+
+/*!
+ * ignore
+ */
+
+var ObjectIdToString = ObjectId.toString.bind(ObjectId);
+module.exports = exports = ObjectId;
+
+ObjectId.fromString = function(str){
+ // patch native driver bug in V0.9.6.4
+ if (!('string' === typeof str && 24 === str.length)) {
+ throw new Error("Invalid ObjectId");
+ }
+
+ return ObjectId.createFromHexString(str);
+};
+
+ObjectId.toString = function(oid){
+ if (!arguments.length) return ObjectIdToString();
+ return oid.toHexString();
+};
diff --git a/test/node_modules/mongoose/lib/error.js b/test/node_modules/mongoose/lib/error.js
new file mode 100644
index 0000000..9216cd9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/error.js
@@ -0,0 +1,38 @@
+
+/**
+ * Mongoose error
+ *
+ * @api private
+ * @inherits Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error
+ */
+
+function MongooseError (msg) {
+ Error.call(this);
+ Error.captureStackTrace(this, arguments.callee);
+ this.message = msg;
+ this.name = 'MongooseError';
+};
+
+/*!
+ * Inherits from Error.
+ */
+
+MongooseError.prototype.__proto__ = Error.prototype;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = MongooseError;
+
+/*!
+ * Expose subclasses
+ */
+
+MongooseError.CastError = require('./errors/cast');
+MongooseError.DocumentError = require('./errors/document');
+MongooseError.ValidationError = require('./errors/validation')
+MongooseError.ValidatorError = require('./errors/validator')
+MongooseError.VersionError =require('./errors/version')
+MongooseError.OverwriteModelError = require('./errors/overwriteModel')
+MongooseError.MissingSchemaError = require('./errors/missingSchema')
diff --git a/test/node_modules/mongoose/lib/errors/cast.js b/test/node_modules/mongoose/lib/errors/cast.js
new file mode 100644
index 0000000..055063a
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/cast.js
@@ -0,0 +1,35 @@
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error');
+
+/**
+ * Casting Error constructor.
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+function CastError (type, value, path) {
+ MongooseError.call(this, 'Cast to ' + type + ' failed for value "' + value + '" at path "' + path + '"');
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'CastError';
+ this.type = type;
+ this.value = value;
+ this.path = path;
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+CastError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * exports
+ */
+
+module.exports = CastError;
diff --git a/test/node_modules/mongoose/lib/errors/document.js b/test/node_modules/mongoose/lib/errors/document.js
new file mode 100644
index 0000000..6955256
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/document.js
@@ -0,0 +1,32 @@
+
+/*!
+ * Module requirements
+ */
+
+var MongooseError = require('../error')
+
+/**
+ * Document Error
+ *
+ * @param {String} msg
+ * @inherits MongooseError
+ * @api private
+ */
+
+function DocumentError (msg) {
+ MongooseError.call(this, msg);
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'DocumentError';
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+DocumentError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = DocumentError;
diff --git a/test/node_modules/mongoose/lib/errors/missingSchema.js b/test/node_modules/mongoose/lib/errors/missingSchema.js
new file mode 100644
index 0000000..02a02ee
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/missingSchema.js
@@ -0,0 +1,32 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error');
+
+/*!
+ * MissingSchema Error constructor.
+ *
+ * @inherits MongooseError
+ */
+
+function MissingSchemaError (name) {
+ var msg = 'Schema hasn\'t been registered for model "' + name + '".\n'
+ + 'Use mongoose.model(name, schema)';
+ MongooseError.call(this, msg);
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'MissingSchemaError';
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+MissingSchemaError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * exports
+ */
+
+module.exports = MissingSchemaError;
diff --git a/test/node_modules/mongoose/lib/errors/overwriteModel.js b/test/node_modules/mongoose/lib/errors/overwriteModel.js
new file mode 100644
index 0000000..2591581
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/overwriteModel.js
@@ -0,0 +1,30 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error');
+
+/*!
+ * OverwriteModel Error constructor.
+ *
+ * @inherits MongooseError
+ */
+
+function OverwriteModelError (name) {
+ MongooseError.call(this, 'Cannot overwrite `' + name + '` model once compiled.');
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'OverwriteModelError';
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+OverwriteModelError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * exports
+ */
+
+module.exports = OverwriteModelError;
diff --git a/test/node_modules/mongoose/lib/errors/validation.js b/test/node_modules/mongoose/lib/errors/validation.js
new file mode 100644
index 0000000..08f2aaa
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/validation.js
@@ -0,0 +1,43 @@
+
+/*!
+ * Module requirements
+ */
+
+var MongooseError = require('../error')
+
+/**
+ * Document Validation Error
+ *
+ * @api private
+ * @param {Document} instance
+ * @inherits MongooseError
+ */
+
+function ValidationError (instance) {
+ MongooseError.call(this, "Validation failed");
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'ValidationError';
+ this.errors = instance.errors = {};
+};
+
+/**
+ * Console.log helper
+ */
+
+ValidationError.prototype.toString = function () {
+ return this.name + ': ' + Object.keys(this.errors).map(function (key) {
+ return String(this.errors[key]);
+ }, this).join(', ');
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+ValidationError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * Module exports
+ */
+
+module.exports = exports = ValidationError;
diff --git a/test/node_modules/mongoose/lib/errors/validator.js b/test/node_modules/mongoose/lib/errors/validator.js
new file mode 100644
index 0000000..5499bee
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/validator.js
@@ -0,0 +1,45 @@
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error');
+
+/**
+ * Schema validator error
+ *
+ * @param {String} path
+ * @param {String} msg
+ * @inherits MongooseError
+ * @api private
+ */
+
+function ValidatorError (path, type) {
+ var msg = type
+ ? '"' + type + '" '
+ : '';
+ MongooseError.call(this, 'Validator ' + msg + 'failed for path ' + path);
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'ValidatorError';
+ this.path = path;
+ this.type = type;
+};
+
+/*!
+ * toString helper
+ */
+
+ValidatorError.prototype.toString = function () {
+ return this.message;
+}
+
+/*!
+ * Inherits from MongooseError
+ */
+
+ValidatorError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * exports
+ */
+
+module.exports = ValidatorError;
diff --git a/test/node_modules/mongoose/lib/errors/version.js b/test/node_modules/mongoose/lib/errors/version.js
new file mode 100644
index 0000000..b2388aa
--- /dev/null
+++ b/test/node_modules/mongoose/lib/errors/version.js
@@ -0,0 +1,31 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var MongooseError = require('../error');
+
+/**
+ * Version Error constructor.
+ *
+ * @inherits MongooseError
+ * @api private
+ */
+
+function VersionError () {
+ MongooseError.call(this, 'No matching document found.');
+ Error.captureStackTrace(this, arguments.callee);
+ this.name = 'VersionError';
+};
+
+/*!
+ * Inherits from MongooseError.
+ */
+
+VersionError.prototype.__proto__ = MongooseError.prototype;
+
+/*!
+ * exports
+ */
+
+module.exports = VersionError;
diff --git a/test/node_modules/mongoose/lib/index.js b/test/node_modules/mongoose/lib/index.js
new file mode 100644
index 0000000..e4d4a9f
--- /dev/null
+++ b/test/node_modules/mongoose/lib/index.js
@@ -0,0 +1,547 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var Schema = require('./schema')
+ , SchemaType = require('./schematype')
+ , VirtualType = require('./virtualtype')
+ , SchemaTypes = Schema.Types
+ , SchemaDefaults = require('./schemadefault')
+ , Types = require('./types')
+ , Query = require('./query')
+ , Promise = require('./promise')
+ , Model = require('./model')
+ , Document = require('./document')
+ , utils = require('./utils')
+ , format = utils.toCollectionName
+ , mongodb = require('mongodb')
+
+/**
+ * Mongoose constructor.
+ *
+ * The exports object of the `mongoose` module is an instance of this class.
+ * Most apps will only use this one instance.
+ *
+ * @api public
+ */
+
+function Mongoose () {
+ this.connections = [];
+ this.plugins = [];
+ this.models = {};
+ this.modelSchemas = {};
+ this.options = {};
+ this.createConnection(); // default connection
+};
+
+/**
+ * Sets mongoose options
+ *
+ * ####Example:
+ *
+ * mongoose.set('test', value) // sets the 'test' option to `value`
+ *
+ * @param {String} key
+ * @param {String} value
+ * @api public
+ */
+
+Mongoose.prototype.set = function (key, value) {
+ if (arguments.length == 1)
+ return this.options[key];
+ this.options[key] = value;
+ return this;
+};
+
+/**
+ * Gets mongoose options
+ *
+ * ####Example:
+ *
+ * mongoose.get('test') // returns the 'test' value
+ *
+ * @param {String} key
+ * @method get
+ * @api public
+ */
+
+Mongoose.prototype.get = Mongoose.prototype.set;
+
+/*!
+ * ReplSet connection string check.
+ */
+
+var rgxReplSet = /^.+,.+$/;
+
+/**
+ * Creates a Connection instance.
+ *
+ * Each `connection` instance maps to a single database. This method is helpful when mangaging multiple db connections.
+ *
+ * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately. This means we can pass `db`, `server`, and `replset` options to the driver.
+ *
+ * _Options passed take precedence over options included in connection strings._
+ *
+ * ####Example:
+ *
+ * // with mongodb:// URI
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
+ *
+ * // and options
+ * var opts = { db: { native_parser: true }}
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
+ *
+ * // replica sets
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
+ *
+ * // and options
+ * var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
+ *
+ * // with [host, database_name[, port] signature
+ * db = mongoose.createConnection('localhost', 'database', port)
+ *
+ * // and options
+ * var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
+ * db = mongoose.createConnection('localhost', 'database', port, opts)
+ *
+ * // initialize now, connect later
+ * db = mongoose.createConnection();
+ * db.open('localhost', 'database', port, [opts]);
+ *
+ * @param {String} [uri] a mongodb:// URI
+ * @param {Object} [options] options to pass to the driver
+ * @see Connection#open #connection_Connection-open
+ * @see Connection#openSet #connection_Connection-openSet
+ * @return {Connection} the created Connection object
+ * @api public
+ */
+
+Mongoose.prototype.createConnection = function () {
+ var conn = new Connection(this);
+ this.connections.push(conn);
+
+ if (arguments.length) {
+ if (rgxReplSet.test(arguments[0])) {
+ conn.openSet.apply(conn, arguments);
+ } else {
+ conn.open.apply(conn, arguments);
+ }
+ }
+
+ return conn;
+};
+
+/**
+ * Opens the default mongoose connection.
+ *
+ * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately.
+ *
+ * _Options passed take precedence over options included in connection strings._
+ *
+ * @see Mongoose#createConnection #index_Mongoose-createConnection
+ * @api public
+ * @return {Mongoose} this
+ */
+
+Mongoose.prototype.connect = function () {
+ var conn = this.connection;
+
+ if (rgxReplSet.test(arguments[0])) {
+ conn.openSet.apply(conn, arguments);
+ } else {
+ conn.open.apply(conn, arguments);
+ }
+
+ return this;
+};
+
+/**
+ * Disconnects all connections.
+ *
+ * @param {Function} [fn] called after all connection close.
+ * @return {Mongoose} this
+ * @api public
+ */
+
+Mongoose.prototype.disconnect = function (fn) {
+ var count = this.connections.length
+ , error
+
+ this.connections.forEach(function(conn){
+ conn.close(function(err){
+ if (error) return;
+
+ if (err) {
+ error = err;
+ if (fn) return fn(err);
+ throw err;
+ }
+
+ if (fn)
+ --count || fn();
+ });
+ });
+ return this;
+};
+
+/**
+ * Defines a model or retrieves it.
+ *
+ * Models defined on the `mongoose` instance are available to all connection created by the same `mongoose` instance.
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ *
+ * // define an Actor model with this mongoose instance
+ * mongoose.model('Actor', new Schema({ name: String }));
+ *
+ * // create a new connection
+ * var conn = mongoose.createConnection(..);
+ *
+ * // retrieve the Actor model
+ * var Actor = conn.model('Actor');
+ *
+ * _When no `collection` argument is passed, Mongoose produces a collection name by passing the model `name` to the [utils.toCollectionName](#utils.toCollectionName) method. This method pluralizes the name. If you don't like this behavior, either pass a collection name or set your schemas collection name option._
+ *
+ * ####Example:
+ *
+ * var schema = new Schema({ name: String }, { collection: 'actor' });
+ *
+ * // or
+ *
+ * schema.set('collection', 'actor');
+ *
+ * // or
+ *
+ * var collectionName = 'actor'
+ * var M = mongoose.model('Actor', schema, collectionName)
+ *
+ * @param {String} name model name
+ * @param {Schema} [schema]
+ * @param {String} [collection] name (optional, induced from model name)
+ * @param {Boolean} [skipInit] whether to skip initialization (defaults to false)
+ * @api public
+ */
+
+Mongoose.prototype.model = function (name, schema, collection, skipInit) {
+ if (!(schema instanceof Schema)) {
+ collection = schema;
+ schema = false;
+ }
+
+ if ('boolean' === typeof collection) {
+ skipInit = collection;
+ collection = null;
+ }
+
+ // handle internal options from connection.model()
+ var options;
+ if (skipInit && utils.isObject(skipInit)) {
+ options = skipInit;
+ skipInit = true;
+ } else {
+ options = {};
+ }
+
+ // look up schema for the collection. this might be a
+ // default schema like system.indexes stored in SchemaDefaults.
+ if (!this.modelSchemas[name]) {
+ if (!schema && name in SchemaDefaults) {
+ schema = SchemaDefaults[name];
+ }
+
+ if (schema) {
+ // cache it so we only apply plugins once
+ this.modelSchemas[name] = schema;
+ this._applyPlugins(schema);
+ } else {
+ throw new mongoose.Error.MissingSchemaError(name);
+ }
+ }
+
+ var model;
+ var sub;
+
+ // connection.model() may be passing a different schema for
+ // an existing model name. in this case don't read from cache.
+ if (this.models[name] && false !== options.cache) {
+ if (schema instanceof Schema && schema != this.models[name].schema) {
+ throw new mongoose.Error.OverwriteModelError(name);
+ }
+
+ if (collection) {
+ // subclass current model with alternate collection
+ model = this.models[name];
+ schema = model.prototype.schema;
+ sub = model.__subclass(this.connection, schema, collection);
+ // do not cache the sub model
+ return sub;
+ }
+
+ return this.models[name];
+ }
+
+ // ensure a schema exists
+ if (!schema) {
+ schema = this.modelSchemas[name];
+ if (!schema) {
+ throw new mongoose.Error.MissingSchemaError(name);
+ }
+ }
+
+ if (!collection) {
+ collection = schema.get('collection') || format(name);
+ }
+
+ var connection = options.connection || this.connection;
+ model = Model.compile(name, schema, collection, connection, this);
+
+ if (!skipInit) {
+ model.init();
+ }
+
+ if (false === options.cache) {
+ return model;
+ }
+
+ return this.models[name] = model;
+}
+
+/**
+ * Applies global plugins to `schema`.
+ *
+ * @param {Schema} schema
+ * @api private
+ */
+
+Mongoose.prototype._applyPlugins = function (schema) {
+ for (var i = 0, l = this.plugins.length; i < l; i++) {
+ schema.plugin(this.plugins[i][0], this.plugins[i][1]);
+ }
+}
+
+/**
+ * Declares a global plugin executed on all Schemas.
+ *
+ * Equivalent to calling `.plugin(fn)` on each Schema you create.
+ *
+ * @param {Function} fn plugin callback
+ * @param {Object} [opts] optional options
+ * @return {Mongoose} this
+ * @see plugins ./plugins.html
+ * @api public
+ */
+
+Mongoose.prototype.plugin = function (fn, opts) {
+ this.plugins.push([fn, opts]);
+ return this;
+};
+
+/**
+ * The default connection of the mongoose module.
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ * mongoose.connect(...);
+ * mongoose.connection.on('error', cb);
+ *
+ * This is the connection used by default for every model created using [mongoose.model](#index_Mongoose-model).
+ *
+ * @property connection
+ * @return {Connection}
+ * @api public
+ */
+
+Mongoose.prototype.__defineGetter__('connection', function(){
+ return this.connections[0];
+});
+
+/*!
+ * Driver depentend APIs
+ */
+
+var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
+
+/*!
+ * Connection
+ */
+
+var Connection = require(driver + '/connection');
+
+/*!
+ * Collection
+ */
+
+var Collection = require(driver + '/collection');
+
+/**
+ * The exports object is an instance of Mongoose.
+ *
+ * @api public
+ */
+
+module.exports = exports = new Mongoose;
+var mongoose = module.exports;
+
+/**
+ * The Mongoose Collection constructor
+ *
+ * @api public
+ */
+
+mongoose.Collection = Collection;
+
+/**
+ * The Mongoose Connection constructor
+ *
+ * @api public
+ */
+
+mongoose.Connection = Connection;
+
+/**
+ * Mongoose version
+ *
+ * @api public
+ */
+
+mongoose.version = JSON.parse(
+ require('fs').readFileSync(__dirname + '/../package.json', 'utf8')
+).version;
+
+/**
+ * The Mongoose constructor
+ *
+ * The exports of the mongoose module is an instance of this class.
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ * var mongoose2 = new mongoose.Mongoose();
+ *
+ * @api public
+ */
+
+mongoose.Mongoose = Mongoose;
+
+/**
+ * The Mongoose Schema constructor
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ * var Schema = mongoose.Schema;
+ * var CatSchema = new Schema(..);
+ *
+ * @api public
+ */
+
+mongoose.Schema = Schema;
+
+/**
+ * The Mongoose SchemaType constructor.
+ *
+ * @api public
+ */
+
+mongoose.SchemaType = SchemaType;
+
+/**
+ * The various Mongoose SchemaTypes.
+ *
+ * ####Note:
+ *
+ * _Alias of mongoose.Schema.Types for backwards compatibility._
+ *
+ * @see Schema.SchemaTypes #schema_Schema-Types
+ * @api public
+ */
+
+mongoose.SchemaTypes = Schema.Types;
+
+/**
+ * The Mongoose VirtualType constructor.
+ *
+ * @api public
+ */
+
+mongoose.VirtualType = VirtualType;
+
+/**
+ * The various Mongoose Types.
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ * var array = mongoose.Types.Array;
+ *
+ * ####Types:
+ *
+ * - Array
+ * - Buffer
+ * - Document
+ * - Embedded
+ * - DocumentArray
+ * - ObjectId
+ *
+ * Using this exposed access to the `ObjectId` type, we can construct ids on demand.
+ *
+ * var ObjectId = mongoose.Types.ObjectId;
+ * var id1 = new ObjectId;
+ *
+ * @api public
+ */
+
+mongoose.Types = Types;
+
+/**
+ * The Mongoose Query constructor.
+ *
+ * @api public
+ */
+
+mongoose.Query = Query;
+
+/**
+ * The Mongoose Promise constructor.
+ *
+ * @api public
+ */
+
+mongoose.Promise = Promise;
+
+/**
+ * The Mongoose Model constructor.
+ *
+ * @api public
+ */
+
+mongoose.Model = Model;
+
+/**
+ * The Mongoose Document constructor.
+ *
+ * @api public
+ */
+
+mongoose.Document = Document;
+
+/**
+ * The MongooseError constructor.
+ *
+ * @api public
+ */
+
+mongoose.Error = require('./error');
+
+/**
+ * The node-mongodb-native driver Mongoose uses.
+ *
+ * @api public
+ */
+
+mongoose.mongo = require('mongodb');
diff --git a/test/node_modules/mongoose/lib/model.js b/test/node_modules/mongoose/lib/model.js
new file mode 100644
index 0000000..ec4aa1b
--- /dev/null
+++ b/test/node_modules/mongoose/lib/model.js
@@ -0,0 +1,1745 @@
+/*!
+ * Module dependencies.
+ */
+
+var Document = require('./document')
+ , MongooseArray = require('./types/array')
+ , MongooseBuffer = require('./types/buffer')
+ , MongooseError = require('./error')
+ , VersionError = require('./errors/version')
+ , Query = require('./query')
+ , Schema = require('./schema')
+ , utils = require('./utils')
+ , isMongooseObject = utils.isMongooseObject
+ , EventEmitter = utils.EventEmitter
+ , merge = utils.merge
+ , Promise = require('./promise')
+ , tick = utils.tick
+
+var VERSION_WHERE = 1
+ , VERSION_INC = 2
+ , VERSION_ALL = VERSION_WHERE | VERSION_INC;
+
+/**
+ * Model constructor
+ *
+ * @param {Object} doc values to with which to create the document
+ * @inherits Document
+ * @event `error`: If listening to this Model event, it is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
+ * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
+ * @api public
+ */
+
+function Model (doc, fields, skipId) {
+ Document.call(this, doc, fields, skipId);
+};
+
+/*!
+ * Inherits from Document.
+ *
+ * All Model.prototype features are available on
+ * top level (non-sub) documents.
+ */
+
+Model.prototype.__proto__ = Document.prototype;
+
+/**
+ * Connection the model uses.
+ *
+ * @api public
+ * @property db
+ */
+
+Model.prototype.db;
+
+/**
+ * Collection the model uses.
+ *
+ * @api public
+ * @property collection
+ */
+
+Model.prototype.collection;
+
+/**
+ * The name of the model
+ *
+ * @api public
+ * @property modelName
+ */
+
+Model.prototype.modelName;
+
+/**
+ * Returns what paths can be populated
+ *
+ * @param {Query} query object
+ * @return {Object|undefined} population paths
+ * @api private
+ */
+
+Model.prototype._getPopulationKeys = function getPopulationKeys (query) {
+ if (!(query && query.options.populate)) return;
+
+ var names = Object.keys(query.options.populate)
+ , n = names.length
+ , name
+ , paths = {}
+ , hasKeys
+ , schema
+
+ while (n--) {
+ name = names[n];
+ schema = this.schema.path(name);
+ hasKeys = true;
+
+ if (!schema) {
+ // if the path is not recognized, it's potentially embedded docs
+ // walk path atoms from right to left to find a matching path
+ var pieces = name.split('.')
+ , i = pieces.length;
+
+ while (i--) {
+ var path = pieces.slice(0, i).join('.')
+ , pathSchema = this.schema.path(path);
+
+ // loop until we find an array schema
+ if (pathSchema && pathSchema.caster) {
+ if (!paths[path]) {
+ paths[path] = { sub: {} };
+ }
+
+ paths[path].sub[pieces.slice(i).join('.')] = query.options.populate[name];
+ hasKeys || (hasKeys = true);
+ break;
+ }
+ }
+ } else {
+ paths[name] = query.options.populate[name];
+ hasKeys || (hasKeys = true);
+ }
+ }
+
+ return hasKeys && paths;
+};
+
+/**
+ * Populates an object
+ *
+ * @param {SchemaType} schema type for the oid
+ * @param {Object} oid object id or array of object ids
+ * @param {Object} query object specifying query conditions, fields, and options
+ * @param {Function} fn
+ * @api private
+ */
+
+Model.prototype._populate = function populate (schema, oid, query, fn) {
+ if (!Array.isArray(oid)) {
+ var conditions = query.conditions || {};
+ conditions._id = oid;
+
+ return this
+ .db.model(query.model || schema.options.ref)
+ .findOne(conditions, query.fields, query.options, fn);
+ }
+
+ if (!oid.length) {
+ return fn(null, oid);
+ }
+
+ var model = this.db.model(query.model || schema.caster.options.ref)
+ , conditions = query && query.conditions || {};
+
+ conditions._id || (conditions._id = { $in: oid });
+
+ model.find(conditions, query.fields, query.options, function (err, docs) {
+ if (err) return fn(err);
+
+ // user specified sort order?
+ if (query.options && query.options.sort) {
+ return fn(null, docs);
+ }
+
+ // put back in original id order (using a hash reduces complexity from n*n to 2n)
+ var docHash = {};
+ docs.forEach(function (doc) {
+ docHash[doc._id] = doc;
+ });
+
+ var arr = [];
+ oid.forEach(function (id) {
+ if (id in docHash) arr.push(docHash[id]);
+ });
+
+ fn(null, arr);
+ });
+};
+
+/**
+ * Performs auto-population of relations.
+ *
+ * @param {Object} doc document returned by mongo
+ * @param {Query} query query that originated the initialization
+ * @param {Function} fn
+ * @api private
+ */
+
+Model.prototype.init = function init (doc, query, fn) {
+ if ('function' == typeof query) {
+ fn = query;
+ query = null;
+ }
+
+ var populate = this._getPopulationKeys(query);
+
+ if (!populate) {
+ return Document.prototype.init.call(this, doc, fn);
+ }
+
+ // population from other models is necessary
+ var self = this;
+
+ init(doc, '', function (err) {
+ if (err) return fn(err);
+ Document.prototype.init.call(self, doc, fn);
+ });
+
+ return this;
+
+ function init (obj, prefix, fn) {
+ prefix = prefix || '';
+
+ var keys = Object.keys(obj)
+ , len = keys.length;
+
+ return next();
+
+ function next () {
+ if (--len < 0) return fn();
+
+ var i = keys[len]
+ , path = prefix + i
+ , schema = self.schema.path(path)
+ , total = 0
+ , inline = false
+ , poppath
+
+ if (!schema && obj[i] && 'Object' === obj[i].constructor.name) {
+ // assume nested object
+ return init(obj[i], path + '.', next);
+ }
+
+ if (!(obj[i] && schema && populate[path])) return next();
+
+ // this query object is re-used and passed around. we clone
+ // it to prevent query condition contamination between
+ // one populate call to the next.
+ poppath = utils.clone(populate[path]);
+
+ if (poppath.sub) {
+ obj[i].forEach(function (subobj) {
+ inline = true;
+
+ var pkeys = Object.keys(poppath.sub)
+ , pi = pkeys.length
+ , key
+
+ while (pi--) {
+ key = pkeys[pi];
+
+ if (subobj[key]) (function (key) {
+ total++;
+ self._populate(schema.schema.path(key), subobj[key], poppath.sub[key], done);
+ function done (err, doc) {
+ if (err) return error(err);
+ subobj[key] = doc;
+ if (--total < 1 && !inline) {
+ next();
+ }
+ }
+ })(key);
+ }
+ });
+
+ inline = false;
+
+ if (0 === total) return next();
+
+ } else {
+ self._populate(schema, obj[i], poppath, function (err, doc) {
+ if (err) return error(err);
+ obj[i] = doc;
+ next();
+ });
+ }
+ };
+ };
+
+ function error (err) {
+ if (error.err) return;
+ fn(error.err = err);
+ }
+};
+
+/*!
+ * Handles doc.save() callbacks
+ */
+
+function handleSave (promise, self) {
+ return tick(function handleSave (err, result) {
+ if (err) {
+ // If the initial insert fails provide a second chance.
+ // (If we did this all the time we would break updates)
+ if (self._inserting) {
+ self.isNew = true;
+ self.emit('isNew', true);
+ }
+ promise.error(err);
+ promise = self = null;
+ return;
+ }
+
+ self._storeShard();
+
+ var numAffected;
+ if (result) {
+ // when inserting, the array of created docs is returned
+ numAffected = result.length
+ ? result.length
+ : result;
+ } else {
+ numAffected = 0;
+ }
+
+ // was this an update that required a version bump?
+ if (self.__version && !self._inserting) {
+ var doIncrement = VERSION_INC === (VERSION_INC & self.__version);
+ self.__version = undefined;
+
+ // increment version if was successful
+ if (numAffected > 0) {
+ if (doIncrement) {
+ var key = self.schema.options.versionKey;
+ var version = self.getValue(key) | 0;
+ self.setValue(key, version + 1);
+ }
+ } else {
+ // the update failed. pass an error back
+ promise.error(new VersionError);
+ promise = self = null;
+ return;
+ }
+ }
+
+ self.emit('save', self, numAffected);
+ promise.complete(self, numAffected);
+ promise = self = null;
+ });
+}
+
+/**
+ * Saves this document.
+ *
+ * ####Example:
+ *
+ * product.sold = Date.now();
+ * product.save(function (err, product) {
+ * if (err) ..
+ * })
+ *
+ * The `fn` callback is optional. If no `fn` is passed and validation fails, the validation error will be emitted on the connection used to create this model.
+ *
+ * var db = mongoose.createConnection(..);
+ * var schema = new Schema(..);
+ * var Product = db.model('Product', schema);
+ *
+ * db.on('error', handleError);
+ *
+ * However, if you desire more local error handling you can add an `error` listener to the model and handle errors there instead.
+ *
+ * Product.on('error', handleError);
+ *
+ * @param {Function} [fn] optional callback
+ * @api public
+ * @see middleware http://mongoosejs.com/docs/middleware.html
+ */
+
+Model.prototype.save = function save (fn) {
+ var promise = new Promise(fn)
+ , complete = handleSave(promise, this)
+ , options = {}
+
+ if (this.schema.options.safe) {
+ options.safe = this.schema.options.safe;
+ }
+
+ if (this.isNew) {
+ // send entire doc
+ var obj = this.toObject({ depopulate: 1 });
+ this._version(true, obj);
+ this.collection.insert(obj, options, complete);
+ this._reset();
+ this.isNew = false;
+ this.emit('isNew', false);
+ // Make it possible to retry the insert
+ this._inserting = true;
+
+ } else {
+ // Make sure we don't treat it as a new object on error,
+ // since it already exists
+ this._inserting = false;
+
+ var delta = this._delta();
+ if (delta) {
+ var where = this._where(delta[0]);
+ this.collection.update(where, delta[1], options, complete);
+ } else {
+ process.nextTick(function () {
+ complete(null);
+ })
+ }
+
+ this._reset();
+ this.emit('isNew', false);
+ }
+};
+
+/*!
+ * Apply the operation to the delta (update) clause as
+ * well as track versioning for our where clause.
+ *
+ * @param {Document} self
+ * @param {Object} where
+ * @param {Object} delta
+ * @param {Object} data
+ * @param {Mixed} val
+ * @param {String} [operation]
+ */
+
+function operand (self, where, delta, data, val, op) {
+ // delta
+ op || (op = '$set');
+ if (!delta[op]) delta[op] = {};
+ delta[op][data.path] = val;
+
+ // disabled versioning?
+ if (false === self.schema.options.versionKey) return;
+
+ // already marked for versioning?
+ if (VERSION_ALL === (VERSION_ALL & self.__version)) return;
+
+ switch (op) {
+ case '$set':
+ case '$unset':
+ case '$pop':
+ case '$pull':
+ case '$pullAll':
+ case '$push':
+ case '$pushAll':
+ case '$addToSet':
+ break;
+ default:
+ // nothing to do
+ return;
+ }
+
+ // ensure updates sent with positional notation are
+ // editing the correct array element.
+ // only increment the version if an array position changes.
+ // modifying elements of an array is ok if position does not change.
+
+ if ('$push' == op || '$pushAll' == op || '$addToSet' == op) {
+ self.__version = VERSION_INC;
+ }
+ else if (/^\$p/.test(op)) {
+ // potentially changing array positions
+ self.increment();
+ }
+ else if (Array.isArray(val)) {
+ // $set an array
+ self.increment();
+ }
+ // now handling $set, $unset
+ else if (/\.\d+/.test(data.path)) {
+ // subpath of array
+ self.__version = VERSION_WHERE;
+ }
+}
+
+/*!
+ * Compiles an update and where clause for a `val` with _atomics.
+ *
+ * @param {Document} self
+ * @param {Object} where
+ * @param {Object} delta
+ * @param {Object} data
+ * @param {Array} val
+ */
+
+function handleAtomics (self, where, delta, data, val) {
+ if (delta.$set && delta.$set[data.path]) {
+ // $set has precedence over other atomics
+ return;
+ }
+
+ var atomics = val._atomics
+ , ops = Object.keys(atomics)
+ , schema = data.schema
+ , path = data.path
+ , i = ops.length
+ , val
+ , op;
+
+ if (0 === i) {
+ // $set
+
+ if (isMongooseObject(val)) {
+ val = val.toObject({ depopulate: 1 });
+ } else if (val.valueOf) {
+ val = val.valueOf();
+ }
+
+ return operand(self, where, delta, data, val);
+ }
+
+ while (i--) {
+ op = ops[i];
+ val = atomics[op];
+ if (isMongooseObject(val)) {
+ val = val.toObject({ depopulate: 1 })
+ } else if (Array.isArray(val)) {
+ val = val.map(function (mem) {
+ return isMongooseObject(mem)
+ ? mem.toObject({ depopulate: 1 })
+ : mem;
+ })
+ } else if (val.valueOf) {
+ val = val.valueOf()
+ }
+
+ if ('$addToSet' === op)
+ val = { $each: val };
+
+ operand(self, where, delta, data, val, op);
+ }
+}
+
+/**
+ * Produces a special query document of the modified properties used in updates.
+ *
+ * @api private
+ */
+
+Model.prototype._delta = function _delta () {
+ var dirty = this._dirty();
+ if (!dirty.length) return;
+
+ var self = this
+ , where = {}
+ , delta = {}
+ , len = dirty.length
+ , d = 0
+ , val
+ , obj
+
+ for (; d < len; ++d) {
+ var data = dirty[d]
+ var value = data.value
+ var schema = data.schema
+
+ if (undefined === value) {
+ operand(self, where, delta, data, 1, '$unset');
+
+ } else if (null === value) {
+ operand(self, where, delta, data, null);
+
+ } else if (value._path && value._atomics) {
+ // arrays and other custom types (support plugins etc)
+ handleAtomics(self, where, delta, data, value);
+
+ } else if (value._path && Buffer.isBuffer(value)) {
+ // MongooseBuffer
+ value = value.toObject();
+ operand(self, where, delta, data, value);
+
+ } else {
+ value = utils.clone(value);
+ operand(self, where, delta, data, value);
+ }
+ }
+
+ if (this.__version) {
+ this._version(where, delta);
+ }
+
+ return [where, delta];
+}
+
+/**
+ * Appends versioning to the where and update clauses.
+ *
+ * @api private
+ */
+
+Model.prototype._version = function _version (where, delta) {
+ var key = this.schema.options.versionKey;
+
+ if (true === where) {
+ // this is an insert
+ if (key) this.setValue(key, delta[key] = 0);
+ return;
+ }
+
+ // updates
+
+ // only apply versioning if our versionKey was selected. else
+ // there is no way to select the correct version. we could fail
+ // fast here and force them to include the versionKey but
+ // thats a bit intrusive. can we do this automatically?
+ // TODO fail fast option?
+ if (!this.isSelected(key)) {
+ return;
+ }
+
+ // $push $addToSet don't need the where clause set
+ if (VERSION_WHERE === (VERSION_WHERE & this.__version)) {
+ where[key] = this.getValue(key);
+ }
+
+ if (VERSION_INC === (VERSION_INC & this.__version)) {
+ delta.$inc || (delta.$inc = {});
+ delta.$inc[key] = 1;
+ }
+}
+
+/**
+ * Signal that we desire an increment of this documents version.
+ *
+ * @see versionKeys http://mongoosejs.com/docs/guide.html#versionKey
+ * @api public
+ */
+
+Model.prototype.increment = function increment () {
+ this.__version = VERSION_ALL;
+ return this;
+}
+
+/**
+ * Returns a query object which applies shardkeys if they exist.
+ *
+ * @api private
+ */
+
+Model.prototype._where = function _where (where) {
+ where || (where = {});
+
+ var paths
+ , len
+
+ if (this._shardval) {
+ paths = Object.keys(this._shardval)
+ len = paths.length
+
+ for (var i = 0; i < len; ++i) {
+ where[paths[i]] = this._shardval[paths[i]];
+ }
+ }
+
+ where._id = this._doc._id;
+ return where;
+}
+
+/**
+ * Removes this document from the db.
+ *
+ * ####Example:
+ *
+ * product.remove(function (err, product) {
+ * if (err) return handleError(err);
+ * Product.findById(product._id, function (err, product) {
+ * console.log(product) // null
+ * })
+ * })
+ *
+ * @param {Function} [fn] optional callback
+ * @api public
+ */
+
+Model.prototype.remove = function remove (fn) {
+ if (this._removing) {
+ this._removing.addBack(fn);
+ return this;
+ }
+
+ var promise = this._removing = new Promise(fn)
+ , where = this._where()
+ , self = this
+ , options = {}
+
+ if (this.schema.options.safe) {
+ options.safe = this.schema.options.safe;
+ }
+
+ this.collection.remove(where, options, tick(function (err) {
+ if (err) {
+ promise.error(err);
+ promise = self = self._removing = where = options = null;
+ return;
+ }
+ self.emit('remove', self);
+ promise.complete();
+ promise = self = where = options = null;
+ }));
+
+ return this;
+};
+
+/**
+ * Register hooks override
+ *
+ * @api private
+ */
+
+Model.prototype._registerHooks = function registerHooks () {
+ Document.prototype._registerHooks.call(this);
+};
+
+/**
+ * Returns another Model instance.
+ *
+ * ####Example:
+ *
+ * var doc = new Tank;
+ * doc.model('User').findById(id, callback);
+ *
+ * @param {String} name model name
+ * @api public
+ */
+
+Model.prototype.model = function model (name) {
+ return this.db.model(name);
+};
+
+// Model (class) features
+
+/*!
+ * Give the constructor the ability to emit events.
+ */
+
+for (var i in EventEmitter.prototype)
+ Model[i] = EventEmitter.prototype[i];
+
+/**
+ * Called when the model compiles.
+ *
+ * @api private
+ */
+
+Model.init = function init () {
+ if (this.schema.options.autoIndex) {
+ this.ensureIndexes();
+ }
+
+ this.schema.emit('init', this);
+};
+
+/**
+ * Sends `ensureIndex` commands to mongo for each index declared in the schema.
+ *
+ * After completion, an `index` event is emitted on this `Model` passing an error if one occurred.
+ *
+ * _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._
+ *
+ * ####Example:
+ *
+ * Event.ensureIndexes(function (err) {
+ * if (err) return handleError(err);
+ * });
+ *
+ * @param {Function} [cb] optional callback
+ * @api public
+ */
+
+Model.ensureIndexes = function ensureIndexes (cb) {
+ var indexes = this.schema.indexes();
+ if (!indexes.length) {
+ return cb && cb();
+ }
+
+ var self = this
+ , safe = self.schema.options.safe
+ , count = indexes.length
+ , error
+
+ indexes.forEach(function (index) {
+ var options = index[1];
+ options.safe = safe;
+ self.collection.ensureIndex(index[0], options, tick(function (err) {
+ if (err) error = err;
+ if (--count) return;
+
+ self.emit('index', error);
+ cb && cb(error);
+ }));
+ });
+}
+
+/**
+ * Schema the model uses.
+ *
+ * @property schema
+ * @receiver Model
+ * @api public
+ */
+
+Model.schema;
+
+/**
+ * Database instance the model uses.
+ *
+ * @property db
+ * @receiver Model
+ * @api public
+ */
+
+Model.db;
+
+/**
+ * Collection the model uses.
+ *
+ * @property collection
+ * @receiver Model
+ * @api public
+ */
+
+Model.collection;
+
+/**
+ * Base Mongoose instance the model uses.
+ *
+ * @property base
+ * @receiver Model
+ * @api public
+ */
+
+Model.base;
+
+/**
+ * Removes documents from the collection.
+ *
+ * ####Note:
+ *
+ * To remove documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js):
+ *
+ * Comment.remove({ _id: id }).exec();
+ *
+ * ####Note:
+ *
+ * This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, _no middleware (hooks) are executed_.
+ *
+ * @param {Object} conditions
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.remove = function remove (conditions, callback) {
+ if ('function' === typeof conditions) {
+ callback = conditions;
+ conditions = {};
+ }
+
+ var query = new Query(conditions).bind(this, 'remove');
+
+ if ('undefined' === typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.remove(callback);
+};
+
+/**
+ * Finds documents
+ *
+ * ####Examples:
+ *
+ * // retrieve only certain keys
+ * MyModel.find({ name: /john/i }, 'name friends', function () { })
+ *
+ * // pass options
+ * MyModel.find({ name: /john/i }, null, { skip: 10 } )
+ *
+ * @param {Object} conditions
+ * @param {Object} [fields] optional fields to select
+ * @param {Object} [options] optional
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @api public
+ */
+
+Model.find = function find (conditions, fields, options, callback) {
+ if ('function' == typeof conditions) {
+ callback = conditions;
+ conditions = {};
+ fields = null;
+ options = null;
+ } else if ('function' == typeof fields) {
+ callback = fields;
+ fields = null;
+ options = null;
+ } else if ('function' == typeof options) {
+ callback = options;
+ options = null;
+ }
+
+ var query = new Query(conditions, options);
+ query.bind(this, 'find');
+ query.select(fields);
+
+ if ('undefined' === typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.find(callback);
+};
+
+/**
+ * Merges the current named scope query into `query`.
+ *
+ * @param {Query} query
+ * @return {Query}
+ * @api private
+ */
+
+Model._applyNamedScope = function _applyNamedScope (query) {
+ var cQuery = this._cumulativeQuery;
+
+ if (cQuery) {
+ merge(query._conditions, cQuery._conditions);
+ if (query._fields && cQuery._fields)
+ merge(query._fields, cQuery._fields);
+ if (query.options && cQuery.options)
+ merge(query.options, cQuery.options);
+ delete this._cumulativeQuery;
+ }
+
+ return query;
+}
+
+/**
+ * Finds a single document by id.
+ *
+ * The `id` is cast to an ObjectId before sending the command.
+ *
+ * ####Example:
+ *
+ * Adventure.findById(id, callback);
+ *
+ * @param {ObjectId|HexId} id objectid, or a value that can be casted to one
+ * @param {Object} [fields] optional fields to select
+ * @param {Object} [options] optional
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @api public
+ */
+
+Model.findById = function findById (id, fields, options, callback) {
+ return this.findOne({ _id: id }, fields, options, callback);
+};
+
+/**
+ * Finds one document.
+ *
+ * The `conditions` are cast to their respective SchemaTypes before the command is sent.
+ *
+ * ####Example:
+ *
+ * Adventure.findOne({ type: 'iphone' }, 'name', { safe: true }, callback);
+ *
+ * @param {Object} conditions
+ * @param {Object} [fields] optional fields to select
+ * @param {Object} [options] optional
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @api public
+ */
+
+Model.findOne = function findOne (conditions, fields, options, callback) {
+ if ('function' == typeof options) {
+ callback = options;
+ options = null;
+ } else if ('function' == typeof fields) {
+ callback = fields;
+ fields = null;
+ options = null;
+ } else if ('function' == typeof conditions) {
+ callback = conditions;
+ conditions = {};
+ fields = null;
+ options = null;
+ }
+
+ var query = new Query(conditions, options).select(fields).bind(this, 'findOne');
+
+ if ('undefined' == typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.findOne(callback);
+};
+
+/**
+ * Counts number of matching documents in a database collection.
+ *
+ * ####Example:
+ *
+ * Adventure.count({ type: 'jungle' }, function (err, count) {
+ * if (err) ..
+ * console.log('there are %d jungle adventures', count);
+ * });
+ *
+ * @param {Object} conditions
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.count = function count (conditions, callback) {
+ if ('function' === typeof conditions)
+ callback = conditions, conditions = {};
+
+ var query = new Query(conditions).bind(this, 'count');
+ if ('undefined' == typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.count(callback);
+};
+
+/**
+ * Executes a DISTINCT command
+ *
+ * @param {String} field
+ * @param {Object} [conditions] optional
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.distinct = function distinct (field, conditions, callback) {
+ var query = new Query(conditions).bind(this, 'distinct');
+ if ('undefined' == typeof callback) {
+ query._distinctArg = field;
+ return query;
+ }
+
+ this._applyNamedScope(query);
+ return query.distinct(field, callback);
+};
+
+/**
+ * Creates a Query, applies the passed conditions, and returns the Query.
+ *
+ * For example, instead of writing:
+ *
+ * User.find({age: {$gte: 21, $lte: 65}}, callback);
+ *
+ * we can instead write:
+ *
+ * User.where('age').gte(21).lte(65).exec(callback);
+ *
+ * Since the Query class also supports `where` you can continue chaining
+ *
+ * User
+ * .where('age').gte(21).lte(65)
+ * .where('name', /^b/i)
+ * ... etc
+ *
+ * @param {String} path
+ * @param {Object} [val] optional value
+ * @return {Query}
+ * @api public
+ */
+
+Model.where = function where (path, val) {
+ var q = new Query().bind(this, 'find');
+ return q.where.apply(q, arguments);
+};
+
+/**
+ * Creates a `Query` and specifies a `$where` condition.
+ *
+ * Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.
+ *
+ * Blog.$where('this.comments.length > 5');
+ *
+ * @param {String|Function} argument is a javascript string or anonymous function
+ * @method $where
+ * @memberOf Model
+ * @return {Query}
+ * @see Query.$where #query_Query-%24where
+ * @api public
+ */
+
+Model.$where = function $where () {
+ var q = new Query().bind(this, 'find');
+ return q.$where.apply(q, arguments);
+};
+
+/**
+ * Issues a mongodb findAndModify update command.
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Options:
+ *
+ * - `new`: bool - true to return the modified document rather than the original. defaults to true
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ *
+ * ####Examples:
+ *
+ * A.findOneAndUpdate(conditions, update, options, callback) // executes
+ * A.findOneAndUpdate(conditions, update, options) // returns Query
+ * A.findOneAndUpdate(conditions, update, callback) // executes
+ * A.findOneAndUpdate(conditions, update) // returns Query
+ * A.findOneAndUpdate() // returns Query
+ *
+ * ####Note:
+ *
+ * All top level update keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * var query = { name: 'borne' };
+ * Model.findOneAndUpdate(query, { name: 'jason borne' }, options, callback)
+ *
+ * // is sent as
+ * Model.findOneAndUpdate(query, { $set: { name: 'jason borne' }}, options, callback)
+ *
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
+ *
+ * ####Note:
+ *
+ * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied:
+ *
+ * - defaults
+ * - setters
+ * - validators
+ * - middleware
+ *
+ * If you need those features, use the traditional approach of first retrieving the document.
+ *
+ * Model.findOne({ name: 'borne' }, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason borne';
+ * doc.save(callback);
+ * })
+ *
+ * @param {Object} [conditions]
+ * @param {Object} [update]
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findOneAndUpdate = function (conditions, update, options, callback) {
+ if ('function' == typeof options) {
+ callback = options;
+ options = null;
+ }
+ else if (1 === arguments.length) {
+ if ('function' == typeof conditions) {
+ var msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(update)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate()\n';
+ throw new TypeError(msg)
+ }
+ update = conditions;
+ conditions = undefined;
+ }
+
+ var fields;
+ if (options && options.fields) {
+ fields = options.fields;
+ options.fields = undefined;
+ }
+
+ var query = new Query(conditions);
+ query.setOptions(options);
+ query.select(fields);
+ query.bind(this, 'findOneAndUpdate', update);
+
+ if ('undefined' == typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.findOneAndUpdate(callback);
+}
+
+/**
+ * Issues a mongodb findAndModify update command by a documents id.
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Options:
+ *
+ * - `new`: bool - true to return the modified document rather than the original. defaults to true
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ *
+ * ####Examples:
+ *
+ * A.findByIdAndUpdate(id, update, options, callback) // executes
+ * A.findByIdAndUpdate(id, update, options) // returns Query
+ * A.findByIdAndUpdate(id, update, callback) // executes
+ * A.findByIdAndUpdate(id, update) // returns Query
+ * A.findByIdAndUpdate() // returns Query
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Options:
+ *
+ * - `new`: bool - true to return the modified document rather than the original. defaults to true
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ *
+ * ####Note:
+ *
+ * All top level update keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * Model.findByIdAndUpdate(id, { name: 'jason borne' }, options, callback)
+ *
+ * // is sent as
+ * Model.findByIdAndUpdate(id, { $set: { name: 'jason borne' }}, options, callback)
+ *
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason borne' }`.
+ *
+ * ####Note:
+ *
+ * Although values are cast to their appropriate types when using the findAndModify helpers, the following are *not* applied:
+ *
+ * - defaults
+ * - setters
+ * - validators
+ * - middleware
+ *
+ * If you need those features, use the traditional approach of first retrieving the document.
+ *
+ * Model.findById(id, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason borne';
+ * doc.save(callback);
+ * })
+ *
+ * @param {ObjectId|HexId} id an ObjectId or string that can be cast to one.
+ * @param {Object} [update]
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Model.findOneAndUpdate #model_Model-findOneAndUpdate
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findByIdAndUpdate = function (id, update, options, callback) {
+ var args;
+
+ if (1 === arguments.length) {
+ if ('function' == typeof id) {
+ var msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate()\n';
+ throw new TypeError(msg)
+ }
+ return this.findOneAndUpdate({_id: id }, undefined);
+ }
+
+ args = utils.args(arguments, 1);
+ args.unshift({ _id: id });
+ return this.findOneAndUpdate.apply(this, args);
+}
+
+/**
+ * Issue a mongodb findAndModify remove command.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to the callback.
+ *
+ * Executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ *
+ * ####Examples:
+ *
+ * A.findOneAndRemove(conditions, options, callback) // executes
+ * A.findOneAndRemove(conditions, options) // return Query
+ * A.findOneAndRemove(conditions, callback) // executes
+ * A.findOneAndRemove(conditions) // returns Query
+ * A.findOneAndRemove() // returns Query
+ *
+ * @param {Object} conditions
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findOneAndRemove = function (conditions, options, callback) {
+ if (1 === arguments.length && 'function' == typeof conditions) {
+ var msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
+ + ' ' + this.modelName + '.findOneAndRemove(conditions)\n'
+ + ' ' + this.modelName + '.findOneAndRemove()\n';
+ throw new TypeError(msg)
+ }
+
+ if ('function' == typeof options) {
+ callback = options;
+ options = undefined;
+ }
+
+ var fields;
+ if (options) {
+ fields = options.select;
+ options.select = undefined;
+ }
+
+ var query = new Query(conditions);
+ query.setOptions(options);
+ query.select(fields);
+ query.bind(this, 'findOneAndRemove');
+
+ if ('undefined' == typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.findOneAndRemove(callback);
+}
+
+/**
+ * Issue a mongodb findAndModify remove command by a documents id.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to the callback.
+ *
+ * Executes immediately if `callback` is passed, else a `Query` object is returned.
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ *
+ * ####Examples:
+ *
+ * A.findByIdAndRemove(id, options, callback) // executes
+ * A.findByIdAndRemove(id, options) // return Query
+ * A.findByIdAndRemove(id, callback) // executes
+ * A.findByIdAndRemove(id) // returns Query
+ * A.findByIdAndRemove() // returns Query
+ *
+ * @param {ObjectId|HexString} id ObjectId or string that can be cast to one
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Model.findOneAndRemove #model_Model-findOneAndRemove
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ */
+
+Model.findByIdAndRemove = function (id, options, callback) {
+ if (1 === arguments.length && 'function' == typeof id) {
+ var msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
+ + ' ' + this.modelName + '.findByIdAndRemove(id)\n'
+ + ' ' + this.modelName + '.findByIdAndRemove()\n';
+ throw new TypeError(msg)
+ }
+
+ return this.findOneAndRemove({ _id: id }, options, callback);
+}
+
+/**
+ * Shortcut for creating a new Document that is automatically saved to the db if valid.
+ *
+ * ####Example:
+ *
+ * Candy.create({ type: 'jelly bean' }, { type: 'snickers' }, function (err, jellybean, snickers) {
+ * if (err) // ...
+ * });
+ *
+ * var array = [{ type: 'jelly bean' }, { type: 'snickers' }];
+ * Candy.create(array, function (err, jellybean, snickers) {
+ * if (err) // ...
+ * });
+ *
+ * @param {Array|Object...} doc
+ * @param {Function} fn callback
+ * @api public
+ */
+
+Model.create = function create (doc, fn) {
+ if (1 === arguments.length) {
+ return 'function' === typeof doc && doc(null);
+ }
+
+ var self = this
+ , docs = [null]
+ , promise
+ , count
+ , args
+
+ if (Array.isArray(doc)) {
+ args = doc;
+ } else {
+ args = utils.args(arguments, 0, arguments.length - 1);
+ fn = arguments[arguments.length - 1];
+ }
+
+ if (0 === args.length) return fn(null);
+
+ promise = new Promise(fn);
+ count = args.length;
+
+ args.forEach(function (arg, i) {
+ var doc = new self(arg);
+ docs[i+1] = doc;
+ doc.save(function (err) {
+ if (err) return promise.error(err);
+ --count || fn.apply(null, docs);
+ });
+ });
+
+ // TODO
+ // utilize collection.insertAll for batch processing?
+};
+
+/**
+ * Updates documents in the database without returning them.
+ *
+ * ####Examples:
+ *
+ * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
+ * MyModel.update({ name: 'Tobi' }, { ferret: true }, { multi: true }, function (err, numberAffected, raw) {
+ * if (err) return handleError(err);
+ * console.log('The number of updated documents was %d', numberAffected);
+ * console.log('The raw response from Mongo was ', raw);
+ * });
+ *
+ * ####Valid options:
+ *
+ * - `safe` (boolean) safe mode (defaults to value set in schema (true))
+ * - `upsert` (boolean) whether to create the doc if it doesn't match (false)
+ * - `multi` (boolean) whether multiple documents should be updated (false)
+ *
+ * All `update` values are cast to their appropriate SchemaTypes before being sent.
+ *
+ * The `callback` function receives `(err, numberAffected, rawResponse)`.
+ *
+ * - `err` is the error if any occurred
+ * - `numberAffected` is the count of updated documents Mongo reported
+ * - `rawResponse` is the full response from Mongo
+ *
+ * ####Note:
+ *
+ * All top level keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * var query = { name: 'borne' };
+ * Model.update(query, { name: 'jason borne' }, options, callback)
+ *
+ * // is sent as
+ * Model.update(query, { $set: { name: 'jason borne' }}, options, callback)
+ *
+ * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason borne' }`.
+ *
+ * ####Note:
+ *
+ * To update documents without waiting for a response from MongoDB, do not pass a `callback`, then call `exec` on the returned [Query](#query-js):
+ *
+ * Comment.update({ _id: id }, { $set: { text: 'changed' }}).exec();
+ *
+ * ####Note:
+ *
+ * Although values are casted to their appropriate types when using update, the following are *not* applied:
+ *
+ * - defaults
+ * - setters
+ * - validators
+ * - middleware
+ *
+ * If you need those features, use the traditional approach of first retrieving the document.
+ *
+ * Model.findOne({ name: 'borne' }, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason borne';
+ * doc.save(callback);
+ * })
+ *
+ * @param {Object} conditions
+ * @param {Object} update
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.update = function update (conditions, doc, options, callback) {
+ if (arguments.length < 4) {
+ if ('function' === typeof options) {
+ // Scenario: update(conditions, doc, callback)
+ callback = options;
+ options = null;
+ } else if ('function' === typeof doc) {
+ // Scenario: update(doc, callback);
+ callback = doc;
+ doc = conditions;
+ conditions = {};
+ options = null;
+ }
+ }
+
+ var query = new Query(conditions, options).bind(this, 'update', doc);
+
+ if ('undefined' == typeof callback)
+ return query;
+
+ this._applyNamedScope(query);
+ return query.update(doc, callback);
+};
+
+/**
+ * Executes a mapReduce command.
+ *
+ * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation.
+ *
+ * ####Example:
+ *
+ * var o = {};
+ * o.map = function () { emit(this.name, 1) }
+ * o.reduce = function (k, vals) { return vals.length }
+ * User.mapReduce(o, function (err, results) {
+ * console.log(results)
+ * })
+ *
+ * ####Other options:
+ *
+ * - `query` {Object} query filter object.
+ * - `limit` {Number} max number of documents
+ * - `keeptemp` {Boolean, default:false} keep temporary data
+ * - `finalize` {Function} finalize function
+ * - `scope` {Object} scope variables exposed to map/reduce/finalize during execution
+ * - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
+ * - `verbose` {Boolean, default:false} provide statistics on job execution time.
+ * - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job.
+ *
+ * ####* out options:
+ *
+ * - `{inline:1}` the results are returned in an array
+ * - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection
+ * - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions
+ * - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old
+ *
+ * If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the `lean` option; meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).
+ *
+ * ####Example:
+ *
+ * var o = {};
+ * o.map = function () { emit(this.name, 1) }
+ * o.reduce = function (k, vals) { return vals.length }
+ * o.out = { replace: 'createdCollectionNameForResults' }
+ * o.verbose = true;
+ * User.mapReduce(o, function (err, model, stats) {
+ * console.log('map reduce took %d ms', stats.processtime)
+ * model.find().where('value').gt(10).exec(function (err, docs) {
+ * console.log(docs);
+ * });
+ * })
+ *
+ * @param {Object} o an object specifying map-reduce options
+ * @param {Function} callback
+ * @see http://www.mongodb.org/display/DOCS/MapReduce
+ * @api public
+ */
+
+Model.mapReduce = function mapReduce (o, callback) {
+ if ('function' != typeof callback) throw new Error('missing callback');
+
+ var self = this;
+
+ if (!Model.mapReduce.schema) {
+ var opts = { noId: true, noVirtualId: true, strict: false }
+ Model.mapReduce.schema = new Schema({}, opts);
+ }
+
+ if (!o.out) o.out = { inline: 1 };
+
+ o.map = String(o.map);
+ o.reduce = String(o.reduce);
+
+ if (o.query) {
+ var q = new Query(o.query);
+ q.cast(this);
+ o.query = q._conditions;
+ q = undefined;
+ }
+
+ this.collection.mapReduce(null, null, o, function (err, ret, stats) {
+ if (err) return callback(err);
+
+ if (ret.findOne && ret.mapReduce) {
+ // returned a collection, convert to Model
+ var model = Model.compile(
+ '_mapreduce_' + ret.collectionName
+ , Model.mapReduce.schema
+ , ret.collectionName
+ , self.db
+ , self.base);
+
+ model._mapreduce = true;
+
+ return callback(err, model, stats);
+ }
+
+ callback(err, ret, stats);
+ });
+}
+
+/**
+ * Executes an aggregate command on this models collection.
+ *
+ * ####Example:
+ *
+ * // find the max age of all users
+ * Users.aggregate(
+ * { $group: { _id: null, maxAge: { $max: '$age' }}}
+ * , { $project: { _id: 0, maxAge: 1 }}
+ * , function (err, res) {
+ * if (err) return handleError(err);
+ * console.log(res); // [ { maxAge: 98 } ]
+ * });
+ *
+ * _NOTE: the documents returned are plain javascript objects, not mongoose documents cast to this models schema definition (since any shape of document can be returned)._
+ *
+ * _NOTE: this requires running MongoDB >= 2.1_
+ *
+ * @param {Array} array an array of pipeline commands
+ * @param {Object} [options]
+ * @param {Function} callback
+ * @see aggregation http://docs.mongodb.org/manual/applications/aggregation/
+ * @see driver http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate
+ * @api public
+ */
+
+Model.aggregate = function aggregate () {
+ return this.collection.aggregate.apply(this.collection, arguments);
+}
+
+/*!
+ * Compiler utility.
+ *
+ * @param {String} name model name
+ * @param {Schema} schema
+ * @param {String} collectionName
+ * @param {Connection} connection
+ * @param {Mongoose} base mongoose instance
+ */
+
+Model.compile = function compile (name, schema, collectionName, connection, base) {
+ // generate new class
+ function model (doc, fields, skipId) {
+ if (!(this instanceof model))
+ return new model(doc, fields, skipId);
+ Model.call(this, doc, fields, skipId);
+ };
+
+ model.modelName = name;
+ model.__proto__ = Model;
+ model.prototype.__proto__ = Model.prototype;
+ model.prototype.db = connection;
+ model.prototype._setSchema(schema);
+ model.prototype.collection = connection.collection(
+ collectionName
+ , schema.options.capped
+ );
+
+ // apply methods
+ for (var i in schema.methods)
+ model.prototype[i] = schema.methods[i];
+
+ // apply statics
+ for (var i in schema.statics)
+ model[i] = schema.statics[i];
+
+ // apply named scopes
+ if (schema.namedScopes) schema.namedScopes.compile(model);
+
+ model.model = model.prototype.model;
+ model.options = model.prototype.options;
+ model.db = model.prototype.db;
+ model.schema = model.prototype.schema;
+ model.collection = model.prototype.collection;
+ model.base = base;
+
+ return model;
+};
+
+/*!
+ * Subclass this model with `conn`, `schema`, and `collection` settings.
+ *
+ * @param {Connection} conn
+ * @param {Schema} [schema]
+ * @param {String} [collection]
+ * @return {Model}
+ */
+
+Model.__subclass = function subclass (conn, schema, collection) {
+ // subclass model using this connection and collection name
+ var model = this;
+
+ var Model = function Model (doc, fields, skipId) {
+ if (!(this instanceof Model)) {
+ return new Model(doc, fields, skipId);
+ }
+ model.call(this, doc, fields, skipId);
+ }
+
+ Model.__proto__ = model;
+ Model.prototype.__proto__ = model.prototype;
+ Model.db = Model.prototype.db = conn;
+
+ var s = 'string' != typeof schema
+ ? schema
+ : model.prototype.schema;
+
+ if (!collection) {
+ collection = model.prototype.schema.get('collection')
+ || utils.toCollectionName(model.modelName);
+ }
+
+ Model.prototype.collection = conn.collection(collection, s && s.options.capped);
+ Model.collection = Model.prototype.collection;
+ Model.init();
+ return Model;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = Model;
diff --git a/test/node_modules/mongoose/lib/namedscope.js b/test/node_modules/mongoose/lib/namedscope.js
new file mode 100644
index 0000000..1b3f5d4
--- /dev/null
+++ b/test/node_modules/mongoose/lib/namedscope.js
@@ -0,0 +1,70 @@
+var Query = require('./query');
+function NamedScope () {}
+
+NamedScope.prototype.query;
+
+NamedScope.prototype.where = function () {
+ var q = this.query || (this.query = new Query());
+ q.where.apply(q, arguments);
+ return q;
+};
+
+/**
+ * Decorate
+ *
+ * @param {NamedScope} target
+ * @param {Object} getters
+ * @api private
+ */
+
+NamedScope.prototype.decorate = function (target, getters) {
+ var name = this.name
+ , block = this.block
+ , query = this.query;
+ if (block) {
+ if (block.length === 0) {
+ Object.defineProperty(target, name, {
+ get: getters.block0(block)
+ });
+ } else {
+ target[name] = getters.blockN(block);
+ }
+ } else {
+ Object.defineProperty(target, name, {
+ get: getters.basic(query)
+ });
+ }
+};
+
+NamedScope.prototype.compile = function (model) {
+ var allScopes = this.scopesByName
+ , scope;
+ for (var k in allScopes) {
+ scope = allScopes[k];
+ scope.decorate(model, {
+ block0: function (block) {
+ return function () {
+ var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
+ block.call(cquery);
+ return this;
+ };
+ },
+ blockN: function (block) {
+ return function () {
+ var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
+ block.apply(cquery, arguments);
+ return this;
+ };
+ },
+ basic: function (query) {
+ return function () {
+ var cquery = this._cumulativeQuery || (this._cumulativeQuery = new Query().bind(this));
+ cquery.find(query);
+ return this;
+ };
+ }
+ });
+ }
+};
+
+module.exports = NamedScope;
diff --git a/test/node_modules/mongoose/lib/promise.js b/test/node_modules/mongoose/lib/promise.js
new file mode 100644
index 0000000..26639c1
--- /dev/null
+++ b/test/node_modules/mongoose/lib/promise.js
@@ -0,0 +1,151 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var util = require('./utils');
+var EventEmitter = util.EventEmitter;
+
+/**
+ * Promise constructor.
+ *
+ * @param {Function} back a callback+errback that accepts `fn(err, ...){}` as signature
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `err`: Emits when the promise resolves to an error.
+ * @event `complete`: Emits when the promise resolves sucessfully.
+ * @api public
+ */
+
+function Promise (back) {
+ this.emitted = {};
+ if ('function' == typeof back)
+ this.addBack(back);
+};
+
+/*!
+ * Inherits from EventEmitter.
+ */
+
+Promise.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Adds `listener` to the `event`.
+ *
+ * If `event` is either `error` or `complete` and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.
+ *
+ * @param {Event} event
+ * @param {Function} callback
+ * @return {Promise} this
+ * @api public
+ */
+
+Promise.prototype.on = function (event, callback) {
+ if (this.emitted[event])
+ callback.apply(this, this.emitted[event]);
+ else
+ EventEmitter.prototype.on.call(this, event, callback);
+
+ return this;
+};
+
+/**
+ * Keeps track of emitted events to run them on `on`.
+ *
+ * @api private
+ */
+
+Promise.prototype.emit = function (event) {
+ // ensures a promise can't be complete() or error() twice
+ if (event == 'err' || event == 'complete'){
+ if (this.emitted.err || this.emitted.complete) {
+ return this;
+ }
+ this.emitted[event] = util.args(arguments, 1);
+ }
+
+ return EventEmitter.prototype.emit.apply(this, arguments);
+};
+
+/**
+ * Shortcut for emitting the `complete` event.
+ *
+ * @api public
+ */
+
+Promise.prototype.complete = function () {
+ var args = util.args(arguments);
+ return this.emit.apply(this, ['complete'].concat(args));
+};
+
+/**
+ * Shortcut for emitting the `err` event.
+ *
+ * @api public
+ * @return {Promise}
+ */
+
+Promise.prototype.error = function (err) {
+ if (!(err instanceof Error)) err = new Error(err);
+ return this.emit('err', err);
+};
+
+/**
+ * Shortcut for `.on('complete', fn)`.
+ *
+ * @return {Promise}
+ * @api public
+ */
+
+Promise.prototype.addCallback = function (fn) {
+ return this.on('complete', fn);
+};
+
+/**
+ * Shortcut for `.on('err', fn)`.
+ *
+ * @return {Promise}
+ * @api public
+ */
+
+Promise.prototype.addErrback = function (fn) {
+ return this.on('err', fn);
+};
+
+/**
+ * Adds a single function that's both a callback and errback.
+ *
+ * @param {Function} fn
+ * @return {Promise}
+ */
+
+Promise.prototype.addBack = function (fn) {
+ this.on('err', function(err){
+ fn.call(this, err);
+ });
+
+ this.on('complete', function(){
+ var args = util.args(arguments);
+ fn.apply(this, [null].concat(args));
+ });
+
+ return this;
+};
+
+/**
+ * Sugar for handling cases where you may be resolving to either an error condition or a success condition.
+ *
+ * @param {Error} err optional error or null
+ * @param {Object} val value to complete the promise with
+ * @api public
+ */
+
+Promise.prototype.resolve = function (err, val) {
+ if (err) return this.error(err);
+ return this.complete(val);
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Promise;
diff --git a/test/node_modules/mongoose/lib/query.js b/test/node_modules/mongoose/lib/query.js
new file mode 100644
index 0000000..eebf7a5
--- /dev/null
+++ b/test/node_modules/mongoose/lib/query.js
@@ -0,0 +1,2395 @@
+/*!
+ * Module dependencies.
+ */
+
+var utils = require('./utils')
+ , merge = utils.merge
+ , Promise = require('./promise')
+ , Document = require('./document')
+ , Types = require('./schema/index')
+ , inGroupsOf = utils.inGroupsOf
+ , tick = utils.tick
+ , QueryStream = require('./querystream')
+ , ReadPref = require('mongodb').ReadPreference
+
+/**
+ * Query constructor used for building queries.
+ *
+ * ####Example:
+ *
+ * var query = Model.find();
+ * query.where('age').gte(21).exec(callback);
+ *
+ * @param {Object} criteria
+ * @param {Object} options
+ * @api public
+ */
+
+function Query (criteria, options) {
+ this.setOptions(options, true);
+ this._conditions = {};
+ this._updateArg = {};
+ this._fields = undefined;
+ if (criteria) this.find(criteria);
+}
+
+/**
+ * Sets query options.
+ *
+ * ####Options:
+ *
+ * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors) *
+ * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D) *
+ * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D) *
+ * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D) *
+ * - [maxscan](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan) *
+ * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D) *
+ * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment) *
+ * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D) *
+ * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint) *
+ * - [slaveOk](http://docs.mongodb.org/manual/applications/replication/#read-preference) *
+ * - [lean](./api.html#query_Query-lean) *
+ * - [safe](http://www.mongodb.org/display/DOCS/getLastError+Command)
+ *
+ * _* denotes a query helper method is also available_
+ *
+ * @param {Object} options
+ * @api public
+ */
+
+Query.prototype.setOptions = function (options, overwrite) {
+ // overwrite is internal use only
+ if (overwrite) {
+ options = this.options = options || {};
+ this.safe = options.safe
+
+ // normalize population options
+ var pop = this.options.populate;
+ this.options.populate = {};
+
+ if (pop && Array.isArray(pop)) {
+ for (var i = 0, l = pop.length; i < l; i++) {
+ this.options.populate[pop[i]] = {};
+ }
+ }
+
+ return this;
+ }
+
+ if (!(options && 'Object' == options.constructor.name))
+ return this;
+
+ if ('safe' in options)
+ this.safe = options.safe;
+
+ // set arbitrary options
+ var methods = Object.keys(options)
+ , i = methods.length
+ , method
+
+ while (i--) {
+ method = methods[i];
+
+ // use methods if exist (safer option manipulation)
+ if ('function' == typeof this[method]) {
+ var args = Array.isArray(options[method])
+ ? options[method]
+ : [options[method]];
+ this[method].apply(this, args)
+ } else {
+ this.options[method] = options[method];
+ }
+ }
+ return this;
+}
+
+/**
+ * Binds this query to a model.
+ *
+ * @param {Model} model the model to which the query is bound
+ * @param {String} op the operation to execute
+ * @param {Object} updateArg used in update methods
+ * @return {Query}
+ * @api private
+ */
+
+Query.prototype.bind = function bind (model, op, updateArg) {
+ this.model = model;
+ this.op = op;
+
+ if (model._mapreduce) this.options.lean = true;
+
+ if (op == 'update' || op == 'findOneAndUpdate') {
+ merge(this._updateArg, updateArg || {});
+ }
+
+ return this;
+};
+
+/**
+ * Executes the query
+ *
+ * ####Examples
+ *
+ * query.exec();
+ * query.exec(callback);
+ * query.exec('update');
+ * query.exec('find', callback);
+ *
+ * @param {String|Function} [operation]
+ * @param {Function} [callback]
+ * @return {Promise}
+ * @api public
+ */
+
+Query.prototype.exec = function exec (op, callback) {
+ var promise = new Promise();
+
+ switch (typeof op) {
+ case 'function':
+ callback = op;
+ op = null;
+ break;
+ case 'string':
+ this.op = op;
+ break;
+ }
+
+ if (callback) promise.addBack(callback);
+
+ if (!this.op) {
+ promise.complete();
+ return promise;
+ }
+
+ if ('update' == this.op) {
+ this[this.op](this._updateArg, promise.resolve.bind(promise));
+ return promise;
+ }
+
+ if ('distinct' == this.op) {
+ this.distinct(this._distinctArg, promise.resolve.bind(promise));
+ return promise;
+ }
+
+ this[this.op](promise.resolve.bind(promise));
+ return promise;
+};
+
+/**
+ * Finds documents.
+ *
+ * When no `callback` is passed, the query is not executed.
+ *
+ * ####Example
+ *
+ * query.find({ name: 'Los Pollos Hermanos' }).find(callback)
+ *
+ * @param {Object} [criteria] mongodb selector
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.find = function (criteria, callback) {
+ this.op = 'find';
+ if ('function' === typeof criteria) {
+ callback = criteria;
+ criteria = {};
+ } else if (criteria instanceof Query) {
+ // TODO Merge options, too
+ merge(this._conditions, criteria._conditions);
+ } else if (criteria instanceof Document) {
+ merge(this._conditions, criteria.toObject());
+ } else if (criteria && 'Object' === criteria.constructor.name) {
+ merge(this._conditions, criteria);
+ }
+ if (!callback) return this;
+ return this.execFind(callback);
+};
+
+/**
+ * Casts this query to the schema of `model`
+ *
+ * ####Note
+ *
+ * If `obj` is present, it is cast instead of this query.
+ *
+ * @param {Model} model
+ * @param {Object} [obj]
+ * @return {Object}
+ * @api public
+ */
+
+Query.prototype.cast = function (model, obj) {
+ obj || (obj= this._conditions);
+
+ var schema = model.schema
+ , paths = Object.keys(obj)
+ , i = paths.length
+ , any$conditionals
+ , schematype
+ , nested
+ , path
+ , type
+ , val;
+
+ while (i--) {
+ path = paths[i];
+ val = obj[path];
+
+ if ('$or' === path || '$nor' === path || '$and' === path) {
+ var k = val.length
+ , orComponentQuery;
+
+ while (k--) {
+ orComponentQuery = new Query(val[k]);
+ orComponentQuery.cast(model);
+ val[k] = orComponentQuery._conditions;
+ }
+
+ } else if (path === '$where') {
+ type = typeof val;
+
+ if ('string' !== type && 'function' !== type) {
+ throw new Error("Must have a string or function for $where");
+ }
+
+ if ('function' === type) {
+ obj[path] = val.toString();
+ }
+
+ continue;
+
+ } else {
+
+ if (!schema) {
+ // no casting for Mixed types
+ continue;
+ }
+
+ schematype = schema.path(path);
+
+ if (!schematype) {
+ // Handle potential embedded array queries
+ var split = path.split('.')
+ , j = split.length
+ , pathFirstHalf
+ , pathLastHalf
+ , remainingConds
+ , castingQuery;
+
+ // Find the part of the var path that is a path of the Schema
+ while (j--) {
+ pathFirstHalf = split.slice(0, j).join('.');
+ schematype = schema.path(pathFirstHalf);
+ if (schematype) break;
+ }
+
+ // If a substring of the input path resolves to an actual real path...
+ if (schematype) {
+ // Apply the casting; similar code for $elemMatch in schema/array.js
+ if (schematype.caster && schematype.caster.schema) {
+ remainingConds = {};
+ pathLastHalf = split.slice(j).join('.');
+ remainingConds[pathLastHalf] = val;
+ castingQuery = new Query(remainingConds);
+ castingQuery.cast(schematype.caster);
+ obj[path] = castingQuery._conditions[pathLastHalf];
+ } else {
+ obj[path] = val;
+ }
+ continue;
+ }
+
+ if (utils.isObject(val)) {
+ // handle geo schemas that use object notation
+ // { loc: { long: Number, lat: Number }
+
+ var geo = val.$near ? '$near' :
+ val.$nearSphere ? '$nearSphere' :
+ val.$within ? '$within' : '';
+
+ if (!geo) {
+ continue;
+ }
+
+ var numbertype = new Types.Number('__QueryCasting__')
+ var value = val[geo];
+
+ if (val.$maxDistance) {
+ val.$maxDistance = numbertype.castForQuery(val.$maxDistance);
+ }
+
+ if ('$within' == geo) {
+ // find $center, $centerSphere, $box, $polygon
+ var withinType = value.$center || value.$centerSphere || value.$box || value.$polygon;
+ if (!withinType) {
+ throw new Error('Bad $within paramater: ' + JSON.stringify(val));
+ }
+
+ value = withinType;
+ }
+
+ ;(function _cast (val) {
+ if (Array.isArray(val)) {
+ val.forEach(function (item, i) {
+ if (Array.isArray(item) || utils.isObject(item)) {
+ return _cast(item);
+ }
+ val[i] = numbertype.castForQuery(item);
+ });
+ } else {
+ var nearKeys= Object.keys(val);
+ var nearLen = nearKeys.length;
+ while (nearLen--) {
+ var nkey = nearKeys[nearLen];
+ var item = val[nkey];
+ if (Array.isArray(item) || utils.isObject(item)) {
+ _cast(item);
+ val[nkey] = item;
+ } else {
+ val[nkey] = numbertype.castForQuery(item);
+ }
+ }
+ }
+ })(value);
+ }
+
+ } else if (val === null || val === undefined) {
+ continue;
+ } else if ('Object' === val.constructor.name) {
+
+ any$conditionals = Object.keys(val).some(function (k) {
+ return k.charAt(0) === '$' && k !== '$id' && k !== '$ref';
+ });
+
+ if (!any$conditionals) {
+ obj[path] = schematype.castForQuery(val);
+ } else {
+
+ var ks = Object.keys(val)
+ , k = ks.length
+ , $cond;
+
+ while (k--) {
+ $cond = ks[k];
+ nested = val[$cond];
+
+ if ('$exists' === $cond) {
+ if ('boolean' !== typeof nested) {
+ throw new Error("$exists parameter must be Boolean");
+ }
+ continue;
+ }
+
+ if ('$type' === $cond) {
+ if ('number' !== typeof nested) {
+ throw new Error("$type parameter must be Number");
+ }
+ continue;
+ }
+
+ if ('$not' === $cond) {
+ this.cast(model, nested);
+ } else {
+ val[$cond] = schematype.castForQuery($cond, nested);
+ }
+ }
+ }
+ } else {
+ obj[path] = schematype.castForQuery(val);
+ }
+ }
+ }
+
+ return obj;
+};
+
+/**
+ * Returns default options.
+ * @param {Model} model
+ * @api private
+ */
+
+Query.prototype._optionsForExec = function (model) {
+ var options = utils.clone(this.options, { retainKeyOrder: true });
+ delete options.populate;
+
+ if (!('safe' in options))
+ options.safe = model.schema.options.safe;
+
+ if (!('readPreference' in options) && model.schema.options.read)
+ options.readPreference = model.schema.options.read;
+
+ return options;
+};
+
+/**
+ * Applies schematype selected options to this query.
+ * @api private
+ */
+
+Query.prototype._applyPaths = function applyPaths () {
+ // determine if query is selecting or excluding fields
+
+ var fields = this._fields
+ , exclude
+ , keys
+ , ki
+
+ if (fields) {
+ keys = Object.keys(fields);
+ ki = keys.length;
+
+ while (ki--) {
+ if ('+' == keys[ki][0]) continue;
+ exclude = 0 === fields[keys[ki]];
+ break;
+ }
+ }
+
+ // if selecting, apply default schematype select:true fields
+ // if excluding, apply schematype select:false fields
+
+ var selected = []
+ , excluded = []
+ , seen = [];
+
+ analyzeSchema(this.model.schema);
+
+ switch (exclude) {
+ case true:
+ excluded.length && this.select('-' + excluded.join(' -'));
+ break;
+ case false:
+ selected.length && this.select(selected.join(' '));
+ break;
+ case undefined:
+ // user didn't specify fields, implies returning all fields.
+ // only need to apply excluded fields
+ excluded.length && this.select('-' + excluded.join(' -'));
+ break;
+ }
+
+ return seen = excluded = selected = keys = fields = null;
+
+ function analyzeSchema (schema, prefix) {
+ prefix || (prefix = '');
+
+ // avoid recursion
+ if (~seen.indexOf(schema)) return;
+ seen.push(schema);
+
+ schema.eachPath(function (path, type) {
+ if (prefix) path = prefix + '.' + path;
+
+ // array of subdocs?
+ if (type.schema) {
+ analyzeSchema(type.schema, path);
+ }
+
+ analyzePath(path, type);
+ });
+ }
+
+ function analyzePath (path, type) {
+ if ('boolean' != typeof type.selected) return;
+
+ if (fields && ('+' + path) in fields) {
+ // forced inclusion
+ delete fields['+' + path];
+
+ // if there are other fields being included, add this one
+ // if no other included fields, leave this out (implied inclusion)
+ if (false === exclude && keys.length > 1) {
+ fields[path] = 1;
+ }
+
+ return
+ };
+
+ ;(type.selected ? selected : excluded).push(path);
+ }
+}
+
+/**
+ * Specifies a `$where` condition
+ *
+ * Use `$where` when you need to select documents using a JavaScript expression.
+ *
+ * ####Example
+ *
+ * query.$where('this.comments.length > 10 || this.name.length > 5')
+ *
+ * query.$where(function () {
+ * return this.comments.length > 10 || this.name.length > 5;
+ * })
+ *
+ * @param {String|Function} js javascript string or function
+ * @return {Query} this
+ * @memberOf Query
+ * @method $where
+ * @api public
+ */
+
+Query.prototype.$where = function (js) {
+ this._conditions['$where'] = js;
+ return this;
+};
+
+/**
+ * Specifies a `path` for use with chaining.
+ *
+ * ####Example
+ *
+ * // instead of writing:
+ * User.find({age: {$gte: 21, $lte: 65}}, callback);
+ *
+ * // we can instead write:
+ * User.where('age').gte(21).lte(65);
+ *
+ * // Moreover, you can also chain a bunch of these together:
+ *
+ * User
+ * .where('age').gte(21).lte(65)
+ * .where('name', /^b/i)
+ * .where('friends').slice(10)
+ * .exec(callback)
+ *
+ * @param {String} [path]
+ * @param {Object} [val]
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.where = function (path, val) {
+ if (!arguments.length) return this;
+
+ if ('string' != typeof path) {
+ throw new TypeError('path must be a string');
+ }
+
+ this._currPath = path;
+
+ if (2 === arguments.length) {
+ this._conditions[path] = val;
+ }
+
+ return this;
+};
+
+/**
+ * Specifies the complementary comparison value for paths specified with `where()`
+ *
+ * ####Example
+ *
+ * User.where('age').equals(49);
+ *
+ * // is the same as
+ *
+ * User.where('age', 49);
+ *
+ * @param {Object} val
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.equals = function equals (val) {
+ var path = this._currPath;
+ if (!path) throw new Error('equals() must be used after where()');
+ this._conditions[path] = val;
+ return this;
+}
+
+/**
+ * Specifies arguments for an `$or` condition.
+ *
+ * ####Example
+ *
+ * query.or([{ color: 'red' }, { status: 'emergency' }])
+ *
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.or = function or (array) {
+ var or = this._conditions.$or || (this._conditions.$or = []);
+ if (!Array.isArray(array)) array = [array];
+ or.push.apply(or, array);
+ return this;
+}
+
+/**
+ * Specifies arguments for a `$nor` condition.
+ *
+ * ####Example
+ *
+ * query.nor([{ color: 'green' }, { status: 'ok' }])
+ *
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.nor = function nor (array) {
+ var nor = this._conditions.$nor || (this._conditions.$nor = []);
+ if (!Array.isArray(array)) array = [array];
+ nor.push.apply(nor, array);
+ return this;
+}
+
+/**
+ * Specifies arguments for a `$and` condition.
+ *
+ * ####Example
+ *
+ * query.and([{ color: 'green' }, { status: 'ok' }])
+ *
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.and = function and (array) {
+ var and = this._conditions.$and || (this._conditions.$and = []);
+ if (!Array.isArray(array)) array = [array];
+ and.push.apply(and, array);
+ return this;
+}
+
+/**
+ * Specifies a $gt query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * ####Example
+ *
+ * Thing.find().where('age').gt(21)
+ *
+ * // or
+ * Thing.find().gt('age', 21)
+ *
+ * @method gt
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $gte query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method gte
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $lt query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method lt
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $lte query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method lte
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $ne query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method ne
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an $in query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method in
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an $nin query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method nin
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an $all query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method all
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an $size query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method size
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $regex query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method regex
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a $maxDistance query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method maxDistance
+ * @memberOf Query
+ * @param {String} path
+ * @param {Number} val
+ * @api public
+ */
+
+/*!
+ * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance
+ *
+ * Thing.where('type').nin(array)
+ */
+
+'gt gte lt lte ne in nin all regex size maxDistance'.split(' ').forEach(function ($conditional) {
+ Query.prototype[$conditional] = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$' + $conditional] = val;
+ return this;
+ };
+});
+
+/**
+ * Specifies a `$near` condition
+ *
+ * @param {String} path
+ * @param {Number} val
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+Query.prototype.near = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath
+ } else if (arguments.length === 2 && !Array.isArray(val)) {
+ val = utils.args(arguments);
+ path = this._currPath;
+ } else if (arguments.length === 3) {
+ val = utils.args(arguments, 1);
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds.$near = val;
+ return this;
+}
+
+/**
+ * Specifies a `$nearSphere` condition.
+ *
+ * @param {String} path
+ * @param {Object} val
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+Query.prototype.nearSphere = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath
+ } else if (arguments.length === 2 && !Array.isArray(val)) {
+ val = utils.args(arguments);
+ path = this._currPath;
+ } else if (arguments.length === 3) {
+ val = utils.args(arguments, 1);
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds.$nearSphere = val;
+ return this;
+}
+
+/**
+ * Specifies a `$mod` condition
+ *
+ * @param {String} path
+ * @param {Number} val
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.mod = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath
+ } else if (arguments.length === 2 && !Array.isArray(val)) {
+ val = utils.args(arguments);
+ path = this._currPath;
+ } else if (arguments.length === 3) {
+ val = utils.args(arguments, 1);
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds.$mod = val;
+ return this;
+}
+
+/**
+ * Specifies an `$exists` condition
+ *
+ * @param {String} path
+ * @param {Number} val
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.exists = function (path, val) {
+ if (arguments.length === 0) {
+ path = this._currPath
+ val = true;
+ } else if (arguments.length === 1) {
+ if ('boolean' === typeof path) {
+ val = path;
+ path = this._currPath;
+ } else {
+ val = true;
+ }
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$exists'] = val;
+ return this;
+};
+
+/**
+ * Specifies an `$elemMatch` condition
+ *
+ * ####Example
+ *
+ * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
+ *
+ * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
+ *
+ * query.elemMatch('comment', function (elem) {
+ * elem.where('author').equals('autobot');
+ * elem.where('votes').gte(5);
+ * })
+ *
+ * query.where('comment').elemMatch(function (elem) {
+ * elem.where('author').equals('autobot');
+ * elem.where('votes').gte(5);
+ * })
+ *
+ * @param {String|Object|Function} path
+ * @param {Object|Function} criteria
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.elemMatch = function (path, criteria) {
+ var block;
+ if ('Object' === path.constructor.name) {
+ criteria = path;
+ path = this._currPath;
+ } else if ('function' === typeof path) {
+ block = path;
+ path = this._currPath;
+ } else if ('Object' === criteria.constructor.name) {
+ } else if ('function' === typeof criteria) {
+ block = criteria;
+ } else {
+ throw new Error("Argument error");
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ if (block) {
+ criteria = new Query();
+ block(criteria);
+ conds['$elemMatch'] = criteria._conditions;
+ } else {
+ conds['$elemMatch'] = criteria;
+ }
+ return this;
+};
+
+// Spatial queries
+
+/**
+ * Syntax sugar for expressive queries.
+ *
+ * ####Example
+ *
+ * query.within.box()
+ * query.within.center()
+ *
+ * @property within
+ * @memberOf Query
+ * @return {Query} this
+ * @api public
+ */
+
+Object.defineProperty(Query.prototype, 'within', {
+ get: function () { return this }
+});
+
+/**
+ * Specifies a $box condition
+ *
+ * ####Example
+ *
+ * var lowerLeft = [40.73083, -73.99756]
+ * var upperRight= [40.741404, -73.988135]
+ * query.where('loc').within.box({ ll: lowerLeft , ur: upperRight })
+ *
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @see Query#within #query_Query-within
+ * @param {String} path
+ * @param {Object} val
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.box = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath;
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$within'] = { '$box': [val.ll, val.ur] };
+ return this;
+};
+
+/**
+ * Specifies a $center condition
+ *
+ * ####Example
+ *
+ * var area = { center: [50, 50], radius: 10 }
+ * query.where('loc').within.center(area)
+ *
+ * @param {String} path
+ * @param {Object} val
+ * @param {Object} [opts] options e.g. { $uniqueDocs: true }
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+Query.prototype.center = function (path, val, opts) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath;
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$within'] = { '$center': [val.center, val.radius] };
+
+ // copy any options
+ if (opts && 'Object' == opts.constructor.name) {
+ utils.options(opts, conds.$within);
+ }
+
+ return this;
+};
+
+/**
+ * Specifies a $centerSphere condition
+ *
+ * ####Example
+ *
+ * var area = { center: [50, 50], radius: 10 }
+ * query.where('loc').within.centerSphere(area)
+ *
+ * @param {String} path
+ * @param {Object} val
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+Query.prototype.centerSphere = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath;
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$within'] = { '$centerSphere': [val.center, val.radius] };
+ return this;
+};
+
+/**
+ * Specifies a $polygon condition
+ *
+ * ####Example
+ *
+ * var polyA = [ [ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ] ]
+ * query.where('loc').within.polygon(polyA)
+ *
+ * // or
+ * var polyB = { a : { x : 10, y : 20 }, b : { x : 15, y : 25 }, c : { x : 20, y : 20 } }
+ * query.where('loc').within.polygon(polyB)
+ *
+ * @param {String} path
+ * @param {Array|Object} val
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+Query.prototype.polygon = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath;
+ }
+ var conds = this._conditions[path] || (this._conditions[path] = {});
+ conds['$within'] = { '$polygon': val };
+ return this;
+};
+
+/**
+ * Specifies which document fields to include or exclude
+ *
+ * When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the [schema level](/docs/api.html#schematype_SchemaType-select).
+ *
+ * ####Example
+ *
+ * // include a and b, exclude c
+ * query.select('a b -c');
+ *
+ * // or you may use object notation, useful when
+ * // you have keys already prefixed with a "-"
+ * query.select({a: 1, b: 1, c: 0});
+ *
+ * // force inclusion of field excluded at schema level
+ * query.select('+path')
+ *
+ * ####NOTE:
+ *
+ * _v2 had slightly different syntax such as allowing arrays of field names. This support was removed in v3._
+ *
+ * @param {Object|String} arg
+ * @return {Query} this
+ * @see SchemaType
+ * @api public
+ */
+
+Query.prototype.select = function select (arg) {
+ if (!arg) return this;
+
+ var fields = this._fields || (this._fields = {});
+
+ if ('Object' === arg.constructor.name) {
+ Object.keys(arg).forEach(function (field) {
+ fields[field] = arg[field];
+ });
+ } else if (1 === arguments.length && 'string' == typeof arg) {
+ arg.split(/\s+/).forEach(function (field) {
+ if (!field) return;
+ var include = '-' == field[0] ? 0 : 1;
+ if (include === 0) field = field.substring(1);
+ fields[field] = include;
+ });
+ } else {
+ throw new TypeError('Invalid select() argument. Must be a string or object.');
+ }
+
+ return this;
+};
+
+/**
+ * Specifies a $slice condition
+ *
+ * ####Example
+ *
+ * query.slice('comments', 5)
+ * query.slice('comments', -5)
+ * query.slice('comments', [10, 5])
+ * query.where('comments').slice(5)
+ * query.where('comments').slice([-10, 5])
+ *
+ * @param {String} path
+ * @param {Number} val number of elements to slice
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
+ * @api public
+ */
+
+Query.prototype.slice = function (path, val) {
+ if (arguments.length === 1) {
+ val = path;
+ path = this._currPath
+ } else if (arguments.length === 2) {
+ if ('number' === typeof path) {
+ val = [path, val];
+ path = this._currPath;
+ }
+ } else if (arguments.length === 3) {
+ val = utils.args(arguments, 1);
+ }
+ var myFields = this._fields || (this._fields = {});
+ myFields[path] = { '$slice': val };
+ return this;
+};
+
+/**
+ * Sets the sort order
+ *
+ * If an object is passed, values allowed are 'asc', 'desc', 'ascending', 'descending', 1, and -1.
+ *
+ * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.
+ *
+ * ####Example
+ *
+ * // these are equivalent
+ * query.sort({ field: 'asc', test: -1 });
+ * query.sort('field -test');
+ *
+ * @param {Object|String} arg
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.sort = function (arg) {
+ if (!arg) return this;
+
+ var sort = this.options.sort || (this.options.sort = []);
+
+ if ('Object' === arg.constructor.name) {
+ Object.keys(arg).forEach(function (field) {
+ push(sort, field, arg[field]);
+ });
+ } else if (1 === arguments.length && 'string' == typeof arg) {
+ arg.split(/\s+/).forEach(function (field) {
+ if (!field) return;
+ var ascend = '-' == field[0] ? -1 : 1;
+ if (ascend === -1) field = field.substring(1);
+ push(sort, field, ascend);
+ });
+ } else {
+ throw new TypeError('Invalid sort() argument. Must be a string or object.');
+ }
+
+ return this;
+};
+
+/*!
+ * @ignore
+ */
+
+function push (arr, field, value) {
+ var val = String(value || 1).toLowerCase();
+ if (!/^(?:ascending|asc|descending|desc|1|-1)$/.test(val)) {
+ if (Array.isArray(value)) value = '['+value+']';
+ throw new TypeError('Invalid sort value: {' + field + ': ' + value + ' }');
+ }
+ arr.push([field, value]);
+}
+
+/**
+ * Specifies the limit option.
+ *
+ * ####Example
+ *
+ * Kitten.find().limit(20)
+ *
+ * @method limit
+ * @memberOf Query
+ * @param {Number} val
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D
+ * @api public
+ */
+/**
+ * Specifies the skip option.
+ *
+ * ####Example
+ *
+ * Kitten.find().skip(100).limit(20)
+ *
+ * @method skip
+ * @memberOf Query
+ * @param {Number} val
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D
+ * @api public
+ */
+/**
+ * Specifies the maxscan option.
+ *
+ * ####Example
+ *
+ * Kitten.find().maxscan(100)
+ *
+ * @method maxscan
+ * @memberOf Query
+ * @param {Number} val
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24maxScan
+ * @api public
+ */
+/**
+ * Specifies the batchSize option.
+ *
+ * ####Example
+ *
+ * Kitten.find().batchSize(100)
+ *
+ * @method batchSize
+ * @memberOf Query
+ * @param {Number} val
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D
+ * @api public
+ */
+/**
+ * Specifies the `comment` option.
+ *
+ * ####Example
+ *
+ * Kitten.findOne(condition).comment('login query')
+ *
+ * @method comment
+ * @memberOf Query
+ * @param {Number} val
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment
+ * @api public
+ */
+
+/*!
+ * limit, skip, maxscan, batchSize, comment
+ *
+ * Sets these associated options.
+ *
+ * query.comment('feed query');
+ */
+
+;['limit', 'skip', 'maxscan', 'batchSize', 'comment'].forEach(function (method) {
+ Query.prototype[method] = function (v) {
+ this.options[method] = v;
+ return this;
+ };
+});
+
+/**
+ * Specifies this query as a `snapshot` query.
+ *
+ * ####Example
+ *
+ * Kitten.find().snapshot()
+ *
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.snapshot = function () {
+ this.options.snapshot = true;
+ return this;
+};
+
+/**
+ * Sets query hints.
+ *
+ * ####Example
+ *
+ * Model.find().hint({ indexA: 1, indexB: -1})
+ *
+ * @param {Object} val a hint object
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint
+ * @api public
+ */
+
+Query.prototype.hint = function (val) {
+ if (!val) return this;
+
+ var hint = this.options.hint || (this.options.hint = {});
+
+ if ('Object' === val.constructor.name) {
+ // must keep object keys in order so don't use Object.keys()
+ for (var k in val) {
+ hint[k] = val[k];
+ }
+ } else {
+ throw new TypeError('Invalid hint. ' + val);
+ }
+
+ return this;
+};
+
+/**
+ * Sets the slaveOk option.
+ *
+ * ####Example:
+ *
+ * new Query().slaveOk() // true
+ * new Query().slaveOk(true)
+ * new Query().slaveOk(false)
+ *
+ * @param {Boolean} v defaults to true
+ * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.slaveOk = function (v) {
+ this.options.slaveOk = arguments.length ? !!v : true;
+ return this;
+}
+
+/**
+ * Sets the readPreference option for the query.
+ *
+ * ####Example:
+ *
+ * new Query().read('primary')
+ * new Query().read('p') // same as primary
+ *
+ * new Query().read('primaryPreferred')
+ * new Query().read('pp') // same as primaryPreferred
+ *
+ * new Query().read('secondary')
+ * new Query().read('s') // same as secondary
+ *
+ * new Query().read('secondaryPreferred')
+ * new Query().read('sp') // same as secondaryPreferred
+ *
+ * new Query().read('nearest')
+ * new Query().read('n') // same as nearest
+ *
+ * // with tags
+ * new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
+ *
+ * ####Preferences:
+ *
+ * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
+ * secondary Read from secondary if available, otherwise error.
+ * primaryPreferred Read from primary if available, otherwise a secondary.
+ * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
+ * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
+ *
+ * Aliases
+ *
+ * p primary
+ * pp primaryPreferred
+ * s secondary
+ * sp secondaryPreferred
+ * n nearest
+ *
+ * Read more about how to use read preferrences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences).
+ *
+ * @param {String} pref one of the listed preference options or their aliases
+ * @param {Array} [tags] optional tags for this query
+ * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
+ * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.read = function (pref, tags) {
+ this.options.readPreference = utils.readPref(pref, tags);
+ return this;
+}
+
+/**
+ * Sets the lean option.
+ *
+ * Documents returned from queries with the `lean` option enabled are plain javascript objects, not [MongooseDocuments](#document-js). They have no `save` method, getters/setters or any other Mongoose magic applied.
+ *
+ * This is a [great](https://groups.google.com/forum/#!topic/mongoose-orm/u2_DzDydcnA/discussion) option in high-performance read-only scenarios, especially when combined with the [stream](#query_Query-stream) option.
+ *
+ * ####Example:
+ *
+ * new Query().lean() // true
+ * new Query().lean(true)
+ * new Query().lean(false)
+ *
+ * Model.find().lean().exec();
+ *
+ * var leanStream = Model.find().lean().stream();
+ *
+ * @param {Boolean} v defaults to true
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.lean = function (v) {
+ this.options.lean = arguments.length ? !!v : true;
+ return this;
+}
+
+/**
+ * Sets tailable option.
+ *
+ * ####Example
+ *
+ * Kitten.find().tailable() <== true
+ * Kitten.find().tailable(true)
+ * Kitten.find().tailable(false)
+ *
+ * @param {Boolean} v defaults to true
+ * @see mongodb http://www.mongodb.org/display/DOCS/Tailable+Cursors
+ * @api public
+ */
+
+Query.prototype.tailable = function (v) {
+ this.options.tailable = arguments.length ? !!v : true;
+ return this;
+};
+
+/**
+ * Executes the query as a find() operation.
+ *
+ * @param {Function} callback
+ * @return {Query} this
+ * @api private
+ */
+
+Query.prototype.execFind = function (callback) {
+ var model = this.model
+ , promise = new Promise(callback);
+
+ try {
+ this.cast(model);
+ } catch (err) {
+ promise.error(err);
+ return this;
+ }
+
+ // apply default schematype path selections
+ this._applyPaths();
+
+ var self = this
+ , castQuery = this._conditions
+ , options = this._optionsForExec(model)
+ , fields = utils.clone(this._fields)
+
+ options.fields = this._castFields(fields);
+ if (options.fields instanceof Error) {
+ promise.error(options.fields);
+ return this;
+ }
+
+ model.collection.find(castQuery, options, function (err, cursor) {
+ if (err) return promise.error(err);
+ cursor.toArray(tick(cb));
+ });
+
+ function cb (err, docs) {
+ if (err) return promise.error(err);
+
+ if (true === options.lean)
+ return promise.complete(docs);
+
+ var arr = []
+ , count = docs.length;
+
+ if (!count) return promise.complete([]);
+
+ for (var i = 0, l = docs.length; i < l; i++) {
+ arr[i] = new model(undefined, fields, true);
+ arr[i].init(docs[i], self, function (err) {
+ if (err) return promise.error(err);
+ --count || promise.complete(arr);
+ });
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Executes the query as a findOne() operation.
+ *
+ * ####Example
+ *
+ * Kitten.where('color', 'white').findOne(function (err, kitten) {
+ * if (err) return handleError(err);
+ *
+ * // kitten may be null if no document matched
+ * if (kitten) {
+ * ...
+ * }
+ * })
+ *
+ * @param {Function} callback
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.findOne = function (callback) {
+ this.op = 'findOne';
+
+ if (!callback) return this;
+
+ var model = this.model;
+ var promise = new Promise(callback);
+
+ try {
+ this.cast(model);
+ } catch (err) {
+ promise.error(err);
+ return this;
+ }
+
+ // apply default schematype path selections
+ this._applyPaths();
+
+ var self = this
+ , castQuery = this._conditions
+ , options = this._optionsForExec(model)
+ , fields = utils.clone(this._fields)
+
+ options.fields = this._castFields(fields);
+ if (options.fields instanceof Error) {
+ promise.error(options.fields);
+ return this;
+ }
+
+ model.collection.findOne(castQuery, options, tick(function (err, doc) {
+ if (err) return promise.error(err);
+ if (!doc) return promise.complete(null);
+
+ if (true === options.lean) return promise.complete(doc);
+
+ var casted = new model(undefined, fields, true);
+ casted.init(doc, self, function (err) {
+ if (err) return promise.error(err);
+ promise.complete(casted);
+ });
+ }));
+
+ return this;
+};
+
+/**
+ * Exectues the query as a count() operation.
+ *
+ * ####Example
+ *
+ * Kitten.where('color', 'black').count(function (err, count) {
+ * if (err) return handleError(err);
+ * console.log('there are %d black kittens', count);
+ * })
+ *
+ * @param {Function} callback
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Count
+ * @api public
+ */
+
+Query.prototype.count = function (callback) {
+ this.op = 'count';
+ var model = this.model;
+
+ try {
+ this.cast(model);
+ } catch (err) {
+ return callback(err);
+ }
+
+ var castQuery = this._conditions;
+ model.collection.count(castQuery, tick(callback));
+
+ return this;
+};
+
+/**
+ * Executes this query as a distict() operation.
+ *
+ * @param {String} field
+ * @param {Function} callback
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Distinct
+ * @api public
+ */
+
+Query.prototype.distinct = function (field, callback) {
+ this.op = 'distinct';
+ var model = this.model;
+
+ try {
+ this.cast(model);
+ } catch (err) {
+ return callback(err);
+ }
+
+ var castQuery = this._conditions;
+ model.collection.distinct(field, castQuery, tick(callback));
+
+ return this;
+};
+
+/*!
+ * These operators require casting docs
+ * to real Documents for Update operations.
+ */
+
+var castOps = {
+ $push: 1
+ , $pushAll: 1
+ , $addToSet: 1
+ , $set: 1
+};
+
+/*!
+ * These operators should be cast to numbers instead
+ * of their path schema type.
+ */
+
+var numberOps = {
+ $pop: 1
+ , $unset: 1
+ , $inc: 1
+}
+
+/**
+ * Executes this query as an update() operation.
+ *
+ * _All paths passed that are not $atomic operations will become $set ops so we retain backwards compatibility._
+ *
+ * ####Example
+ *
+ * Model.update({..}, { title: 'remove words' }, ...)
+ *
+ * becomes
+ *
+ * Model.update({..}, { $set: { title: 'remove words' }}, ...)
+ *
+ * ####Note
+ *
+ * Passing an empty object `{}` as the doc will result in a no-op. The update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting the collection.
+ *
+ * @param {Object} doc the update conditions
+ * @param {Function} callback
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.update = function update (doc, callback) {
+ this.op = 'update';
+ this._updateArg = doc;
+
+ var model = this.model
+ , options = this._optionsForExec(model)
+ , fn = 'function' == typeof callback
+ , castedQuery
+ , castedDoc
+
+ castedQuery = castQuery(this);
+ if (castedQuery instanceof Error) {
+ if (fn) {
+ process.nextTick(callback.bind(null, castedQuery));
+ return this;
+ }
+ throw castedQuery;
+ }
+
+ castedDoc = castDoc(this);
+ if (!castedDoc) {
+ fn && process.nextTick(callback.bind(null, null, 0));
+ return this;
+ }
+
+ if (castedDoc instanceof Error) {
+ if (fn) {
+ process.nextTick(callback.bind(null, castedDoc));
+ return this;
+ }
+ throw castedDoc;
+ }
+
+ if (!fn) {
+ options.safe = { w: 0 };
+ }
+
+ model.collection.update(castedQuery, castedDoc, options, tick(callback));
+ return this;
+};
+
+/**
+ * Casts obj for an update command.
+ *
+ * @param {Object} obj
+ * @return {Object} obj after casting its values
+ * @api private
+ */
+
+Query.prototype._castUpdate = function _castUpdate (obj) {
+ var ops = Object.keys(obj)
+ , i = ops.length
+ , ret = {}
+ , hasKeys
+ , val
+
+ while (i--) {
+ var op = ops[i];
+ if ('$' !== op[0]) {
+ // fix up $set sugar
+ if (!ret.$set) {
+ if (obj.$set) {
+ ret.$set = obj.$set;
+ } else {
+ ret.$set = {};
+ }
+ }
+ ret.$set[op] = obj[op];
+ ops.splice(i, 1);
+ if (!~ops.indexOf('$set')) ops.push('$set');
+ } else if ('$set' === op) {
+ if (!ret.$set) {
+ ret[op] = obj[op];
+ }
+ } else {
+ ret[op] = obj[op];
+ }
+ }
+
+ // cast each value
+ i = ops.length;
+
+ while (i--) {
+ op = ops[i];
+ val = ret[op];
+ if ('Object' === val.constructor.name) {
+ hasKeys |= this._walkUpdatePath(val, op);
+ } else {
+ var msg = 'Invalid atomic update value for ' + op + '. '
+ + 'Expected an object, received ' + typeof val;
+ throw new Error(msg);
+ }
+ }
+
+ return hasKeys && ret;
+}
+
+/**
+ * Walk each path of obj and cast its values
+ * according to its schema.
+ *
+ * @param {Object} obj - part of a query
+ * @param {String} op - the atomic operator ($pull, $set, etc)
+ * @param {String} pref - path prefix (internal only)
+ * @return {Bool} true if this path has keys to update
+ * @api private
+ */
+
+Query.prototype._walkUpdatePath = function _walkUpdatePath (obj, op, pref) {
+ var strict = this.model.schema.options.strict
+ , prefix = pref ? pref + '.' : ''
+ , keys = Object.keys(obj)
+ , i = keys.length
+ , hasKeys = false
+ , schema
+ , key
+ , val
+
+ while (i--) {
+ key = keys[i];
+ val = obj[key];
+
+ if (val && 'Object' === val.constructor.name) {
+ // watch for embedded doc schemas
+ schema = this._getSchema(prefix + key);
+ if (schema && schema.caster && op in castOps) {
+ // embedded doc schema
+
+ if (strict && !schema) {
+ // path is not in our strict schema
+ if ('throw' == strict) {
+ throw new Error('Field `' + key + '` is not in schema.');
+ } else {
+ // ignore paths not specified in schema
+ delete obj[key];
+ }
+ } else {
+ hasKeys = true;
+ if ('$each' in val) {
+ obj[key] = {
+ $each: this._castUpdateVal(schema, val.$each, op)
+ }
+ } else {
+ obj[key] = this._castUpdateVal(schema, val, op);
+ }
+ }
+ } else {
+ hasKeys |= this._walkUpdatePath(val, op, prefix + key);
+ }
+ } else {
+ schema = '$each' === key
+ ? this._getSchema(pref)
+ : this._getSchema(prefix + key);
+
+ var skip = strict &&
+ !schema &&
+ !/real|nested/.test(this.model.schema.pathType(prefix + key));
+
+ if (skip) {
+ if ('throw' == strict) {
+ throw new Error('Field `' + prefix + key + '` is not in schema.');
+ } else {
+ delete obj[key];
+ }
+ } else {
+ hasKeys = true;
+ obj[key] = this._castUpdateVal(schema, val, op, key);
+ }
+ }
+ }
+ return hasKeys;
+}
+
+/**
+ * Casts `val` according to `schema` and atomic `op`.
+ *
+ * @param {Schema} schema
+ * @param {Object} val
+ * @param {String} op - the atomic operator ($pull, $set, etc)
+ * @param {String} [$conditional]
+ * @api private
+ */
+
+Query.prototype._castUpdateVal = function _castUpdateVal (schema, val, op, $conditional) {
+ if (!schema) {
+ // non-existing schema path
+ return op in numberOps
+ ? Number(val)
+ : val
+ }
+
+ if (schema.caster && op in castOps &&
+ ('Object' === val.constructor.name || Array.isArray(val))) {
+ // Cast values for ops that add data to MongoDB.
+ // Ensures embedded documents get ObjectIds etc.
+ var tmp = schema.cast(val);
+
+ if (Array.isArray(val)) {
+ val = tmp;
+ } else {
+ val = tmp[0];
+ }
+ }
+
+ if (op in numberOps) return Number(val);
+ if (/^\$/.test($conditional)) return schema.castForQuery($conditional, val);
+ return schema.castForQuery(val)
+}
+
+/**
+ * Finds the schema for `path`. This is different than
+ * calling `schema.path` as it also resolves paths with
+ * positional selectors (something.$.another.$.path).
+ *
+ * @param {String} path
+ * @api private
+ */
+
+Query.prototype._getSchema = function _getSchema (path) {
+ var schema = this.model.schema
+ , pathschema = schema.path(path);
+
+ if (pathschema)
+ return pathschema;
+
+ // look for arrays
+ return (function search (parts, schema) {
+ var p = parts.length + 1
+ , foundschema
+ , trypath
+
+ while (p--) {
+ trypath = parts.slice(0, p).join('.');
+ foundschema = schema.path(trypath);
+ if (foundschema) {
+ if (foundschema.caster) {
+
+ // array of Mixed?
+ if (foundschema.caster instanceof Types.Mixed) {
+ return foundschema.caster;
+ }
+
+ // Now that we found the array, we need to check if there
+ // are remaining document paths to look up for casting.
+ // Also we need to handle array.$.path since schema.path
+ // doesn't work for that.
+ if (p !== parts.length) {
+ if ('$' === parts[p]) {
+ // comments.$.comments.$.title
+ return search(parts.slice(p+1), foundschema.schema);
+ } else {
+ // this is the last path of the selector
+ return search(parts.slice(p), foundschema.schema);
+ }
+ }
+ }
+ return foundschema;
+ }
+ }
+ })(path.split('.'), schema)
+}
+
+/**
+ * Casts selected field arguments for field selection with mongo 2.2
+ *
+ * query.select({ ids: { $elemMatch: { $in: [hexString] }})
+ *
+ * @param {Object} fields
+ * @see https://github.com/LearnBoost/mongoose/issues/1091
+ * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
+ * @api private
+ */
+
+Query.prototype._castFields = function _castFields (fields) {
+ var selected
+ , elemMatchKeys
+ , keys
+ , key
+ , out
+ , i
+
+ if (fields) {
+ keys = Object.keys(fields);
+ elemMatchKeys = [];
+ i = keys.length;
+
+ // collect $elemMatch args
+ while (i--) {
+ key = keys[i];
+ if (fields[key].$elemMatch) {
+ selected || (selected = {});
+ selected[key] = fields[key];
+ elemMatchKeys.push(key);
+ }
+ }
+ }
+
+ if (selected) {
+ // they passed $elemMatch, cast em
+ try {
+ out = this.cast(this.model, selected);
+ } catch (err) {
+ return err;
+ }
+
+ // apply the casted field args
+ i = elemMatchKeys.length;
+ while (i--) {
+ key = elemMatchKeys[i];
+ fields[key] = out[key];
+ }
+ }
+
+ return fields;
+}
+
+/**
+ * Executes this query as a remove() operation.
+ *
+ * ####Example
+ *
+ * Cassette.where('artist').equals('Anne Murray').remove(callback)
+ *
+ * @param {Function} callback
+ * @api public
+ */
+
+Query.prototype.remove = function (callback) {
+ this.op = 'remove';
+
+ var model = this.model
+ , options = this._optionsForExec(model)
+ , cb = 'function' == typeof callback
+
+ try {
+ this.cast(model);
+ } catch (err) {
+ if (cb) return callback(err);
+ throw err;
+ }
+
+ if (!cb) {
+ options.safe = { w: 0 };
+ }
+
+ var castQuery = this._conditions;
+ model.collection.remove(castQuery, options, tick(callback));
+ return this;
+};
+
+/**
+ * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command.
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Available options
+ *
+ * - `new`: bool - true to return the modified document rather than the original. defaults to true
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ *
+ * ####Examples
+ *
+ * query.findOneAndUpdate(conditions, update, options, callback) // executes
+ * query.findOneAndUpdate(conditions, update, options) // returns Query
+ * query.findOneAndUpdate(conditions, update, callback) // executes
+ * query.findOneAndUpdate(conditions, update) // returns Query
+ * query.findOneAndUpdate(callback) // executes
+ * query.findOneAndUpdate() // returns Query
+ *
+ * @param {Object} [query]
+ * @param {Object} [doc]
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.findOneAndUpdate = function (query, doc, options, callback) {
+ this.op = 'findOneAndUpdate';
+
+ switch (arguments.length) {
+ case 3:
+ if ('function' == typeof options)
+ callback = options, options = {};
+ break;
+ case 2:
+ if ('function' == typeof doc) {
+ callback = doc;
+ doc = query;
+ query = undefined;
+ }
+ options = undefined;
+ break;
+ case 1:
+ if ('function' == typeof query) {
+ callback = query;
+ query = options = doc = undefined;
+ } else {
+ doc = query;
+ query = options = undefined;
+ }
+ }
+
+ // apply query
+ if (query) {
+ if ('Object' === query.constructor.name) {
+ merge(this._conditions, query);
+ } else if (query instanceof Query) {
+ merge(this._conditions, query._conditions);
+ } else if (query instanceof Document) {
+ merge(this._conditions, query.toObject());
+ }
+ }
+
+ // apply doc
+ if (doc) {
+ merge(this._updateArg, doc);
+ }
+
+ // apply options
+ options && this.setOptions(options);
+
+ if (!callback) return this;
+
+ return this._findAndModify('update', callback);
+}
+
+/**
+ * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to the callback. Executes immediately if `callback` is passed else a Query object is returned.
+ *
+ * ####Available options
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ *
+ * ####Examples
+ *
+ * A.where().findOneAndRemove(conditions, options, callback) // executes
+ * A.where().findOneAndRemove(conditions, options) // return Query
+ * A.where().findOneAndRemove(conditions, callback) // executes
+ * A.where().findOneAndRemove(conditions) // returns Query
+ * A.where().findOneAndRemove(callback) // executes
+ * A.where().findOneAndRemove() // returns Query
+ *
+ * @param {Object} [conditions]
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Query.prototype.findOneAndRemove = function (conditions, options, callback) {
+ this.op = 'findOneAndRemove';
+
+ if ('function' == typeof options) {
+ callback = options;
+ options = undefined;
+ } else if ('function' == typeof conditions) {
+ callback = conditions;
+ conditions = undefined;
+ }
+
+ // apply conditions
+ if (conditions) {
+ if ('Object' === conditions.constructor.name) {
+ merge(this._conditions, conditions);
+ } else if (conditions instanceof Query) {
+ merge(this._conditions, conditions._conditions);
+ } else if (conditions instanceof Document) {
+ merge(this._conditions, conditions.toObject());
+ }
+ }
+
+ // apply options
+ options && this.setOptions(options);
+
+ if (!callback) return this;
+
+ return this._findAndModify('remove', callback);
+}
+
+/**
+ * _findAndModify
+ *
+ * @param {String} type - either "remove" or "update"
+ * @param {Function} callback
+ * @api private
+ */
+
+Query.prototype._findAndModify = function (type, callback) {
+ var model = this.model
+ , promise = new Promise(callback)
+ , self = this
+ , castedQuery
+ , castedDoc
+ , fields
+ , sort
+ , opts
+
+ castedQuery = castQuery(this);
+ if (castedQuery instanceof Error) {
+ process.nextTick(promise.error.bind(promise, castedQuery));
+ return promise;
+ }
+
+ opts = this._optionsForExec(model);
+
+ if ('remove' == type) {
+ opts.remove = true;
+ } else {
+ if (!('new' in opts)) opts.new = true;
+ if (!('upsert' in opts)) opts.upsert = false;
+
+ castedDoc = castDoc(this);
+ if (!castedDoc) {
+ if (opts.upsert) {
+ // still need to do the upsert to empty doc
+ castedDoc = { $set: {} };
+ } else {
+ return this.findOne(callback);
+ }
+ } else if (castedDoc instanceof Error) {
+ process.nextTick(promise.error.bind(promise, castedDoc));
+ return promise;
+ }
+ }
+
+ this._applyPaths();
+
+ if (this._fields) {
+ fields = utils.clone(this._fields)
+ opts.fields = this._castFields(fields);
+ if (opts.fields instanceof Error) {
+ process.nextTick(promise.error.bind(promise, opts.fields));
+ return promise;
+ }
+ }
+
+ // the driver needs a default
+ sort = opts.sort || [];
+
+ model
+ .collection
+ .findAndModify(castedQuery, sort, castedDoc, opts, tick(function (err, doc) {
+ if (err) return promise.error(err);
+ if (!doc) return promise.complete(null);
+
+ if (true === opts.lean) {
+ return promise.complete(doc);
+ }
+
+ var casted = new model(undefined, fields, true);
+ casted.init(doc, self, function (err) {
+ if (err) return promise.error(err);
+ promise.complete(casted);
+ });
+ }));
+
+ return promise;
+}
+
+/**
+ * Specifies paths which should be populated with other documents.
+ *
+ * Paths are populated after the query executes and a response is received. A separate query is then executed for each path specified for population. After a response for each query has also been returned, the results are passed to the callback.
+ *
+ * ####Example:
+ *
+ * Kitten.findOne().populate('owner').exec(function (err, kitten) {
+ * console.log(kitten.owner.name) // Max
+ * })
+ *
+ * @param {String} path
+ * @param {Object|String} [fields]
+ * @param {Model} [model]
+ * @param {Object} [conditions]
+ * @param {Object} [options]
+ * @see population ./populate.html
+ * @see Query#select #query_Query-select
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.populate = function (path, fields, model, conditions, options) {
+ if ('string' !== typeof model) {
+ options = conditions;
+ conditions = model;
+ model = undefined;
+ }
+ // The order of fields/conditions args is opposite Model.find but
+ // necessary to keep backward compatibility (fields could be
+ // an array, string, or object literal).
+ this.options.populate[path] =
+ new PopulateOptions(fields, conditions, options, model);
+
+ return this;
+};
+
+/*!
+ * Populate options constructor
+ */
+
+function PopulateOptions (fields, conditions, options, model) {
+ this.conditions = conditions;
+ this.fields = fields;
+ this.options = options;
+ this.model = model;
+}
+
+// make it compatible with utils.clone
+PopulateOptions.prototype.constructor = Object;
+
+/**
+ * Returns a stream interface
+ *
+ * ####Example
+ *
+ * // follows the nodejs stream api
+ * Thing.find({ name: /^hello/ }).stream().pipe(res)
+ *
+ * // manual streaming
+ * var stream = Thing.find({ name: /^hello/ }).stream();
+ *
+ * stream.on('data', function (doc) {
+ * // do something with the mongoose document
+ * }).on('error', function (err) {
+ * // handle the error
+ * }).on('close', function () {
+ * // the stream is closed
+ * });
+ *
+ * @return {QueryStream}
+ * @see QueryStream
+ * @api public
+ */
+
+Query.prototype.stream = function stream () {
+ return new QueryStream(this);
+}
+
+// helpers
+
+/*!
+ * castDoc
+ * @api private
+ */
+
+function castDoc (query) {
+ try {
+ return query._castUpdate(query._updateArg);
+ } catch (err) {
+ return err;
+ }
+}
+
+/*!
+ * castQuery
+ * @api private
+ */
+
+function castQuery (query) {
+ try {
+ return query.cast(query.model);
+ } catch (err) {
+ return err;
+ }
+}
+
+/*!
+ * Exports.
+ */
+
+module.exports = Query;
+module.exports.QueryStream = QueryStream;
diff --git a/test/node_modules/mongoose/lib/querystream.js b/test/node_modules/mongoose/lib/querystream.js
new file mode 100644
index 0000000..69726c4
--- /dev/null
+++ b/test/node_modules/mongoose/lib/querystream.js
@@ -0,0 +1,313 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var Stream = require('stream').Stream
+var utils = require('./utils')
+
+/**
+ * Provides a [ReadStream](http://nodejs.org/api/stream.html#stream_readable_stream) interface for Queries.
+ *
+ * var stream = Model.find().stream();
+ *
+ * stream.on('data', function (doc) {
+ * // do something with the mongoose document
+ * }).on('error', function (err) {
+ * // handle the error
+ * }).on('close', function () {
+ * // the stream is closed
+ * });
+ *
+ *
+ * The stream interface allows us to simply "plug-in" to other Node.js write streams (fs.createWriteStream) so everything "just works" out of the box.
+ *
+ * Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
+ *
+ * _NOTE: plugging into an HTTP response will *not* work out of the box. Those streams expect only strings or buffers to be emitted, so first formatting our documents as strings/buffers is necessary._
+ *
+ * @param {Query} query
+ * @inherits NodeJS Stream http://nodejs.org/api/stream.html
+ * @event `data`: emits a single Mongoose document
+ * @event `error`: emits when an error occurs during streaming. This will emit _before_ the `close` event.
+ * @event `close`: emits when the stream reaches the end of the cursor or an error occurs, or the stream is manually `destroy`ed. After this event, no more events are emitted.
+ * @api public
+ */
+
+function QueryStream (query) {
+ Stream.call(this);
+
+ this.query = query;
+ this.readable = true;
+ this.paused = false;
+ this._cursor = null;
+ this._destroyed = null;
+ this._fields = null;
+ this._buffer = null;
+ this._inline = T_INIT;
+ this._running = false;
+
+ // give time to hook up events
+ var self = this;
+ process.nextTick(function () {
+ self._init();
+ });
+}
+
+/*!
+ * Inherit from Stream
+ */
+
+QueryStream.prototype.__proto__ = Stream.prototype;
+
+/**
+ * Flag stating whether or not this stream is readable.
+ *
+ * @property readable
+ * @api public
+ */
+
+QueryStream.prototype.readable;
+
+/**
+ * Flag stating whether or not this stream is paused.
+ *
+ * @property paused
+ * @api public
+ */
+
+QueryStream.prototype.paused;
+
+// trampoline flags
+var T_INIT = 0;
+var T_IDLE = 1;
+var T_CONT = 2;
+
+/**
+ * Initializes the query.
+ *
+ * @api private
+ */
+
+QueryStream.prototype._init = function () {
+ if (this._destroyed) return;
+
+ var query = this.query
+ , model = query.model
+ , options = query._optionsForExec(model)
+ , self = this
+
+ try {
+ query.cast(model);
+ } catch (err) {
+ return self.destroy(err);
+ }
+
+ self._fields = utils.clone(query._fields);
+ options.fields = query._castFields(self._fields);
+
+ model.collection.find(query._conditions, options, function (err, cursor) {
+ if (err) return self.destroy(err);
+ self._cursor = cursor;
+ self._next();
+ });
+}
+
+/**
+ * Trampoline for pulling the next doc from cursor.
+ *
+ * @see QueryStream#__next #querystream_QueryStream-__next
+ * @api private
+ */
+
+QueryStream.prototype._next = function _next () {
+ if (this.paused || this._destroyed) {
+ return this._running = false;
+ }
+
+ this._running = true;
+
+ if (this._buffer && this._buffer.length) {
+ var arg;
+ while (!this.paused && !this._destroyed && (arg = this._buffer.shift())) {
+ this._onNextObject.apply(this, arg);
+ }
+ }
+
+ // avoid stack overflows with large result sets.
+ // trampoline instead of recursion.
+ while (this.__next()) {}
+}
+
+/**
+ * Pulls the next doc from the cursor.
+ *
+ * @see QueryStream#_next #querystream_QueryStream-_next
+ * @api private
+ */
+
+QueryStream.prototype.__next = function () {
+ if (this.paused || this._destroyed)
+ return this._running = false;
+
+ var self = this;
+ self._inline = T_INIT;
+
+ self._cursor.nextObject(function cursorcb (err, doc) {
+ self._onNextObject(err, doc);
+ });
+
+ // if onNextObject() was already called in this tick
+ // return ourselves to the trampoline.
+ if (T_CONT === this._inline) {
+ return true;
+ } else {
+ // onNextObject() hasn't fired yet. tell onNextObject
+ // that its ok to call _next b/c we are not within
+ // the trampoline anymore.
+ this._inline = T_IDLE;
+ }
+}
+
+/**
+ * Transforms raw `doc`s returned from the cursor into a model instance.
+ *
+ * @param {Error|null} err
+ * @param {Object} doc
+ * @api private
+ */
+
+QueryStream.prototype._onNextObject = function _onNextObject (err, doc) {
+ if (this._destroyed) return;
+
+ if (this.paused) {
+ this._buffer || (this._buffer = []);
+ this._buffer.push([err, doc]);
+ return this._running = false;
+ }
+
+ if (err) return this.destroy(err);
+
+ // when doc is null we hit the end of the cursor
+ if (!doc) {
+ this.emit('end');
+ return this.destroy();
+ }
+
+ if (this.query.options && true === this.query.options.lean) {
+ this.emit('data', doc);
+
+ // trampoline management
+ if (T_IDLE === this._inline) {
+ // no longer in trampoline. restart it.
+ this._next();
+ } else {
+ // in a trampoline. tell __next that its
+ // ok to continue jumping.
+ this._inline = T_CONT;
+ }
+ return;
+ }
+
+ var instance = new this.query.model(undefined, this._fields, true);
+
+ var self = this;
+ instance.init(doc, this.query, function (err) {
+ if (err) return self.destroy(err);
+ self.emit('data', instance);
+
+ // trampoline management
+ if (T_IDLE === self._inline) {
+ // no longer in trampoline. restart it.
+ self._next();
+ } else
+ // in a trampoline. tell __next that its
+ // ok to continue jumping.
+ self._inline = T_CONT;
+ });
+}
+
+/**
+ * Pauses this stream.
+ *
+ * @api public
+ */
+
+QueryStream.prototype.pause = function () {
+ this.paused = true;
+}
+
+/**
+ * Resumes this stream.
+ *
+ * @api public
+ */
+
+QueryStream.prototype.resume = function () {
+ this.paused = false;
+
+ if (!this._cursor) {
+ // cannot start if not initialized
+ return;
+ }
+
+ // are we within the trampoline?
+ if (T_INIT === this._inline) {
+ return;
+ }
+
+ if (!this._running) {
+ // outside QueryStream control, need manual restart
+ return this._next();
+ }
+}
+
+/**
+ * Destroys the stream, closing the underlying cursor. No more events will be emitted.
+ *
+ * @param {Error} [err]
+ * @api public
+ */
+
+QueryStream.prototype.destroy = function (err) {
+ if (this._destroyed) return;
+ this._destroyed = true;
+ this._running = false;
+ this.readable = false;
+
+ if (this._cursor) {
+ this._cursor.close();
+ }
+
+ if (err) {
+ this.emit('error', err);
+ }
+
+ this.emit('close');
+}
+
+/**
+ * Pipes this query stream into another stream. This method is inherited from NodeJS Streams.
+ *
+ * ####Example:
+ *
+ * query.stream().pipe(writeStream [, options])
+ *
+ * This could be particularily useful if you are, for example, setting up an API for a service and want to stream out the docs based on some criteria. We could first pipe the QueryStream into a sort of filter that formats the stream as an array before passing on the document to an http response.
+ *
+ * var format = new ArrayFormatter;
+ * Events.find().stream().pipe(format).pipe(res);
+ *
+ * As long as ArrayFormat implements the WriteStream API we can stream large formatted result sets out to the client. See this [gist](https://gist.github.com/1403797) for a hacked example.
+ *
+ * @method pipe
+ * @memberOf QueryStream
+ * @see NodeJS http://nodejs.org/api/stream.html
+ * @api public
+ */
+
+/*!
+ * Module exports
+ */
+
+module.exports = exports = QueryStream;
diff --git a/test/node_modules/mongoose/lib/schema.js b/test/node_modules/mongoose/lib/schema.js
new file mode 100644
index 0000000..ef6b017
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema.js
@@ -0,0 +1,869 @@
+/*!
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+ , VirtualType = require('./virtualtype')
+ , utils = require('./utils')
+ , NamedScope
+ , Query
+ , Types
+
+/**
+ * Schema constructor.
+ *
+ * ####Example:
+ *
+ * var child = new Schema({ name: String });
+ * var schema = new Schema({ name: String, age: Number, children: [child] });
+ * var Tree = mongoose.model('Tree', schema);
+ *
+ * // setting schema options
+ * new Schema({ name: String }, { _id: false, autoIndex: false })
+ *
+ * ####Options:
+ *
+ * - [autoIndex](/docs/guide.html#autoIndex): bool - defaults to true
+ * - [capped](/docs/guide.html#capped): bool - defaults to false
+ * - [collection](/docs/guide.html#collection): string - no default
+ * - [id](/docs/guide.html#id): bool - defaults to true
+ * - [_id](/docs/guide.html#_id): bool - defaults to true
+ * - [read](/docs/guide.html#read): string
+ * - [safe](/docs/guide.html#safe): bool - defaults to true.
+ * - [shardKey](/docs/guide.html#shardKey): bool - defaults to `null`
+ * - [strict](/docs/guide.html#strict): bool - defaults to true
+ * - [toJSON](/docs/guide.html#toJSON) - object - no default
+ * - [toObject](/docs/guide.html#toObject) - object - no default
+ * - [versionKey](/docs/guide.html#versionKey): bool - defaults to "__v"
+ * - `minimize`: bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true
+ *
+ * ####Note:
+ *
+ * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into is parent._
+ *
+ * @param {Object} definition
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `init`: Emitted after the schema is compiled into a `Model`.
+ * @api public
+ */
+
+function Schema (obj, options) {
+ if (!(this instanceof Schema))
+ return new Schema(obj, options);
+
+ this.paths = {};
+ this.subpaths = {};
+ this.virtuals = {};
+ this.nested = {};
+ this.inherits = {};
+ this.callQueue = [];
+ this._indexes = [];
+ this.methods = {};
+ this.statics = {};
+ this.tree = {};
+ this._requiredpaths = undefined;
+
+ this.options = this.defaultOptions(options);
+
+ // build paths
+ if (obj) {
+ this.add(obj);
+ }
+
+ // ensure the documents get an auto _id unless disabled
+ var auto_id = !this.paths['_id'] && (!this.options.noId && this.options._id);
+ if (auto_id) {
+ this.add({ _id: {type: Schema.ObjectId, auto: true} });
+ }
+
+ // ensure the documents receive an id getter unless disabled
+ var autoid = !this.paths['id'] && (!this.options.noVirtualId && this.options.id);
+ if (autoid) {
+ this.virtual('id').get(idGetter);
+ }
+
+ // versioning not directly added to schema b/c we only want
+ // it in the top level document, not embedded ones.
+};
+
+/*!
+ * Returns this documents _id cast to a string.
+ */
+
+function idGetter () {
+ if (this.__id) {
+ return this.__id;
+ }
+
+ return this.__id = null == this._id
+ ? null
+ : String(this._id);
+}
+
+/*!
+ * Inherit from EventEmitter.
+ */
+
+Schema.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Schema as flat paths
+ *
+ * ####Example:
+ * {
+ * '_id' : SchemaType,
+ * , 'nested.key' : SchemaType,
+ * }
+ *
+ * @api private
+ * @property paths
+ */
+
+Schema.prototype.paths;
+
+/**
+ * Schema as a tree
+ *
+ * ####Example:
+ * {
+ * '_id' : ObjectId
+ * , 'nested' : {
+ * 'key' : String
+ * }
+ * }
+ *
+ * @api private
+ * @property tree
+ */
+
+Schema.prototype.tree;
+
+/**
+ * Returns default options for this schema, merged with `options`.
+ *
+ * @param {Object} options
+ * @return {Object}
+ * @api private
+ */
+
+Schema.prototype.defaultOptions = function (options) {
+ if (options && false === options.safe) {
+ options.safe = { w: 0 };
+ }
+
+ options = utils.options({
+ strict: true
+ , capped: false // { size, max, autoIndexId }
+ , versionKey: '__v'
+ , minimize: true
+ , autoIndex: true
+ , shardKey: null
+ , read: null
+ // the following are only applied at construction time
+ , noId: false // deprecated, use { _id: false }
+ , _id: true
+ , noVirtualId: false // deprecated, use { id: false }
+ , id: true
+ }, options);
+
+ if (options.read)
+ options.read = utils.readPref(options.read);
+
+ return options;
+}
+
+/**
+ * Adds key path / schema type pairs to this schema.
+ *
+ * ####Example:
+ *
+ * var ToySchema = new Schema;
+ * ToySchema.add({ name: 'string', color: 'string', price: 'number' });
+ *
+ * @param {Object} obj
+ * @param {String} prefix
+ * @api public
+ */
+
+Schema.prototype.add = function add (obj, prefix) {
+ prefix = prefix || '';
+ for (var i in obj) {
+ if (null == obj[i]) {
+ throw new TypeError('Invalid value for schema path `'+ prefix + i +'`');
+ }
+
+ if (obj[i].constructor.name == 'Object' && (!obj[i].type || obj[i].type.type)) {
+ if (Object.keys(obj[i]).length) {
+ // nested object { last: { name: String }}
+ this.nested[prefix + i] = true;
+ this.add(obj[i], prefix + i + '.');
+ } else {
+ this.path(prefix + i, obj[i]); // mixed type
+ }
+ } else {
+ this.path(prefix + i, obj[i]);
+ }
+ }
+};
+
+/**
+ * Reserved document keys.
+ *
+ * Keys in this object are names that are rejected in schema declarations b/c they conflict with mongoose functionality. Using these key name will throw an error.
+ *
+ * on, db, init, isNew, errors, schema, options, modelName, collection
+ *
+ * _NOTE:_ Use of these terms as method names is permitted, but play at your own risk, as they may be existing mongoose document methods you are stomping on.
+ *
+ * var schema = new Schema(..);
+ * schema.methods.init = function () {} // potentially breaking
+ */
+
+Schema.reserved = Object.create(null);
+var reserved = Schema.reserved;
+reserved.on =
+reserved.db =
+reserved.init =
+reserved.isNew =
+reserved.errors =
+reserved.schema =
+reserved.options =
+reserved.modelName =
+reserved._pres = reserved._posts = // hooks.js
+reserved.collection = 1;
+
+/**
+ * Gets/sets schema paths.
+ *
+ * Sets a path (if arity 2)
+ * Gets a path (if arity 1)
+ *
+ * ####Example
+ *
+ * schema.path('name') // returns a SchemaType
+ * schema.path('name', Number) // changes the schemaType of `name` to Number
+ *
+ * @param {String} path
+ * @param {Object} constructor
+ * @api public
+ */
+
+Schema.prototype.path = function (path, obj) {
+ if (obj == undefined) {
+ if (this.paths[path]) return this.paths[path];
+ if (this.subpaths[path]) return this.subpaths[path];
+
+ // subpaths?
+ return /\.\d+\.?$/.test(path)
+ ? getPositionalPath(this, path)
+ : undefined;
+ }
+
+ // some path names conflict with document methods
+ if (reserved[path]) {
+ throw new Error("`" + path + "` may not be used as a schema pathname");
+ }
+
+ // update the tree
+ var subpaths = path.split(/\./)
+ , last = subpaths.pop()
+ , branch = this.tree;
+
+ subpaths.forEach(function(sub, i) {
+ if (!branch[sub]) branch[sub] = {};
+ if ('object' != typeof branch[sub]) {
+ var msg = 'Cannot set nested path `' + path + '`. '
+ + 'Parent path `'
+ + subpaths.slice(0, i).concat([sub]).join('.')
+ + '` already set to type ' + branch[sub].name
+ + '.';
+ throw new Error(msg);
+ }
+ branch = branch[sub];
+ });
+
+ branch[last] = utils.clone(obj);
+
+ this.paths[path] = Schema.interpretAsType(path, obj);
+ return this;
+};
+
+/**
+ * Converts type arguments into Mongoose Types.
+ *
+ * @param {String} path
+ * @param {Object} obj constructor
+ * @api private
+ */
+
+Schema.interpretAsType = function (path, obj) {
+ if (obj.constructor.name != 'Object')
+ obj = { type: obj };
+
+ // Get the type making sure to allow keys named "type"
+ // and default to mixed if not specified.
+ // { type: { type: String, default: 'freshcut' } }
+ var type = obj.type && !obj.type.type
+ ? obj.type
+ : {};
+
+ if ('Object' == type.constructor.name || 'mixed' == type) {
+ return new Types.Mixed(path, obj);
+ }
+
+ if (Array.isArray(type) || Array == type || 'array' == type) {
+ // if it was specified through { type } look for `cast`
+ var cast = (Array == type || 'array' == type)
+ ? obj.cast
+ : type[0];
+
+ if (cast instanceof Schema) {
+ return new Types.DocumentArray(path, cast, obj);
+ }
+
+ if ('string' == typeof cast) {
+ cast = Types[cast.charAt(0).toUpperCase() + cast.substring(1)];
+ } else if (cast && (!cast.type || cast.type.type)
+ && 'Object' == cast.constructor.name
+ && Object.keys(cast).length) {
+ return new Types.DocumentArray(path, new Schema(cast), obj);
+ }
+
+ return new Types.Array(path, cast || Types.Mixed, obj);
+ }
+
+ var name = 'string' == typeof type
+ ? type
+ : type.name;
+
+ if (name) {
+ name = name.charAt(0).toUpperCase() + name.substring(1);
+ }
+
+ if (undefined == Types[name]) {
+ throw new TypeError('Undefined type at `' + path +
+ '`\n Did you try nesting Schemas? ' +
+ 'You can only nest using refs or arrays.');
+ }
+
+ return new Types[name](path, obj);
+};
+
+/**
+ * Iterates the schemas paths similar to Array#forEach.
+ *
+ * The callback is passed the pathname and schemaType as arguments on each iteration.
+ *
+ * @param {Function} fn callback function
+ * @return {Schema} this
+ * @api public
+ */
+
+Schema.prototype.eachPath = function (fn) {
+ var keys = Object.keys(this.paths)
+ , len = keys.length;
+
+ for (var i = 0; i < len; ++i) {
+ fn(keys[i], this.paths[keys[i]]);
+ }
+
+ return this;
+};
+
+/**
+ * Returns an Array of path strings that are required by this schema.
+ *
+ * @api public
+ * @return {Array}
+ */
+
+Schema.prototype.requiredPaths = function requiredPaths () {
+ if (this._requiredpaths) return this._requiredpaths;
+
+ var paths = Object.keys(this.paths)
+ , i = paths.length
+ , ret = [];
+
+ while (i--) {
+ var path = paths[i];
+ if (this.paths[path].isRequired) ret.push(path);
+ }
+
+ return this._requiredpaths = ret;
+}
+
+/**
+ * Returns the pathType of `path` for this schema.
+ *
+ * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.
+ *
+ * @param {String} path
+ * @return {String}
+ * @api public
+ */
+
+Schema.prototype.pathType = function (path) {
+ if (path in this.paths) return 'real';
+ if (path in this.virtuals) return 'virtual';
+ if (path in this.nested) return 'nested';
+ if (path in this.subpaths) return 'real';
+
+ if (/\.\d+\.?/.test(path) && getPositionalPath(this, path)) {
+ return 'real';
+ } else {
+ return 'adhocOrUndefined'
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function getPositionalPath (self, path) {
+ var subpaths = path.split(/\.(\d+)\.?/).filter(Boolean);
+ if (subpaths.length < 2) {
+ return self.paths[subpaths[0]];
+ }
+
+ var val = self.path(subpaths[0]);
+ if (!val) return val;
+
+ var last = subpaths.length - 1
+ , subpath
+ , i = 1;
+
+ for (; i < subpaths.length; ++i) {
+ subpath = subpaths[i];
+
+ if (i === last &&
+ val &&
+ !val.schema &&
+ !/\D/.test(subpath) &&
+ val instanceof Types.Array) {
+ // StringSchema, NumberSchema, etc
+ val = val.caster;
+ continue;
+ }
+
+ // 'path.0.subpath'
+ if (!/\D/.test(subpath)) continue;
+ val = val.schema.path(subpath);
+ }
+
+ return self.subpaths[path] = val;
+}
+
+/**
+ * Adds a method call to the queue.
+ *
+ * @param {String} name name of the document method to call later
+ * @param {Array} args arguments to pass to the method
+ * @api private
+ */
+
+Schema.prototype.queue = function(name, args){
+ this.callQueue.push([name, args]);
+ return this;
+};
+
+/**
+ * Defines a pre hook for the document.
+ *
+ * ####Example
+ *
+ * var toySchema = new Schema(..);
+ *
+ * toySchema.pre('save', function (next) {
+ * if (!this.created) this.created = new Date;
+ * next();
+ * })
+ *
+ * toySchema.pre('validate', function (next) {
+ * if (this.name != 'Woody') this.name = 'Woody';
+ * next();
+ * })
+ *
+ * @param {String} method
+ * @param {Function} callback
+ * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
+ * @api public
+ */
+
+Schema.prototype.pre = function(){
+ return this.queue('pre', arguments);
+};
+
+/**
+ * Defines a post for the document
+ *
+ * Post hooks fire `on` the event emitted from document instances of Models compiled from this schema.
+ *
+ * var schema = new Schema(..);
+ * schema.post('save', function (doc) {
+ * console.log('this fired after a document was saved');
+ * });
+ *
+ * var Model = mongoose.model('Model', schema);
+ *
+ * var m = new Model(..);
+ * m.save(function (err) {
+ * console.log('this fires after the `post` hook');
+ * });
+ *
+ * @param {String} method name of the method to hook
+ * @param {Function} fn callback
+ * @see hooks.js https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3
+ * @api public
+ */
+
+Schema.prototype.post = function(method, fn){
+ return this.queue('on', arguments);
+};
+
+/**
+ * Registers a plugin for this schema.
+ *
+ * @param {Function} plugin callback
+ * @param {Object} opts
+ * @see plugins
+ * @api public
+ */
+
+Schema.prototype.plugin = function (fn, opts) {
+ fn(this, opts);
+ return this;
+};
+
+/**
+ * Adds an instance method to documents constructed from Models compiled from this schema.
+ *
+ * ####Example
+ *
+ * var schema = kittySchema = new Schema(..);
+ *
+ * schema.methods.meow = function () {
+ * console.log('meeeeeoooooooooooow');
+ * })
+ *
+ * var Kitty = mongoose.model('Kitty', schema);
+ *
+ * var fizz = new Kitty;
+ * fizz.meow(); // meeeeeooooooooooooow
+ *
+ * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.
+ *
+ * schema.method({
+ * purr: function () {}
+ * , scratch: function () {}
+ * });
+ *
+ * // later
+ * fizz.purr();
+ * fizz.scratch();
+ *
+ * @param {String|Object} method name
+ * @param {Function} [fn]
+ * @api public
+ */
+
+Schema.prototype.method = function (name, fn) {
+ if ('string' != typeof name)
+ for (var i in name)
+ this.methods[i] = name[i];
+ else
+ this.methods[name] = fn;
+ return this;
+};
+
+/**
+ * Adds static "class" methods to Models compiled from this schema.
+ *
+ * ####Example
+ *
+ * var schema = new Schema(..);
+ * schema.static('findByName', function (name, callback) {
+ * return this.find({ name: name }, callback);
+ * });
+ *
+ * var Drink = mongoose.model('Drink', schema);
+ * Drink.findByName('sanpellegrino', function (err, drinks) {
+ * //
+ * });
+ *
+ * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
+ *
+ * @param {String} name
+ * @param {Function} fn
+ * @api public
+ */
+
+Schema.prototype.static = function(name, fn) {
+ if ('string' != typeof name)
+ for (var i in name)
+ this.statics[i] = name[i];
+ else
+ this.statics[name] = fn;
+ return this;
+};
+
+/**
+ * Defines an index (most likely compound) for this schema.
+ *
+ * ####Example
+ *
+ * schema.index({ first: 1, last: -1 })
+ *
+ * @param {Object} fields
+ * @param {Object} [options]
+ * @api public
+ */
+
+Schema.prototype.index = function (fields, options) {
+ options || (options = {});
+
+ if (options.expires)
+ utils.expires(options);
+
+ this._indexes.push([fields, options]);
+ return this;
+};
+
+/**
+ * Sets/gets a schema option.
+ *
+ * @param {String} key option name
+ * @param {Object} [value] if not passed, the current option value is returned
+ * @api public
+ */
+
+Schema.prototype.set = function (key, value, _tags) {
+ if (1 === arguments.length) {
+ return this.options[key];
+ }
+
+ switch (key) {
+ case 'read':
+ this.options[key] = utils.readPref(value, _tags)
+ break;
+ case 'safe':
+ this.options[key] = false === value
+ ? { w: 0 }
+ : value
+ break;
+ default:
+ this.options[key] = value;
+ }
+
+ return this;
+}
+
+/**
+ * Gets a schema option.
+ *
+ * @param {String} key option name
+ * @api public
+ */
+
+Schema.prototype.get = function (key) {
+ return this.options[key];
+}
+
+/**
+ * Compiles indexes from fields and schema-level indexes
+ *
+ * @api public
+ */
+
+Schema.prototype.indexes = function () {
+ var indexes = []
+ , seenSchemas = [];
+
+ collectIndexes(this);
+
+ return indexes;
+
+ function collectIndexes (schema, prefix) {
+ if (~seenSchemas.indexOf(schema)) return;
+ seenSchemas.push(schema);
+
+ var index;
+ var paths = schema.paths;
+ prefix = prefix || '';
+
+ for (var i in paths) {
+ if (paths[i]) {
+ if (paths[i] instanceof Types.DocumentArray) {
+ collectIndexes(paths[i].schema, i + '.');
+ } else {
+ index = paths[i]._index;
+
+ if (index !== false && index !== null){
+ var field = {};
+ field[prefix + i] = '2d' === index ? index : 1;
+ var options = 'Object' === index.constructor.name ? index : {};
+ if (!('background' in options)) options.background = true;
+ indexes.push([field, options]);
+ }
+ }
+ }
+ }
+
+ if (prefix) {
+ fixSubIndexPaths(schema, prefix);
+ } else {
+ schema._indexes.forEach(function (index) {
+ if (!('background' in index[1])) index[1].background = true;
+ });
+ indexes = indexes.concat(schema._indexes);
+ }
+ }
+
+ /*!
+ * Checks for indexes added to subdocs using Schema.index().
+ * These indexes need their paths prefixed properly.
+ *
+ * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
+ */
+
+ function fixSubIndexPaths (schema, prefix) {
+ var subindexes = schema._indexes
+ , len = subindexes.length
+ , indexObj
+ , newindex
+ , klen
+ , keys
+ , key
+ , i = 0
+ , j
+
+ for (i = 0; i < len; ++i) {
+ indexObj = subindexes[i][0];
+ keys = Object.keys(indexObj);
+ klen = keys.length;
+ newindex = {};
+
+ // use forward iteration, order matters
+ for (j = 0; j < klen; ++j) {
+ key = keys[j];
+ newindex[prefix + key] = indexObj[key];
+ }
+
+ indexes.push([newindex, subindexes[i][1]]);
+ }
+ }
+}
+
+/**
+ * Creates a virtual type with the given name.
+ *
+ * @param {String} name
+ * @param {Object} [options]
+ * @return {VirtualType}
+ */
+
+Schema.prototype.virtual = function (name, options) {
+ var virtuals = this.virtuals;
+ var parts = name.split('.');
+ return virtuals[name] = parts.reduce(function (mem, part, i) {
+ mem[part] || (mem[part] = (i === parts.length-1)
+ ? new VirtualType(options, name)
+ : {});
+ return mem[part];
+ }, this.tree);
+};
+
+/**
+ * Returns the virtual type with the given `name`.
+ *
+ * @param {String} name
+ * @return {VirtualType}
+ */
+
+Schema.prototype.virtualpath = function (name) {
+ return this.virtuals[name];
+};
+
+/**
+ * These still haven't been fixed. Once they're working we'll make them public again.
+ * @api private
+ */
+
+Schema.prototype.namedScope = function (name, fn) {
+ var namedScopes = this.namedScopes || (this.namedScopes = new NamedScope)
+ , newScope = Object.create(namedScopes)
+ , allScopes = namedScopes.scopesByName || (namedScopes.scopesByName = {});
+ allScopes[name] = newScope;
+ newScope.name = name;
+ newScope.block = fn;
+ newScope.query = new Query();
+ newScope.decorate(namedScopes, {
+ block0: function (block) {
+ return function () {
+ block.call(this.query);
+ return this;
+ };
+ },
+ blockN: function (block) {
+ return function () {
+ block.apply(this.query, arguments);
+ return this;
+ };
+ },
+ basic: function (query) {
+ return function () {
+ this.query.find(query);
+ return this;
+ };
+ }
+ });
+ return newScope;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = Schema;
+
+// require down here because of reference issues
+
+/**
+ * The various Mongoose Schema Types.
+ *
+ * ####Example:
+ *
+ * ####Example:
+ *
+ * var mongoose = require('mongoose');
+ * var ObjectId = mongoose.Schema.Types.ObjectId;
+ *
+ * ####Types:
+ *
+ * - String
+ * - Number
+ * - Boolean | Bool
+ * - Array
+ * - Buffer
+ * - Date
+ * - ObjectId | Oid
+ * - Mixed
+ *
+ * Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
+ *
+ * var Mixed = mongoose.Schema.Types.Mixed;
+ * new mongoose.Schema({ _user: Mixed })
+ *
+ * @api public
+ */
+
+Schema.Types = require('./schema/index');
+
+/*!
+ * ignore
+ */
+
+Types = Schema.Types;
+NamedScope = require('./namedscope')
+Query = require('./query');
+var ObjectId = exports.ObjectId = Types.ObjectId;
+
diff --git a/test/node_modules/mongoose/lib/schema/array.js b/test/node_modules/mongoose/lib/schema/array.js
new file mode 100644
index 0000000..89ab4d4
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/array.js
@@ -0,0 +1,261 @@
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError
+ , NumberSchema = require('./number')
+ , Types = {
+ Boolean: require('./boolean')
+ , Date: require('./date')
+ , Number: require('./number')
+ , String: require('./string')
+ , ObjectId: require('./objectid')
+ , Buffer: require('./buffer')
+ }
+ , MongooseArray = require('../types').Array
+ , EmbeddedDoc = require('../types').Embedded
+ , Mixed = require('./mixed')
+ , Query = require('../query')
+ , isMongooseObject = require('../utils').isMongooseObject
+
+/**
+ * Array SchemaType constructor
+ *
+ * @param {String} key
+ * @param {SchemaType} cast
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaArray (key, cast, options) {
+ if (cast) {
+ var castOptions = {};
+
+ if ('Object' === cast.constructor.name) {
+ if (cast.type) {
+ // support { type: Woot }
+ castOptions = cast;
+ cast = cast.type;
+ delete castOptions.type;
+ } else {
+ cast = Mixed;
+ }
+ }
+
+ var caster = cast.name in Types ? Types[cast.name] : cast;
+ this.casterConstructor = caster;
+ this.caster = new caster(null, castOptions);
+ if (!(this.caster instanceof EmbeddedDoc)) {
+ this.caster.path = key;
+ }
+ }
+
+ SchemaType.call(this, key, options);
+
+ var self = this
+ , defaultArr
+ , fn;
+
+ if (this.defaultValue) {
+ defaultArr = this.defaultValue;
+ fn = 'function' == typeof defaultArr;
+ }
+
+ this.default(function(){
+ var arr = fn ? defaultArr() : defaultArr || [];
+ return new MongooseArray(arr, self.path, this);
+ });
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+SchemaArray.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Check required
+ *
+ * @param {Array} value
+ * @api private
+ */
+
+SchemaArray.prototype.checkRequired = function (value) {
+ return !!(value && value.length);
+};
+
+/**
+ * Overrides the getters application for the population special-case
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaArray.prototype.applyGetters = function (value, scope) {
+ if (this.caster.options && this.caster.options.ref) {
+ // means the object id was populated
+ return value;
+ }
+
+ return SchemaType.prototype.applyGetters.call(this, value, scope);
+};
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init whether this is an initialization cast
+ * @api private
+ */
+
+SchemaArray.prototype.cast = function (value, doc, init) {
+ if (Array.isArray(value)) {
+ if (!(value instanceof MongooseArray)) {
+ value = new MongooseArray(value, this.path, doc);
+ }
+
+ if (this.caster) {
+ try {
+ for (var i = 0, l = value.length; i < l; i++) {
+ value[i] = this.caster.cast(value[i], doc, init);
+ }
+ } catch (e) {
+ // rethrow
+ throw new CastError(e.type, value, this.path);
+ }
+ }
+
+ return value;
+ } else {
+ return this.cast([value], doc, init);
+ }
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaArray.prototype.castForQuery = function ($conditional, value) {
+ var handler
+ , val;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with Array.");
+ val = handler.call(this, value);
+ } else {
+ val = $conditional;
+ var proto = this.casterConstructor.prototype;
+ var method = proto.castForQuery || proto.cast;
+
+ var caster = this.caster;
+ if (Array.isArray(val)) {
+ val = val.map(function (v) {
+ if (method) v = method.call(caster, v);
+
+ return isMongooseObject(v)
+ ? v.toObject()
+ : v;
+ });
+ } else if (method) {
+ val = method.call(caster, val);
+ }
+ }
+ return val && isMongooseObject(val)
+ ? val.toObject()
+ : val;
+};
+
+/*!
+ * @ignore
+ */
+
+function castToNumber (val) {
+ return Types.Number.prototype.cast.call(this, val);
+}
+
+SchemaArray.prototype.$conditionalHandlers = {
+ '$all': function handle$all (val) {
+ if (!Array.isArray(val)) {
+ val = [val];
+ }
+
+ val = val.map(function (v) {
+ if (v && 'Object' === v.constructor.name) {
+ var o = {};
+ o[this.path] = v;
+ var query = new Query(o);
+ query.cast(this.casterConstructor);
+ return query._conditions[this.path];
+ }
+ return v;
+ }, this);
+
+ return this.castForQuery(val);
+ }
+ , '$elemMatch': function (val) {
+ if (val.$in) {
+ val.$in = this.castForQuery('$in', val.$in);
+ return val;
+ }
+
+ var query = new Query(val);
+ query.cast(this.casterConstructor);
+ return query._conditions;
+ }
+ , '$size': castToNumber
+ , '$ne': SchemaArray.prototype.castForQuery
+ , '$in': SchemaArray.prototype.castForQuery
+ , '$nin': SchemaArray.prototype.castForQuery
+ , '$regex': SchemaArray.prototype.castForQuery
+ , '$near': SchemaArray.prototype.castForQuery
+ , '$nearSphere': SchemaArray.prototype.castForQuery
+ , '$gt': SchemaArray.prototype.castForQuery
+ , '$gte': SchemaArray.prototype.castForQuery
+ , '$lt': SchemaArray.prototype.castForQuery
+ , '$lte': SchemaArray.prototype.castForQuery
+ , '$within': function (val) {
+ var self = this;
+
+ if (val.$maxDistance) {
+ val.$maxDistance = castToNumber.call(this, val.$maxDistance);
+ }
+
+ if (val.$box || val.$polygon) {
+ var type = val.$box ? '$box' : '$polygon';
+ val[type].forEach(function (arr) {
+ arr.forEach(function (v, i) {
+ arr[i] = castToNumber.call(this, v);
+ });
+ })
+ } else if (val.$center || val.$centerSphere) {
+ var type = val.$center ? '$center' : '$centerSphere';
+ val[type].forEach(function (item, i) {
+ if (Array.isArray(item)) {
+ item.forEach(function (v, j) {
+ item[j] = castToNumber.call(this, v);
+ });
+ } else {
+ val[type][i] = castToNumber.call(this, item);
+ }
+ })
+ }
+
+ return val;
+ }
+ , '$maxDistance': castToNumber
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaArray;
diff --git a/test/node_modules/mongoose/lib/schema/boolean.js b/test/node_modules/mongoose/lib/schema/boolean.js
new file mode 100644
index 0000000..05635bc
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/boolean.js
@@ -0,0 +1,91 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype');
+
+/**
+ * Boolean SchemaType constructor.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaBoolean (path, options) {
+ SchemaType.call(this, path, options);
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaBoolean.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Required validator
+ *
+ * @api private
+ */
+
+SchemaBoolean.prototype.checkRequired = function (value) {
+ return value === true || value === false;
+};
+
+/**
+ * Casts to boolean
+ *
+ * @param {Object} value
+ * @api private
+ */
+
+SchemaBoolean.prototype.cast = function (value) {
+ if (value === null) return value;
+ if (value === '0') return false;
+ return !!value;
+};
+
+/*!
+ * ignore
+ */
+
+function handleArray (val) {
+ var self = this;
+ return val.map(function (m) {
+ return self.cast(m);
+ });
+}
+
+SchemaBoolean.$conditionalHandlers = {
+ '$in': handleArray
+}
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} val
+ * @api private
+ */
+
+SchemaBoolean.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+ if (2 === arguments.length) {
+ handler = SchemaBoolean.$conditionalHandlers[$conditional];
+
+ if (handler) {
+ return handler.call(this, val);
+ }
+
+ return this.cast(val);
+ }
+
+ return this.cast($conditional);
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaBoolean;
diff --git a/test/node_modules/mongoose/lib/schema/buffer.js b/test/node_modules/mongoose/lib/schema/buffer.js
new file mode 100644
index 0000000..22c4c0e
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/buffer.js
@@ -0,0 +1,118 @@
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError
+ , MongooseBuffer = require('../types').Buffer
+ , Binary = MongooseBuffer.Binary
+ , Query = require('../query');
+
+/**
+ * Buffer SchemaType constructor
+ *
+ * @param {String} key
+ * @param {SchemaType} cast
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaBuffer (key, options) {
+ SchemaType.call(this, key, options, 'Buffer');
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+SchemaBuffer.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Check required
+ *
+ * @api private
+ */
+
+SchemaBuffer.prototype.checkRequired = function (value) {
+ return !!(value && value.length);
+};
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaBuffer.prototype.cast = function (value, doc, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
+ if (Buffer.isBuffer(value)) {
+ if (!(value instanceof MongooseBuffer)) {
+ value = new MongooseBuffer(value, [this.path, doc]);
+ }
+
+ return value;
+ } else if (value instanceof Binary) {
+ return new MongooseBuffer(value.value(true), [this.path, doc]);
+ }
+
+ if ('string' === typeof value || Array.isArray(value)) {
+ return new MongooseBuffer(value, [this.path, doc]);
+ }
+
+ throw new CastError('buffer', value, this.path);
+};
+
+/*!
+ * ignore
+ */
+function handleSingle (val) {
+ return this.castForQuery(val);
+}
+
+function handleArray (val) {
+ var self = this;
+ return val.map( function (m) {
+ return self.castForQuery(m);
+ });
+}
+
+SchemaBuffer.prototype.$conditionalHandlers = {
+ '$ne' : handleSingle
+ , '$in' : handleArray
+ , '$nin': handleArray
+ , '$gt' : handleSingle
+ , '$lt' : handleSingle
+ , '$gte': handleSingle
+ , '$lte': handleSingle
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaBuffer.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with Buffer.");
+ return handler.call(this, val);
+ } else {
+ val = $conditional;
+ return this.cast(val).toObject();
+ }
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaBuffer;
diff --git a/test/node_modules/mongoose/lib/schema/date.js b/test/node_modules/mongoose/lib/schema/date.js
new file mode 100644
index 0000000..fecd7d9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/date.js
@@ -0,0 +1,126 @@
+
+/*!
+ * Module requirements.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError;
+
+/**
+ * Date SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaDate (key, options) {
+ SchemaType.call(this, key, options);
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+SchemaDate.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Required validator for date
+ *
+ * @api private
+ */
+
+SchemaDate.prototype.checkRequired = function (value) {
+ return value instanceof Date;
+};
+
+/**
+ * Casts to date
+ *
+ * @param {Object} value to cast
+ * @api private
+ */
+
+SchemaDate.prototype.cast = function (value) {
+ if (value === null || value === '')
+ return null;
+
+ if (value instanceof Date)
+ return value;
+
+ var date;
+
+ // support for timestamps
+ if (value instanceof Number || 'number' == typeof value
+ || String(value) == Number(value))
+ date = new Date(Number(value));
+
+ // support for date strings
+ else if (value.toString)
+ date = new Date(value.toString());
+
+ if (date.toString() != 'Invalid Date')
+ return date;
+
+ throw new CastError('date', value, this.path);
+};
+
+/*!
+ * Date Query casting.
+ *
+ * @api private
+ */
+
+function handleSingle (val) {
+ return this.cast(val);
+}
+
+function handleArray (val) {
+ var self = this;
+ return val.map( function (m) {
+ return self.cast(m);
+ });
+}
+
+SchemaDate.prototype.$conditionalHandlers = {
+ '$lt': handleSingle
+ , '$lte': handleSingle
+ , '$gt': handleSingle
+ , '$gte': handleSingle
+ , '$ne': handleSingle
+ , '$in': handleArray
+ , '$nin': handleArray
+ , '$all': handleArray
+};
+
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaDate.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+
+ if (2 !== arguments.length) {
+ return this.cast($conditional);
+ }
+
+ handler = this.$conditionalHandlers[$conditional];
+
+ if (!handler) {
+ throw new Error("Can't use " + $conditional + " with Date.");
+ }
+
+ return handler.call(this, val);
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaDate;
diff --git a/test/node_modules/mongoose/lib/schema/documentarray.js b/test/node_modules/mongoose/lib/schema/documentarray.js
new file mode 100644
index 0000000..93f2455
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/documentarray.js
@@ -0,0 +1,189 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype')
+ , ArrayType = require('./array')
+ , MongooseDocumentArray = require('../types/documentarray')
+ , Subdocument = require('../types/embedded')
+ , Document = require('../document');
+
+/**
+ * SubdocsArray SchemaType constructor
+ *
+ * @param {String} key
+ * @param {Schema} schema
+ * @param {Object} options
+ * @inherits SchemaArray
+ * @api private
+ */
+
+function DocumentArray (key, schema, options) {
+
+ // compile an embedded document for this schema
+ function EmbeddedDocument () {
+ Subdocument.apply(this, arguments);
+ }
+
+ EmbeddedDocument.prototype.__proto__ = Subdocument.prototype;
+ EmbeddedDocument.prototype._setSchema(schema);
+ EmbeddedDocument.schema = schema;
+
+ // apply methods
+ for (var i in schema.methods) {
+ EmbeddedDocument.prototype[i] = schema.methods[i];
+ }
+
+ // apply statics
+ for (var i in schema.statics)
+ EmbeddedDocument[i] = schema.statics[i];
+
+ EmbeddedDocument.options = options;
+ this.schema = schema;
+
+ ArrayType.call(this, key, EmbeddedDocument, options);
+
+ this.schema = schema;
+ var path = this.path;
+ var fn = this.defaultValue;
+
+ this.default(function(){
+ var arr = fn.call(this);
+ if (!Array.isArray(arr)) arr = [arr];
+ return new MongooseDocumentArray(arr, path, this);
+ });
+};
+
+/*!
+ * Inherits from ArrayType.
+ */
+
+DocumentArray.prototype.__proto__ = ArrayType.prototype;
+
+/**
+ * Performs local validations first, then validations on each embedded doc
+ *
+ * @api private
+ */
+
+DocumentArray.prototype.doValidate = function (array, fn, scope) {
+ var self = this;
+
+ SchemaType.prototype.doValidate.call(this, array, function (err) {
+ if (err) return fn(err);
+
+ var count = array && array.length
+ , error;
+
+ if (!count) return fn();
+
+ // handle sparse arrays, do not use array.forEach which does not
+ // iterate over sparse elements yet reports array.length including
+ // them :(
+
+ for (var i = 0, len = count; i < len; ++i) {
+ // sidestep sparse entries
+ var doc = array[i];
+ if (!doc) {
+ --count || fn();
+ continue;
+ }
+
+ ;(function (i) {
+ doc.validate(function (err) {
+ if (err && !error) {
+ // rewrite the key
+ err.key = self.key + '.' + i + '.' + err.key;
+ return fn(error = err);
+ }
+ --count || fn();
+ });
+ })(i);
+ }
+ }, scope);
+};
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @param {Document} document that triggers the casting
+ * @api private
+ */
+
+DocumentArray.prototype.cast = function (value, doc, init, prev) {
+ var selected
+ , subdoc
+ , i
+
+ if (!Array.isArray(value)) {
+ return this.cast([value], doc, init, prev);
+ }
+
+ if (!(value instanceof MongooseDocumentArray)) {
+ value = new MongooseDocumentArray(value, this.path, doc);
+ }
+
+ i = value.length;
+
+ while (i--) {
+ if (!(value[i] instanceof Subdocument) && value[i]) {
+ if (init) {
+ selected || (selected = scopePaths(this, doc._selected, init));
+ subdoc = new this.casterConstructor(null, value, true, selected);
+ value[i] = subdoc.init(value[i]);
+ } else {
+ if (prev && (subdoc = prev.id(value[i]._id))) {
+ // handle resetting doc with existing id but differing data
+ // doc.array = [{ doc: 'val' }]
+ subdoc.set(value[i]);
+ } else {
+ subdoc = new this.casterConstructor(value[i], value);
+ }
+
+ // if set() is hooked it will have no return value
+ // see gh-746
+ value[i] = subdoc;
+ }
+ }
+ }
+
+ return value;
+}
+
+/*!
+ * Scopes paths selected in a query to this array.
+ * Necessary for proper default application of subdocument values.
+ *
+ * @param {DocumentArray} array - the array to scope `fields` paths
+ * @param {Object|undefined} fields - the root fields selected in the query
+ * @param {Boolean|undefined} init - if we are being created part of a query result
+ */
+
+function scopePaths (array, fields, init) {
+ if (!(init && fields)) return undefined;
+
+ var path = array.path + '.'
+ , keys = Object.keys(fields)
+ , i = keys.length
+ , selected = {}
+ , hasKeys
+ , key
+
+ while (i--) {
+ key = keys[i];
+ if (0 === key.indexOf(path)) {
+ hasKeys || (hasKeys = true);
+ selected[key.substring(path.length)] = fields[key];
+ }
+ }
+
+ return hasKeys && selected || undefined;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = DocumentArray;
diff --git a/test/node_modules/mongoose/lib/schema/index.js b/test/node_modules/mongoose/lib/schema/index.js
new file mode 100644
index 0000000..d1347ed
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/index.js
@@ -0,0 +1,28 @@
+
+/*!
+ * Module exports.
+ */
+
+exports.String = require('./string');
+
+exports.Number = require('./number');
+
+exports.Boolean = require('./boolean');
+
+exports.DocumentArray = require('./documentarray');
+
+exports.Array = require('./array');
+
+exports.Buffer = require('./buffer');
+
+exports.Date = require('./date');
+
+exports.ObjectId = require('./objectid');
+
+exports.Mixed = require('./mixed');
+
+// alias
+
+exports.Oid = exports.ObjectId;
+exports.Object = exports.Mixed;
+exports.Bool = exports.Boolean;
diff --git a/test/node_modules/mongoose/lib/schema/mixed.js b/test/node_modules/mongoose/lib/schema/mixed.js
new file mode 100644
index 0000000..f22ebb9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/mixed.js
@@ -0,0 +1,75 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype');
+
+/**
+ * Mixed SchemaType constructor.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function Mixed (path, options) {
+ // make sure empty array defaults are handled
+ if (options &&
+ options.default &&
+ Array.isArray(options.default) &&
+ 0 === options.default.length) {
+ options.default = Array;
+ }
+
+ SchemaType.call(this, path, options);
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+Mixed.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Required validator
+ *
+ * @api private
+ */
+
+Mixed.prototype.checkRequired = function (val) {
+ return true;
+};
+
+/**
+ * Casts `val` for Mixed.
+ *
+ * _this is a no-op_
+ *
+ * @param {Object} value to cast
+ * @api private
+ */
+
+Mixed.prototype.cast = function (val) {
+ return val;
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $cond
+ * @param {any} [val]
+ * @api private
+ */
+
+Mixed.prototype.castForQuery = function ($cond, val) {
+ if (arguments.length === 2) return val;
+ return $cond;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Mixed;
diff --git a/test/node_modules/mongoose/lib/schema/number.js b/test/node_modules/mongoose/lib/schema/number.js
new file mode 100644
index 0000000..f0282df
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/number.js
@@ -0,0 +1,182 @@
+/*!
+ * Module requirements.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError
+
+/**
+ * Number SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaNumber (key, options) {
+ SchemaType.call(this, key, options, 'Number');
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+SchemaNumber.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Required validator for number
+ *
+ * @api private
+ */
+
+SchemaNumber.prototype.checkRequired = function checkRequired (value) {
+ if (SchemaType._isRef(this, value, true)) {
+ return null != value;
+ } else {
+ return typeof value == 'number' || value instanceof Number;
+ }
+};
+
+/**
+ * Sets a maximum number validator.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ n: { type: Number, min: 10 })
+ * var M = db.model('M', s)
+ * var m = new M({ n: 9 })
+ * m.save(function (err) {
+ * console.error(err) // validator error
+ * m.n = 10;
+ * m.save() // success
+ * })
+ *
+ * @param {Number} value minimum number
+ * @param {String} message
+ * @api public
+ */
+
+SchemaNumber.prototype.min = function (value, message) {
+ if (this.minValidator)
+ this.validators = this.validators.filter(function(v){
+ return v[1] != 'min';
+ });
+ if (value != null)
+ this.validators.push([function(v){
+ return v === null || v >= value;
+ }, 'min']);
+ return this;
+};
+
+/**
+ * Sets a maximum number validator.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ n: { type: Number, max: 10 })
+ * var M = db.model('M', s)
+ * var m = new M({ n: 11 })
+ * m.save(function (err) {
+ * console.error(err) // validator error
+ * m.n = 10;
+ * m.save() // success
+ * })
+ *
+ * @param {Number} maximum number
+ * @param {String} message
+ * @api public
+ */
+
+SchemaNumber.prototype.max = function (value, message) {
+ if (this.maxValidator)
+ this.validators = this.validators.filter(function(v){
+ return v[1] != 'max';
+ });
+ if (value != null)
+ this.validators.push([this.maxValidator = function(v){
+ return v === null || v <= value;
+ }, 'max']);
+ return this;
+};
+
+/**
+ * Casts to number
+ *
+ * @param {Object} value value to cast
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaNumber.prototype.cast = function (value, doc, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
+ if (!isNaN(value)){
+ if (null === value) return value;
+ if ('' === value) return null;
+ if ('string' == typeof value) value = Number(value);
+ if (value instanceof Number) return value
+ if ('number' == typeof value) return value;
+ if (value.toString && !Array.isArray(value) &&
+ value.toString() == Number(value)) {
+ return new Number(value)
+ }
+ }
+
+ throw new CastError('number', value, this.path);
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle (val) {
+ return this.cast(val)
+}
+
+function handleArray (val) {
+ var self = this;
+ return val.map( function (m) {
+ return self.cast(m)
+ });
+}
+
+SchemaNumber.prototype.$conditionalHandlers = {
+ '$lt' : handleSingle
+ , '$lte': handleSingle
+ , '$gt' : handleSingle
+ , '$gte': handleSingle
+ , '$ne' : handleSingle
+ , '$in' : handleArray
+ , '$nin': handleArray
+ , '$mod': handleArray
+ , '$all': handleArray
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaNumber.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with Number.");
+ return handler.call(this, val);
+ } else {
+ val = this.cast($conditional);
+ return val == null ? val : val
+ }
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaNumber;
diff --git a/test/node_modules/mongoose/lib/schema/objectid.js b/test/node_modules/mongoose/lib/schema/objectid.js
new file mode 100644
index 0000000..05762fe
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/objectid.js
@@ -0,0 +1,151 @@
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError
+ , driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'
+ , oid = require('../types/objectid');
+
+
+/**
+ * ObjectId SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function ObjectId (key, options) {
+ SchemaType.call(this, key, options, 'ObjectID');
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+ObjectId.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Check required
+ *
+ * @api private
+ */
+
+ObjectId.prototype.checkRequired = function checkRequired (value) {
+ if (SchemaType._isRef(this, value, true)) {
+ return null != value;
+ } else {
+ return value instanceof oid;
+ }
+};
+
+/**
+ * Casts to ObjectId
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @param {Boolean} init whether this is an initialization cast
+ * @api private
+ */
+
+ObjectId.prototype.cast = function (value, scope, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
+ if (value === null) return value;
+
+ if (value instanceof oid)
+ return value;
+
+ if (value._id && value._id instanceof oid)
+ return value._id;
+
+ if (value.toString) {
+ try {
+ return oid.fromString(value.toString());
+ } catch (err) {
+ throw new CastError('ObjectId', value, this.path);
+ }
+ }
+
+ throw new CastError('ObjectId', value, this.path);
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle (val) {
+ return this.cast(val);
+}
+
+function handleArray (val) {
+ var self = this;
+ return val.map(function (m) {
+ return self.cast(m);
+ });
+}
+
+ObjectId.prototype.$conditionalHandlers = {
+ '$ne': handleSingle
+ , '$in': handleArray
+ , '$nin': handleArray
+ , '$gt': handleSingle
+ , '$lt': handleSingle
+ , '$gte': handleSingle
+ , '$lte': handleSingle
+ , '$all': handleArray
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [val]
+ * @api private
+ */
+
+ObjectId.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with ObjectId.");
+ return handler.call(this, val);
+ } else {
+ return this.cast($conditional);
+ }
+};
+
+/**
+ * Adds an auto-generated ObjectId default if turnOn is true.
+ * @param {Boolean} turnOn auto generated ObjectId defaults
+ * @api private
+ */
+
+ObjectId.prototype.auto = function (turnOn) {
+ if (turnOn) {
+ this.default(defaultId);
+ this.set(resetId)
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function defaultId () {
+ return new oid();
+};
+
+function resetId (v) {
+ this.__id = null;
+ return v;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = ObjectId;
diff --git a/test/node_modules/mongoose/lib/schema/string.js b/test/node_modules/mongoose/lib/schema/string.js
new file mode 100644
index 0000000..d1bef26
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schema/string.js
@@ -0,0 +1,255 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var SchemaType = require('../schematype')
+ , CastError = SchemaType.CastError;
+
+/**
+ * String SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api private
+ */
+
+function SchemaString (key, options) {
+ this.enumValues = [];
+ this.regExp = null;
+ SchemaType.call(this, key, options, 'String');
+};
+
+/*!
+ * Inherits from SchemaType.
+ */
+
+SchemaString.prototype.__proto__ = SchemaType.prototype;
+
+/**
+ * Adds enumeration values and a coinciding validator.
+ *
+ * ####Example:
+ *
+ * var states = 'opening open closing closed'.split(' ')
+ * var s = new Schema({ state: { type: String, enum: states })
+ * var M = db.model('M', s)
+ * var m = new M({ state: 'invalid' })
+ * m.save(function (err) {
+ * console.error(err) // validator error
+ * m.state = 'open'
+ * m.save() // success
+ * })
+ *
+ * @param {String} [args...] enumeration values
+ * @api public
+ */
+
+SchemaString.prototype.enum = function () {
+ var len = arguments.length;
+ if (!len || undefined === arguments[0] || false === arguments[0]) {
+ if (this.enumValidator){
+ this.enumValidator = false;
+ this.validators = this.validators.filter(function(v){
+ return v[1] != 'enum';
+ });
+ }
+ return;
+ }
+
+ for (var i = 0; i < len; i++) {
+ if (undefined !== arguments[i]) {
+ this.enumValues.push(this.cast(arguments[i]));
+ }
+ }
+
+ if (!this.enumValidator) {
+ var values = this.enumValues;
+ this.enumValidator = function(v){
+ return undefined === v || ~values.indexOf(v);
+ };
+ this.validators.push([this.enumValidator, 'enum']);
+ }
+};
+
+/**
+ * Adds a lowercase setter.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ email: { type: String, lowercase: true }})
+ * var M = db.model('M', s);
+ * var m = new M({ email: 'SomeEmail@example.COM' });
+ * console.log(m.email) // someemail@example.com
+ *
+ * @api public
+ */
+
+SchemaString.prototype.lowercase = function () {
+ return this.set(function (v, self) {
+ if ('string' != typeof v) v = self.cast(v)
+ if (v) return v.toLowerCase();
+ return v;
+ });
+};
+
+/**
+ * Adds an uppercase setter.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ caps: { type: String, uppercase: true }})
+ * var M = db.model('M', s);
+ * var m = new M({ caps: 'an example' });
+ * console.log(m.caps) // AN EXAMPLE
+ *
+ * @api public
+ */
+
+SchemaString.prototype.uppercase = function () {
+ return this.set(function (v, self) {
+ if ('string' != typeof v) v = self.cast(v)
+ if (v) return v.toUpperCase();
+ return v;
+ });
+};
+
+/**
+ * Adds a trim setter.
+ *
+ * The string value will be trimmed when set.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ name: { type: String, trim: true }})
+ * var M = db.model('M', s)
+ * var string = ' some name '
+ * console.log(string.length) // 11
+ * var m = new M({ name: string })
+ * console.log(m.name.length) // 9
+ *
+ * @api public
+ */
+
+SchemaString.prototype.trim = function () {
+ return this.set(function (v, self) {
+ if ('string' != typeof v) v = self.cast(v)
+ if (v) return v.trim();
+ return v;
+ });
+};
+
+/**
+ * Sets a regexp validator.
+ *
+ * Any value that does not pass `regExp`.test(val) will fail validation.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ name: { type: String, match: /^a/ }})
+ * var M = db.model('M', s)
+ * var m = new M({ name: 'invalid' })
+ * m.validate(function (err) {
+ * console.error(err) // validation error
+ * m.name = 'apples'
+ * m.validate(function (err) {
+ * assert.ok(err) // success
+ * })
+ * })
+ *
+ * @param {RegExp} regExp regular expression to test against
+ * @api public
+ */
+
+SchemaString.prototype.match = function match (regExp) {
+ this.validators.push([function(v){
+ return null != v && '' !== v
+ ? regExp.test(v)
+ : true
+ }, 'regexp']);
+};
+
+/**
+ * Check required
+ *
+ * @param {String|null|undefined} value
+ * @api private
+ */
+
+SchemaString.prototype.checkRequired = function checkRequired (value) {
+ if (SchemaType._isRef(this, value, true)) {
+ return null != value;
+ } else {
+ return (value instanceof String || typeof value == 'string') && value.length;
+ }
+};
+
+/**
+ * Casts to String
+ *
+ * @api private
+ */
+
+SchemaString.prototype.cast = function (value, scope, init) {
+ if (SchemaType._isRef(this, value, init)) return value;
+ if (value === null) return value;
+ if ('undefined' !== typeof value && value.toString) return value.toString();
+ throw new CastError('string', value, this.path);
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle (val) {
+ return this.castForQuery(val);
+}
+
+function handleArray (val) {
+ var self = this;
+ return val.map(function (m) {
+ return self.castForQuery(m);
+ });
+}
+
+SchemaString.prototype.$conditionalHandlers = {
+ '$ne' : handleSingle
+ , '$in' : handleArray
+ , '$nin': handleArray
+ , '$gt' : handleSingle
+ , '$lt' : handleSingle
+ , '$gte': handleSingle
+ , '$lte': handleSingle
+ , '$all': handleArray
+ , '$regex': handleSingle
+ , '$options': handleSingle
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [val]
+ * @api private
+ */
+
+SchemaString.prototype.castForQuery = function ($conditional, val) {
+ var handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler)
+ throw new Error("Can't use " + $conditional + " with String.");
+ return handler.call(this, val);
+ } else {
+ val = $conditional;
+ if (val instanceof RegExp) return val;
+ return this.cast(val);
+ }
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaString;
diff --git a/test/node_modules/mongoose/lib/schemadefault.js b/test/node_modules/mongoose/lib/schemadefault.js
new file mode 100644
index 0000000..aebcff5
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schemadefault.js
@@ -0,0 +1,34 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var Schema = require('./schema')
+
+/**
+ * Default model for querying the system.profiles collection.
+ *
+ * @property system.profile
+ * @receiver exports
+ * @api private
+ */
+
+exports['system.profile'] = new Schema({
+ ts: Date
+ , info: String // deprecated
+ , millis: Number
+ , op: String
+ , ns: String
+ , query: Schema.Types.Mixed
+ , updateobj: Schema.Types.Mixed
+ , ntoreturn: Number
+ , nreturned: Number
+ , nscanned: Number
+ , responseLength: Number
+ , client: String
+ , user: String
+ , idhack: Boolean
+ , scanAndOrder: Boolean
+ , keyUpdates: Number
+ , cursorid: Number
+}, { noVirtualId: true, noId: true });
diff --git a/test/node_modules/mongoose/lib/schematype.js b/test/node_modules/mongoose/lib/schematype.js
new file mode 100644
index 0000000..9a1edb9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/schematype.js
@@ -0,0 +1,657 @@
+/*!
+ * Module dependencies.
+ */
+
+var utils = require('./utils');
+var CastError = require('./error').CastError;
+var ValidatorError = require('./error').ValidatorError;
+
+/**
+ * SchemaType constructor
+ *
+ * @param {String} path
+ * @param {Object} [options]
+ * @param {String} [instance]
+ * @api public
+ */
+
+function SchemaType (path, options, instance) {
+ this.path = path;
+ this.instance = instance;
+ this.validators = [];
+ this.setters = [];
+ this.getters = [];
+ this.options = options;
+ this._index = null;
+ this.selected;
+
+ for (var i in options) if (this[i] && 'function' == typeof this[i]) {
+ // { unique: true, index: true }
+ if ('index' == i && this._index) continue;
+
+ var opts = Array.isArray(options[i])
+ ? options[i]
+ : [options[i]];
+
+ this[i].apply(this, opts);
+ }
+};
+
+/**
+ * Sets a default value for this SchemaType.
+ *
+ * ####Example:
+ *
+ * var schema = new Schema({ n: { type: Number, default: 10 })
+ * var M = db.model('M', schema)
+ * var m = new M;
+ * console.log(m.n) // 10
+ *
+ * Defaults can be either `functions` which return the value to use as the default or the literal value itself. Either way, the value will be cast based on its schema type before being set during document creation.
+ *
+ * ####Example:
+ *
+ * // values are cast:
+ * var schema = new Schema({ aNumber: Number, default: "4.815162342" })
+ * var M = db.model('M', schema)
+ * var m = new M;
+ * console.log(m.aNumber) // 4.815162342
+ *
+ * // default unique objects for Mixed types:
+ * var schema = new Schema({ mixed: Schema.Types.Mixed });
+ * schema.path('mixed').default(function () {
+ * return {};
+ * });
+ *
+ * // if we don't use a function to return object literals for Mixed defaults,
+ * // each document will receive a reference to the same object literal creating
+ * // a "shared" object instance:
+ * var schema = new Schema({ mixed: Schema.Types.Mixed });
+ * schema.path('mixed').default({});
+ * var M = db.model('M', schema);
+ * var m1 = new M;
+ * m1.mixed.added = 1;
+ * console.log(m1.mixed); // { added: 1 }
+ * var m2 = new M;
+ * console.log(m2.mixed); // { added: 1 }
+ *
+ * @param {Function|any} val the default value
+ * @return {defaultValue}
+ * @api public
+ */
+
+SchemaType.prototype.default = function (val) {
+ if (1 === arguments.length) {
+ this.defaultValue = typeof val === 'function'
+ ? val
+ : this.cast(val);
+ return this;
+ } else if (arguments.length > 1) {
+ this.defaultValue = utils.args(arguments);
+ }
+ return this.defaultValue;
+};
+
+/**
+ * Declares the index options for this schematype.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ name: { type: String, index: true })
+ * var s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
+ * Schema.path('my.path').index(true);
+ * Schema.path('my.date').index({ expires: 60 });
+ * Schema.path('my.path').index({ unique: true, sparse: true });
+ *
+ * ####NOTE:
+ *
+ * _Indexes are created in the background by default. Specify `background: false` to override._
+ *
+ * [Direction doesn't matter for single key indexes](http://www.mongodb.org/display/DOCS/Indexes#Indexes-CompoundKeysIndexes)
+ *
+ * @param {Object|Boolean} options
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.index = function (options) {
+ this._index = options;
+ utils.expires(this._index);
+ return this;
+};
+
+/**
+ * Declares an unique index.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ name: { type: String, unique: true })
+ * Schema.path('name').index({ unique: true });
+ *
+ * _NOTE: violating the constraint returns an `E11000` error from MongoDB when saving, not a Mongoose validation error._
+ *
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.unique = function (bool) {
+ if (!this._index || 'Object' !== this._index.constructor.name) {
+ this._index = {};
+ }
+
+ this._index.unique = bool;
+ return this;
+};
+
+/**
+ * Declares a sparse index.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ name: { type: String, sparse: true })
+ * Schema.path('name').index({ sparse: true });
+ *
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.sparse = function (bool) {
+ if (!this._index || 'Object' !== this._index.constructor.name) {
+ this._index = {};
+ }
+
+ this._index.sparse = bool;
+ return this;
+};
+
+/**
+ * Declares a TTL index (rounded to the nearest second) for _Date_ types only.
+ *
+ * This sets the `expiresAfterSeconds` index option available in MongoDB >= 2.1.2.
+ * This index type is only compatible with Date types.
+ *
+ * ####Example:
+ *
+ * // expire in 24 hours
+ * new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
+ *
+ * `expires` utilizes the `ms` module from [guille](https://github.com/guille/) allowing us to use a friendlier syntax:
+ *
+ * ####Example:
+ *
+ * // expire in 24 hours
+ * new Schema({ createdAt: { type: Date, expires: '24h' }});
+ *
+ * // expire in 1.5 hours
+ * new Schema({ createdAt: { type: Date, expires: '1.5h' }});
+ *
+ * // expire in 7 days
+ * var schema = new Schema({ createdAt: Date });
+ * schema.path('createdAt').expires('7d');
+ *
+ * @param {Number|String} when
+ * @added 3.0.0
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.expires = function (when) {
+ if (!this._index || 'Object' !== this._index.constructor.name) {
+ this._index = {};
+ }
+
+ this._index.expires = when;
+ utils.expires(this._index);
+ return this;
+};
+
+/**
+ * Adds a setter to this schematype.
+ *
+ * ####Example:
+ *
+ * function capitalize (val) {
+ * if ('string' != typeof val) val = '';
+ * return val.charAt(0).toUpperCase() + val.substring(1);
+ * }
+ *
+ * // defining within the schema
+ * var s = new Schema({ name: { type: String, set: capitalize }})
+ *
+ * // or by retreiving its SchemaType
+ * var s = new Schema({ name: String })
+ * s.path('name').set(capitalize)
+ *
+ * Setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.
+ *
+ * Suppose you are implementing user registration for a website. Users provide an email and password, which gets saved to mongodb. The email is a string that you will want to normalize to lower case, in order to avoid one email having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.
+ *
+ * You can set up email lower case normalization easily via a Mongoose setter.
+ *
+ * function toLower (v) {
+ * return v.toLowerCase();
+ * }
+ *
+ * var UserSchema = new Schema({
+ * email: { type: String, set: toLower }
+ * })
+ *
+ * var User = db.model('User', UserSchema)
+ *
+ * var user = new User({email: 'AVENUE@Q.COM'})
+ * console.log(user.email); // 'avenue@q.com'
+ *
+ * // or
+ * var user = new User
+ * user.email = 'Avenue@Q.com'
+ * console.log(user.email) // 'avenue@q.com'
+ *
+ * As you can see above, setters allow you to transform the data before it gets to the raw mongodb document and is set as a value on an actual key.
+ *
+ * _NOTE: we could have also just used the built-in `lowercase: true` SchemaType option instead of defining our own function._
+ *
+ * new Schema({ email: { type: String, lowercase: true }})
+ *
+ * Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.
+ *
+ * function inspector (val, schematype) {
+ * if (schematype.options.required) {
+ * return schematype.path + ' is required';
+ * } else {
+ * return val;
+ * }
+ * }
+ *
+ * var VirusSchema = new Schema({
+ * name: { type: String, required: true, set: inspector },
+ * taxonomy: { type: String, set: inspector }
+ * })
+ *
+ * var Virus = db.model('Virus', VirusSchema);
+ * var v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
+ *
+ * console.log(v.name); // name is required
+ * console.log(v.taxonomy); // Parvovirinae
+ *
+ * @param {Function} fn
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.set = function (fn) {
+ if ('function' != typeof fn)
+ throw new Error('A setter must be a function.');
+ this.setters.push(fn);
+ return this;
+};
+
+/**
+ * Adds a getter to this schematype.
+ *
+ * ####Example:
+ *
+ * function dob (val) {
+ * if (!val) return val;
+ * return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
+ * }
+ *
+ * // defining within the schema
+ * var s = new Schema({ born: { type: Date, get: dob })
+ *
+ * // or by retreiving its SchemaType
+ * var s = new Schema({ born: Date })
+ * s.path('born').get(dob)
+ *
+ * Getters allow you to transform the representation of the data as it travels from the raw mongodb document to the value that you see.
+ *
+ * Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:
+ *
+ * function obfuscate (cc) {
+ * return '****-****-****-' + cc.slice(cc.length-4, cc.length);
+ * }
+ *
+ * var AccountSchema = new Schema({
+ * creditCardNumber: { type: String, get: obfuscate }
+ * });
+ *
+ * var Account = db.model('Account', AccountSchema);
+ *
+ * Account.findById(id, function (err, found) {
+ * console.log(found.creditCardNumber); // '****-****-****-1234'
+ * });
+ *
+ * Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.
+ *
+ * function inspector (val, schematype) {
+ * if (schematype.options.required) {
+ * return schematype.path + ' is required';
+ * } else {
+ * return schematype.path + ' is not';
+ * }
+ * }
+ *
+ * var VirusSchema = new Schema({
+ * name: { type: String, required: true, get: inspector },
+ * taxonomy: { type: String, get: inspector }
+ * })
+ *
+ * var Virus = db.model('Virus', VirusSchema);
+ *
+ * Virus.findById(id, function (err, virus) {
+ * console.log(virus.name); // name is required
+ * console.log(virus.taxonomy); // taxonomy is not
+ * })
+ *
+ * @param {Function} fn
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.get = function (fn) {
+ if ('function' != typeof fn)
+ throw new Error('A getter must be a function.');
+ this.getters.push(fn);
+ return this;
+};
+
+/**
+ * Adds validator(s) for this document path.
+ *
+ * Validators always receive the value to validate as their first argument and must return `Boolean`. Returning false is interpreted as validation failure.
+ *
+ * ####Examples:
+ *
+ * function validator (val) {
+ * return val == 'something';
+ * }
+ *
+ * new Schema({ name: { type: String, validate: validator }});
+ *
+ * // with a custom error message
+ *
+ * var custom = [validator, 'validation failed']
+ * new Schema({ name: { type: String, validate: custom }});
+ *
+ * var many = [
+ * { validator: validator, msg: 'uh oh' }
+ * , { validator: fn, msg: 'failed' }
+ * ]
+ * new Schema({ name: { type: String, validate: many }});
+ *
+ * // or utilizing SchemaType methods directly:
+ *
+ * var schema = new Schema({ name: 'string' });
+ * schema.path('name').validate(validator, 'validation failed');
+ *
+ * ####Asynchronous validation:
+ *
+ * Passing a validator function that receives two arguments tells mongoose that the validator is an asynchronous validator. The second argument is an callback function that must be passed either `true` or `false` when validation is complete.
+ *
+ * schema.path('name').validate(function (value, respond) {
+ * doStuff(value, function () {
+ * ...
+ * respond(false); // validation failed
+ * })
+* }, 'my error type');
+*
+ * You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.
+ *
+ * Validation occurs `pre('save')` or whenever you manually execute [document#validate](#document_Document-validate).
+ *
+ * If validation fails during `pre('save')` and no callback was passed to receive the error, an `error` event will be emitted on your Models associated db [connection](#connection_Connection), passing the validation error object along.
+ *
+ * var conn = mongoose.createConnection(..);
+ * conn.on('error', handleError);
+ *
+ * var Product = conn.model('Product', yourSchema);
+ * var dvd = new Product(..);
+ * dvd.save(); // emits error on the `conn` above
+ *
+ * If you desire handling these errors at the Model level, attach an `error` listener to your Model and the event will instead be emitted there.
+ *
+ * // registering an error listener on the Model lets us handle errors more locally
+ * Product.on('error', handleError);
+ *
+ * @param {RegExp|Function|Object} obj validator
+ * @param {String} [error] optional error message
+ * @api public
+ */
+
+SchemaType.prototype.validate = function (obj, error) {
+ if ('function' == typeof obj || obj && 'RegExp' === obj.constructor.name) {
+ this.validators.push([obj, error]);
+ return this;
+ }
+
+ var i = arguments.length
+ , arg
+
+ while (i--) {
+ arg = arguments[i];
+ if (!(arg && 'Object' == arg.constructor.name)) {
+ var msg = 'Invalid validator. Received (' + typeof arg + ') '
+ + arg
+ + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
+
+ throw new Error(msg);
+ }
+ this.validate(arg.validator, arg.msg);
+ }
+
+ return this;
+};
+
+/**
+ * Adds a required validator to this schematype.
+ *
+ * ####Example:
+ *
+ * var s = new Schema({ born: { type: Date, required: true })
+ * // or
+ * Schema.path('name').required(true);
+ *
+ *
+ * @param {Boolean} required enable/disable the validator
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.required = function (required) {
+ var self = this;
+
+ function __checkRequired (v) {
+ // in here, `this` refers to the validating document.
+ // no validation when this path wasn't selected in the query.
+ if ('isSelected' in this &&
+ !this.isSelected(self.path) &&
+ !this.isModified(self.path)) return true;
+ return self.checkRequired(v);
+ }
+
+ if (false === required) {
+ this.isRequired = false;
+ this.validators = this.validators.filter(function (v) {
+ return v[0].name !== '__checkRequired';
+ });
+ } else {
+ this.isRequired = true;
+ this.validators.push([__checkRequired, 'required']);
+ }
+
+ return this;
+};
+
+/**
+ * Gets the default value
+ *
+ * @param {Object} scope the scope which callback are executed
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaType.prototype.getDefault = function (scope, init) {
+ var ret = 'function' === typeof this.defaultValue
+ ? this.defaultValue.call(scope)
+ : this.defaultValue;
+
+ if (null !== ret && undefined !== ret) {
+ return this.cast(ret, scope, init);
+ } else {
+ return ret;
+ }
+};
+
+/**
+ * Applies setters
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaType.prototype.applySetters = function (value, scope, init, priorVal) {
+ if (SchemaType._isRef(this, value, init)) return value;
+
+ var v = value
+ , setters = this.setters
+ , len = setters.length
+
+ if (!len) {
+ if (null === v || undefined === v) return v;
+ return init
+ ? v // if we just initialized we dont recast
+ : this.cast(v, scope, init, priorVal)
+ }
+
+ while (len--) {
+ v = setters[len].call(scope, v, this);
+ }
+
+ if (null === v || undefined === v) return v;
+
+ // do not cast until all setters are applied #665
+ v = this.cast(v, scope, init, priorVal);
+
+ return v;
+};
+
+/**
+ * Applies getters to a value
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaType.prototype.applyGetters = function (value, scope) {
+ if (SchemaType._isRef(this, value, true)) return value;
+
+ var v = value
+ , getters = this.getters
+ , len = getters.length;
+
+ if (!len) {
+ return v;
+ }
+
+ while (len--) {
+ v = getters[len].call(scope, v, this);
+ }
+
+ return v;
+};
+
+/**
+ * Sets default `select()` behavior for this path.
+ *
+ * Set to `true` if this path should always be included in the results, `false` if it should be excluded by default. This setting can be overridden at the query level.
+ *
+ * ####Example:
+ *
+ * T = db.model('T', new Schema({ x: { type: String, select: true }}));
+ * T.find(..); // field x will always be selected ..
+ * // .. unless overridden;
+ * T.find().select('-x').exec(callback);
+ *
+ * @param {Boolean} val
+ * @api public
+ */
+
+SchemaType.prototype.select = function select (val) {
+ this.selected = !! val;
+}
+
+/**
+ * Performs a validation of `value` using the validators declared for this SchemaType.
+ *
+ * @param {any} value
+ * @param {Function} callback
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaType.prototype.doValidate = function (value, fn, scope) {
+ var err = false
+ , path = this.path
+ , count = this.validators.length;
+
+ if (!count) return fn(null);
+
+ function validate (val, msg) {
+ if (err) return;
+ if (val === undefined || val) {
+ --count || fn(null);
+ } else {
+ fn(err = new ValidatorError(path, msg));
+ }
+ }
+
+ this.validators.forEach(function (v) {
+ var validator = v[0]
+ , message = v[1];
+
+ if (validator instanceof RegExp) {
+ validate(validator.test(value), message);
+ } else if ('function' === typeof validator) {
+ if (2 === validator.length) {
+ validator.call(scope, value, function (val) {
+ validate(val, message);
+ });
+ } else {
+ validate(validator.call(scope, value), message);
+ }
+ }
+ });
+};
+
+/**
+ * Determines if value is a valid Reference.
+ *
+ * @param {SchemaType} self
+ * @param {Object} value
+ * @param {Boolean} init
+ * @return {Boolean}
+ * @api private
+ */
+
+SchemaType._isRef = function (self, value, init) {
+ if (init && self.options && self.options.ref) {
+ if (null == value) return true;
+ if (value._id && value._id.constructor.name === self.instance) return true;
+ }
+
+ return false;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = SchemaType;
+
+exports.CastError = CastError;
+
+exports.ValidatorError = ValidatorError;
diff --git a/test/node_modules/mongoose/lib/statemachine.js b/test/node_modules/mongoose/lib/statemachine.js
new file mode 100644
index 0000000..76005d8
--- /dev/null
+++ b/test/node_modules/mongoose/lib/statemachine.js
@@ -0,0 +1,179 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var utils = require('./utils');
+
+/*!
+ * StateMachine represents a minimal `interface` for the
+ * constructors it builds via StateMachine.ctor(...).
+ *
+ * @api private
+ */
+
+var StateMachine = module.exports = exports = function StateMachine () {
+ this.paths = {};
+ this.states = {};
+}
+
+/*!
+ * StateMachine.ctor('state1', 'state2', ...)
+ * A factory method for subclassing StateMachine.
+ * The arguments are a list of states. For each state,
+ * the constructor's prototype gets state transition
+ * methods named after each state. These transition methods
+ * place their path argument into the given state.
+ *
+ * @param {String} state
+ * @param {String} [state]
+ * @return {Function} subclass constructor
+ * @private
+ */
+
+StateMachine.ctor = function () {
+ var states = utils.args(arguments);
+
+ var ctor = function () {
+ StateMachine.apply(this, arguments);
+ this.stateNames = states;
+
+ var i = states.length
+ , state;
+
+ while (i--) {
+ state = states[i];
+ this.states[state] = {};
+ }
+ };
+
+ ctor.prototype.__proto__ = StateMachine.prototype;
+
+ states.forEach(function (state) {
+ // Changes the `path`'s state to `state`.
+ ctor.prototype[state] = function (path) {
+ this._changeState(path, state);
+ }
+ });
+
+ return ctor;
+};
+
+/*!
+ * This function is wrapped by the state change functions:
+ *
+ * - `require(path)`
+ * - `modify(path)`
+ * - `init(path)`
+ *
+ * @api private
+ */
+
+StateMachine.prototype._changeState = function _changeState (path, nextState) {
+ var prevBucket = this.states[this.paths[path]];
+ if (prevBucket) delete prevBucket[path];
+
+ this.paths[path] = nextState;
+ this.states[nextState][path] = true;
+}
+
+/*!
+ * ignore
+ */
+
+StateMachine.prototype.clear = function clear (state) {
+ var keys = Object.keys(this.states[state])
+ , i = keys.length
+ , path
+
+ while (i--) {
+ path = keys[i];
+ delete this.states[state][path];
+ delete this.paths[path];
+ }
+}
+
+/*!
+ * Checks to see if at least one path is in the states passed in via `arguments`
+ * e.g., this.some('required', 'inited')
+ *
+ * @param {String} state that we want to check for.
+ * @private
+ */
+
+StateMachine.prototype.some = function some () {
+ var self = this;
+ var what = arguments.length ? arguments : this.stateNames;
+ return Array.prototype.some.call(what, function (state) {
+ return Object.keys(self.states[state]).length;
+ });
+}
+
+/*!
+ * This function builds the functions that get assigned to `forEach` and `map`,
+ * since both of those methods share a lot of the same logic.
+ *
+ * @param {String} iterMethod is either 'forEach' or 'map'
+ * @return {Function}
+ * @api private
+ */
+
+StateMachine.prototype._iter = function _iter (iterMethod) {
+ return function () {
+ var numArgs = arguments.length
+ , states = utils.args(arguments, 0, numArgs-1)
+ , callback = arguments[numArgs-1];
+
+ if (!states.length) states = this.stateNames;
+
+ var self = this;
+
+ var paths = states.reduce(function (paths, state) {
+ return paths.concat(Object.keys(self.states[state]));
+ }, []);
+
+ return paths[iterMethod](function (path, i, paths) {
+ return callback(path, i, paths);
+ });
+ };
+}
+
+/*!
+ * Iterates over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @private
+ */
+
+StateMachine.prototype.forEach = function forEach () {
+ this.forEach = this._iter('forEach');
+ return this.forEach.apply(this, arguments);
+}
+
+/*!
+ * Maps over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @return {Array}
+ * @private
+ */
+
+StateMachine.prototype.map = function map () {
+ this.map = this._iter('map');
+ return this.map.apply(this, arguments);
+}
+
diff --git a/test/node_modules/mongoose/lib/types/array.js b/test/node_modules/mongoose/lib/types/array.js
new file mode 100644
index 0000000..294c989
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/array.js
@@ -0,0 +1,598 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var EmbeddedDocument = require('./embedded');
+var Document = require('../document');
+var ObjectId = require('./objectid');
+
+/**
+ * Mongoose Array constructor.
+ *
+ * ####NOTE:
+ *
+ * _Values always have to be passed to the constructor to initialize, otherwise `MongooseArray#push` will mark the array as modified._
+ *
+ * @param {Array} values
+ * @param {String} path
+ * @param {Document} doc parent document
+ * @api private
+ * @inherits Array
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseArray (values, path, doc) {
+ var arr = [];
+ arr.push.apply(arr, values);
+ arr.__proto__ = MongooseArray.prototype;
+
+ arr._atomics = {};
+ arr.validators = [];
+ arr._path = path;
+
+ if (doc) {
+ arr._parent = doc;
+ arr._schema = doc.schema.path(path);
+ }
+
+ return arr;
+};
+
+/*!
+ * Inherit from Array
+ */
+
+MongooseArray.prototype = new Array;
+
+/**
+ * Stores a queue of atomic operations to perform
+ *
+ * @property _atomics
+ * @api private
+ */
+
+MongooseArray.prototype._atomics;
+
+/**
+ * Parent owner document
+ *
+ * @property _parent
+ * @api private
+ */
+
+MongooseArray.prototype._parent;
+
+/**
+ * Casts a member based on this arrays schema.
+ *
+ * @param {any} value
+ * @return value the casted value
+ * @api private
+ */
+
+MongooseArray.prototype._cast = function (value) {
+ var cast = this._schema.caster.cast
+ , doc = this._parent;
+
+ return cast.call(null, value, doc);
+};
+
+/**
+ * Marks this array as modified.
+ *
+ * If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)
+ *
+ * @param {EmbeddedDocument} embeddedDoc the embedded doc that invoked this method on the Array
+ * @param {String} embeddedPath the path which changed in the embeddedDoc
+ * @api private
+ */
+
+MongooseArray.prototype._markModified = function (elem, embeddedPath) {
+ var parent = this._parent
+ , dirtyPath;
+
+ if (parent) {
+ dirtyPath = this._path;
+
+ if (arguments.length) {
+ if (null != embeddedPath) {
+ // an embedded doc bubbled up the change
+ dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
+ } else {
+ // directly set an index
+ dirtyPath = dirtyPath + '.' + elem;
+ }
+
+ }
+ parent.markModified(dirtyPath);
+ }
+
+ return this;
+};
+
+/**
+ * Register an atomic operation with the parent.
+ *
+ * @param {Array} op operation
+ * @param {any} val
+ * @api private
+ */
+
+MongooseArray.prototype._registerAtomic = function (op, val) {
+ if ('$set' == op) {
+ // $set takes precedence over all other ops.
+ // mark entire array modified.
+ this._atomics = { $set: val };
+ return this;
+ }
+
+ var atomics = this._atomics;
+
+ // reset pop/shift after save
+ if ('$pop' == op && !('$pop' in atomics)) {
+ var self = this;
+ this._parent.once('save', function () {
+ self._popped = self._shifted = null;
+ });
+ }
+
+ // check for impossible $atomic combos (Mongo denies more than one
+ // $atomic op on a single path
+ if (this._atomics.$set ||
+ Object.keys(atomics).length && !(op in atomics)) {
+ // a different op was previously registered.
+ // save the entire thing.
+ this._atomics = { $set: this };
+ return this;
+ }
+
+ if (op === '$pullAll' || op === '$pushAll' || op === '$addToSet') {
+ atomics[op] || (atomics[op] = []);
+ atomics[op] = atomics[op].concat(val);
+ } else if (op === '$pullDocs') {
+ var pullOp = atomics['$pull'] || (atomics['$pull'] = {})
+ , selector = pullOp['_id'] || (pullOp['_id'] = {'$in' : [] });
+ selector['$in'] = selector['$in'].concat(val);
+ } else {
+ atomics[op] = val;
+ }
+
+ return this;
+};
+
+/**
+ * Returns the number of pending atomic operations to send to the db for this array.
+ *
+ * @api private
+ * @return {Number}
+ */
+
+MongooseArray.prototype.hasAtomics = function hasAtomics () {
+ if (!(this._atomics && 'Object' === this._atomics.constructor.name)) {
+ return 0;
+ }
+
+ return Object.keys(this._atomics).length;
+}
+
+/**
+ * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
+ *
+ * @param {Object} [args...]
+ * @api public
+ */
+
+MongooseArray.prototype.push = function () {
+ var values = [].map.call(arguments, this._cast, this)
+ , ret = [].push.apply(this, values);
+
+ // $pushAll might be fibbed (could be $push). But it makes it easier to
+ // handle what could have been $push, $pushAll combos
+ this._registerAtomic('$pushAll', values);
+ this._markModified();
+ return ret;
+};
+
+/**
+ * Pushes items to the array non-atomically.
+ *
+ * ####NOTE:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @param {any} [args...]
+ * @api public
+ */
+
+MongooseArray.prototype.nonAtomicPush = function () {
+ var values = [].map.call(arguments, this._cast, this)
+ , ret = [].push.apply(this, values);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+};
+
+/**
+ * Pops the array atomically at most one time per document `save()`.
+ *
+ * #### NOTE:
+ *
+ * _Calling this mulitple times on an array before saving sends the same command as calling it once._
+ * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
+ *
+ * doc.array = [1,2,3];
+ *
+ * var popped = doc.array.$pop();
+ * console.log(popped); // 3
+ * console.log(doc.array); // [1,2]
+ *
+ * // no affect
+ * popped = doc.array.$pop();
+ * console.log(doc.array); // [1,2]
+ *
+ * doc.save(function (err) {
+ * if (err) return handleError(err);
+ *
+ * // we saved, now $pop works again
+ * popped = doc.array.$pop();
+ * console.log(popped); // 2
+ * console.log(doc.array); // [1]
+ * })
+ *
+ * @api public
+ * @method $pop
+ * @memberOf MongooseArray
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
+ */
+
+MongooseArray.prototype.$pop = function () {
+ this._registerAtomic('$pop', 1);
+ this._markModified();
+
+ // only allow popping once
+ if (this._popped) return;
+ this._popped = true;
+
+ return [].pop.call(this);
+};
+
+/**
+ * Wraps [`Array#pop`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @see MongooseArray#$pop #types_array_MongooseArray-%24pop
+ * @api public
+ */
+
+MongooseArray.prototype.pop = function () {
+ var ret = [].pop.call(this);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+};
+
+/**
+ * Atomically shifts the array at most one time per document `save()`.
+ *
+ * ####NOTE:
+ *
+ * _Calling this mulitple times on an array before saving sends the same command as calling it once._
+ * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
+ *
+ * doc.array = [1,2,3];
+ *
+ * var shifted = doc.array.$shift();
+ * console.log(shifted); // 1
+ * console.log(doc.array); // [2,3]
+ *
+ * // no affect
+ * shifted = doc.array.$shift();
+ * console.log(doc.array); // [2,3]
+ *
+ * doc.save(function (err) {
+ * if (err) return handleError(err);
+ *
+ * // we saved, now $shift works again
+ * shifted = doc.array.$shift();
+ * console.log(shifted ); // 2
+ * console.log(doc.array); // [3]
+ * })
+ *
+ * @api public
+ * @memberOf MongooseArray
+ * @method $shift
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
+ */
+
+MongooseArray.prototype.$shift = function $shift () {
+ this._registerAtomic('$pop', -1);
+ this._markModified();
+
+ // only allow shifting once
+ if (this._shifted) return;
+ this._shifted = true;
+
+ return [].shift.call(this);
+};
+
+/**
+ * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
+ *
+ * ####Example:
+ *
+ * doc.array = [2,3];
+ * var res = doc.array.shift();
+ * console.log(res) // 2
+ * console.log(doc.array) // [3]
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ */
+
+MongooseArray.prototype.shift = function () {
+ var ret = [].shift.call(this);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+};
+
+/**
+ * Removes items from an array atomically
+ *
+ * ####Examples:
+ *
+ * doc.array.remove(ObjectId)
+ * doc.array.remove('tag 1', 'tag 2')
+ *
+ * @param {Object} [args...] values to remove
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
+ * @api public
+ */
+
+MongooseArray.prototype.remove = function () {
+ var args = [].map.call(arguments, this._cast, this);
+ if (args.length == 1)
+ this.pull(args[0]);
+ else
+ this.pull.apply(this, args);
+ return args;
+};
+
+/**
+ * Pulls items from the array atomically.
+ *
+ * @param {any} [args...]
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
+ * @api public
+ */
+
+MongooseArray.prototype.pull = function () {
+ var values = [].map.call(arguments, this._cast, this)
+ , cur = this._parent.get(this._path)
+ , i = cur.length
+ , mem;
+
+ while (i--) {
+ mem = cur[i];
+ if (mem instanceof EmbeddedDocument) {
+ if (values.some(function (v) { return v.equals(mem); } )) {
+ [].splice.call(cur, i, 1);
+ }
+ } else if (~cur.indexOf.call(values, mem)) {
+ [].splice.call(cur, i, 1);
+ }
+ }
+
+ if (values[0] instanceof EmbeddedDocument) {
+ this._registerAtomic('$pullDocs', values.map( function (v) { return v._id; } ));
+ } else {
+ this._registerAtomic('$pullAll', values);
+ }
+
+ this._markModified();
+ return this;
+};
+
+/**
+ * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ */
+
+MongooseArray.prototype.splice = function splice () {
+ var ret, vals, i;
+
+ if (arguments.length) {
+ vals = [];
+ for (i = 0; i < arguments.length; ++i) {
+ vals[i] = i < 2
+ ? arguments[i]
+ : this._cast(arguments[i]);
+ }
+ ret = [].splice.apply(this, vals);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ }
+
+ return ret;
+}
+
+/**
+ * Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ */
+
+MongooseArray.prototype.unshift = function () {
+ var values = [].map.call(arguments, this._cast, this);
+ [].unshift.apply(this, values);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return this.length;
+};
+
+/**
+ * Wraps [`Array#sort`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort) with proper change tracking.
+ *
+ * ####NOTE:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ */
+
+MongooseArray.prototype.sort = function () {
+ var ret = [].sort.apply(this, arguments);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+}
+
+/**
+ * Adds values to the array if not already present.
+ *
+ * ####Example:
+ *
+ * console.log(doc.array) // [2,3,4]
+ * var added = doc.array.addToSet(4,5);
+ * console.log(doc.array) // [2,3,4,5]
+ * console.log(added) // [5]
+ *
+ * @param {any} [args...]
+ * @return {Array} the values that were added
+ * @api public
+ */
+
+MongooseArray.prototype.addToSet = function addToSet () {
+ var values = [].map.call(arguments, this._cast, this)
+ , added = []
+ , type = values[0] instanceof EmbeddedDocument ? 'doc' :
+ values[0] instanceof Date ? 'date' :
+ '';
+
+ values.forEach(function (v) {
+ var found;
+ switch (type) {
+ case 'doc':
+ found = this.some(function(doc){ return doc.equals(v) });
+ break;
+ case 'date':
+ var val = +v;
+ found = this.some(function(d){ return +d === val });
+ break;
+ default:
+ found = ~this.indexOf(v);
+ }
+
+ if (!found) {
+ [].push.call(this, v);
+ this._registerAtomic('$addToSet', v);
+ this._markModified();
+ [].push.call(added, v);
+ }
+ }, this);
+
+ return added;
+};
+
+/**
+ * Sets the casted `val` at index `i` and marks the array modified.
+ *
+ * ####Example:
+ *
+ * // given documents based on the following
+ * var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
+ *
+ * var doc = new Doc({ array: [2,3,4] })
+ *
+ * console.log(doc.array) // [2,3,4]
+ *
+ * doc.array.set(1,"5");
+ * console.log(doc.array); // [2,5,4] // properly cast to number
+ * doc.save() // the change is saved
+ *
+ * // VS not using array#set
+ * doc.array[1] = "5";
+ * console.log(doc.array); // [2,"5",4] // no casting
+ * doc.save() // change is not saved
+ *
+ * @return {Array} this
+ * @api public
+ */
+
+MongooseArray.prototype.set = function set (i, val) {
+ this[i] = this._cast(val);
+ this._markModified(i);
+ return this;
+}
+
+/**
+ * Returns a native js Array.
+ *
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ */
+
+MongooseArray.prototype.toObject = function (options) {
+ if (options && options.depopulate && this[0] instanceof Document) {
+ return this.map(function (doc) {
+ return doc._id;
+ });
+ }
+
+ // return this.slice()?
+ return this.map(function (doc) {
+ return doc;
+ });
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ */
+
+MongooseArray.prototype.inspect = function () {
+ return '[' + this.map(function (doc) {
+ return ' ' + doc;
+ }) + ' ]';
+};
+
+/**
+ * Return the index of `obj` or `-1` if not found.
+ *
+ * @param {Object} obj the item to look for
+ * @return {Number}
+ * @api public
+ */
+
+MongooseArray.prototype.indexOf = function indexOf (obj) {
+ if (obj instanceof ObjectId) obj = obj.toString();
+ for (var i = 0, len = this.length; i < len; ++i) {
+ if (obj == this[i])
+ return i;
+ }
+ return -1;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = MongooseArray;
diff --git a/test/node_modules/mongoose/lib/types/buffer.js b/test/node_modules/mongoose/lib/types/buffer.js
new file mode 100644
index 0000000..45c69a9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/buffer.js
@@ -0,0 +1,185 @@
+
+/*!
+ * Access driver.
+ */
+
+var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';
+
+/*!
+ * Module dependencies.
+ */
+
+var Binary = require(driver + '/binary');
+
+/**
+ * Mongoose Buffer constructor.
+ *
+ * Values always have to be passed to the constructor to initialize.
+ *
+ * @param {Buffer} value
+ * @param {String} encode
+ * @param {Number} offset
+ * @api private
+ * @inherits Buffer
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseBuffer (value, encode, offset) {
+ var length = arguments.length;
+ var val;
+
+ if (0 === length || null === arguments[0] || undefined === arguments[0]) {
+ val = 0;
+ } else {
+ val = value;
+ }
+
+ var encoding;
+ var path;
+ var doc;
+
+ if (Array.isArray(encode)) {
+ // internal casting
+ path = encode[0];
+ doc = encode[1];
+ } else {
+ encoding = encode;
+ }
+
+ var buf = new Buffer(val, encoding, offset);
+ buf.__proto__ = MongooseBuffer.prototype;
+
+ // make sure these internal props don't show up in Object.keys()
+ Object.defineProperties(buf, {
+ validators: { value: [] }
+ , _path: { value: path }
+ , _parent: { value: doc }
+ });
+
+ if (doc && "string" === typeof path) {
+ Object.defineProperty(buf, '_schema', {
+ value: doc.schema.path(path)
+ });
+ }
+
+ return buf;
+};
+
+/*!
+ * Inherit from Buffer.
+ */
+
+MongooseBuffer.prototype = new Buffer(0);
+
+/**
+ * Parent owner document
+ *
+ * @api private
+ * @property _parent
+ */
+
+MongooseBuffer.prototype._parent;
+
+/**
+ * Marks this buffer as modified.
+ *
+ * @api private
+ */
+
+MongooseBuffer.prototype._markModified = function () {
+ var parent = this._parent;
+
+ if (parent) {
+ parent.markModified(this._path);
+ }
+ return this;
+};
+
+/**
+* Writes the buffer.
+*/
+
+MongooseBuffer.prototype.write = function () {
+ var written = Buffer.prototype.write.apply(this, arguments);
+
+ if (written > 0) {
+ this._markModified();
+ }
+
+ return written;
+};
+
+/**
+ * Copies the buffer.
+ *
+ * ####Note:
+ *
+ * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this.
+ *
+ * @return {MongooseBuffer}
+ * @param {Buffer} target
+ */
+
+MongooseBuffer.prototype.copy = function (target) {
+ var ret = Buffer.prototype.copy.apply(this, arguments);
+
+ if (target instanceof MongooseBuffer) {
+ target._markModified();
+ }
+
+ return ret;
+};
+
+/*!
+ * Compile other Buffer methods marking this buffer as modified.
+ */
+
+;(
+// node < 0.5
+'writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
+'writeFloat writeDouble fill ' +
+'utf8Write binaryWrite asciiWrite set ' +
+
+// node >= 0.5
+'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
+'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' +
+'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE'
+).split(' ').forEach(function (method) {
+ if (!Buffer.prototype[method]) return;
+ MongooseBuffer.prototype[method] = new Function(
+ 'var ret = Buffer.prototype.'+method+'.apply(this, arguments);' +
+ 'this._markModified();' +
+ 'return ret;'
+ )
+});
+
+/**
+ * Converts this buffer to its Binary type representation.
+ *
+ * ####SubTypes:
+ *
+ * - 0x00: Binary/Generic
+ * - 0x01: Function
+ * - 0x02: Binary (Deprecated, 0x00 is new default)
+ * - 0x03: UUID
+ * - 0x04: MD5
+ * - 0x80: User Defined
+ *
+ * @see http://bsonspec.org/#/specification
+ * @param {Hex} [subtype]
+ * @return {Binary}
+ * @api public
+ */
+
+MongooseBuffer.prototype.toObject = function (subtype) {
+ subtype = typeof subtype !== 'undefined' ? subtype : 0x00
+ return new Binary(this, subtype);
+};
+
+/*!
+ * Module exports.
+ */
+
+MongooseBuffer.Binary = Binary;
+
+module.exports = MongooseBuffer;
diff --git a/test/node_modules/mongoose/lib/types/documentarray.js b/test/node_modules/mongoose/lib/types/documentarray.js
new file mode 100644
index 0000000..09e6be1
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/documentarray.js
@@ -0,0 +1,171 @@
+
+/*!
+ * Module dependencies.
+ */
+
+var MongooseArray = require('./array')
+ , driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'
+ , ObjectId = require(driver + '/objectid')
+ , ObjectIdSchema = require('../schema/objectid')
+ , util = require('util')
+
+/**
+ * DocumentArray constructor
+ *
+ * @param {Array} values
+ * @param {String} path the path to this array
+ * @param {Document} doc parent document
+ * @api private
+ * @return {MongooseDocumentArray}
+ * @inherits MongooseArray
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseDocumentArray (values, path, doc) {
+ var arr = [];
+
+ // Values always have to be passed to the constructor to initialize, since
+ // otherwise MongooseArray#push will mark the array as modified to the parent.
+ arr.push.apply(arr, values);
+ arr.__proto__ = MongooseDocumentArray.prototype;
+
+ arr._atomics = {};
+ arr.validators = [];
+ arr._path = path;
+
+ if (doc) {
+ arr._parent = doc;
+ arr._schema = doc.schema.path(path);
+ doc.on('save', arr.notify('save'));
+ doc.on('isNew', arr.notify('isNew'));
+ }
+
+ return arr;
+};
+
+/*!
+ * Inherits from MongooseArray
+ */
+
+MongooseDocumentArray.prototype.__proto__ = MongooseArray.prototype;
+
+/**
+ * Overrides MongooseArray#cast
+ *
+ * @api private
+ */
+
+MongooseDocumentArray.prototype._cast = function (value) {
+ if (value instanceof this._schema.casterConstructor)
+ return value;
+
+ return new this._schema.casterConstructor(value, this);
+};
+
+/**
+ * Searches array items for the first document with a matching id.
+ *
+ * ####Example:
+ *
+ * var embeddedDoc = m.array.id(some_id);
+ *
+ * @return {EmbeddedDocument|null} the subdocuent or null if not found.
+ * @param {ObjectId|String|Number|Buffer} id
+ * @api public
+ */
+
+MongooseDocumentArray.prototype.id = function (id) {
+ var casted
+ , _id;
+
+ try {
+ casted = ObjectId.toString(ObjectIdSchema.prototype.cast.call({}, id));
+ } catch (e) {
+ casted = null;
+ }
+
+ for (var i = 0, l = this.length; i < l; i++) {
+ _id = this[i].get('_id');
+ if (!(_id instanceof ObjectId)) {
+ if (String(id) == _id)
+ return this[i];
+ } else {
+ if (casted == _id)
+ return this[i];
+ }
+ }
+
+ return null;
+};
+
+/**
+ * Returns a native js Array of plain js objects
+ *
+ * ####NOTE:
+ *
+ * _Each sub-document is converted to a plain object by calling its `#toObject` method._
+ *
+ * @return {Array}
+ * @api public
+ */
+
+MongooseDocumentArray.prototype.toObject = function () {
+ return this.map(function (doc) {
+ return doc && doc.toObject() || null;
+ });
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ */
+
+MongooseDocumentArray.prototype.inspect = function () {
+ return '[' + this.map(function (doc) {
+ if (doc) {
+ return doc.inspect
+ ? doc.inspect()
+ : util.inspect(doc)
+ }
+ return 'null'
+ }).join('\n') + ']';
+};
+
+/**
+ * Creates a subdocument casted to this schema.
+ *
+ * This is the same subdocument constructor used for casting.
+ *
+ * @param {Object} obj the value to cast to this arrays SubDocument schema
+ * @api public
+ */
+
+MongooseDocumentArray.prototype.create = function (obj) {
+ return new this._schema.casterConstructor(obj);
+}
+
+/**
+ * Creates a fn that notifies all child docs of `event`.
+ *
+ * @param {String} event
+ * @return {Function}
+ * @api private
+ */
+
+MongooseDocumentArray.prototype.notify = function notify (event) {
+ var self = this;
+ return function notify (val) {
+ var i = self.length;
+ while (i--) {
+ if (!self[i]) continue;
+ self[i].emit(event, val);
+ }
+ }
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = MongooseDocumentArray;
diff --git a/test/node_modules/mongoose/lib/types/embedded.js b/test/node_modules/mongoose/lib/types/embedded.js
new file mode 100644
index 0000000..3ebc842
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/embedded.js
@@ -0,0 +1,199 @@
+/*!
+ * Module dependencies.
+ */
+
+var Document = require('../document')
+ , inspect = require('util').inspect;
+
+/**
+ * EmbeddedDocument constructor.
+ *
+ * @param {Object} obj js object returned from the db
+ * @param {MongooseDocumentArray} parentArr the parent array of this document
+ * @param {Boolean} skipId
+ * @inherits Document
+ * @api private
+ */
+
+function EmbeddedDocument (obj, parentArr, skipId, fields) {
+ if (parentArr) {
+ this.__parentArray = parentArr;
+ this.__parent = parentArr._parent;
+ } else {
+ this.__parentArray = undefined;
+ this.__parent = undefined;
+ }
+
+ Document.call(this, obj, fields, skipId);
+
+ var self = this;
+ this.on('isNew', function (val) {
+ self.isNew = val;
+ });
+};
+
+/*!
+ * Inherit from Document
+ */
+
+EmbeddedDocument.prototype.__proto__ = Document.prototype;
+
+/**
+ * Marks the embedded doc modified.
+ *
+ * ####Example:
+ *
+ * var doc = blogpost.comments.id(hexstring);
+ * doc.mixed.type = 'changed';
+ * doc.markModified('mixed.type');
+ *
+ * @param {String} path the path which changed
+ * @api public
+ */
+
+EmbeddedDocument.prototype.markModified = function (path) {
+ if (!this.__parentArray) return;
+
+ this._activePaths.modify(path);
+
+ if (this.isNew) {
+ // Mark the WHOLE parent array as modified
+ // if this is a new document (i.e., we are initializing
+ // a document),
+ this.__parentArray._markModified();
+ } else
+ this.__parentArray._markModified(this, path);
+};
+
+/**
+ * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3)
+ *
+ * ####NOTE:
+ *
+ * _This is a no-op. Does not actually save the doc to the db._
+ *
+ * @param {Function} [fn]
+ * @return {EmbeddedDocument} this
+ * @api private
+ */
+
+EmbeddedDocument.prototype.save = function(fn) {
+ if (fn)
+ fn(null);
+ return this;
+};
+
+/**
+ * Removes the subdocument from its parent array.
+ *
+ * @param {Function} [fn]
+ * @api public
+ */
+
+EmbeddedDocument.prototype.remove = function (fn) {
+ if (!this.__parentArray) return this;
+
+ var _id;
+ if (!this.willRemove) {
+ _id = this._doc._id;
+ if (!_id) {
+ throw new Error('For your own good, Mongoose does not know ' +
+ 'how to remove an EmbeddedDocument that has no _id');
+ }
+ this.__parentArray.pull({ _id: _id });
+ this.willRemove = true;
+ }
+
+ if (fn)
+ fn(null);
+
+ return this;
+};
+
+/**
+ * Override #update method of parent documents.
+ * @api private
+ */
+
+EmbeddedDocument.prototype.update = function () {
+ throw new Error('The #update method is not available on EmbeddedDocuments');
+}
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.inspect = function () {
+ return inspect(this.toObject());
+};
+
+/**
+ * Marks a path as invalid, causing validation to fail.
+ *
+ * @param {String} path the field to invalidate
+ * @param {String|Error} err error which states the reason `path` was invalid
+ * @return {Boolean}
+ * @api public
+ */
+
+EmbeddedDocument.prototype.invalidate = function (path, err, first) {
+ if (!this.__parent) return false;
+ var index = this.__parentArray.indexOf(this);
+ var parentPath = this.__parentArray._path;
+ var fullPath = [parentPath, index, path].join('.');
+ this.__parent.invalidate(fullPath, err);
+ if (first)
+ this._validationError = ownerDocument(this)._validationError;
+ return true;
+}
+
+/**
+ * Returns the top level document of this sub-document.
+ *
+ * @return {Document}
+ */
+
+EmbeddedDocument.prototype.ownerDocument = function () {
+ return ownerDocument(this);
+}
+
+/*!
+ * Returns the top level document of this sub-document.
+ *
+ * @return {Document}
+ */
+
+function ownerDocument (self) {
+ var parent = self.__parent;
+ while (parent.__parent)
+ parent = parent.__parent;
+ return parent;
+}
+
+/**
+ * Returns this sub-documents parent document.
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.parent = function () {
+ return this.__parent;
+}
+
+/**
+ * Returns this sub-documents parent array.
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.parentArray = function () {
+ return this.__parentArray;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = EmbeddedDocument;
diff --git a/test/node_modules/mongoose/lib/types/index.js b/test/node_modules/mongoose/lib/types/index.js
new file mode 100644
index 0000000..e6a9901
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/index.js
@@ -0,0 +1,13 @@
+
+/*!
+ * Module exports.
+ */
+
+exports.Array = require('./array');
+exports.Buffer = require('./buffer');
+
+exports.Document = // @deprecate
+exports.Embedded = require('./embedded');
+
+exports.DocumentArray = require('./documentarray');
+exports.ObjectId = require('./objectid');
diff --git a/test/node_modules/mongoose/lib/types/objectid.js b/test/node_modules/mongoose/lib/types/objectid.js
new file mode 100644
index 0000000..44ad43f
--- /dev/null
+++ b/test/node_modules/mongoose/lib/types/objectid.js
@@ -0,0 +1,43 @@
+
+/*!
+ * Access driver.
+ */
+
+var driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native';
+
+/**
+ * ObjectId type constructor
+ *
+ * ####Example
+ *
+ * var id = new mongoose.Types.ObjectId;
+ *
+ * @constructor ObjectId
+ */
+
+var ObjectId = require(driver + '/objectid');
+module.exports = ObjectId;
+
+/**
+ * Creates an ObjectId from `str`
+ *
+ * @param {ObjectId|HexString} str
+ * @static fromString
+ * @receiver ObjectId
+ * @return {ObjectId}
+ * @api private
+ */
+
+ObjectId.fromString;
+
+/**
+ * Converts `oid` to a string.
+ *
+ * @param {ObjectId} oid ObjectId instance
+ * @static toString
+ * @receiver ObjectId
+ * @return {String}
+ * @api private
+ */
+
+ObjectId.toString;
diff --git a/test/node_modules/mongoose/lib/utils.js b/test/node_modules/mongoose/lib/utils.js
new file mode 100644
index 0000000..b9492c9
--- /dev/null
+++ b/test/node_modules/mongoose/lib/utils.js
@@ -0,0 +1,506 @@
+/*!
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+ , ReadPref = require('mongodb').ReadPreference
+ , ObjectId = require('./types/objectid')
+ , ms = require('ms')
+ , sliced = require('sliced')
+ , MongooseBuffer
+ , MongooseArray
+ , Document
+
+/**
+ * Produces a collection name from model `name`.
+ *
+ * @param {String} name a model name
+ * @return {String} a collection name
+ * @api private
+ */
+
+exports.toCollectionName = function (name) {
+ if ('system.profile' === name) return name;
+ if ('system.indexes' === name) return name;
+ return pluralize(name.toLowerCase());
+};
+
+/**
+ * Pluralization rules.
+ *
+ * These rules are applied while processing the argument to `toCollectionName`.
+ */
+
+exports.pluralization = [
+ [/(m)an$/gi, '$1en'],
+ [/(pe)rson$/gi, '$1ople'],
+ [/(child)$/gi, '$1ren'],
+ [/^(ox)$/gi, '$1en'],
+ [/(ax|test)is$/gi, '$1es'],
+ [/(octop|vir)us$/gi, '$1i'],
+ [/(alias|status)$/gi, '$1es'],
+ [/(bu)s$/gi, '$1ses'],
+ [/(buffal|tomat|potat)o$/gi, '$1oes'],
+ [/([ti])um$/gi, '$1a'],
+ [/sis$/gi, 'ses'],
+ [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
+ [/(hive)$/gi, '$1s'],
+ [/([^aeiouy]|qu)y$/gi, '$1ies'],
+ [/(x|ch|ss|sh)$/gi, '$1es'],
+ [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
+ [/([m|l])ouse$/gi, '$1ice'],
+ [/(quiz)$/gi, '$1zes'],
+ [/s$/gi, 's'],
+ [/$/gi, 's']
+];
+var rules = exports.pluralization;
+
+/**
+ * Uncountable words.
+ *
+ * These words are applied while processing the argument to `toCollectionName`.
+ */
+
+exports.uncountables = [
+ 'advice',
+ 'energy',
+ 'excretion',
+ 'digestion',
+ 'cooperation',
+ 'health',
+ 'justice',
+ 'labour',
+ 'machinery',
+ 'equipment',
+ 'information',
+ 'pollution',
+ 'sewage',
+ 'paper',
+ 'money',
+ 'species',
+ 'series',
+ 'rain',
+ 'rice',
+ 'fish',
+ 'sheep',
+ 'moose',
+ 'deer',
+ 'news',
+ 'expertise',
+ 'status',
+ 'media'
+];
+var uncountables = exports.uncountables;
+
+/*!
+ * Pluralize function.
+ *
+ * @author TJ Holowaychuk (extracted from _ext.js_)
+ * @param {String} string to pluralize
+ * @api private
+ */
+
+function pluralize (str) {
+ var rule, found;
+ if (!~uncountables.indexOf(str.toLowerCase())){
+ found = rules.filter(function(rule){
+ return str.match(rule[0]);
+ });
+ if (found[0]) return str.replace(found[0][0], found[0][1]);
+ }
+ return str;
+};
+
+/*!
+ * Add `once` to EventEmitter if absent
+ *
+ * @param {String} event name
+ * @param {Function} listener
+ * @api private
+ */
+
+var Events = EventEmitter;
+
+if (!('once' in EventEmitter.prototype)){
+
+ Events = function () {
+ EventEmitter.apply(this, arguments);
+ };
+
+ /*!
+ * Inherit from EventEmitter.
+ */
+
+ Events.prototype.__proto__ = EventEmitter.prototype;
+
+ /*!
+ * Add `once`.
+ */
+
+ Events.prototype.once = function (type, listener) {
+ var self = this;
+ self.on(type, function g(){
+ self.removeListener(type, g);
+ listener.apply(this, arguments);
+ });
+ };
+}
+exports.EventEmitter = Events;
+
+/**
+ * Determines if `a` and `b` are deep equal.
+ *
+ * Modified from node/lib/assert.js
+ *
+ * @param {any} a a value to compare to `b`
+ * @param {any} b a value to compare to `a`
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.deepEqual = function deepEqual (a, b) {
+ if (a === b) return true;
+
+ if (a instanceof Date && b instanceof Date)
+ return a.getTime() === b.getTime();
+
+ if (a instanceof ObjectId && b instanceof ObjectId) {
+ return a.toString() === b.toString();
+ }
+
+ if (typeof a !== 'object' && typeof b !== 'object')
+ return a == b;
+
+ if (a === null || b === null || a === undefined || b === undefined)
+ return false
+
+ if (a.prototype !== b.prototype) return false;
+
+ // Handle MongooseNumbers
+ if (a instanceof Number && b instanceof Number) {
+ return a.valueOf() === b.valueOf();
+ }
+
+ if (Buffer.isBuffer(a)) {
+ if (!Buffer.isBuffer(b)) return false;
+ if (a.length !== b.length) return false;
+ for (var i = 0, len = a.length; i < len; ++i) {
+ if (a[i] !== b[i]) return false;
+ }
+ return true;
+ }
+
+ if (isMongooseObject(a)) a = a.toObject();
+ if (isMongooseObject(b)) b = b.toObject();
+
+ try {
+ var ka = Object.keys(a),
+ kb = Object.keys(b),
+ key, i;
+ } catch (e) {//happens when one is a string literal and the other isn't
+ return false;
+ }
+
+ // having the same number of owned properties (keys incorporates
+ // hasOwnProperty)
+ if (ka.length != kb.length)
+ return false;
+
+ //the same set of keys (although not necessarily the same order),
+ ka.sort();
+ kb.sort();
+
+ //~~~cheap key test
+ for (i = ka.length - 1; i >= 0; i--) {
+ if (ka[i] != kb[i])
+ return false;
+ }
+
+ //equivalent values for every corresponding key, and
+ //~~~possibly expensive deep test
+ for (i = ka.length - 1; i >= 0; i--) {
+ key = ka[i];
+ if (!deepEqual(a[key], b[key])) return false;
+ }
+
+ return true;
+};
+
+/**
+ * Object clone with Mongoose natives support.
+ *
+ * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
+ *
+ * Functions are never cloned.
+ *
+ * @param {Object} obj the object to clone
+ * @param {Object} options
+ * @return {Object} the cloned object
+ * @api private
+ */
+
+exports.clone = function clone (obj, options) {
+ if (obj === undefined || obj === null)
+ return obj;
+
+ if (Array.isArray(obj))
+ return cloneArray(obj, options);
+
+ if (isMongooseObject(obj)) {
+ if (options && options.json && 'function' === typeof obj.toJSON) {
+ return obj.toJSON(options);
+ } else {
+ return obj.toObject(options);
+ }
+ }
+
+ if ('Object' === obj.constructor.name)
+ return cloneObject(obj, options);
+
+ if ('Date' === obj.constructor.name)
+ return new obj.constructor(+obj);
+
+ if ('RegExp' === obj.constructor.name)
+ return new RegExp(obj.source);
+
+ if (obj instanceof ObjectId)
+ return new ObjectId(obj.id);
+
+ if (obj.valueOf)
+ return obj.valueOf();
+};
+var clone = exports.clone;
+
+/*!
+ * ignore
+ */
+
+function cloneObject (obj, options) {
+ var retainKeyOrder = options && options.retainKeyOrder
+ , minimize = options && options.minimize
+ , ret = {}
+ , hasKeys
+ , keys
+ , val
+ , k
+ , i
+
+ if (retainKeyOrder) {
+ for (k in obj) {
+ val = clone(obj[k], options);
+
+ if (!minimize || ('undefined' !== typeof val)) {
+ hasKeys || (hasKeys = true);
+ ret[k] = val;
+ }
+ }
+ } else {
+ // faster
+
+ keys = Object.keys(obj);
+ i = keys.length;
+
+ while (i--) {
+ k = keys[i];
+ val = clone(obj[k], options);
+
+ if (!minimize || ('undefined' !== typeof val)) {
+ if (!hasKeys) hasKeys = true;
+ ret[k] = val;
+ }
+ }
+ }
+
+ return minimize
+ ? hasKeys && ret
+ : ret;
+};
+
+function cloneArray (arr, options) {
+ var ret = [];
+ for (var i = 0, l = arr.length; i < l; i++)
+ ret.push(clone(arr[i], options));
+ return ret;
+};
+
+
+/**
+ * Copies and merges options with defaults.
+ *
+ * @param {Object} defaults
+ * @param {Object} options
+ * @return {Object} the merged object
+ * @api private
+ */
+
+exports.options = function (defaults, options) {
+ var keys = Object.keys(defaults)
+ , i = keys.length
+ , k ;
+
+ options = options || {};
+
+ while (i--) {
+ k = keys[i];
+ if (!(k in options)) {
+ options[k] = defaults[k];
+ }
+ }
+
+ return options;
+};
+
+/**
+ * Generates a random string
+ *
+ * @api private
+ */
+
+exports.random = function () {
+ return Math.random().toString().substr(3);
+};
+
+/**
+ * Merges `from` into `to` without overwriting existing properties.
+ *
+ * @param {Object} to
+ * @param {Object} from
+ * @api private
+ */
+
+exports.merge = function merge (to, from) {
+ var keys = Object.keys(from)
+ , i = keys.length
+ , key
+
+ while (i--) {
+ key = keys[i];
+ if ('undefined' === typeof to[key]) {
+ to[key] = from[key];
+ } else {
+ if (exports.isObject(from[key])) {
+ merge(to[key], from[key]);
+ } else {
+ to[key] = from[key];
+ }
+ }
+ }
+};
+
+/*!
+ * toString helper
+ */
+
+var toString = Object.prototype.toString;
+
+/**
+ * Determines if `arg` is an object.
+ *
+ * @param {Object|Array|String|Function|RegExp|any} arg
+ * @return {Boolean}
+ */
+
+exports.isObject = function (arg) {
+ return '[object Object]' == toString.call(arg);
+}
+
+/**
+ * A faster Array.prototype.slice.call(arguments) alternative
+ * @api private
+ */
+
+exports.args = sliced;
+
+/**
+ * process.nextTick helper.
+ *
+ * Wraps `callback` in a try/catch + nextTick.
+ *
+ * node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.
+ *
+ * @param {Function} callback
+ * @api private
+ */
+
+exports.tick = function tick (callback) {
+ if ('function' !== typeof callback) return;
+ return function () {
+ try {
+ callback.apply(this, arguments);
+ } catch (err) {
+ // only nextTick on err to get out of
+ // the event loop and avoid state corruption.
+ process.nextTick(function () {
+ throw err;
+ });
+ }
+ }
+}
+
+/**
+ * Returns if `v` is a mongoose object that has a `toObject()` method we can use.
+ *
+ * This is for compatibility with libs like Date.js which do foolish things to Natives.
+ *
+ * @param {any} v
+ * @api private
+ */
+
+exports.isMongooseObject = function (v) {
+ Document || (Document = require('./document'));
+ MongooseArray || (MongooseArray = require('./types').Array);
+ MongooseBuffer || (MongooseBuffer = require('./types').Buffer);
+
+ return v instanceof Document ||
+ v instanceof MongooseArray ||
+ v instanceof MongooseBuffer
+}
+var isMongooseObject = exports.isMongooseObject;
+
+/**
+ * Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB.
+ *
+ * @param {Object} object
+ * @api private
+ */
+
+exports.expires = function expires (object) {
+ if (!(object && 'Object' == object.constructor.name)) return;
+ if (!('expires' in object)) return;
+
+ var when;
+ if ('string' != typeof object.expires) {
+ when = object.expires;
+ } else {
+ when = Math.round(ms(object.expires) / 1000);
+ }
+ object.expireAfterSeconds = when;
+ delete object.expires;
+}
+
+exports.readPref = function readPref (pref, tags) {
+ if (Array.isArray(pref)) {
+ tags = pref[1];
+ pref = pref[0];
+ }
+
+ switch (pref) {
+ case 'p':
+ pref = 'primary';
+ break;
+ case 'pp':
+ pref = 'primaryPrefered';
+ break;
+ case 's':
+ pref = 'secondary';
+ break;
+ case 'sp':
+ pref = 'secondaryPrefered';
+ break;
+ case 'n':
+ pref = 'nearest';
+ break;
+ }
+
+ return new ReadPref(pref, tags);
+}
diff --git a/test/node_modules/mongoose/lib/virtualtype.js b/test/node_modules/mongoose/lib/virtualtype.js
new file mode 100644
index 0000000..819ac10
--- /dev/null
+++ b/test/node_modules/mongoose/lib/virtualtype.js
@@ -0,0 +1,103 @@
+
+/**
+ * VirtualType constructor
+ *
+ * This is what mongoose uses to define virtual attributes via `Schema.prototype.virtual`.
+ *
+ * ####Example:
+ *
+ * var fullname = schema.virtual('fullname');
+ * fullname instanceof mongoose.VirtualType // true
+ *
+ * @parma {Object} options
+ * @api public
+ */
+
+function VirtualType (options, name) {
+ this.path = name;
+ this.getters = [];
+ this.setters = [];
+ this.options = options || {};
+}
+
+/**
+ * Defines a getter.
+ *
+ * ####Example:
+ *
+ * var virtual = schema.virtual('fullname');
+ * virtual.get(function () {
+ * return this.name.first + ' ' + this.name.last;
+ * });
+ *
+ * @param {Function} fn
+ * @return {VirtualType} this
+ * @api public
+ */
+
+VirtualType.prototype.get = function (fn) {
+ this.getters.push(fn);
+ return this;
+};
+
+/**
+ * Defines a setter.
+ *
+ * ####Example:
+ *
+ * var virtual = schema.virtual('fullname');
+ * virtual.set(function (v) {
+ * var parts = v.split(' ');
+ * this.name.first = parts[0];
+ * this.name.last = parts[1];
+ * });
+ *
+ * @param {Function} fn
+ * @return {VirtualType} this
+ * @api public
+ */
+
+VirtualType.prototype.set = function (fn) {
+ this.setters.push(fn);
+ return this;
+};
+
+/**
+ * Applies getters to `value` using optional `scope`.
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @return {any} the value after applying all getters
+ * @api public
+ */
+
+VirtualType.prototype.applyGetters = function (value, scope) {
+ var v = value;
+ for (var l = this.getters.length - 1; l >= 0; l--) {
+ v = this.getters[l].call(scope, v, this);
+ }
+ return v;
+};
+
+/**
+ * Applies setters to `value` using optional `scope`.
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @return {any} the value after applying all setters
+ * @api public
+ */
+
+VirtualType.prototype.applySetters = function (value, scope) {
+ var v = value;
+ for (var l = this.setters.length - 1; l >= 0; l--) {
+ v = this.setters[l].call(scope, v, this);
+ }
+ return v;
+};
+
+/*!
+ * exports
+ */
+
+module.exports = VirtualType;
diff --git a/test/node_modules/mongoose/node_modules/hooks/.npmignore b/test/node_modules/mongoose/node_modules/hooks/.npmignore
new file mode 100644
index 0000000..96e29a8
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/.npmignore
@@ -0,0 +1,2 @@
+**.swp
+node_modules
diff --git a/test/node_modules/mongoose/node_modules/hooks/Makefile b/test/node_modules/mongoose/node_modules/hooks/Makefile
new file mode 100644
index 0000000..1db5d65
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/Makefile
@@ -0,0 +1,9 @@
+test:
+ @NODE_ENV=test ./node_modules/expresso/bin/expresso \
+ $(TESTFLAGS) \
+ ./test.js
+
+test-cov:
+ @TESTFLAGS=--cov $(MAKE) test
+
+.PHONY: test test-cov
diff --git a/test/node_modules/mongoose/node_modules/hooks/README.md b/test/node_modules/mongoose/node_modules/hooks/README.md
new file mode 100644
index 0000000..af90a48
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/README.md
@@ -0,0 +1,306 @@
+hooks
+============
+
+Add pre and post middleware hooks to your JavaScript methods.
+
+## Installation
+ npm install hooks
+
+## Motivation
+Suppose you have a JavaScript object with a `save` method.
+
+It would be nice to be able to declare code that runs before `save` and after `save`.
+For example, you might want to run validation code before every `save`,
+and you might want to dispatch a job to a background job queue after `save`.
+
+One might have an urge to hard code this all into `save`, but that turns out to
+couple all these pieces of functionality (validation, save, and job creation) more
+tightly than is necessary. For example, what if someone does not want to do background
+job creation after the logical save?
+
+It is nicer to tack on functionality using what we call `pre` and `post` hooks. These
+are functions that you define and that you direct to execute before or after particular
+methods.
+
+## Example
+We can use `hooks` to add validation and background jobs in the following way:
+
+ var hooks = require('hooks')
+ , Document = require('./path/to/some/document/constructor');
+
+ // Add hooks' methods: `hook`, `pre`, and `post`
+ for (var k in hooks) {
+ Document[k] = hooks[k];
+ }
+
+ // Define a new method that is able to invoke pre and post middleware
+ Document.hook('save', Document.prototype.save);
+
+ // Define a middleware function to be invoked before 'save'
+ Document.pre('save', function validate (next) {
+ // The `this` context inside of `pre` and `post` functions
+ // is the Document instance
+ if (this.isValid()) next(); // next() passes control to the next middleware
+ // or to the target method itself
+ else next(new Error("Invalid")); // next(error) invokes an error callback
+ });
+
+ // Define a middleware function to be invoked after 'save'
+ Document.post('save', function createJob () {
+ this.sendToBackgroundQueue();
+ });
+
+If you already have defined `Document.prototype` methods for which you want pres and posts,
+then you do not need to explicitly invoke `Document.hook(...)`. Invoking `Document.pre(methodName, fn)`
+or `Document.post(methodName, fn)` will automatically and lazily change `Document.prototype[methodName]`
+so that it plays well with `hooks`. An equivalent way to implement the previous example is:
+
+```javascript
+var hooks = require('hooks')
+ , Document = require('./path/to/some/document/constructor');
+
+// Add hooks' methods: `hook`, `pre`, and `post`
+for (var k in hooks) {
+ Document[k] = hooks[k];
+}
+
+Document.prototype.save = function () {
+ // ...
+};
+
+// Define a middleware function to be invoked before 'save'
+Document.pre('save', function validate (next) {
+ // The `this` context inside of `pre` and `post` functions
+ // is the Document instance
+ if (this.isValid()) next(); // next() passes control to the next middleware
+ // or to the target method itself
+ else next(new Error("Invalid")); // next(error) invokes an error callback
+});
+
+// Define a middleware function to be invoked after 'save'
+Document.post('save', function createJob () {
+ this.sendToBackgroundQueue();
+});
+```
+
+## Pres and Posts as Middleware
+We structure pres and posts as middleware to give you maximum flexibility:
+
+1. You can define **multiple** pres (or posts) for a single method.
+2. These pres (or posts) are then executed as a chain of methods.
+3. Any functions in this middleware chain can choose to halt the chain's execution by `next`ing an Error from that middleware function. If this occurs, then none of the other middleware in the chain will execute, and the main method (e.g., `save`) will not execute. This is nice, for example, when we don't want a document to save if it is invalid.
+
+## Defining multiple pres (or posts)
+`pre` is chainable, so you can define multiple pres via:
+ Document.pre('save', function (next, halt) {
+ console.log("hello");
+ }).pre('save', function (next, halt) {
+ console.log("world");
+ });
+
+As soon as one pre finishes executing, the next one will be invoked, and so on.
+
+## Error Handling
+You can define a default error handler by passing a 2nd function as the 3rd argument to `hook`:
+ Document.hook('set', function (path, val) {
+ this[path] = val;
+ }, function (err) {
+ // Handler the error here
+ console.error(err);
+ });
+
+Then, we can pass errors to this handler from a pre or post middleware function:
+ Document.pre('set', function (next, path, val) {
+ next(new Error());
+ });
+
+If you do not set up a default handler, then `hooks` makes the default handler that just throws the `Error`.
+
+The default error handler can be over-rided on a per method invocation basis.
+
+If the main method that you are surrounding with pre and post middleware expects its last argument to be a function
+with callback signature `function (error, ...)`, then that callback becomes the error handler, over-riding the default
+error handler you may have set up.
+
+```javascript
+Document.hook('save', function (callback) {
+ // Save logic goes here
+ ...
+});
+
+var doc = new Document();
+doc.save( function (err, saved) {
+ // We can pass err via `next` in any of our pre or post middleware functions
+ if (err) console.error(err);
+
+ // Rest of callback logic follows ...
+});
+```
+
+## Mutating Arguments via Middleware
+`pre` and `post` middleware can also accept the intended arguments for the method
+they augment. This is useful if you want to mutate the arguments before passing
+them along to the next middleware and eventually pass a mutated arguments list to
+the main method itself.
+
+As a simple example, let's define a method `set` that just sets a key, value pair.
+If we want to namespace the key, we can do so by adding a `pre` middleware hook
+that runs before `set`, alters the arguments by namespacing the `key` argument, and passes them onto `set`:
+
+ Document.hook('set', function (key, val) {
+ this[key] = val;
+ });
+ Document.pre('set', function (next, key, val) {
+ next('namespace-' + key, val);
+ });
+ var doc = new Document();
+ doc.set('hello', 'world');
+ console.log(doc.hello); // undefined
+ console.log(doc['namespace-hello']); // 'world'
+
+As you can see above, we pass arguments via `next`.
+
+If you are not mutating the arguments, then you can pass zero arguments
+to `next`, and the next middleware function will still have access
+to the arguments.
+
+ Document.hook('set', function (key, val) {
+ this[key] = val;
+ });
+ Document.pre('set', function (next, key, val) {
+ // I have access to key and val here
+ next(); // We don't need to pass anything to next
+ });
+ Document.pre('set', function (next, key, val) {
+ // And I still have access to the original key and val here
+ next();
+ });
+
+Finally, you can add arguments that downstream middleware can also see:
+
+ // Note that in the definition of `set`, there is no 3rd argument, options
+ Document.hook('set', function (key, val) {
+ // But...
+ var options = arguments[2]; // ...I have access to an options argument
+ // because of pre function pre2 (defined below)
+ console.log(options); // '{debug: true}'
+ this[key] = val;
+ });
+ Document.pre('set', function pre1 (next, key, val) {
+ // I only have access to key and val arguments
+ console.log(arguments.length); // 3
+ next(key, val, {debug: true});
+ });
+ Document.pre('set', function pre2 (next, key, val, options) {
+ console.log(arguments.length); // 4
+ console.log(options); // '{ debug: true}'
+ next();
+ });
+ Document.pre('set', function pre3 (next, key, val, options) {
+ // I still have access to key, val, AND the options argument introduced via the preceding middleware
+ console.log(arguments.length); // 4
+ console.log(options); // '{ debug: true}'
+ next();
+ });
+
+ var doc = new Document()
+ doc.set('hey', 'there');
+
+## Parallel `pre` middleware
+
+All middleware up to this point has been "serial" middleware -- i.e., middleware whose logic
+is executed as a serial chain.
+
+Some scenarios call for parallel middleware -- i.e., middleware that can wait for several
+asynchronous services at once to respond.
+
+For instance, you may only want to save a Document only after you have checked
+that the Document is valid according to two different remote services.
+
+We accomplish asynchronous middleware by adding a second kind of flow control callback
+(the only flow control callback so far has been `next`), called `done`.
+
+- `next` passes control to the next middleware in the chain
+- `done` keeps track of how many parallel middleware have invoked `done` and passes
+ control to the target method when ALL parallel middleware have invoked `done`. If
+ you pass an `Error` to `done`, then the error is handled, and the main method that is
+ wrapped by pres and posts will not get invoked.
+
+We declare pre middleware that is parallel by passing a 3rd boolean argument to our `pre`
+definition method.
+
+We illustrate via the parallel validation example mentioned above:
+
+ Document.hook('save', function targetFn (callback) {
+ // Save logic goes here
+ // ...
+ // This only gets run once the two `done`s are both invoked via preOne and preTwo.
+ });
+
+ // true marks this as parallel middleware
+ Document.pre('save', true, function preOne (next, doneOne, callback) {
+ remoteServiceOne.validate(this.serialize(), function (err, isValid) {
+ // The code in here will probably be run after the `next` below this block
+ // and could possibly be run after the console.log("Hola") in `preTwo
+ if (err) return doneOne(err);
+ if (isValid) doneOne();
+ });
+ next(); // Pass control to the next middleware
+ });
+
+ // We will suppose that we need 2 different remote services to validate our document
+ Document.pre('save', true, function preTwo (next, doneTwo, callback) {
+ remoteServiceTwo.validate(this.serialize(), function (err, isValid) {
+ if (err) return doneTwo(err);
+ if (isValid) doneTwo();
+ });
+ next();
+ });
+
+ // While preOne and preTwo are parallel, preThree is a serial pre middleware
+ Document.pre('save', function preThree (next, callback) {
+ next();
+ });
+
+ var doc = new Document();
+ doc.save( function (err, doc) {
+ // Do stuff with the saved doc here...
+ });
+
+In the above example, flow control may happen in the following way:
+
+(1) doc.save -> (2) preOne --(next)--> (3) preTwo --(next)--> (4) preThree --(next)--> (wait for dones to invoke) -> (5) doneTwo -> (6) doneOne -> (7) targetFn
+
+So what's happening is that:
+
+1. You call `doc.save(...)`
+2. First, your preOne middleware gets executed. It makes a remote call to the validation service and `next()`s to the preTwo middleware.
+3. Now, your preTwo middleware gets executed. It makes a remote call to another validation service and `next()`s to the preThree middleware.
+4. Your preThree middleware gets executed. It immediately `next()`s. But nothing else gets executing until both `doneOne` and `doneTwo` are invoked inside the callbacks handling the response from the two valiation services.
+5. We will suppose that validation remoteServiceTwo returns a response to us first. In this case, we call `doneTwo` inside the callback to remoteServiceTwo.
+6. Some fractions of a second later, remoteServiceOne returns a response to us. In this case, we call `doneOne` inside the callback to remoteServiceOne.
+7. `hooks` implementation keeps track of how many parallel middleware has been defined per target function. It detects that both asynchronous pre middlewares (`preOne` and `preTwo`) have finally called their `done` functions (`doneOne` and `doneTwo`), so the implementation finally invokes our `targetFn` (i.e., our core `save` business logic).
+
+## Removing Pres
+
+You can remove a particular pre associated with a hook:
+
+ Document.pre('set', someFn);
+ Document.removePre('set', someFn);
+
+And you can also remove all pres associated with a hook:
+ Document.removePre('set'); // Removes all declared `pre`s on the hook 'set'
+
+## Tests
+To run the tests:
+ make test
+
+### Contributors
+- [Brian Noguchi](https://github.com/bnoguchi)
+
+### License
+MIT License
+
+---
+### Author
+Brian Noguchi
diff --git a/test/node_modules/mongoose/node_modules/hooks/hooks.alt.js b/test/node_modules/mongoose/node_modules/hooks/hooks.alt.js
new file mode 100644
index 0000000..6ced357
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/hooks.alt.js
@@ -0,0 +1,134 @@
+/**
+ * Hooks are useful if we want to add a method that automatically has `pre` and `post` hooks.
+ * For example, it would be convenient to have `pre` and `post` hooks for `save`.
+ * _.extend(Model, mixins.hooks);
+ * Model.hook('save', function () {
+ * console.log('saving');
+ * });
+ * Model.pre('save', function (next, done) {
+ * console.log('about to save');
+ * next();
+ * });
+ * Model.post('save', function (next, done) {
+ * console.log('saved');
+ * next();
+ * });
+ *
+ * var m = new Model();
+ * m.save();
+ * // about to save
+ * // saving
+ * // saved
+ */
+
+// TODO Add in pre and post skipping options
+module.exports = {
+ /**
+ * Declares a new hook to which you can add pres and posts
+ * @param {String} name of the function
+ * @param {Function} the method
+ * @param {Function} the error handler callback
+ */
+ hook: function (name, fn, err) {
+ if (arguments.length === 1 && typeof name === 'object') {
+ for (var k in name) { // `name` is a hash of hookName->hookFn
+ this.hook(k, name[k]);
+ }
+ return;
+ }
+
+ if (!err) err = fn;
+
+ var proto = this.prototype || this
+ , pres = proto._pres = proto._pres || {}
+ , posts = proto._posts = proto._posts || {};
+ pres[name] = pres[name] || [];
+ posts[name] = posts[name] || [];
+
+ function noop () {}
+
+ proto[name] = function () {
+ var self = this
+ , pres = this._pres[name]
+ , posts = this._posts[name]
+ , numAsyncPres = 0
+ , hookArgs = [].slice.call(arguments)
+ , preChain = pres.map( function (pre, i) {
+ var wrapper = function () {
+ if (arguments[0] instanceof Error)
+ return err(arguments[0]);
+ if (numAsyncPres) {
+ // arguments[1] === asyncComplete
+ if (arguments.length)
+ hookArgs = [].slice.call(arguments, 2);
+ pre.apply(self,
+ [ preChain[i+1] || allPresInvoked,
+ asyncComplete
+ ].concat(hookArgs)
+ );
+ } else {
+ if (arguments.length)
+ hookArgs = [].slice.call(arguments);
+ pre.apply(self,
+ [ preChain[i+1] || allPresDone ].concat(hookArgs));
+ }
+ }; // end wrapper = function () {...
+ if (wrapper.isAsync = pre.isAsync)
+ numAsyncPres++;
+ return wrapper;
+ }); // end posts.map(...)
+ function allPresInvoked () {
+ if (arguments[0] instanceof Error)
+ err(arguments[0]);
+ }
+
+ function allPresDone () {
+ if (arguments[0] instanceof Error)
+ return err(arguments[0]);
+ if (arguments.length)
+ hookArgs = [].slice.call(arguments);
+ fn.apply(self, hookArgs);
+ var postChain = posts.map( function (post, i) {
+ var wrapper = function () {
+ if (arguments[0] instanceof Error)
+ return err(arguments[0]);
+ if (arguments.length)
+ hookArgs = [].slice.call(arguments);
+ post.apply(self,
+ [ postChain[i+1] || noop].concat(hookArgs));
+ }; // end wrapper = function () {...
+ return wrapper;
+ }); // end posts.map(...)
+ if (postChain.length) postChain[0]();
+ }
+
+ if (numAsyncPres) {
+ complete = numAsyncPres;
+ function asyncComplete () {
+ if (arguments[0] instanceof Error)
+ return err(arguments[0]);
+ --complete || allPresDone.call(this);
+ }
+ }
+ (preChain[0] || allPresDone)();
+ };
+
+ return this;
+ },
+
+ pre: function (name, fn, isAsync) {
+ var proto = this.prototype
+ , pres = proto._pres = proto._pres || {};
+ if (fn.isAsync = isAsync) {
+ this.prototype[name].numAsyncPres++;
+ }
+ (pres[name] = pres[name] || []).push(fn);
+ return this;
+ },
+ post: function (name, fn, isAsync) {
+ var proto = this.prototype
+ , posts = proto._posts = proto._posts || {};
+ (posts[name] = posts[name] || []).push(fn);
+ return this;
+ }
+};
diff --git a/test/node_modules/mongoose/node_modules/hooks/hooks.js b/test/node_modules/mongoose/node_modules/hooks/hooks.js
new file mode 100644
index 0000000..9a887c7
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/hooks.js
@@ -0,0 +1,161 @@
+// TODO Add in pre and post skipping options
+module.exports = {
+ /**
+ * Declares a new hook to which you can add pres and posts
+ * @param {String} name of the function
+ * @param {Function} the method
+ * @param {Function} the error handler callback
+ */
+ hook: function (name, fn, errorCb) {
+ if (arguments.length === 1 && typeof name === 'object') {
+ for (var k in name) { // `name` is a hash of hookName->hookFn
+ this.hook(k, name[k]);
+ }
+ return;
+ }
+
+ var proto = this.prototype || this
+ , pres = proto._pres = proto._pres || {}
+ , posts = proto._posts = proto._posts || {};
+ pres[name] = pres[name] || [];
+ posts[name] = posts[name] || [];
+
+ proto[name] = function () {
+ var self = this
+ , hookArgs // arguments eventually passed to the hook - are mutable
+ , lastArg = arguments[arguments.length-1]
+ , pres = this._pres[name]
+ , posts = this._posts[name]
+ , _total = pres.length
+ , _current = -1
+ , _asyncsLeft = proto[name].numAsyncPres
+ , _next = function () {
+ if (arguments[0] instanceof Error) {
+ return handleError(arguments[0]);
+ }
+ var _args = Array.prototype.slice.call(arguments)
+ , currPre
+ , preArgs;
+ if (_args.length && !(arguments[0] == null && typeof lastArg === 'function'))
+ hookArgs = _args;
+ if (++_current < _total) {
+ currPre = pres[_current]
+ if (currPre.isAsync && currPre.length < 2)
+ throw new Error("Your pre must have next and done arguments -- e.g., function (next, done, ...)");
+ if (currPre.length < 1)
+ throw new Error("Your pre must have a next argument -- e.g., function (next, ...)");
+ preArgs = (currPre.isAsync
+ ? [once(_next), once(_asyncsDone)]
+ : [once(_next)]).concat(hookArgs);
+ return currPre.apply(self, preArgs);
+ } else if (!proto[name].numAsyncPres) {
+ return _done.apply(self, hookArgs);
+ }
+ }
+ , _done = function () {
+ var args_ = Array.prototype.slice.call(arguments)
+ , ret, total_, current_, next_, done_, postArgs;
+ if (_current === _total) {
+ ret = fn.apply(self, args_);
+ total_ = posts.length;
+ current_ = -1;
+ next_ = function () {
+ if (arguments[0] instanceof Error) {
+ return handleError(arguments[0]);
+ }
+ var args_ = Array.prototype.slice.call(arguments, 1)
+ , currPost
+ , postArgs;
+ if (args_.length) hookArgs = args_;
+ if (++current_ < total_) {
+ currPost = posts[current_]
+ if (currPost.length < 1)
+ throw new Error("Your post must have a next argument -- e.g., function (next, ...)");
+ postArgs = [once(next_)].concat(hookArgs);
+ return currPost.apply(self, postArgs);
+ }
+ };
+ if (total_) return next_();
+ return ret;
+ }
+ };
+ if (_asyncsLeft) {
+ function _asyncsDone (err) {
+ if (err && err instanceof Error) {
+ return handleError(err);
+ }
+ --_asyncsLeft || _done.apply(self, hookArgs);
+ }
+ }
+ function handleError (err) {
+ if ('function' == typeof lastArg)
+ return lastArg(err);
+ if (errorCb) return errorCb.call(self, err);
+ throw err;
+ }
+ return _next.apply(this, arguments);
+ };
+
+ proto[name].numAsyncPres = 0;
+
+ return this;
+ },
+
+ pre: function (name, isAsync, fn, errorCb) {
+ if ('boolean' !== typeof arguments[1]) {
+ errorCb = fn;
+ fn = isAsync;
+ isAsync = false;
+ }
+ var proto = this.prototype || this
+ , pres = proto._pres = proto._pres || {};
+
+ this._lazySetupHooks(proto, name, errorCb);
+
+ if (fn.isAsync = isAsync) {
+ proto[name].numAsyncPres++;
+ }
+
+ (pres[name] = pres[name] || []).push(fn);
+ return this;
+ },
+ post: function (name, isAsync, fn) {
+ if (arguments.length === 2) {
+ fn = isAsync;
+ isAsync = false;
+ }
+ var proto = this.prototype || this
+ , posts = proto._posts = proto._posts || {};
+
+ this._lazySetupHooks(proto, name);
+ (posts[name] = posts[name] || []).push(fn);
+ return this;
+ },
+ removePre: function (name, fnToRemove) {
+ var proto = this.prototype || this
+ , pres = proto._pres || (proto._pres || {});
+ if (!pres[name]) return this;
+ if (arguments.length === 1) {
+ // Remove all pre callbacks for hook `name`
+ pres[name].length = 0;
+ } else {
+ pres[name] = pres[name].filter( function (currFn) {
+ return currFn !== fnToRemove;
+ });
+ }
+ return this;
+ },
+ _lazySetupHooks: function (proto, methodName, errorCb) {
+ if ('undefined' === typeof proto[methodName].numAsyncPres) {
+ this.hook(methodName, proto[methodName], errorCb);
+ }
+ }
+};
+
+function once (fn, scope) {
+ return function fnWrapper () {
+ if (fnWrapper.hookCalled) return;
+ fnWrapper.hookCalled = true;
+ fn.apply(scope, arguments);
+ };
+}
diff --git a/test/node_modules/mongoose/node_modules/hooks/package.json b/test/node_modules/mongoose/node_modules/hooks/package.json
new file mode 100644
index 0000000..acc84cc
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/package.json
@@ -0,0 +1,49 @@
+{
+ "name": "hooks",
+ "description": "Adds pre and post hook functionality to your JavaScript methods.",
+ "version": "0.2.1",
+ "keywords": [
+ "node",
+ "hooks",
+ "middleware",
+ "pre",
+ "post"
+ ],
+ "homepage": "https://github.com/bnoguchi/hooks-js/",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/bnoguchi/hooks-js.git"
+ },
+ "author": {
+ "name": "Brian Noguchi",
+ "email": "brian.noguchi@gmail.com",
+ "url": "https://github.com/bnoguchi/"
+ },
+ "main": "./hooks.js",
+ "directories": {
+ "lib": "."
+ },
+ "scripts": {
+ "test": "make test"
+ },
+ "dependencies": {},
+ "devDependencies": {
+ "expresso": ">=0.7.6",
+ "should": ">=0.2.1",
+ "underscore": ">=1.1.4"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ },
+ "licenses": [
+ "MIT"
+ ],
+ "optionalDependencies": {},
+ "readme": "hooks\n============\n\nAdd pre and post middleware hooks to your JavaScript methods.\n\n## Installation\n npm install hooks\n\n## Motivation\nSuppose you have a JavaScript object with a `save` method.\n\nIt would be nice to be able to declare code that runs before `save` and after `save`.\nFor example, you might want to run validation code before every `save`,\nand you might want to dispatch a job to a background job queue after `save`.\n\nOne might have an urge to hard code this all into `save`, but that turns out to\ncouple all these pieces of functionality (validation, save, and job creation) more\ntightly than is necessary. For example, what if someone does not want to do background\njob creation after the logical save? \n\nIt is nicer to tack on functionality using what we call `pre` and `post` hooks. These\nare functions that you define and that you direct to execute before or after particular\nmethods.\n\n## Example\nWe can use `hooks` to add validation and background jobs in the following way:\n\n var hooks = require('hooks')\n , Document = require('./path/to/some/document/constructor');\n\n // Add hooks' methods: `hook`, `pre`, and `post` \n for (var k in hooks) {\n Document[k] = hooks[k];\n }\n\n // Define a new method that is able to invoke pre and post middleware\n Document.hook('save', Document.prototype.save);\n\n // Define a middleware function to be invoked before 'save'\n Document.pre('save', function validate (next) {\n // The `this` context inside of `pre` and `post` functions\n // is the Document instance\n if (this.isValid()) next(); // next() passes control to the next middleware\n // or to the target method itself\n else next(new Error(\"Invalid\")); // next(error) invokes an error callback\n });\n\n // Define a middleware function to be invoked after 'save'\n Document.post('save', function createJob () {\n this.sendToBackgroundQueue();\n });\n\nIf you already have defined `Document.prototype` methods for which you want pres and posts,\nthen you do not need to explicitly invoke `Document.hook(...)`. Invoking `Document.pre(methodName, fn)`\nor `Document.post(methodName, fn)` will automatically and lazily change `Document.prototype[methodName]`\nso that it plays well with `hooks`. An equivalent way to implement the previous example is:\n\n```javascript\nvar hooks = require('hooks')\n , Document = require('./path/to/some/document/constructor');\n\n// Add hooks' methods: `hook`, `pre`, and `post` \nfor (var k in hooks) {\n Document[k] = hooks[k];\n}\n\nDocument.prototype.save = function () {\n // ...\n};\n\n// Define a middleware function to be invoked before 'save'\nDocument.pre('save', function validate (next) {\n // The `this` context inside of `pre` and `post` functions\n // is the Document instance\n if (this.isValid()) next(); // next() passes control to the next middleware\n // or to the target method itself\n else next(new Error(\"Invalid\")); // next(error) invokes an error callback\n});\n\n// Define a middleware function to be invoked after 'save'\nDocument.post('save', function createJob () {\n this.sendToBackgroundQueue();\n});\n```\n\n## Pres and Posts as Middleware\nWe structure pres and posts as middleware to give you maximum flexibility:\n\n1. You can define **multiple** pres (or posts) for a single method.\n2. These pres (or posts) are then executed as a chain of methods.\n3. Any functions in this middleware chain can choose to halt the chain's execution by `next`ing an Error from that middleware function. If this occurs, then none of the other middleware in the chain will execute, and the main method (e.g., `save`) will not execute. This is nice, for example, when we don't want a document to save if it is invalid.\n\n## Defining multiple pres (or posts)\n`pre` is chainable, so you can define multiple pres via:\n Document.pre('save', function (next, halt) {\n console.log(\"hello\");\n }).pre('save', function (next, halt) {\n console.log(\"world\");\n });\n\nAs soon as one pre finishes executing, the next one will be invoked, and so on.\n\n## Error Handling\nYou can define a default error handler by passing a 2nd function as the 3rd argument to `hook`:\n Document.hook('set', function (path, val) {\n this[path] = val;\n }, function (err) {\n // Handler the error here\n console.error(err);\n });\n\nThen, we can pass errors to this handler from a pre or post middleware function:\n Document.pre('set', function (next, path, val) {\n next(new Error());\n });\n\nIf you do not set up a default handler, then `hooks` makes the default handler that just throws the `Error`.\n\nThe default error handler can be over-rided on a per method invocation basis.\n\nIf the main method that you are surrounding with pre and post middleware expects its last argument to be a function\nwith callback signature `function (error, ...)`, then that callback becomes the error handler, over-riding the default\nerror handler you may have set up.\n \n```javascript\nDocument.hook('save', function (callback) {\n // Save logic goes here\n ...\n});\n\nvar doc = new Document();\ndoc.save( function (err, saved) {\n // We can pass err via `next` in any of our pre or post middleware functions\n if (err) console.error(err);\n \n // Rest of callback logic follows ...\n});\n```\n\n## Mutating Arguments via Middleware\n`pre` and `post` middleware can also accept the intended arguments for the method\nthey augment. This is useful if you want to mutate the arguments before passing\nthem along to the next middleware and eventually pass a mutated arguments list to\nthe main method itself.\n\nAs a simple example, let's define a method `set` that just sets a key, value pair.\nIf we want to namespace the key, we can do so by adding a `pre` middleware hook\nthat runs before `set`, alters the arguments by namespacing the `key` argument, and passes them onto `set`:\n\n Document.hook('set', function (key, val) {\n this[key] = val;\n });\n Document.pre('set', function (next, key, val) {\n next('namespace-' + key, val);\n });\n var doc = new Document();\n doc.set('hello', 'world');\n console.log(doc.hello); // undefined\n console.log(doc['namespace-hello']); // 'world'\n\nAs you can see above, we pass arguments via `next`.\n\nIf you are not mutating the arguments, then you can pass zero arguments\nto `next`, and the next middleware function will still have access\nto the arguments.\n\n Document.hook('set', function (key, val) {\n this[key] = val;\n });\n Document.pre('set', function (next, key, val) {\n // I have access to key and val here\n next(); // We don't need to pass anything to next\n });\n Document.pre('set', function (next, key, val) {\n // And I still have access to the original key and val here\n next();\n });\n\nFinally, you can add arguments that downstream middleware can also see:\n\n // Note that in the definition of `set`, there is no 3rd argument, options\n Document.hook('set', function (key, val) {\n // But...\n var options = arguments[2]; // ...I have access to an options argument\n // because of pre function pre2 (defined below)\n console.log(options); // '{debug: true}'\n this[key] = val;\n });\n Document.pre('set', function pre1 (next, key, val) {\n // I only have access to key and val arguments\n console.log(arguments.length); // 3\n next(key, val, {debug: true});\n });\n Document.pre('set', function pre2 (next, key, val, options) {\n console.log(arguments.length); // 4\n console.log(options); // '{ debug: true}'\n next();\n });\n Document.pre('set', function pre3 (next, key, val, options) {\n // I still have access to key, val, AND the options argument introduced via the preceding middleware\n console.log(arguments.length); // 4\n console.log(options); // '{ debug: true}'\n next();\n });\n \n var doc = new Document()\n doc.set('hey', 'there');\n\n## Parallel `pre` middleware\n\nAll middleware up to this point has been \"serial\" middleware -- i.e., middleware whose logic\nis executed as a serial chain.\n\nSome scenarios call for parallel middleware -- i.e., middleware that can wait for several\nasynchronous services at once to respond.\n\nFor instance, you may only want to save a Document only after you have checked\nthat the Document is valid according to two different remote services.\n\nWe accomplish asynchronous middleware by adding a second kind of flow control callback\n(the only flow control callback so far has been `next`), called `done`.\n\n- `next` passes control to the next middleware in the chain\n- `done` keeps track of how many parallel middleware have invoked `done` and passes\n control to the target method when ALL parallel middleware have invoked `done`. If\n you pass an `Error` to `done`, then the error is handled, and the main method that is\n wrapped by pres and posts will not get invoked.\n\nWe declare pre middleware that is parallel by passing a 3rd boolean argument to our `pre`\ndefinition method.\n\nWe illustrate via the parallel validation example mentioned above:\n\n Document.hook('save', function targetFn (callback) {\n // Save logic goes here\n // ...\n // This only gets run once the two `done`s are both invoked via preOne and preTwo.\n });\n\n // true marks this as parallel middleware\n Document.pre('save', true, function preOne (next, doneOne, callback) {\n remoteServiceOne.validate(this.serialize(), function (err, isValid) {\n // The code in here will probably be run after the `next` below this block\n // and could possibly be run after the console.log(\"Hola\") in `preTwo\n if (err) return doneOne(err);\n if (isValid) doneOne();\n });\n next(); // Pass control to the next middleware\n });\n \n // We will suppose that we need 2 different remote services to validate our document\n Document.pre('save', true, function preTwo (next, doneTwo, callback) {\n remoteServiceTwo.validate(this.serialize(), function (err, isValid) {\n if (err) return doneTwo(err);\n if (isValid) doneTwo();\n });\n next();\n });\n \n // While preOne and preTwo are parallel, preThree is a serial pre middleware\n Document.pre('save', function preThree (next, callback) {\n next();\n });\n \n var doc = new Document();\n doc.save( function (err, doc) {\n // Do stuff with the saved doc here...\n });\n\nIn the above example, flow control may happen in the following way:\n\n(1) doc.save -> (2) preOne --(next)--> (3) preTwo --(next)--> (4) preThree --(next)--> (wait for dones to invoke) -> (5) doneTwo -> (6) doneOne -> (7) targetFn\n\nSo what's happening is that:\n\n1. You call `doc.save(...)`\n2. First, your preOne middleware gets executed. It makes a remote call to the validation service and `next()`s to the preTwo middleware.\n3. Now, your preTwo middleware gets executed. It makes a remote call to another validation service and `next()`s to the preThree middleware.\n4. Your preThree middleware gets executed. It immediately `next()`s. But nothing else gets executing until both `doneOne` and `doneTwo` are invoked inside the callbacks handling the response from the two valiation services.\n5. We will suppose that validation remoteServiceTwo returns a response to us first. In this case, we call `doneTwo` inside the callback to remoteServiceTwo.\n6. Some fractions of a second later, remoteServiceOne returns a response to us. In this case, we call `doneOne` inside the callback to remoteServiceOne.\n7. `hooks` implementation keeps track of how many parallel middleware has been defined per target function. It detects that both asynchronous pre middlewares (`preOne` and `preTwo`) have finally called their `done` functions (`doneOne` and `doneTwo`), so the implementation finally invokes our `targetFn` (i.e., our core `save` business logic).\n\n## Removing Pres\n\nYou can remove a particular pre associated with a hook:\n\n Document.pre('set', someFn);\n Document.removePre('set', someFn);\n\nAnd you can also remove all pres associated with a hook:\n Document.removePre('set'); // Removes all declared `pre`s on the hook 'set'\n\n## Tests\nTo run the tests:\n make test\n\n### Contributors\n- [Brian Noguchi](https://github.com/bnoguchi)\n\n### License\nMIT License\n\n---\n### Author\nBrian Noguchi\n",
+ "readmeFilename": "README.md",
+ "_id": "hooks@0.2.1",
+ "dist": {
+ "shasum": "f84022ce913384a20369adb2d062761465f6b931"
+ },
+ "_from": "hooks@0.2.1"
+}
diff --git a/test/node_modules/mongoose/node_modules/hooks/test.js b/test/node_modules/mongoose/node_modules/hooks/test.js
new file mode 100644
index 0000000..efe2f3e
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/hooks/test.js
@@ -0,0 +1,691 @@
+var hooks = require('./hooks')
+ , should = require('should')
+ , assert = require('assert')
+ , _ = require('underscore');
+
+// TODO Add in test for making sure all pres get called if pre is defined directly on an instance.
+// TODO Test for calling `done` twice or `next` twice in the same function counts only once
+module.exports = {
+ 'should be able to assign multiple hooks at once': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook({
+ hook1: function (a) {},
+ hook2: function (b) {}
+ });
+ var a = new A();
+ assert.equal(typeof a.hook1, 'function');
+ assert.equal(typeof a.hook2, 'function');
+ },
+ 'should run without pres and posts when not present': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ },
+ 'should run with pres when present': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.preValue = 2;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ a.preValue.should.equal(2);
+ },
+ 'should run with posts when present': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.post('save', function (next) {
+ this.value = 2;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(2);
+ },
+ 'should run pres and posts when present': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.preValue = 2;
+ next();
+ });
+ A.post('save', function (next) {
+ this.value = 3;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(3);
+ a.preValue.should.equal(2);
+ },
+ 'should run posts after pres': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.override = 100;
+ next();
+ });
+ A.post('save', function (next) {
+ this.override = 200;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ a.override.should.equal(200);
+ },
+ 'should not run a hook if a pre fails': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function () {
+ this.value = 1;
+ }, function (err) {
+ counter++;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save();
+ counter.should.equal(1);
+ assert.equal(typeof a.value, 'undefined');
+ },
+ 'should be able to run multiple pres': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.v1 = 1;
+ next();
+ }).pre('save', function (next) {
+ this.v2 = 2;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.v1.should.equal(1);
+ a.v2.should.equal(2);
+ },
+ 'should run multiple pres until a pre fails and not call the hook': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ }, function (err) {});
+ A.pre('save', function (next) {
+ this.v1 = 1;
+ next();
+ }).pre('save', function (next) {
+ next(new Error());
+ }).pre('save', function (next) {
+ this.v3 = 3;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.v1.should.equal(1);
+ assert.equal(typeof a.v3, 'undefined');
+ assert.equal(typeof a.value, 'undefined');
+ },
+ 'should be able to run multiple posts': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.post('save', function (next) {
+ this.value = 2;
+ next();
+ }).post('save', function (next) {
+ this.value = 3.14;
+ next();
+ }).post('save', function (next) {
+ this.v3 = 3;
+ next();
+ });
+ var a = new A();
+ a.save();
+ assert.equal(a.value, 3.14);
+ assert.equal(a.v3, 3);
+ },
+ 'should run only posts up until an error': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ }, function (err) {});
+ A.post('save', function (next) {
+ this.value = 2;
+ next();
+ }).post('save', function (next) {
+ this.value = 3;
+ next(new Error());
+ }).post('save', function (next) {
+ this.value = 4;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(3);
+ },
+ "should fall back first to the hook method's last argument as the error handler if it is a function of arity 1 or 2": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (callback) {
+ this.value = 1;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save( function (err) {
+ if (err instanceof Error) counter++;
+ });
+ counter.should.equal(1);
+ should.deepEqual(undefined, a.value);
+ },
+ 'should fall back second to the default error handler if specified': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (callback) {
+ this.value = 1;
+ }, function (err) {
+ if (err instanceof Error) counter++;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save();
+ counter.should.equal(1);
+ should.deepEqual(undefined, a.value);
+ },
+ 'fallback default error handler should scope to the object': function () {
+ var A = function () {
+ this.counter = 0;
+ };
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (callback) {
+ this.value = 1;
+ }, function (err) {
+ if (err instanceof Error) this.counter++;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ a.save();
+ a.counter.should.equal(1);
+ should.deepEqual(undefined, a.value);
+ },
+ 'should fall back last to throwing the error': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.hook('save', function (err) {
+ if (err instanceof Error) return counter++;
+ this.value = 1;
+ });
+ A.pre('save', true, function (next, done) {
+ next(new Error());
+ });
+ var a = new A();
+ var didCatch = false;
+ try {
+ a.save();
+ } catch (e) {
+ didCatch = true;
+ e.should.be.an.instanceof(Error);
+ counter.should.equal(0);
+ assert.equal(typeof a.value, 'undefined');
+ }
+ didCatch.should.be.true;
+ },
+ "should proceed without mutating arguments if `next(null|undefined)` is called in a serial pre, and the last argument of the target method is a callback with node-like signature function (err, obj) {...} or function (err) {...}": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ var counter = 0;
+ A.prototype.save = function (callback) {
+ this.value = 1;
+ callback();
+ };
+ A.pre('save', function (next) {
+ next(null);
+ });
+ A.pre('save', function (next) {
+ next(undefined);
+ });
+ var a = new A();
+ a.save( function (err) {
+ if (err instanceof Error) counter++;
+ else counter--;
+ });
+ counter.should.equal(-1);
+ a.value.should.eql(1);
+ },
+ "should proceed with mutating arguments if `next(null|undefined)` is callback in a serial pre, and the last argument of the target method is not a function": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.prototype.set = function (v) {
+ this.value = v;
+ };
+ A.pre('set', function (next) {
+ next(undefined);
+ });
+ A.pre('set', function (next) {
+ next(null);
+ });
+ var a = new A();
+ a.set(1);
+ should.strictEqual(null, a.value);
+ },
+ 'should not run any posts if a pre fails': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 2;
+ }, function (err) {});
+ A.pre('save', function (next) {
+ this.value = 1;
+ next(new Error());
+ }).post('save', function (next) {
+ this.value = 3;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ },
+
+ "can pass the hook's arguments verbatim to pres": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ this[path] = val;
+ });
+ A.pre('set', function (next, path, val) {
+ path.should.equal('hello');
+ val.should.equal('world');
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ a.hello.should.equal('world');
+ },
+// "can pass the hook's arguments as an array to pres": function () {
+// // Great for dynamic arity - e.g., slice(...)
+// var A = function () {};
+// _.extend(A, hooks);
+// A.hook('set', function (path, val) {
+// this[path] = val;
+// });
+// A.pre('set', function (next, hello, world) {
+// hello.should.equal('hello');
+// world.should.equal('world');
+// next();
+// });
+// var a = new A();
+// a.set('hello', 'world');
+// assert.equal(a.hello, 'world');
+// },
+ "can pass the hook's arguments verbatim to posts": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ this[path] = val;
+ });
+ A.post('set', function (next, path, val) {
+ path.should.equal('hello');
+ val.should.equal('world');
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ assert.equal(a.hello, 'world');
+ },
+// "can pass the hook's arguments as an array to posts": function () {
+// var A = function () {};
+// _.extend(A, hooks);
+// A.hook('set', function (path, val) {
+// this[path] = val;
+// });
+// A.post('set', function (next, halt, args) {
+// assert.equal(args[0], 'hello');
+// assert.equal(args[1], 'world');
+// next();
+// });
+// var a = new A();
+// a.set('hello', 'world');
+// assert.equal(a.hello, 'world');
+// },
+ "pres should be able to modify and pass on a modified version of the hook's arguments": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ this[path] = val;
+ assert.equal(arguments[2], 'optional');
+ });
+ A.pre('set', function (next, path, val) {
+ next('foo', 'bar');
+ });
+ A.pre('set', function (next, path, val) {
+ assert.equal(path, 'foo');
+ assert.equal(val, 'bar');
+ next('rock', 'says', 'optional');
+ });
+ A.pre('set', function (next, path, val, opt) {
+ assert.equal(path, 'rock');
+ assert.equal(val, 'says');
+ assert.equal(opt, 'optional');
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ assert.equal(typeof a.hello, 'undefined');
+ a.rock.should.equal('says');
+ },
+ 'posts should see the modified version of arguments if the pres modified them': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ this[path] = val;
+ });
+ A.pre('set', function (next, path, val) {
+ next('foo', 'bar');
+ });
+ A.post('set', function (next, path, val) {
+ path.should.equal('foo');
+ val.should.equal('bar');
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ assert.equal(typeof a.hello, 'undefined');
+ a.foo.should.equal('bar');
+ },
+ 'should pad missing arguments (relative to expected arguments of the hook) with null': function () {
+ // Otherwise, with hookFn = function (a, b, next, ),
+ // if we use hookFn(a), then because the pre functions are of the form
+ // preFn = function (a, b, next, ), then it actually gets executed with
+ // preFn(a, next, ), so when we call next() from within preFn, we are actually
+ // calling ()
+
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val, opts) {
+ this[path] = val;
+ });
+ A.pre('set', function (next, path, val, opts) {
+ next('foo', 'bar');
+ assert.equal(typeof opts, 'undefined');
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ },
+
+ 'should not invoke the target method until all asynchronous middleware have invoked dones': function () {
+ var counter = 0;
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ counter++;
+ this[path] = val;
+ counter.should.equal(7);
+ });
+ A.pre('set', function (next, path, val) {
+ counter++;
+ next();
+ });
+ A.pre('set', true, function (next, done, path, val) {
+ counter++;
+ setTimeout(function () {
+ counter++;
+ done();
+ }, 1000);
+ next();
+ });
+ A.pre('set', function (next, path, val) {
+ counter++;
+ next();
+ });
+ A.pre('set', true, function (next, done, path, val) {
+ counter++;
+ setTimeout(function () {
+ counter++;
+ done();
+ }, 500);
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ },
+
+ 'invoking a method twice should run its async middleware twice': function () {
+ var counter = 0;
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val) {
+ this[path] = val;
+ if (path === 'hello') counter.should.equal(1);
+ if (path === 'foo') counter.should.equal(2);
+ });
+ A.pre('set', true, function (next, done, path, val) {
+ setTimeout(function () {
+ counter++;
+ done();
+ }, 1000);
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world');
+ a.set('foo', 'bar');
+ },
+
+ 'calling the same done multiple times should have the effect of only calling it once': function () {
+ var A = function () {
+ this.acked = false;
+ };
+ _.extend(A, hooks);
+ A.hook('ack', function () {
+ console.log("UH OH, YOU SHOULD NOT BE SEEING THIS");
+ this.acked = true;
+ });
+ A.pre('ack', true, function (next, done) {
+ next();
+ done();
+ done();
+ });
+ A.pre('ack', true, function (next, done) {
+ next();
+ // Notice that done() is not invoked here
+ });
+ var a = new A();
+ a.ack();
+ setTimeout( function () {
+ a.acked.should.be.false;
+ }, 1000);
+ },
+
+ 'calling the same next multiple times should have the effect of only calling it once': function (beforeExit) {
+ var A = function () {
+ this.acked = false;
+ };
+ _.extend(A, hooks);
+ A.hook('ack', function () {
+ console.log("UH OH, YOU SHOULD NOT BE SEEING THIS");
+ this.acked = true;
+ });
+ A.pre('ack', function (next) {
+ // force a throw to re-exec next()
+ try {
+ next(new Error('bam'));
+ } catch (err) {
+ next();
+ }
+ });
+ A.pre('ack', function (next) {
+ next();
+ });
+ var a = new A();
+ a.ack();
+ beforeExit( function () {
+ a.acked.should.be.false;
+ });
+ },
+
+ 'asynchronous middleware should be able to pass an error via `done`, stopping the middleware chain': function () {
+ var counter = 0;
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('set', function (path, val, fn) {
+ counter++;
+ this[path] = val;
+ fn(null);
+ });
+ A.pre('set', true, function (next, done, path, val, fn) {
+ setTimeout(function () {
+ counter++;
+ done(new Error);
+ }, 1000);
+ next();
+ });
+ var a = new A();
+ a.set('hello', 'world', function (err) {
+ err.should.be.an.instanceof(Error);
+ should.strictEqual(undefined, a['hello']);
+ counter.should.eql(1);
+ });
+ },
+
+ 'should be able to remove a particular pre': function () {
+ var A = function () {}
+ , preTwo;
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.preValueOne = 2;
+ next();
+ });
+ A.pre('save', preTwo = function (next) {
+ this.preValueTwo = 4;
+ next();
+ });
+ A.removePre('save', preTwo);
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ a.preValueOne.should.equal(2);
+ should.strictEqual(undefined, a.preValueTwo);
+ },
+
+ 'should be able to remove all pres associated with a hook': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.hook('save', function () {
+ this.value = 1;
+ });
+ A.pre('save', function (next) {
+ this.preValueOne = 2;
+ next();
+ });
+ A.pre('save', function (next) {
+ this.preValueTwo = 4;
+ next();
+ });
+ A.removePre('save');
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ should.strictEqual(undefined, a.preValueOne);
+ should.strictEqual(undefined, a.preValueTwo);
+ },
+
+ '#pre should lazily make a method hookable': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.prototype.save = function () {
+ this.value = 1;
+ };
+ A.pre('save', function (next) {
+ this.preValue = 2;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(1);
+ a.preValue.should.equal(2);
+ },
+
+ '#pre lazily making a method hookable should be able to provide a default errorHandler as the last argument': function () {
+ var A = function () {};
+ var preValue = "";
+ _.extend(A, hooks);
+ A.prototype.save = function () {
+ this.value = 1;
+ };
+ A.pre('save', function (next) {
+ next(new Error);
+ }, function (err) {
+ preValue = 'ERROR';
+ });
+ var a = new A();
+ a.save();
+ should.strictEqual(undefined, a.value);
+ preValue.should.equal('ERROR');
+ },
+
+ '#post should lazily make a method hookable': function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.prototype.save = function () {
+ this.value = 1;
+ };
+ A.post('save', function (next) {
+ this.value = 2;
+ next();
+ });
+ var a = new A();
+ a.save();
+ a.value.should.equal(2);
+ },
+
+ "a lazy hooks setup should handle errors via a method's last argument, if it's a callback": function () {
+ var A = function () {};
+ _.extend(A, hooks);
+ A.prototype.save = function (fn) {};
+ A.pre('save', function (next) {
+ next(new Error("hi there"));
+ });
+ var a = new A();
+ a.save( function (err) {
+ err.should.be.an.instanceof(Error);
+ });
+ }
+};
diff --git a/test/node_modules/mongoose/node_modules/mongodb/.travis.yml b/test/node_modules/mongoose/node_modules/mongodb/.travis.yml
new file mode 100644
index 0000000..94740d0
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9 # development version of 0.8, may be unstable
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md b/test/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md
new file mode 100644
index 0000000..2a1c52e
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md
@@ -0,0 +1,23 @@
+## Contributing to the driver
+
+### Bugfixes
+
+- Before starting to write code, look for existing [tickets](https://github.com/mongodb/node-mongodb-native/issues) or [create one](https://github.com/mongodb/node-mongodb-native/issues/new) for your specific issue. That way you avoid working on something that might not be of interest or that has been addressed already in a different branch.
+- Fork the [repo](https://github.com/mongodb/node-mongodb-native) _or_ for small documentation changes, navigate to the source on github and click the [Edit](https://github.com/blog/844-forking-with-the-edit-button) button.
+- Follow the general coding style of the rest of the project:
+ - 2 space tabs
+ - no trailing whitespace
+ - comma last
+ - inline documentation for new methods, class members, etc
+ - 0 space between conditionals/functions, and their parenthesis and curly braces
+ - `if(..) {`
+ - `for(..) {`
+ - `while(..) {`
+ - `function(err) {`
+- Write tests and make sure they pass (execute `make test` from the cmd line to run the test suite).
+
+### Documentation
+
+To contribute to the [API documentation](http://mongodb.github.com/node-mongodb-native/) just make your changes to the inline documentation of the appropriate [source code](https://github.com/mongodb/node-mongodb-native/tree/master/docs) in the master branch and submit a [pull request](https://help.github.com/articles/using-pull-requests/). You might also use the github [Edit](https://github.com/blog/844-forking-with-the-edit-button) button.
+
+If you'd like to preview your documentation changes, first commit your changes to your local master branch, then execute `make generate_docs`. Make sure you have the python documentation framework sphinx installed `easy_install sphinx`. The docs are generated under `docs/build'. If all looks good, submit a [pull request](https://help.github.com/articles/using-pull-requests/) to the master branch with your changes.
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/Makefile b/test/node_modules/mongoose/node_modules/mongodb/Makefile
new file mode 100644
index 0000000..ac55626
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/Makefile
@@ -0,0 +1,64 @@
+NODE = node
+NPM = npm
+NODEUNIT = node_modules/nodeunit/bin/nodeunit
+DOX = node_modules/dox/bin/dox
+name = all
+
+total: build_native
+
+test-coverage:
+ rm -rf lib-cov/
+ jscoverage lib/ lib-cov/
+ @TEST_COVERAGE=true nodeunit test/ test/gridstore test/connection
+
+build_native:
+
+test: build_native
+ @echo "\n == Run All tests minus replicaset tests=="
+ $(NODE) dev/tools/test_all.js --noreplicaset --boot
+
+test_pure: build_native
+ @echo "\n == Run All tests minus replicaset tests=="
+ $(NODE) dev/tools/test_all.js --noreplicaset --boot --nonative
+
+test_junit: build_native
+ @echo "\n == Run All tests minus replicaset tests=="
+ $(NODE) dev/tools/test_all.js --junit --noreplicaset --nokill
+
+jenkins: build_native
+ @echo "\n == Run All tests minus replicaset tests=="
+ $(NODE) dev/tools/test_all.js --junit --noreplicaset --nokill
+
+test_nodeunit_pure:
+ @echo "\n == Execute Test Suite using Pure JS BSON Parser == "
+ @$(NODEUNIT) test/ test/gridstore test/bson
+
+test_nodeunit_replicaset_pure:
+ @echo "\n == Execute Test Suite using Pure JS BSON Parser == "
+ @$(NODEUNIT) test/replicaset
+
+test_nodeunit_native:
+ @echo "\n == Execute Test Suite using Native BSON Parser == "
+ @TEST_NATIVE=TRUE $(NODEUNIT) test/ test/gridstore test/bson
+
+test_nodeunit_replicaset_native:
+ @echo "\n == Execute Test Suite using Native BSON Parser == "
+ @TEST_NATIVE=TRUE $(NODEUNIT) test/replicaset
+
+test_all: build_native
+ @echo "\n == Run All tests =="
+ $(NODE) dev/tools/test_all.js --boot
+
+test_all_junit: build_native
+ @echo "\n == Run All tests =="
+ $(NODE) dev/tools/test_all.js --junit --boot
+
+clean:
+ rm ./external-libs/bson/bson.node
+ rm -r ./external-libs/bson/build
+
+generate_docs:
+ $(NODE) dev/tools/build-docs.js
+ make --directory=./docs/sphinx-docs --file=Makefile html
+
+.PHONY: total
diff --git a/test/node_modules/mongoose/node_modules/mongodb/Readme.md b/test/node_modules/mongoose/node_modules/mongodb/Readme.md
new file mode 100644
index 0000000..b81e719
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/Readme.md
@@ -0,0 +1,442 @@
+Up to date documentation
+========================
+
+[Documentation](http://mongodb.github.com/node-mongodb-native/)
+
+Install
+=======
+
+To install the most recent release from npm, run:
+
+ npm install mongodb
+
+That may give you a warning telling you that bugs['web'] should be bugs['url'], it would be safe to ignore it (this has been fixed in the development version)
+
+To install the latest from the repository, run::
+
+ npm install path/to/node-mongodb-native
+
+Community
+=========
+Check out the google group [node-mongodb-native](http://groups.google.com/group/node-mongodb-native) for questions/answers from users of the driver.
+
+Try it live
+============
+
+
+Introduction
+============
+
+This is a node.js driver for MongoDB. It's a port (or close to a port) of the library for ruby at http://github.com/mongodb/mongo-ruby-driver/.
+
+A simple example of inserting a document.
+
+```javascript
+ var client = new Db('test', new Server("127.0.0.1", 27017, {}), {w: 1}),
+ test = function (err, collection) {
+ collection.insert({a:2}, function(err, docs) {
+
+ collection.count(function(err, count) {
+ test.assertEquals(1, count);
+ });
+
+ // Locate all the entries using find
+ collection.find().toArray(function(err, results) {
+ test.assertEquals(1, results.length);
+ test.assertTrue(results[0].a === 2);
+
+ // Let's close the db
+ client.close();
+ });
+ });
+ };
+
+ client.open(function(err, p_client) {
+ client.collection('test_insert', test);
+ });
+```
+
+Data types
+==========
+
+To store and retrieve the non-JSON MongoDb primitives ([ObjectID](http://www.mongodb.org/display/DOCS/Object+IDs), Long, Binary, [Timestamp](http://www.mongodb.org/display/DOCS/Timestamp+data+type), [DBRef](http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef), Code).
+
+In particular, every document has a unique `_id` which can be almost any type, and by default a 12-byte ObjectID is created. ObjectIDs can be represented as 24-digit hexadecimal strings, but you must convert the string back into an ObjectID before you can use it in the database. For example:
+
+```javascript
+ // Get the objectID type
+ var ObjectID = require('mongodb').ObjectID;
+
+ var idString = '4e4e1638c85e808431000003';
+ collection.findOne({_id: new ObjectID(idString)}, console.log) // ok
+ collection.findOne({_id: idString}, console.log) // wrong! callback gets undefined
+```
+
+Here are the constructors the non-Javascript BSON primitive types:
+
+```javascript
+ // Fetch the library
+ var mongo = require('mongodb');
+ // Create new instances of BSON types
+ new mongo.Long(numberString)
+ new mongo.ObjectID(hexString)
+ new mongo.Timestamp() // the actual unique number is generated on insert.
+ new mongo.DBRef(collectionName, id, dbName)
+ new mongo.Binary(buffer) // takes a string or Buffer
+ new mongo.Code(code, [context])
+ new mongo.Symbol(string)
+ new mongo.MinKey()
+ new mongo.MaxKey()
+ new mongo.Double(number) // Force double storage
+```
+
+The C/C++ bson parser/serializer
+--------------------------------
+
+If you are running a version of this library has the C/C++ parser compiled, to enable the driver to use the C/C++ bson parser pass it the option native_parser:true like below
+
+```javascript
+ // using native_parser:
+ var client = new Db('integration_tests_20',
+ new Server("127.0.0.1", 27017),
+ {native_parser:true});
+```
+
+The C++ parser uses the js objects both for serialization and deserialization.
+
+GitHub information
+==================
+
+The source code is available at http://github.com/mongodb/node-mongodb-native.
+You can either clone the repository or download a tarball of the latest release.
+
+Once you have the source you can test the driver by running
+
+ $ make test
+
+in the main directory. You will need to have a mongo instance running on localhost for the integration tests to pass.
+
+Examples
+========
+
+For examples look in the examples/ directory. You can execute the examples using node.
+
+ $ cd examples
+ $ node queries.js
+
+GridStore
+=========
+
+The GridStore class allows for storage of binary files in mongoDB using the mongoDB defined files and chunks collection definition.
+
+For more information have a look at [Gridstore](https://github.com/mongodb/node-mongodb-native/blob/master/docs/gridfs.md)
+
+Replicasets
+===========
+For more information about how to connect to a replicaset have a look at [Replicasets](https://github.com/mongodb/node-mongodb-native/blob/master/docs/replicaset.md)
+
+Primary Key Factories
+---------------------
+
+Defining your own primary key factory allows you to generate your own series of id's
+(this could f.ex be to use something like ISBN numbers). The generated the id needs to be a 12 byte long "string".
+
+Simple example below
+
+```javascript
+ // Custom factory (need to provide a 12 byte array);
+ CustomPKFactory = function() {}
+ CustomPKFactory.prototype = new Object();
+ CustomPKFactory.createPk = function() {
+ return new ObjectID("aaaaaaaaaaaa");
+ }
+
+ var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});
+ p_client.open(function(err, p_client) {
+ p_client.dropDatabase(function(err, done) {
+ p_client.createCollection('test_custom_key', function(err, collection) {
+ collection.insert({'a':1}, function(err, docs) {
+ collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) {
+ cursor.toArray(function(err, items) {
+ test.assertEquals(1, items.length);
+
+ // Let's close the db
+ p_client.close();
+ });
+ });
+ });
+ });
+ });
+ });
+```
+
+Strict mode
+-----------
+
+Each database has an optional strict mode. If it is set then asking for a collection
+that does not exist will return an Error object in the callback. Similarly if you
+attempt to create a collection that already exists. Strict is provided for convenience.
+
+```javascript
+ var error_client = new Db('integration_tests_', new Server("127.0.0.1", 27017, {auto_reconnect: false}), {strict:true});
+ test.assertEquals(true, error_client.strict);
+
+ error_client.open(function(err, error_client) {
+ error_client.collection('does-not-exist', function(err, collection) {
+ test.assertTrue(err instanceof Error);
+ test.assertEquals("Collection does-not-exist does not exist. Currently in strict mode.", err.message);
+ });
+
+ error_client.createCollection('test_strict_access_collection', function(err, collection) {
+ error_client.collection('test_strict_access_collection', function(err, collection) {
+ test.assertTrue(collection instanceof Collection);
+ // Let's close the db
+ error_client.close();
+ });
+ });
+ });
+```
+
+Documentation
+=============
+
+If this document doesn't answer your questions, see the source of
+[Collection](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/collection.js)
+or [Cursor](https://github.com/mongodb/node-mongodb-native/blob/master/lib/mongodb/cursor.js),
+or the documentation at MongoDB for query and update formats.
+
+Find
+----
+
+The find method is actually a factory method to create
+Cursor objects. A Cursor lazily uses the connection the first time
+you call `nextObject`, `each`, or `toArray`.
+
+The basic operation on a cursor is the `nextObject` method
+that fetches the next matching document from the database. The convenience
+methods `each` and `toArray` call `nextObject` until the cursor is exhausted.
+
+Signatures:
+
+```javascript
+ var cursor = collection.find(query, [fields], options);
+ cursor.sort(fields).limit(n).skip(m).
+
+ cursor.nextObject(function(err, doc) {});
+ cursor.each(function(err, doc) {});
+ cursor.toArray(function(err, docs) {});
+
+ cursor.rewind() // reset the cursor to its initial state.
+```
+
+Useful chainable methods of cursor. These can optionally be options of `find` instead of method calls:
+
+* `.limit(n).skip(m)` to control paging.
+* `.sort(fields)` Order by the given fields. There are several equivalent syntaxes:
+ * `.sort({field1: -1, field2: 1})` descending by field1, then ascending by field2.
+ * `.sort([['field1', 'desc'], ['field2', 'asc']])` same as above
+ * `.sort([['field1', 'desc'], 'field2'])` same as above
+ * `.sort('field1')` ascending by field1
+
+Other options of `find`:
+
+* `fields` the fields to fetch (to avoid transferring the entire document)
+* `tailable` if true, makes the cursor [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors).
+* `batchSize` The number of the subset of results to request the database
+to return for every request. This should initially be greater than 1 otherwise
+the database will automatically close the cursor. The batch size can be set to 1
+with `batchSize(n, function(err){})` after performing the initial query to the database.
+* `hint` See [Optimization: hint](http://www.mongodb.org/display/DOCS/Optimization#Optimization-Hint).
+* `explain` turns this into an explain query. You can also call
+`explain()` on any cursor to fetch the explanation.
+* `snapshot` prevents documents that are updated while the query is active
+from being returned multiple times. See more
+[details about query snapshots](http://www.mongodb.org/display/DOCS/How+to+do+Snapshotted+Queries+in+the+Mongo+Database).
+* `timeout` if false, asks MongoDb not to time out this cursor after an
+inactivity period.
+
+
+For information on how to create queries, see the
+[MongoDB section on querying](http://www.mongodb.org/display/DOCS/Querying).
+
+```javascript
+ var mongodb = require('mongodb');
+ var server = new mongodb.Server("127.0.0.1", 27017, {});
+ new mongodb.Db('test', server, {}).open(function (error, client) {
+ if (error) throw error;
+ var collection = new mongodb.Collection(client, 'test_collection');
+ collection.find({}, {limit:10}).toArray(function(err, docs) {
+ console.dir(docs);
+ });
+ });
+```
+
+Insert
+------
+
+Signature:
+
+```javascript
+ collection.insert(docs, options, [callback]);
+```
+
+where `docs` can be a single document or an array of documents.
+
+Useful options:
+
+* `safe:true` Should always set if you have a callback.
+
+See also: [MongoDB docs for insert](http://www.mongodb.org/display/DOCS/Inserting).
+
+```javascript
+ var mongodb = require('mongodb');
+ var server = new mongodb.Server("127.0.0.1", 27017, {});
+ new mongodb.Db('test', server, {w: 1}).open(function (error, client) {
+ if (error) throw error;
+ var collection = new mongodb.Collection(client, 'test_collection');
+ collection.insert({hello: 'world'}, {safe:true},
+ function(err, objects) {
+ if (err) console.warn(err.message);
+ if (err && err.message.indexOf('E11000 ') !== -1) {
+ // this _id was already inserted in the database
+ }
+ });
+ });
+```
+
+Note that there's no reason to pass a callback to the insert or update commands
+unless you use the `safe:true` option. If you don't specify `safe:true`, then
+your callback will be called immediately.
+
+Update; update and insert (upsert)
+----------------------------------
+
+The update operation will update the first document that matches your query
+(or all documents that match if you use `multi:true`).
+If `safe:true`, `upsert` is not set, and no documents match, your callback will return 0 documents updated.
+
+See the [MongoDB docs](http://www.mongodb.org/display/DOCS/Updating) for
+the modifier (`$inc`, `$set`, `$push`, etc.) formats.
+
+Signature:
+
+```javascript
+ collection.update(criteria, objNew, options, [callback]);
+```
+
+Useful options:
+
+* `safe:true` Should always set if you have a callback.
+* `multi:true` If set, all matching documents are updated, not just the first.
+* `upsert:true` Atomically inserts the document if no documents matched.
+
+Example for `update`:
+
+```javascript
+ var mongodb = require('mongodb');
+ var server = new mongodb.Server("127.0.0.1", 27017, {});
+ new mongodb.Db('test', server, {w: 1}).open(function (error, client) {
+ if (error) throw error;
+ var collection = new mongodb.Collection(client, 'test_collection');
+ collection.update({hi: 'here'}, {$set: {hi: 'there'}}, {safe:true},
+ function(err) {
+ if (err) console.warn(err.message);
+ else console.log('successfully updated');
+ });
+ });
+```
+
+Find and modify
+---------------
+
+`findAndModify` is like `update`, but it also gives the updated document to
+your callback. But there are a few key differences between findAndModify and
+update:
+
+ 1. The signatures differ.
+ 2. You can only findAndModify a single item, not multiple items.
+
+Signature:
+
+```javascript
+ collection.findAndModify(query, sort, update, options, callback)
+```
+
+The sort parameter is used to specify which object to operate on, if more than
+one document matches. It takes the same format as the cursor sort (see
+Connection.find above).
+
+See the
+[MongoDB docs for findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command)
+for more details.
+
+Useful options:
+
+* `remove:true` set to a true to remove the object before returning
+* `new:true` set to true if you want to return the modified object rather than the original. Ignored for remove.
+* `upsert:true` Atomically inserts the document if no documents matched.
+
+Example for `findAndModify`:
+
+```javascript
+ var mongodb = require('mongodb');
+ var server = new mongodb.Server("127.0.0.1", 27017, {});
+ new mongodb.Db('test', server, {w: 1}).open(function (error, client) {
+ if (error) throw error;
+ var collection = new mongodb.Collection(client, 'test_collection');
+ collection.findAndModify({hello: 'world'}, [['_id','asc']], {$set: {hi: 'there'}}, {},
+ function(err, object) {
+ if (err) console.warn(err.message);
+ else console.dir(object); // undefined if no matching object exists.
+ });
+ });
+```
+
+Save
+----
+
+The `save` method is a shorthand for upsert if the document contains an
+`_id`, or an insert if there is no `_id`.
+
+Sponsors
+========
+Just as Felix Geisendörfer I'm also working on the driver for my own startup and this driver is a big project that also benefits other companies who are using MongoDB.
+
+If your company could benefit from a even better-engineered node.js mongodb driver I would appreciate any type of sponsorship you may be able to provide. All the sponsors will get a lifetime display in this readme, priority support and help on problems and votes on the roadmap decisions for the driver. If you are interested contact me on [christkv AT g m a i l.com](mailto:christkv@gmail.com) for details.
+
+And I'm very thankful for code contributions. If you are interested in working on features please contact me so we can discuss API design and testing.
+
+Release Notes
+=============
+
+See HISTORY
+
+Credits
+=======
+
+1. [10gen](http://github.com/mongodb/mongo-ruby-driver/)
+2. [Google Closure Library](http://code.google.com/closure/library/)
+3. [Jonas Raoni Soares Silva](http://jsfromhell.com/classes/binary-parser)
+
+Contributors
+============
+
+Aaron Heckmann, Christoph Pojer, Pau Ramon Revilla, Nathan White, Emmerman, Seth LaForge, Boris Filipov, Stefan Schärmeli, Tedde Lundgren, renctan, Sergey Ukustov, Ciaran Jessup, kuno, srimonti, Erik Abele, Pratik Daga, Slobodan Utvic, Kristina Chodorow, Yonathan Randolph, Brian Noguchi, Sam Epstein, James Harrison Fisher, Vladimir Dronnikov, Ben Hockey, Henrik Johansson, Simon Weare, Alex Gorbatchev, Shimon Doodkin, Kyle Mueller, Eran Hammer-Lahav, Marcin Ciszak, François de Metz, Vinay Pulim, nstielau, Adam Wiggins, entrinzikyl, Jeremy Selier, Ian Millington, Public Keating, andrewjstone, Christopher Stott, Corey Jewett, brettkiefer, Rob Holland, Senmiao Liu, heroic, gitfy
+
+License
+=======
+
+ Copyright 2009 - 2012 Christian Amor Kvalheim.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/test/node_modules/mongoose/node_modules/mongodb/index.js b/test/node_modules/mongoose/node_modules/mongodb/index.js
new file mode 100644
index 0000000..4f59e9d
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/index.js
@@ -0,0 +1 @@
+module.exports = require('./lib/mongodb');
diff --git a/test/node_modules/mongoose/node_modules/mongodb/install.js b/test/node_modules/mongoose/node_modules/mongodb/install.js
new file mode 100644
index 0000000..f9f2a57
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/install.js
@@ -0,0 +1,40 @@
+var spawn = require('child_process').spawn,
+ exec = require('child_process').exec;
+
+process.stdout.write("================================================================================\n");
+process.stdout.write("= =\n");
+process.stdout.write("= To install with C++ bson parser do
+ * {
+ * '_id' : , // {number} id for this chunk
+ * 'files_id' : , // {number} foreign key to the file collection
+ * 'n' : , // {number} chunk number
+ * 'data' : , // {bson#Binary} the chunk data itself
+ * }
+ *
+ *
+ * @see MongoDB GridFS Chunk Object Structure
+ */
+Chunk.prototype.buildMongoObject = function(callback) {
+ var mongoObject = {'_id': this.objectId,
+ 'files_id': this.file.fileId,
+ 'n': this.chunkNumber,
+ 'data': this.data};
+ callback(mongoObject);
+};
+
+/**
+ * @return {number} the length of the data
+ */
+Chunk.prototype.length = function() {
+ return this.data.length();
+};
+
+/**
+ * The position of the read/write head
+ * @name position
+ * @lends Chunk#
+ * @field
+ */
+Object.defineProperty(Chunk.prototype, "position", { enumerable: true
+ , get: function () {
+ return this.internalPosition;
+ }
+ , set: function(value) {
+ this.internalPosition = value;
+ }
+});
+
+/**
+ * The default chunk size
+ * @constant
+ */
+Chunk.DEFAULT_CHUNK_SIZE = 1024 * 256;
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js
new file mode 100644
index 0000000..aa695b7
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/grid.js
@@ -0,0 +1,103 @@
+var GridStore = require('./gridstore').GridStore,
+ ObjectID = require('bson').ObjectID;
+
+/**
+ * A class representation of a simple Grid interface.
+ *
+ * @class Represents the Grid.
+ * @param {Db} db A database instance to interact with.
+ * @param {String} [fsName] optional different root collection for GridFS.
+ * @return {Grid}
+ */
+function Grid(db, fsName) {
+
+ if(!(this instanceof Grid)) return new Grid(db, fsName);
+
+ this.db = db;
+ this.fsName = fsName == null ? GridStore.DEFAULT_ROOT_COLLECTION : fsName;
+}
+
+/**
+ * Puts binary data to the grid
+ *
+ * Options
+ * - **_id** {Any}, unique id for this file
+ * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
+ * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
+ * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
+ * - **metadata** {Object}, arbitrary data the user wants to store.
+ *
+ * @param {Buffer} data buffer with Binary Data.
+ * @param {Object} [options] the options for the files.
+ * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+Grid.prototype.put = function(data, options, callback) {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments, 1);
+ callback = args.pop();
+ options = args.length ? args.shift() : {};
+ // If root is not defined add our default one
+ options['root'] = options['root'] == null ? this.fsName : options['root'];
+
+ // Return if we don't have a buffer object as data
+ if(!(Buffer.isBuffer(data))) return callback(new Error("Data object must be a buffer object"), null);
+ // Get filename if we are using it
+ var filename = options['filename'] || null;
+ // Get id if we are using it
+ var id = options['_id'] || null;
+ // Create gridstore
+ var gridStore = new GridStore(this.db, id, filename, "w", options);
+ gridStore.open(function(err, gridStore) {
+ if(err) return callback(err, null);
+
+ gridStore.write(data, function(err, result) {
+ if(err) return callback(err, null);
+
+ gridStore.close(function(err, result) {
+ if(err) return callback(err, null);
+ callback(null, result);
+ })
+ })
+ })
+}
+
+/**
+ * Get binary data to the grid
+ *
+ * @param {Any} id for file.
+ * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+Grid.prototype.get = function(id, callback) {
+ // Create gridstore
+ var gridStore = new GridStore(this.db, id, null, "r", {root:this.fsName});
+ gridStore.open(function(err, gridStore) {
+ if(err) return callback(err, null);
+
+ // Return the data
+ gridStore.read(function(err, data) {
+ return callback(err, data)
+ });
+ })
+}
+
+/**
+ * Delete file from grid
+ *
+ * @param {Any} id for file.
+ * @param {Function} callback this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+Grid.prototype.delete = function(id, callback) {
+ // Create gridstore
+ GridStore.unlink(this.db, id, {root:this.fsName}, function(err, result) {
+ if(err) return callback(err, false);
+ return callback(null, true);
+ });
+}
+
+exports.Grid = Grid;
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js
new file mode 100644
index 0000000..586a491
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/gridstore.js
@@ -0,0 +1,1486 @@
+/**
+ * @fileOverview GridFS is a tool for MongoDB to store files to the database.
+ * Because of the restrictions of the object size the database can hold, a
+ * facility to split a file into several chunks is needed. The {@link GridStore}
+ * class offers a simplified api to interact with files while managing the
+ * chunks of split files behind the scenes. More information about GridFS can be
+ * found here.
+ */
+var Chunk = require('./chunk').Chunk,
+ DbCommand = require('../commands/db_command').DbCommand,
+ ObjectID = require('bson').ObjectID,
+ Buffer = require('buffer').Buffer,
+ fs = require('fs'),
+ util = require('util'),
+ inherits = util.inherits,
+ ReadStream = require('./readstream').ReadStream,
+ Stream = require('stream');
+
+var REFERENCE_BY_FILENAME = 0,
+ REFERENCE_BY_ID = 1;
+
+/**
+ * A class representation of a file stored in GridFS.
+ *
+ * Modes
+ * - **"r"** - read only. This is the default mode.
+ * - **"w"** - write in truncate mode. Existing data will be overwriten.
+ * - **w+"** - write in edit mode.
+ *
+ * Options
+ * - **root** {String}, root collection to use. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
+ * - **content_type** {String}, mime type of the file. Defaults to **{GridStore.DEFAULT_CONTENT_TYPE}**.
+ * - **chunk_size** {Number}, size for the chunk. Defaults to **{Chunk.DEFAULT_CHUNK_SIZE}**.
+ * - **metadata** {Object}, arbitrary data the user wants to store.
+ *
+ * @class Represents the GridStore.
+ * @param {Db} db A database instance to interact with.
+ * @param {Any} [id] optional unique id for this file
+ * @param {String} [filename] optional filename for this file, no unique constrain on the field
+ * @param {String} mode set the mode for this file.
+ * @param {Object} options optional properties to specify.
+ * @return {GridStore}
+ */
+var GridStore = function GridStore(db, id, filename, mode, options) {
+ if(!(this instanceof GridStore)) return new GridStore(db, id, filename, mode, options);
+
+ var self = this;
+ this.db = db;
+
+ // Call stream constructor
+ if(typeof Stream == 'function') {
+ Stream.call(this);
+ } else {
+ // 0.4.X backward compatibility fix
+ Stream.Stream.call(this);
+ }
+
+ // Handle options
+ if(typeof options === 'undefined') options = {};
+ // Handle mode
+ if(typeof mode === 'undefined') {
+ mode = filename;
+ filename = undefined;
+ } else if(typeof mode == 'object') {
+ options = mode;
+ mode = filename;
+ filename = undefined;
+ }
+
+ if(id instanceof ObjectID) {
+ this.referenceBy = REFERENCE_BY_ID;
+ this.fileId = id;
+ this.filename = filename;
+ } else if(typeof filename == 'undefined') {
+ this.referenceBy = REFERENCE_BY_FILENAME;
+ this.filename = id;
+ if (mode.indexOf('w') != null) {
+ this.fileId = new ObjectID();
+ }
+ } else {
+ this.referenceBy = REFERENCE_BY_ID;
+ this.fileId = id;
+ this.filename = filename;
+ }
+
+ /*
+ // Handle id
+ if(id instanceof ObjectID && (typeof filename == 'string' || filename == null)) {
+ this.referenceBy = REFERENCE_BY_ID;
+ this.fileId = id;
+ this.filename = filename;
+ } else if(!(id instanceof ObjectID) && typeof id == 'string' && mode.indexOf("w") != null) {
+ this.referenceBy = REFERENCE_BY_FILENAME;
+ this.fileId = new ObjectID();
+ this.filename = id;
+ } else if(!(id instanceof ObjectID) && typeof id == 'string' && mode.indexOf("r") != null) {
+ this.referenceBy = REFERENCE_BY_FILENAME;
+ this.filename = id;
+ } else {
+ this.referenceBy = REFERENCE_BY_ID;
+ this.fileId = id;
+ this.filename = filename;
+ }
+ */
+
+ // Set up the rest
+ this.mode = mode == null ? "r" : mode;
+ this.options = options == null ? {} : options;
+ this.root = this.options['root'] == null ? exports.GridStore.DEFAULT_ROOT_COLLECTION : this.options['root'];
+ this.position = 0;
+ // Set default chunk size
+ this.internalChunkSize = this.options['chunkSize'] == null ? Chunk.DEFAULT_CHUNK_SIZE : this.options['chunkSize'];
+}
+
+/**
+ * Code for the streaming capabilities of the gridstore object
+ * Most code from Aaron heckmanns project https://github.com/aheckmann/gridfs-stream
+ * Modified to work on the gridstore object itself
+ * @ignore
+ */
+if(typeof Stream == 'function') {
+ GridStore.prototype = { __proto__: Stream.prototype }
+} else {
+ // Node 0.4.X compatibility code
+ GridStore.prototype = { __proto__: Stream.Stream.prototype }
+}
+
+// Move pipe to _pipe
+GridStore.prototype._pipe = GridStore.prototype.pipe;
+
+/**
+ * Opens the file from the database and initialize this object. Also creates a
+ * new one if file does not exist.
+ *
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain an **{Error}** object and the second parameter will be null if an error occured. Otherwise, the first parameter will be null and the second will contain the reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.open = function(callback) {
+ if( this.mode != "w" && this.mode != "w+" && this.mode != "r"){
+ callback(new Error("Illegal mode " + this.mode), null);
+ return;
+ }
+
+ var self = this;
+
+ if((self.mode == "w" || self.mode == "w+") && self.db.serverConfig.primary != null) {
+ // Get files collection
+ self.collection(function(err, collection) {
+ if(err) return callback(err);
+
+ // Put index on filename
+ collection.ensureIndex([['filename', 1]], function(err, index) {
+ if(err) return callback(err);
+
+ // Get chunk collection
+ self.chunkCollection(function(err, chunkCollection) {
+ if(err) return callback(err);
+
+ // Ensure index on chunk collection
+ chunkCollection.ensureIndex([['files_id', 1], ['n', 1]], function(err, index) {
+ if(err) return callback(err);
+ _open(self, callback);
+ });
+ });
+ });
+ });
+ } else {
+ // Open the gridstore
+ _open(self, callback);
+ }
+};
+
+/**
+ * Hidding the _open function
+ * @ignore
+ * @api private
+ */
+var _open = function(self, callback) {
+ self.collection(function(err, collection) {
+ if(err!==null) {
+ callback(new Error("at collection: "+err), null);
+ return;
+ }
+
+ // Create the query
+ var query = self.referenceBy == REFERENCE_BY_ID ? {_id:self.fileId} : {filename:self.filename};
+ query = null == self.fileId && this.filename == null ? null : query;
+
+ // Fetch the chunks
+ if(query != null) {
+ collection.find(query, function(err, cursor) {
+ if(err) return error(err);
+
+ // Fetch the file
+ cursor.nextObject(function(err, doc) {
+ if(err) return error(err);
+
+ // Check if the collection for the files exists otherwise prepare the new one
+ if(doc != null) {
+ self.fileId = doc._id;
+ self.filename = doc.filename;
+ self.contentType = doc.contentType;
+ self.internalChunkSize = doc.chunkSize;
+ self.uploadDate = doc.uploadDate;
+ self.aliases = doc.aliases;
+ self.length = doc.length;
+ self.metadata = doc.metadata;
+ self.internalMd5 = doc.md5;
+ } else if (self.mode != 'r') {
+ self.fileId = self.fileId == null ? new ObjectID() : self.fileId;
+ self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
+ self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
+ self.length = 0;
+ } else {
+ self.length = 0;
+ var txtId = self.fileId instanceof ObjectID ? self.fileId.toHexString() : self.fileId;
+ return error(new Error((self.referenceBy == REFERENCE_BY_ID ? txtId : self.filename) + " does not exist", self));
+ }
+
+ // Process the mode of the object
+ if(self.mode == "r") {
+ nthChunk(self, 0, function(err, chunk) {
+ if(err) return error(err);
+ self.currentChunk = chunk;
+ self.position = 0;
+ callback(null, self);
+ });
+ } else if(self.mode == "w") {
+ // Delete any existing chunks
+ deleteChunks(self, function(err, result) {
+ if(err) return error(err);
+ self.currentChunk = new Chunk(self, {'n':0});
+ self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
+ self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
+ self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
+ self.position = 0;
+ callback(null, self);
+ });
+ } else if(self.mode == "w+") {
+ nthChunk(self, lastChunkNumber(self), function(err, chunk) {
+ if(err) return error(err);
+ // Set the current chunk
+ self.currentChunk = chunk == null ? new Chunk(self, {'n':0}) : chunk;
+ self.currentChunk.position = self.currentChunk.data.length();
+ self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
+ self.position = self.length;
+ callback(null, self);
+ });
+ }
+ });
+ });
+ } else {
+ // Write only mode
+ self.fileId = null == self.fileId ? new ObjectID() : self.fileId;
+ self.contentType = exports.GridStore.DEFAULT_CONTENT_TYPE;
+ self.internalChunkSize = self.internalChunkSize == null ? Chunk.DEFAULT_CHUNK_SIZE : self.internalChunkSize;
+ self.length = 0;
+
+ self.chunkCollection(function(err, collection2) {
+ if(err) return error(err);
+
+ // No file exists set up write mode
+ if(self.mode == "w") {
+ // Delete any existing chunks
+ deleteChunks(self, function(err, result) {
+ if(err) return error(err);
+ self.currentChunk = new Chunk(self, {'n':0});
+ self.contentType = self.options['content_type'] == null ? self.contentType : self.options['content_type'];
+ self.internalChunkSize = self.options['chunk_size'] == null ? self.internalChunkSize : self.options['chunk_size'];
+ self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
+ self.position = 0;
+ callback(null, self);
+ });
+ } else if(self.mode == "w+") {
+ nthChunk(self, lastChunkNumber(self), function(err, chunk) {
+ if(err) return error(err);
+ // Set the current chunk
+ self.currentChunk = chunk == null ? new Chunk(self, {'n':0}) : chunk;
+ self.currentChunk.position = self.currentChunk.data.length();
+ self.metadata = self.options['metadata'] == null ? self.metadata : self.options['metadata'];
+ self.position = self.length;
+ callback(null, self);
+ });
+ }
+ });
+ }
+ });
+
+ // only pass error to callback once
+ function error (err) {
+ if(error.err) return;
+ callback(error.err = err);
+ }
+};
+
+/**
+ * Stores a file from the file system to the GridFS database.
+ *
+ * @param {String|Buffer|FileHandle} file the file to store.
+ * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the the second will contain the reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.writeFile = function (file, callback) {
+ var self = this;
+ if (typeof file === 'string') {
+ fs.open(file, 'r', 0666, function (err, fd) {
+ if(err) return callback(err);
+ self.writeFile(fd, callback);
+ });
+ return;
+ }
+
+ self.open(function (err, self) {
+ if(err) return callback(err);
+
+ fs.fstat(file, function (err, stats) {
+ if(err) return callback(err);
+
+ var offset = 0;
+ var index = 0;
+ var numberOfChunksLeft = Math.min(stats.size / self.chunkSize);
+
+ // Write a chunk
+ var writeChunk = function() {
+ fs.read(file, self.chunkSize, offset, 'binary', function(err, data, bytesRead) {
+ if(err) return callback(err);
+
+ offset = offset + bytesRead;
+
+ // Create a new chunk for the data
+ var chunk = new Chunk(self, {n:index++});
+ chunk.write(data, function(err, chunk) {
+ if(err) return callback(err);
+
+ chunk.save(function(err, result) {
+ if(err) return callback(err);
+
+ self.position = self.position + data.length;
+
+ // Point to current chunk
+ self.currentChunk = chunk;
+
+ if(offset >= stats.size) {
+ fs.close(file);
+ self.close(callback);
+ } else {
+ return process.nextTick(writeChunk);
+ }
+ });
+ });
+ });
+ }
+
+ // Process the first write
+ process.nextTick(writeChunk);
+ });
+ });
+};
+
+/**
+ * Writes some data. This method will work properly only if initialized with mode
+ * "w" or "w+".
+ *
+ * @param string {string} The data to write.
+ * @param close {boolean=false} opt_argument Closes this file after writing if
+ * true.
+ * @param callback {function(*, GridStore)} This will be called after executing
+ * this method. The first parameter will contain null and the second one
+ * will contain a reference to this object.
+ *
+ * @ignore
+ * @api private
+ */
+var writeBuffer = function(self, buffer, close, callback) {
+ if(typeof close === "function") { callback = close; close = null; }
+ var finalClose = (close == null) ? false : close;
+
+ if(self.mode[0] != "w") {
+ callback(new Error((self.referenceBy == REFERENCE_BY_ID ? self.toHexString() : self.filename) + " not opened for writing"), null);
+ } else {
+ if(self.currentChunk.position + buffer.length >= self.chunkSize) {
+ // Write out the current Chunk and then keep writing until we have less data left than a chunkSize left
+ // to a new chunk (recursively)
+ var previousChunkNumber = self.currentChunk.chunkNumber;
+ var leftOverDataSize = self.chunkSize - self.currentChunk.position;
+ var firstChunkData = buffer.slice(0, leftOverDataSize);
+ var leftOverData = buffer.slice(leftOverDataSize);
+ // A list of chunks to write out
+ var chunksToWrite = [self.currentChunk.write(firstChunkData)];
+ // If we have more data left than the chunk size let's keep writing new chunks
+ while(leftOverData.length >= self.chunkSize) {
+ // Create a new chunk and write to it
+ var newChunk = new Chunk(self, {'n': (previousChunkNumber + 1)});
+ var firstChunkData = leftOverData.slice(0, self.chunkSize);
+ leftOverData = leftOverData.slice(self.chunkSize);
+ // Update chunk number
+ previousChunkNumber = previousChunkNumber + 1;
+ // Write data
+ newChunk.write(firstChunkData);
+ // Push chunk to save list
+ chunksToWrite.push(newChunk);
+ }
+
+ // Set current chunk with remaining data
+ self.currentChunk = new Chunk(self, {'n': (previousChunkNumber + 1)});
+ // If we have left over data write it
+ if(leftOverData.length > 0) self.currentChunk.write(leftOverData);
+
+ // Update the position for the gridstore
+ self.position = self.position + buffer.length;
+ // Total number of chunks to write
+ var numberOfChunksToWrite = chunksToWrite.length;
+ // Write out all the chunks and then return
+ for(var i = 0; i < chunksToWrite.length; i++) {
+ var chunk = chunksToWrite[i];
+ chunk.save(function(err, result) {
+ if(err) return callback(err);
+
+ numberOfChunksToWrite = numberOfChunksToWrite - 1;
+
+ if(numberOfChunksToWrite <= 0) {
+ return callback(null, self);
+ }
+ })
+ }
+ } else {
+ // Update the position for the gridstore
+ self.position = self.position + buffer.length;
+ // We have less data than the chunk size just write it and callback
+ self.currentChunk.write(buffer);
+ callback(null, self);
+ }
+ }
+};
+
+/**
+ * Creates a mongoDB object representation of this object.
+ *
+ * @param callback {function(object)} This will be called after executing this
+ * method. The object will be passed to the first parameter and will have
+ * the structure:
+ *
+ *
+ * {
+ * '_id' : , // {number} id for this file
+ * 'filename' : , // {string} name for this file
+ * 'contentType' : , // {string} mime type for this file
+ * 'length' : , // {number} size of this file?
+ * 'chunksize' : , // {number} chunk size used by this file
+ * 'uploadDate' : , // {Date}
+ * 'aliases' : , // {array of string}
+ * 'metadata' : , // {string}
+ * }
+ *
+ *
+ * @ignore
+ * @api private
+ */
+var buildMongoObject = function(self, callback) {
+ // // Keeps the final chunk number
+ // var chunkNumber = 0;
+ // var previousChunkSize = 0;
+ // // Get the correct chunk Number, if we have an empty chunk return the previous chunk number
+ // if(null != self.currentChunk && self.currentChunk.chunkNumber > 0 && self.currentChunk.position == 0) {
+ // chunkNumber = self.currentChunk.chunkNumber - 1;
+ // } else {
+ // chunkNumber = self.currentChunk.chunkNumber;
+ // previousChunkSize = self.currentChunk.position;
+ // }
+
+ // // Calcuate the length
+ // var length = self.currentChunk != null ? (chunkNumber * self.chunkSize + previousChunkSize) : 0;
+ var mongoObject = {
+ '_id': self.fileId,
+ 'filename': self.filename,
+ 'contentType': self.contentType,
+ 'length': self.position ? self.position : 0,
+ 'chunkSize': self.chunkSize,
+ 'uploadDate': self.uploadDate,
+ 'aliases': self.aliases,
+ 'metadata': self.metadata
+ };
+
+ var md5Command = {filemd5:self.fileId, root:self.root};
+ self.db.command(md5Command, function(err, results) {
+ mongoObject.md5 = results.md5;
+ callback(mongoObject);
+ });
+};
+
+/**
+ * Saves this file to the database. This will overwrite the old entry if it
+ * already exists. This will work properly only if mode was initialized to
+ * "w" or "w+".
+ *
+ * @param {Function} callback this will be called after executing this method. Passes an **{Error}** object to the first parameter and null to the second if an error occured. Otherwise, passes null to the first and a reference to this object to the second.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.close = function(callback) {
+ var self = this;
+
+ if(self.mode[0] == "w") {
+ if(self.currentChunk != null && self.currentChunk.position > 0) {
+ self.currentChunk.save(function(err, chunk) {
+ if(err) return callback(err);
+
+ self.collection(function(err, files) {
+ if(err) return callback(err);
+
+ // Build the mongo object
+ if(self.uploadDate != null) {
+ files.remove({'_id':self.fileId}, {safe:true}, function(err, collection) {
+ if(err) return callback(err);
+
+ buildMongoObject(self, function(mongoObject) {
+ files.save(mongoObject, {safe:true}, function(err) {
+ callback(err, mongoObject);
+ });
+ });
+ });
+ } else {
+ self.uploadDate = new Date();
+ buildMongoObject(self, function(mongoObject) {
+ files.save(mongoObject, {safe:true}, function(err) {
+ callback(err, mongoObject);
+ });
+ });
+ }
+ });
+ });
+ } else {
+ self.collection(function(err, files) {
+ if(err) return callback(err);
+
+ self.uploadDate = new Date();
+ buildMongoObject(self, function(mongoObject) {
+ files.save(mongoObject, {safe:true}, function(err) {
+ callback(err, mongoObject);
+ });
+ });
+ });
+ }
+ } else if(self.mode[0] == "r") {
+ callback(null, null);
+ } else {
+ callback(new Error("Illegal mode " + self.mode), null);
+ }
+};
+
+/**
+ * Gets the nth chunk of this file.
+ *
+ * @param chunkNumber {number} The nth chunk to retrieve.
+ * @param callback {function(*, Chunk|object)} This will be called after
+ * executing this method. null will be passed to the first parameter while
+ * a new {@link Chunk} instance will be passed to the second parameter if
+ * the chunk was found or an empty object {} if not.
+ *
+ * @ignore
+ * @api private
+ */
+var nthChunk = function(self, chunkNumber, callback) {
+ self.chunkCollection(function(err, collection) {
+ if(err) return callback(err);
+
+ collection.find({'files_id':self.fileId, 'n':chunkNumber}, function(err, cursor) {
+ if(err) return callback(err);
+
+ cursor.nextObject(function(err, chunk) {
+ if(err) return callback(err);
+
+ var finalChunk = chunk == null ? {} : chunk;
+ callback(null, new Chunk(self, finalChunk));
+ });
+ });
+ });
+};
+
+/**
+ *
+ * @ignore
+ * @api private
+ */
+GridStore.prototype._nthChunk = function(chunkNumber, callback) {
+ nthChunk(this, chunkNumber, callback);
+}
+
+/**
+ * @return {Number} The last chunk number of this file.
+ *
+ * @ignore
+ * @api private
+ */
+var lastChunkNumber = function(self) {
+ return Math.floor(self.length/self.chunkSize);
+};
+
+/**
+ * Retrieve this file's chunks collection.
+ *
+ * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.chunkCollection = function(callback) {
+ this.db.collection((this.root + ".chunks"), callback);
+};
+
+/**
+ * Deletes all the chunks of this file in the database.
+ *
+ * @param callback {function(*, boolean)} This will be called after this method
+ * executes. Passes null to the first and true to the second argument.
+ *
+ * @ignore
+ * @api private
+ */
+var deleteChunks = function(self, callback) {
+ if(self.fileId != null) {
+ self.chunkCollection(function(err, collection) {
+ if(err) return callback(err, false);
+ collection.remove({'files_id':self.fileId}, {safe:true}, function(err, result) {
+ if(err) return callback(err, false);
+ callback(null, true);
+ });
+ });
+ } else {
+ callback(null, true);
+ }
+};
+
+/**
+ * Deletes all the chunks of this file in the database.
+ *
+ * @param {Function} callback this will be called after this method executes. Passes null to the first and true to the second argument.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.unlink = function(callback) {
+ var self = this;
+ deleteChunks(this, function(err) {
+ if(err!==null) {
+ err.message = "at deleteChunks: " + err.message;
+ return callback(err);
+ }
+
+ self.collection(function(err, collection) {
+ if(err!==null) {
+ err.message = "at collection: " + err.message;
+ return callback(err);
+ }
+
+ collection.remove({'_id':self.fileId}, {safe:true}, function(err) {
+ callback(err, self);
+ });
+ });
+ });
+};
+
+/**
+ * Retrieves the file collection associated with this object.
+ *
+ * @param {Function} callback this will be called after executing this method. An exception object will be passed to the first parameter when an error occured or null otherwise. A new **{Collection}** object will be passed to the second parameter if no error occured.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.collection = function(callback) {
+ this.db.collection(this.root + ".files", callback);
+};
+
+/**
+ * Reads the data of this file.
+ *
+ * @param {String} [separator] the character to be recognized as the newline separator.
+ * @param {Function} callback This will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.readlines = function(separator, callback) {
+ var args = Array.prototype.slice.call(arguments, 0);
+ callback = args.pop();
+ separator = args.length ? args.shift() : "\n";
+
+ this.read(function(err, data) {
+ if(err) return callback(err);
+
+ var items = data.toString().split(separator);
+ items = items.length > 0 ? items.splice(0, items.length - 1) : [];
+ for(var i = 0; i < items.length; i++) {
+ items[i] = items[i] + separator;
+ }
+
+ callback(null, items);
+ });
+};
+
+/**
+ * Deletes all the chunks of this file in the database if mode was set to "w" or
+ * "w+" and resets the read/write head to the initial position.
+ *
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.rewind = function(callback) {
+ var self = this;
+
+ if(this.currentChunk.chunkNumber != 0) {
+ if(this.mode[0] == "w") {
+ deleteChunks(self, function(err, gridStore) {
+ if(err) return callback(err);
+ self.currentChunk = new Chunk(self, {'n': 0});
+ self.position = 0;
+ callback(null, self);
+ });
+ } else {
+ self.currentChunk(0, function(err, chunk) {
+ if(err) return callback(err);
+ self.currentChunk = chunk;
+ self.currentChunk.rewind();
+ self.position = 0;
+ callback(null, self);
+ });
+ }
+ } else {
+ self.currentChunk.rewind();
+ self.position = 0;
+ callback(null, self);
+ }
+};
+
+/**
+ * Retrieves the contents of this file and advances the read/write head. Works with Buffers only.
+ *
+ * There are 3 signatures for this method:
+ *
+ * (callback)
+ * (length, callback)
+ * (length, buffer, callback)
+ *
+ * @param {Number} [length] the number of characters to read. Reads all the characters from the read/write head to the EOF if not specified.
+ * @param {String|Buffer} [buffer] a string to hold temporary data. This is used for storing the string data read so far when recursively calling this method.
+ * @param {Function} callback this will be called after this method is executed. null will be passed to the first parameter and a string containing the contents of the buffer concatenated with the contents read from this file will be passed to the second.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.read = function(length, buffer, callback) {
+ var self = this;
+
+ var args = Array.prototype.slice.call(arguments, 0);
+ callback = args.pop();
+ length = args.length ? args.shift() : null;
+ buffer = args.length ? args.shift() : null;
+
+ // The data is a c-terminated string and thus the length - 1
+ var finalLength = length == null ? self.length - self.position : length;
+ var finalBuffer = buffer == null ? new Buffer(finalLength) : buffer;
+ // Add a index to buffer to keep track of writing position or apply current index
+ finalBuffer._index = buffer != null && buffer._index != null ? buffer._index : 0;
+
+ if((self.currentChunk.length() - self.currentChunk.position + finalBuffer._index) >= finalLength) {
+ var slice = self.currentChunk.readSlice(finalLength - finalBuffer._index);
+ // Copy content to final buffer
+ slice.copy(finalBuffer, finalBuffer._index);
+ // Update internal position
+ self.position = finalBuffer.length;
+ // Check if we don't have a file at all
+ if(finalLength == 0 && finalBuffer.length == 0) return callback(new Error("File does not exist"), null);
+ // Else return data
+ callback(null, finalBuffer);
+ } else {
+ var slice = self.currentChunk.readSlice(self.currentChunk.length() - self.currentChunk.position);
+ // Copy content to final buffer
+ slice.copy(finalBuffer, finalBuffer._index);
+ // Update index position
+ finalBuffer._index += slice.length;
+
+ // Load next chunk and read more
+ nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
+ if(err) return callback(err);
+
+ if(chunk.length() > 0) {
+ self.currentChunk = chunk;
+ self.read(length, finalBuffer, callback);
+ } else {
+ if (finalBuffer._index > 0) {
+ callback(null, finalBuffer)
+ } else {
+ callback(new Error("no chunks found for file, possibly corrupt"), null);
+ }
+ }
+ });
+ }
+}
+
+/**
+ * Retrieves the position of the read/write head of this file.
+ *
+ * @param {Function} callback This gets called after this method terminates. null is passed to the first parameter and the position is passed to the second.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.tell = function(callback) {
+ callback(null, this.position);
+};
+
+/**
+ * Moves the read/write head to a new location.
+ *
+ * There are 3 signatures for this method
+ *
+ * Seek Location Modes
+ * - **GridStore.IO_SEEK_SET**, **(default)** set the position from the start of the file.
+ * - **GridStore.IO_SEEK_CUR**, set the position from the current position in the file.
+ * - **GridStore.IO_SEEK_END**, set the position from the end of the file.
+ *
+ * @param {Number} [position] the position to seek to
+ * @param {Number} [seekLocation] seek mode. Use one of the Seek Location modes.
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.seek = function(position, seekLocation, callback) {
+ var self = this;
+
+ var args = Array.prototype.slice.call(arguments, 1);
+ callback = args.pop();
+ seekLocation = args.length ? args.shift() : null;
+
+ var seekLocationFinal = seekLocation == null ? exports.GridStore.IO_SEEK_SET : seekLocation;
+ var finalPosition = position;
+ var targetPosition = 0;
+ if(seekLocationFinal == exports.GridStore.IO_SEEK_CUR) {
+ targetPosition = self.position + finalPosition;
+ } else if(seekLocationFinal == exports.GridStore.IO_SEEK_END) {
+ targetPosition = self.length + finalPosition;
+ } else {
+ targetPosition = finalPosition;
+ }
+
+ var newChunkNumber = Math.floor(targetPosition/self.chunkSize);
+ if(newChunkNumber != self.currentChunk.chunkNumber) {
+ var seekChunk = function() {
+ nthChunk(self, newChunkNumber, function(err, chunk) {
+ self.currentChunk = chunk;
+ self.position = targetPosition;
+ self.currentChunk.position = (self.position % self.chunkSize);
+ callback(err, self);
+ });
+ };
+
+ if(self.mode[0] == 'w') {
+ self.currentChunk.save(function(err) {
+ if(err) return callback(err);
+ seekChunk();
+ });
+ } else {
+ seekChunk();
+ }
+ } else {
+ self.position = targetPosition;
+ self.currentChunk.position = (self.position % self.chunkSize);
+ callback(null, self);
+ }
+};
+
+/**
+ * Verify if the file is at EOF.
+ *
+ * @return {Boolean} true if the read/write head is at the end of this file.
+ * @api public
+ */
+GridStore.prototype.eof = function() {
+ return this.position == this.length ? true : false;
+};
+
+/**
+ * Retrieves a single character from this file.
+ *
+ * @param {Function} callback this gets called after this method is executed. Passes null to the first parameter and the character read to the second or null to the second if the read/write head is at the end of the file.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.getc = function(callback) {
+ var self = this;
+
+ if(self.eof()) {
+ callback(null, null);
+ } else if(self.currentChunk.eof()) {
+ nthChunk(self, self.currentChunk.chunkNumber + 1, function(err, chunk) {
+ self.currentChunk = chunk;
+ self.position = self.position + 1;
+ callback(err, self.currentChunk.getc());
+ });
+ } else {
+ self.position = self.position + 1;
+ callback(null, self.currentChunk.getc());
+ }
+};
+
+/**
+ * Writes a string to the file with a newline character appended at the end if
+ * the given string does not have one.
+ *
+ * @param {String} string the string to write.
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.puts = function(string, callback) {
+ var finalString = string.match(/\n$/) == null ? string + "\n" : string;
+ this.write(finalString, callback);
+};
+
+/**
+ * Returns read stream based on this GridStore file
+ *
+ * Events
+ * - **data** {function(item) {}} the data event triggers when a document is ready.
+ * - **end** {function() {}} the end event triggers when there is no more documents available.
+ * - **close** {function() {}} the close event triggers when the stream is closed.
+ * - **error** {function(err) {}} the error event triggers if an error happens.
+ *
+ * @param {Boolean} autoclose if true current GridStore will be closed when EOF and 'close' event will be fired
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.stream = function(autoclose) {
+ return new ReadStream(autoclose, this);
+};
+
+/**
+* The collection to be used for holding the files and chunks collection.
+*
+* @classconstant DEFAULT_ROOT_COLLECTION
+**/
+GridStore.DEFAULT_ROOT_COLLECTION = 'fs';
+
+/**
+* Default file mime type
+*
+* @classconstant DEFAULT_CONTENT_TYPE
+**/
+GridStore.DEFAULT_CONTENT_TYPE = 'binary/octet-stream';
+
+/**
+* Seek mode where the given length is absolute.
+*
+* @classconstant IO_SEEK_SET
+**/
+GridStore.IO_SEEK_SET = 0;
+
+/**
+* Seek mode where the given length is an offset to the current read/write head.
+*
+* @classconstant IO_SEEK_CUR
+**/
+GridStore.IO_SEEK_CUR = 1;
+
+/**
+* Seek mode where the given length is an offset to the end of the file.
+*
+* @classconstant IO_SEEK_END
+**/
+GridStore.IO_SEEK_END = 2;
+
+/**
+ * Checks if a file exists in the database.
+ *
+ * @param {Db} db the database to query.
+ * @param {String} name the name of the file to look for.
+ * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
+ * @param {Function} callback this will be called after this method executes. Passes null to the first and passes true to the second if the file exists and false otherwise.
+ * @return {null}
+ * @api public
+ */
+GridStore.exist = function(db, fileIdObject, rootCollection, callback) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ callback = args.pop();
+ rootCollection = args.length ? args.shift() : null;
+
+ // Fetch collection
+ var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
+ db.collection(rootCollectionFinal + ".files", function(err, collection) {
+ if(err) return callback(err);
+
+ // Build query
+ var query = (typeof fileIdObject == 'string' || Object.prototype.toString.call(fileIdObject) == '[object RegExp]' )
+ ? {'filename':fileIdObject}
+ : {'_id':fileIdObject}; // Attempt to locate file
+
+ collection.find(query, function(err, cursor) {
+ if(err) return callback(err);
+
+ cursor.nextObject(function(err, item) {
+ if(err) return callback(err);
+ callback(null, item == null ? false : true);
+ });
+ });
+ });
+};
+
+/**
+ * Gets the list of files stored in the GridFS.
+ *
+ * @param {Db} db the database to query.
+ * @param {String} [rootCollection] the root collection that holds the files and chunks collection. Defaults to **{GridStore.DEFAULT_ROOT_COLLECTION}**.
+ * @param {Function} callback this will be called after this method executes. Passes null to the first and passes an array of strings containing the names of the files.
+ * @return {null}
+ * @api public
+ */
+GridStore.list = function(db, rootCollection, options, callback) {
+ var args = Array.prototype.slice.call(arguments, 1);
+ callback = args.pop();
+ rootCollection = args.length ? args.shift() : null;
+ options = args.length ? args.shift() : {};
+
+ // Ensure we have correct values
+ if(rootCollection != null && typeof rootCollection == 'object') {
+ options = rootCollection;
+ rootCollection = null;
+ }
+
+ // Check if we are returning by id not filename
+ var byId = options['id'] != null ? options['id'] : false;
+ // Fetch item
+ var rootCollectionFinal = rootCollection != null ? rootCollection : GridStore.DEFAULT_ROOT_COLLECTION;
+ var items = [];
+ db.collection((rootCollectionFinal + ".files"), function(err, collection) {
+ if(err) return callback(err);
+
+ collection.find(function(err, cursor) {
+ if(err) return callback(err);
+
+ cursor.each(function(err, item) {
+ if(item != null) {
+ items.push(byId ? item._id : item.filename);
+ } else {
+ callback(err, items);
+ }
+ });
+ });
+ });
+};
+
+/**
+ * Reads the contents of a file.
+ *
+ * This method has the following signatures
+ *
+ * (db, name, callback)
+ * (db, name, length, callback)
+ * (db, name, length, offset, callback)
+ * (db, name, length, offset, options, callback)
+ *
+ * @param {Db} db the database to query.
+ * @param {String} name the name of the file.
+ * @param {Number} [length] the size of data to read.
+ * @param {Number} [offset] the offset from the head of the file of which to start reading from.
+ * @param {Object} [options] the options for the file.
+ * @param {Function} callback this will be called after this method executes. A string with an error message will be passed to the first parameter when the length and offset combination exceeds the length of the file while an Error object will be passed if other forms of error occured, otherwise, a string is passed. The second parameter will contain the data read if successful or null if an error occured.
+ * @return {null}
+ * @api public
+ */
+GridStore.read = function(db, name, length, offset, options, callback) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ callback = args.pop();
+ length = args.length ? args.shift() : null;
+ offset = args.length ? args.shift() : null;
+ options = args.length ? args.shift() : null;
+
+ new GridStore(db, name, "r", options).open(function(err, gridStore) {
+ if(err) return callback(err);
+ // Make sure we are not reading out of bounds
+ if(offset && offset >= gridStore.length) return callback("offset larger than size of file", null);
+ if(length && length > gridStore.length) return callback("length is larger than the size of the file", null);
+ if(offset && length && (offset + length) > gridStore.length) return callback("offset and length is larger than the size of the file", null);
+
+ if(offset != null) {
+ gridStore.seek(offset, function(err, gridStore) {
+ if(err) return callback(err);
+ gridStore.read(length, callback);
+ });
+ } else {
+ gridStore.read(length, callback);
+ }
+ });
+};
+
+/**
+ * Reads the data of this file.
+ *
+ * @param {Db} db the database to query.
+ * @param {String} name the name of the file.
+ * @param {String} [separator] the character to be recognized as the newline separator.
+ * @param {Object} [options] file options.
+ * @param {Function} callback this will be called after this method is executed. The first parameter will be null and the second parameter will contain an array of strings representing the entire data, each element representing a line including the separator character.
+ * @return {null}
+ * @api public
+ */
+GridStore.readlines = function(db, name, separator, options, callback) {
+ var args = Array.prototype.slice.call(arguments, 2);
+ callback = args.pop();
+ separator = args.length ? args.shift() : null;
+ options = args.length ? args.shift() : null;
+
+ var finalSeperator = separator == null ? "\n" : separator;
+ new GridStore(db, name, "r", options).open(function(err, gridStore) {
+ if(err) return callback(err);
+ gridStore.readlines(finalSeperator, callback);
+ });
+};
+
+/**
+ * Deletes the chunks and metadata information of a file from GridFS.
+ *
+ * @param {Db} db the database to interact with.
+ * @param {String|Array} names the name/names of the files to delete.
+ * @param {Object} [options] the options for the files.
+ * @callback {Function} this will be called after this method is executed. The first parameter will contain an Error object if an error occured or null otherwise. The second parameter will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.unlink = function(db, names, options, callback) {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments, 2);
+ callback = args.pop();
+ options = args.length ? args.shift() : null;
+
+ if(names.constructor == Array) {
+ var tc = 0;
+ for(var i = 0; i < names.length; i++) {
+ ++tc;
+ self.unlink(db, names[i], function(result) {
+ if(--tc == 0) {
+ callback(null, self);
+ }
+ });
+ }
+ } else {
+ new GridStore(db, names, "w", options).open(function(err, gridStore) {
+ if(err) return callback(err);
+ deleteChunks(gridStore, function(err, result) {
+ if(err) return callback(err);
+ gridStore.collection(function(err, collection) {
+ if(err) return callback(err);
+ collection.remove({'_id':gridStore.fileId}, {safe:true}, function(err, collection) {
+ callback(err, self);
+ });
+ });
+ });
+ });
+ }
+};
+
+/**
+ * Returns the current chunksize of the file.
+ *
+ * @field chunkSize
+ * @type {Number}
+ * @getter
+ * @setter
+ * @property return number of bytes in the current chunkSize.
+ */
+Object.defineProperty(GridStore.prototype, "chunkSize", { enumerable: true
+ , get: function () {
+ return this.internalChunkSize;
+ }
+ , set: function(value) {
+ if(!(this.mode[0] == "w" && this.position == 0 && this.uploadDate == null)) {
+ this.internalChunkSize = this.internalChunkSize;
+ } else {
+ this.internalChunkSize = value;
+ }
+ }
+});
+
+/**
+ * The md5 checksum for this file.
+ *
+ * @field md5
+ * @type {Number}
+ * @getter
+ * @setter
+ * @property return this files md5 checksum.
+ */
+Object.defineProperty(GridStore.prototype, "md5", { enumerable: true
+ , get: function () {
+ return this.internalMd5;
+ }
+});
+
+/**
+ * GridStore Streaming methods
+ * Handles the correct return of the writeable stream status
+ * @ignore
+ */
+Object.defineProperty(GridStore.prototype, "writable", { enumerable: true
+ , get: function () {
+ if(this._writeable == null) {
+ this._writeable = this.mode != null && this.mode.indexOf("w") != -1;
+ }
+ // Return the _writeable
+ return this._writeable;
+ }
+ , set: function(value) {
+ this._writeable = value;
+ }
+});
+
+/**
+ * Handles the correct return of the readable stream status
+ * @ignore
+ */
+Object.defineProperty(GridStore.prototype, "readable", { enumerable: true
+ , get: function () {
+ if(this._readable == null) {
+ this._readable = this.mode != null && this.mode.indexOf("r") != -1;
+ }
+ return this._readable;
+ }
+ , set: function(value) {
+ this._readable = value;
+ }
+});
+
+GridStore.prototype.paused;
+
+/**
+ * Handles the correct setting of encoding for the stream
+ * @ignore
+ */
+GridStore.prototype.setEncoding = fs.ReadStream.prototype.setEncoding;
+
+/**
+ * Handles the end events
+ * @ignore
+ */
+GridStore.prototype.end = function end(data) {
+ var self = this;
+ // allow queued data to write before closing
+ if(!this.writable) return;
+ this.writable = false;
+
+ if(data) {
+ this._q.push(data);
+ }
+
+ this.on('drain', function () {
+ self.close(function (err) {
+ if (err) return _error(self, err);
+ self.emit('close');
+ });
+ });
+
+ _flush(self);
+}
+
+/**
+ * Handles the normal writes to gridstore
+ * @ignore
+ */
+var _writeNormal = function(self, data, close, callback) {
+ // If we have a buffer write it using the writeBuffer method
+ if(Buffer.isBuffer(data)) {
+ return writeBuffer(self, data, close, callback);
+ } else {
+ // Wrap the string in a buffer and write
+ return writeBuffer(self, new Buffer(data, 'binary'), close, callback);
+ }
+}
+
+/**
+ * Writes some data. This method will work properly only if initialized with mode "w" or "w+".
+ *
+ * @param {String|Buffer} data the data to write.
+ * @param {Boolean} [close] closes this file after writing if set to true.
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain null and the second one will contain a reference to this object.
+ * @return {null}
+ * @api public
+ */
+GridStore.prototype.write = function write(data, close, callback) {
+ // If it's a normal write delegate the call
+ if(typeof close == 'function' || typeof callback == 'function') {
+ return _writeNormal(this, data, close, callback);
+ }
+
+ // Otherwise it's a stream write
+ var self = this;
+ if (!this.writable) {
+ throw new Error('GridWriteStream is not writable');
+ }
+
+ // queue data until we open.
+ if (!this._opened) {
+ // Set up a queue to save data until gridstore object is ready
+ this._q = [];
+ _openStream(self);
+ this._q.push(data);
+ return false;
+ }
+
+ // Push data to queue
+ this._q.push(data);
+ _flush(this);
+ // Return write successful
+ return true;
+}
+
+/**
+ * Handles the destroy part of a stream
+ * @ignore
+ */
+GridStore.prototype.destroy = function destroy() {
+ // close and do not emit any more events. queued data is not sent.
+ if(!this.writable) return;
+ this.readable = false;
+ if(this.writable) {
+ this.writable = false;
+ this._q.length = 0;
+ this.emit('close');
+ }
+}
+
+/**
+ * Handles the destroySoon part of a stream
+ * @ignore
+ */
+GridStore.prototype.destroySoon = function destroySoon() {
+ // as soon as write queue is drained, destroy.
+ // may call destroy immediately if no data is queued.
+ if(!this._q.length) {
+ return this.destroy();
+ }
+ this._destroying = true;
+}
+
+/**
+ * Handles the pipe part of the stream
+ * @ignore
+ */
+GridStore.prototype.pipe = function(destination, options) {
+ var self = this;
+ // Open the gridstore
+ this.open(function(err, result) {
+ if(err) _errorRead(self, err);
+ if(!self.readable) return;
+ // Set up the pipe
+ self._pipe(destination, options);
+ // Emit the stream is open
+ self.emit('open');
+ // Read from the stream
+ _read(self);
+ })
+}
+
+/**
+ * Internal module methods
+ * @ignore
+ */
+var _read = function _read(self) {
+ if (!self.readable || self.paused || self.reading) {
+ return;
+ }
+
+ self.reading = true;
+ var stream = self._stream = self.stream();
+ stream.paused = self.paused;
+
+ stream.on('data', function (data) {
+ if (self._decoder) {
+ var str = self._decoder.write(data);
+ if (str.length) self.emit('data', str);
+ } else {
+ self.emit('data', data);
+ }
+ });
+
+ stream.on('end', function (data) {
+ self.emit('end', data);
+ });
+
+ stream.on('error', function (data) {
+ _errorRead(self, data);
+ });
+
+ stream.on('close', function (data) {
+ self.emit('close', data);
+ });
+
+ self.pause = function () {
+ // native doesn't always pause.
+ // bypass its pause() method to hack it
+ self.paused = stream.paused = true;
+ }
+
+ self.resume = function () {
+ if(!self.paused) return;
+
+ self.paused = false;
+ stream.resume();
+ self.readable = stream.readable;
+ }
+
+ self.destroy = function () {
+ self.readable = false;
+ stream.destroy();
+ }
+}
+
+/**
+ * pause
+ * @ignore
+ */
+GridStore.prototype.pause = function pause () {
+ // Overridden when the GridStore opens.
+ this.paused = true;
+}
+
+/**
+ * resume
+ * @ignore
+ */
+GridStore.prototype.resume = function resume () {
+ // Overridden when the GridStore opens.
+ this.paused = false;
+}
+
+/**
+ * Internal module methods
+ * @ignore
+ */
+var _flush = function _flush(self, _force) {
+ if (!self._opened) return;
+ if (!_force && self._flushing) return;
+ self._flushing = true;
+
+ // write the entire q to gridfs
+ if (!self._q.length) {
+ self._flushing = false;
+ self.emit('drain');
+
+ if(self._destroying) {
+ self.destroy();
+ }
+ return;
+ }
+
+ self.write(self._q.shift(), function (err, store) {
+ if (err) return _error(self, err);
+ self.emit('progress', store.position);
+ _flush(self, true);
+ });
+}
+
+var _openStream = function _openStream (self) {
+ if(self._opening == true) return;
+ self._opening = true;
+
+ // Open the store
+ self.open(function (err, gridstore) {
+ if (err) return _error(self, err);
+ self._opened = true;
+ self.emit('open');
+ _flush(self);
+ });
+}
+
+var _error = function _error(self, err) {
+ self.destroy();
+ self.emit('error', err);
+}
+
+var _errorRead = function _errorRead (self, err) {
+ self.readable = false;
+ self.emit('error', err);
+}
+
+/**
+ * @ignore
+ * @api private
+ */
+exports.GridStore = GridStore;
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js
new file mode 100644
index 0000000..ebb09bd
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/gridfs/readstream.js
@@ -0,0 +1,188 @@
+var Stream = require('stream').Stream,
+ util = require('util');
+
+/**
+ * ReadStream
+ *
+ * Returns a stream interface for the **file**.
+ *
+ * Events
+ * - **data** {function(item) {}} the data event triggers when a document is ready.
+ * - **end** {function() {}} the end event triggers when there is no more documents available.
+ * - **close** {function() {}} the close event triggers when the stream is closed.
+ * - **error** {function(err) {}} the error event triggers if an error happens.
+ *
+ * @class Represents a GridFS File Stream.
+ * @param {Boolean} autoclose automatically close file when the stream reaches the end.
+ * @param {GridStore} cursor a cursor object that the stream wraps.
+ * @return {ReadStream}
+ */
+function ReadStream(autoclose, gstore) {
+ if (!(this instanceof ReadStream)) return new ReadStream(autoclose, gstore);
+ Stream.call(this);
+
+ this.autoclose = !!autoclose;
+ this.gstore = gstore;
+
+ this.finalLength = gstore.length - gstore.position;
+ this.completedLength = 0;
+ this.currentChunkNumber = gstore.currentChunk.chunkNumber;
+
+ this.paused = false;
+ this.readable = true;
+ this.pendingChunk = null;
+ this.executing = false;
+
+ // Calculate the number of chunks
+ this.numberOfChunks = Math.ceil(gstore.length/gstore.chunkSize);
+
+ // This seek start position inside the current chunk
+ this.seekStartPosition = gstore.position - (this.currentChunkNumber * gstore.chunkSize);
+
+ var self = this;
+ process.nextTick(function() {
+ self._execute();
+ });
+};
+
+/**
+ * Inherit from Stream
+ * @ignore
+ * @api private
+ */
+ReadStream.prototype.__proto__ = Stream.prototype;
+
+/**
+ * Flag stating whether or not this stream is readable.
+ */
+ReadStream.prototype.readable;
+
+/**
+ * Flag stating whether or not this stream is paused.
+ */
+ReadStream.prototype.paused;
+
+/**
+ * @ignore
+ * @api private
+ */
+ReadStream.prototype._execute = function() {
+ if(this.paused === true || this.readable === false) {
+ return;
+ }
+
+ var gstore = this.gstore;
+ var self = this;
+ // Set that we are executing
+ this.executing = true;
+
+ var last = false;
+ var toRead = 0;
+
+ if(gstore.currentChunk.chunkNumber >= (this.numberOfChunks - 1)) {
+ self.executing = false;
+ last = true;
+ }
+
+ // Data setup
+ var data = null;
+
+ // Read a slice (with seek set if none)
+ if(this.seekStartPosition > 0 && (gstore.currentChunk.length() - this.seekStartPosition) > 0) {
+ data = gstore.currentChunk.readSlice(gstore.currentChunk.length() - this.seekStartPosition);
+ this.seekStartPosition = 0;
+ } else {
+ data = gstore.currentChunk.readSlice(gstore.currentChunk.length());
+ }
+
+ // Return the data
+ if(data != null && gstore.currentChunk.chunkNumber == self.currentChunkNumber) {
+ self.currentChunkNumber = self.currentChunkNumber + 1;
+ self.completedLength += data.length;
+ self.pendingChunk = null;
+ self.emit("data", data);
+ }
+
+ if(last === true) {
+ self.readable = false;
+ self.emit("end");
+
+ if(self.autoclose === true) {
+ if(gstore.mode[0] == "w") {
+ gstore.close(function(err, doc) {
+ if (err) {
+ self.emit("error", err);
+ return;
+ }
+ self.readable = false;
+ self.emit("close", doc);
+ });
+ } else {
+ self.readable = false;
+ self.emit("close");
+ }
+ }
+ } else {
+ gstore._nthChunk(gstore.currentChunk.chunkNumber + 1, function(err, chunk) {
+ if(err) {
+ self.readable = false;
+ self.emit("error", err);
+ self.executing = false;
+ return;
+ }
+
+ self.pendingChunk = chunk;
+ if(self.paused === true) {
+ self.executing = false;
+ return;
+ }
+
+ gstore.currentChunk = self.pendingChunk;
+ self._execute();
+ });
+ }
+};
+
+/**
+ * Pauses this stream, then no farther events will be fired.
+ *
+ * @ignore
+ * @api public
+ */
+ReadStream.prototype.pause = function() {
+ if(!this.executing) {
+ this.paused = true;
+ }
+};
+
+/**
+ * Destroys the stream, then no farther events will be fired.
+ *
+ * @ignore
+ * @api public
+ */
+ReadStream.prototype.destroy = function() {
+ this.readable = false;
+ // Emit close event
+ this.emit("close");
+};
+
+/**
+ * Resumes this stream.
+ *
+ * @ignore
+ * @api public
+ */
+ReadStream.prototype.resume = function() {
+ if(this.paused === false || !this.readable) {
+ return;
+ }
+
+ this.paused = false;
+ var self = this;
+ process.nextTick(function() {
+ self._execute();
+ });
+};
+
+exports.ReadStream = ReadStream;
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js
new file mode 100644
index 0000000..6a2b727
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/index.js
@@ -0,0 +1,69 @@
+try {
+ exports.BSONPure = require('bson').BSONPure;
+ exports.BSONNative = require('bson').BSONNative;
+} catch(err) {
+ // do nothing
+}
+
+[ 'commands/base_command'
+ , 'admin'
+ , 'collection'
+ , 'connection/read_preference'
+ , 'connection/connection'
+ , 'connection/server'
+ , 'connection/mongos'
+ , 'connection/repl_set'
+ , 'mongo_client'
+ , 'cursor'
+ , 'db'
+ , 'mongo_client'
+ , 'gridfs/grid'
+ , 'gridfs/chunk'
+ , 'gridfs/gridstore'].forEach(function (path) {
+ var module = require('./' + path);
+ for (var i in module) {
+ exports[i] = module[i];
+ }
+
+ // backwards compat
+ exports.ReplSetServers = exports.ReplSet;
+
+ // Add BSON Classes
+ exports.Binary = require('bson').Binary;
+ exports.Code = require('bson').Code;
+ exports.DBRef = require('bson').DBRef;
+ exports.Double = require('bson').Double;
+ exports.Long = require('bson').Long;
+ exports.MinKey = require('bson').MinKey;
+ exports.MaxKey = require('bson').MaxKey;
+ exports.ObjectID = require('bson').ObjectID;
+ exports.Symbol = require('bson').Symbol;
+ exports.Timestamp = require('bson').Timestamp;
+
+ // Add BSON Parser
+ exports.BSON = require('bson').BSONPure.BSON;
+
+});
+
+// Get the Db object
+var Db = require('./db').Db;
+// Set up the connect function
+var connect = Db.connect;
+var obj = connect;
+// Map all values to the exports value
+for(var name in exports) {
+ obj[name] = exports[name];
+}
+
+// Add the pure and native backward compatible functions
+exports.pure = exports.native = function() {
+ return obj;
+}
+
+// Map all values to the exports value
+for(var name in exports) {
+ connect[name] = exports[name];
+}
+
+// Set our exports to be the connect function
+module.exports = connect;
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js
new file mode 100644
index 0000000..cfc9e6f
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/mongo_client.js
@@ -0,0 +1,116 @@
+var Db = require('./db').Db;
+
+/**
+ * Create a new MongoClient instance.
+ *
+ * Options
+ * - **w**, {Number/String, > -1 || 'majority' || tag name} the write concern for the operation where < 1 is no acknowlegement of write and w >= 1, w = 'majority' or tag acknowledges the write
+ * - **wtimeout**, {Number, 0} set the timeout for waiting for write concern to finish (combines with w option)
+ * - **fsync**, (Boolean, default:false) write waits for fsync before returning
+ * - **journal**, (Boolean, default:false) write waits for journal sync before returning
+ * - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
+ * - **native_parser** {Boolean, default:false}, use c++ bson parser.
+ * - **forceServerObjectId** {Boolean, default:false}, force server to create _id fields instead of client.
+ * - **pkFactory** {Object}, object overriding the basic ObjectID primary key generation.
+ * - **serializeFunctions** {Boolean, default:false}, serialize functions.
+ * - **raw** {Boolean, default:false}, peform operations using raw bson buffers.
+ * - **recordQueryStats** {Boolean, default:false}, record query statistics during execution.
+ * - **retryMiliSeconds** {Number, default:5000}, number of miliseconds between retries.
+ * - **numberOfRetries** {Number, default:5}, number of retries off connection.
+ *
+ * Deprecated Options
+ * - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
+ *
+ * @class Represents a MongoClient
+ * @param {Object} serverConfig server config object.
+ * @param {Object} [options] additional options for the collection.
+ */
+function MongoClient(serverConfig, options) {
+ options = options == null ? {} : options;
+ // If no write concern is set set the default to w:1
+ if(options != null && !options.journal && !options.w && !options.fsync) {
+ options.w = 1;
+ }
+
+ // The internal db instance we are wrapping
+ this._db = new Db('test', serverConfig, options);
+}
+
+/**
+ * Initialize the database connection.
+ *
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the connected mongoclient or null if an error occured.
+ * @return {null}
+ * @api public
+ */
+MongoClient.prototype.open = function(callback) {
+ // Self reference
+ var self = this;
+
+ this._db.open(function(err, db) {
+ if(err) return callback(err, null);
+ callback(null, self);
+ })
+}
+
+/**
+ * Close the current db connection, including all the child db instances. Emits close event if no callback is provided.
+ *
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the results from the close method or null if an error occured.
+ * @return {null}
+ * @api public
+ */
+MongoClient.prototype.close = function(callback) {
+ this._db.close(callback);
+}
+
+/**
+ * Create a new Db instance sharing the current socket connections.
+ *
+ * @param {String} dbName the name of the database we want to use.
+ * @return {Db} a db instance using the new database.
+ * @api public
+ */
+MongoClient.prototype.db = function(dbName) {
+ return this._db.db(dbName);
+}
+
+/**
+ * Connect to MongoDB using a url as documented at
+ *
+ * www.mongodb.org/display/DOCS/Connections
+ *
+ * Options
+ * - **uri_decode_auth** {Boolean, default:false} uri decode the user name and password for authentication
+ * - **db** {Object, default: null} a hash off options to set on the db object, see **Db constructor**
+ * - **server** {Object, default: null} a hash off options to set on the server objects, see **Server** constructor**
+ * - **replSet** {Object, default: null} a hash off options to set on the replSet object, see **ReplSet** constructor**
+ * - **mongos** {Object, default: null} a hash off options to set on the mongos object, see **Mongos** constructor**
+ *
+ * @param {String} url connection url for MongoDB.
+ * @param {Object} [options] optional options for insert command
+ * @param {Function} callback this will be called after executing this method. The first parameter will contain the Error object if an error occured, or null otherwise. While the second parameter will contain the initialized db object or null if an error occured.
+ * @return {null}
+ * @api public
+ */
+MongoClient.connect = function(url, options, callback) {
+ if(typeof options == 'function') {
+ callback = options;
+ options = {};
+ }
+
+ Db.connect(url, options, function(err, db) {
+ if(err) return callback(err, null);
+
+ if(db.options !== null && !db.options.safe && !db.options.journal
+ && !db.options.w && !db.options.fsync && typeof db.options.w != 'number'
+ && (db.options.safe == false && url.indexOf("safe=") == -1)) {
+ db.options.w = 1;
+ }
+
+ // Return the db
+ callback(null, db);
+ });
+}
+
+exports.MongoClient = MongoClient;
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js
new file mode 100644
index 0000000..b129dc6
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/responses/mongo_reply.js
@@ -0,0 +1,140 @@
+var Long = require('bson').Long;
+
+/**
+ Reply message from mongo db
+**/
+var MongoReply = exports.MongoReply = function() {
+ this.documents = [];
+ this.index = 0;
+};
+
+MongoReply.prototype.parseHeader = function(binary_reply, bson) {
+ // Unpack the standard header first
+ this.messageLength = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ // Fetch the request id for this reply
+ this.requestId = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ // Fetch the id of the request that triggered the response
+ this.responseTo = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ // Skip op-code field
+ this.index = this.index + 4 + 4;
+ // Unpack the reply message
+ this.responseFlag = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ // Unpack the cursor id (a 64 bit long integer)
+ var low_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ var high_bits = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ this.cursorId = new Long(low_bits, high_bits);
+ // Unpack the starting from
+ this.startingFrom = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+ // Unpack the number of objects returned
+ this.numberReturned = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ this.index = this.index + 4;
+}
+
+MongoReply.prototype.parseBody = function(binary_reply, bson, raw, callback) {
+ raw = raw == null ? false : raw;
+ // Just set a doc limit for deserializing
+ var docLimitSize = 1024*20;
+
+ // If our message length is very long, let's switch to process.nextTick for messages
+ if(this.messageLength > docLimitSize) {
+ var batchSize = this.numberReturned;
+ this.documents = new Array(this.numberReturned);
+
+ // Just walk down until we get a positive number >= 1
+ for(var i = 50; i > 0; i--) {
+ if((this.numberReturned/i) >= 1) {
+ batchSize = i;
+ break;
+ }
+ }
+
+ // Actual main creator of the processFunction setting internal state to control the flow
+ var parseFunction = function(_self, _binary_reply, _batchSize, _numberReturned) {
+ var object_index = 0;
+ // Internal loop process that will use nextTick to ensure we yield some time
+ var processFunction = function() {
+ // Adjust batchSize if we have less results left than batchsize
+ if((_numberReturned - object_index) < _batchSize) {
+ _batchSize = _numberReturned - object_index;
+ }
+
+ // If raw just process the entries
+ if(raw) {
+ // Iterate over the batch
+ for(var i = 0; i < _batchSize; i++) {
+ // Are we done ?
+ if(object_index <= _numberReturned) {
+ // Read the size of the bson object
+ var bsonObjectSize = _binary_reply[_self.index] | _binary_reply[_self.index + 1] << 8 | _binary_reply[_self.index + 2] << 16 | _binary_reply[_self.index + 3] << 24;
+ // If we are storing the raw responses to pipe straight through
+ _self.documents[object_index] = binary_reply.slice(_self.index, _self.index + bsonObjectSize);
+ // Adjust binary index to point to next block of binary bson data
+ _self.index = _self.index + bsonObjectSize;
+ // Update number of docs parsed
+ object_index = object_index + 1;
+ }
+ }
+ } else {
+ try {
+ // Parse documents
+ _self.index = bson.deserializeStream(binary_reply, _self.index, _batchSize, _self.documents, object_index);
+ // Adjust index
+ object_index = object_index + _batchSize;
+ } catch (err) {
+ return callback(err);
+ }
+ }
+
+ // If we hav more documents process NextTick
+ if(object_index < _numberReturned) {
+ process.nextTick(processFunction);
+ } else {
+ callback(null);
+ }
+ }
+
+ // Return the process function
+ return processFunction;
+ }(this, binary_reply, batchSize, this.numberReturned)();
+ } else {
+ try {
+ // Let's unpack all the bson documents, deserialize them and store them
+ for(var object_index = 0; object_index < this.numberReturned; object_index++) {
+ // Read the size of the bson object
+ var bsonObjectSize = binary_reply[this.index] | binary_reply[this.index + 1] << 8 | binary_reply[this.index + 2] << 16 | binary_reply[this.index + 3] << 24;
+ // If we are storing the raw responses to pipe straight through
+ if(raw) {
+ // Deserialize the object and add to the documents array
+ this.documents.push(binary_reply.slice(this.index, this.index + bsonObjectSize));
+ } else {
+ // Deserialize the object and add to the documents array
+ this.documents.push(bson.deserialize(binary_reply.slice(this.index, this.index + bsonObjectSize)));
+ }
+ // Adjust binary index to point to next block of binary bson data
+ this.index = this.index + bsonObjectSize;
+ }
+ } catch(err) {
+ return callback(err);
+ }
+
+ // No error return
+ callback(null);
+ }
+}
+
+MongoReply.prototype.is_error = function(){
+ if(this.documents.length == 1) {
+ return this.documents[0].ok == 1 ? false : true;
+ }
+ return false;
+};
+
+MongoReply.prototype.error_message = function() {
+ return this.documents.length == 1 && this.documents[0].ok == 1 ? '' : this.documents[0].errmsg;
+};
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js
new file mode 100644
index 0000000..120a584
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/lib/mongodb/utils.js
@@ -0,0 +1,97 @@
+/**
+ * Sort functions, Normalize and prepare sort parameters
+ */
+var formatSortValue = exports.formatSortValue = function(sortDirection) {
+ var value = ("" + sortDirection).toLowerCase();
+
+ switch (value) {
+ case 'ascending':
+ case 'asc':
+ case '1':
+ return 1;
+ case 'descending':
+ case 'desc':
+ case '-1':
+ return -1;
+ default:
+ throw new Error("Illegal sort clause, must be of the form "
+ + "[['field1', '(ascending|descending)'], "
+ + "['field2', '(ascending|descending)']]");
+ }
+};
+
+var formattedOrderClause = exports.formattedOrderClause = function(sortValue) {
+ var orderBy = {};
+
+ if (Array.isArray(sortValue)) {
+ for(var i = 0; i < sortValue.length; i++) {
+ if(sortValue[i].constructor == String) {
+ orderBy[sortValue[i]] = 1;
+ } else {
+ orderBy[sortValue[i][0]] = formatSortValue(sortValue[i][1]);
+ }
+ }
+ } else if(Object.prototype.toString.call(sortValue) === '[object Object]') {
+ orderBy = sortValue;
+ } else if (sortValue.constructor == String) {
+ orderBy[sortValue] = 1;
+ } else {
+ throw new Error("Illegal sort clause, must be of the form " +
+ "[['field1', '(ascending|descending)'], ['field2', '(ascending|descending)']]");
+ }
+
+ return orderBy;
+};
+
+exports.encodeInt = function(value) {
+ var buffer = new Buffer(4);
+ buffer[3] = (value >> 24) & 0xff;
+ buffer[2] = (value >> 16) & 0xff;
+ buffer[1] = (value >> 8) & 0xff;
+ buffer[0] = value & 0xff;
+ return buffer;
+}
+
+exports.encodeIntInPlace = function(value, buffer, index) {
+ buffer[index + 3] = (value >> 24) & 0xff;
+ buffer[index + 2] = (value >> 16) & 0xff;
+ buffer[index + 1] = (value >> 8) & 0xff;
+ buffer[index] = value & 0xff;
+}
+
+exports.encodeCString = function(string) {
+ var buf = new Buffer(string, 'utf8');
+ return [buf, new Buffer([0])];
+}
+
+exports.decodeUInt32 = function(array, index) {
+ return array[index] | array[index + 1] << 8 | array[index + 2] << 16 | array[index + 3] << 24;
+}
+
+// Decode the int
+exports.decodeUInt8 = function(array, index) {
+ return array[index];
+}
+
+/**
+ * Context insensitive type checks
+ */
+
+var toString = Object.prototype.toString;
+
+exports.isObject = function (arg) {
+ return '[object Object]' == toString.call(arg)
+}
+
+exports.isArray = function (arg) {
+ return Array.isArray(arg) ||
+ 'object' == typeof arg && '[object Array]' == toString.call(arg)
+}
+
+exports.isDate = function (arg) {
+ return 'object' == typeof arg && '[object Date]' == toString.call(arg)
+}
+
+exports.isRegExp = function (arg) {
+ return 'object' == typeof arg && '[object RegExp]' == toString.call(arg)
+}
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml
new file mode 100644
index 0000000..94740d0
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/.travis.yml
@@ -0,0 +1,5 @@
+language: node_js
+node_js:
+ - 0.6
+ - 0.8
+ - 0.9 # development version of 0.8, may be unstable
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile
new file mode 100644
index 0000000..2ca5592
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/Makefile
@@ -0,0 +1,16 @@
+NODE = node
+NPM = npm
+NODEUNIT = node_modules/nodeunit/bin/nodeunit
+
+all: clean node_gyp
+
+test: clean node_gyp
+ npm test
+
+node_gyp: clean
+ node-gyp configure build
+
+clean:
+ node-gyp clean
+
+.PHONY: all
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md
new file mode 100644
index 0000000..73892e2
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/README.md
@@ -0,0 +1 @@
+A JS/C++ Bson parser for node, used in the MongoDB Native driver
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/benchmarks/benchmarks.js b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/benchmarks/benchmarks.js
new file mode 100644
index 0000000..45a1111
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/benchmarks/benchmarks.js
@@ -0,0 +1,130 @@
+// var BSON = require('../../lib/mongodb').BSONNative.BSON,
+// ObjectID = require('../../lib/mongodb').BSONNative.ObjectID,
+// Code = require('../../lib/mongodb').BSONNative.Code,
+// Long = require('../../lib/mongodb').BSONNative.Long,
+// Binary = require('../../lib/mongodb').BSONNative.Binary,
+// debug = require('util').debug,
+// inspect = require('util').inspect,
+//
+// Long = require('../../lib/mongodb').Long,
+// ObjectID = require('../../lib/mongodb').ObjectID,
+// Binary = require('../../lib/mongodb').Binary,
+// Code = require('../../lib/mongodb').Code,
+// DBRef = require('../../lib/mongodb').DBRef,
+// Symbol = require('../../lib/mongodb').Symbol,
+// Double = require('../../lib/mongodb').Double,
+// MaxKey = require('../../lib/mongodb').MaxKey,
+// MinKey = require('../../lib/mongodb').MinKey,
+// Timestamp = require('../../lib/mongodb').Timestamp;
+
+
+// var BSON = require('../../lib/mongodb').BSONPure.BSON,
+// ObjectID = require('../../lib/mongodb').BSONPure.ObjectID,
+// Code = require('../../lib/mongodb').BSONPure.Code,
+// Long = require('../../lib/mongodb').BSONPure.Long,
+// Binary = require('../../lib/mongodb').BSONPure.Binary;
+
+var BSON = require('../lib/bson').BSONNative.BSON,
+ Long = require('../lib/bson').Long,
+ ObjectID = require('../lib/bson').ObjectID,
+ Binary = require('../lib/bson').Binary,
+ Code = require('../lib/bson').Code,
+ DBRef = require('../lib/bson').DBRef,
+ Symbol = require('../lib/bson').Symbol,
+ Double = require('../lib/bson').Double,
+ MaxKey = require('../lib/bson').MaxKey,
+ MinKey = require('../lib/bson').MinKey,
+ Timestamp = require('../lib/bson').Timestamp;
+
+ // console.dir(require('../lib/bson'))
+
+var COUNT = 1000;
+var COUNT = 100;
+
+var object = {
+ string: "Strings are great",
+ decimal: 3.14159265,
+ bool: true,
+ integer: 5,
+ date: new Date(),
+ double: new Double(1.4),
+ id: new ObjectID(),
+ min: new MinKey(),
+ max: new MaxKey(),
+ symbol: new Symbol('hello'),
+ long: Long.fromNumber(100),
+ bin: new Binary(new Buffer(100)),
+
+ subObject: {
+ moreText: "Bacon ipsum dolor sit amet cow pork belly rump ribeye pastrami andouille. Tail hamburger pork belly, drumstick flank salami t-bone sirloin pork chop ribeye ham chuck pork loin shankle. Ham fatback pork swine, sirloin shankle short loin andouille shank sausage meatloaf drumstick. Pig chicken cow bresaola, pork loin jerky meatball tenderloin brisket strip steak jowl spare ribs. Biltong sirloin pork belly boudin, bacon pastrami rump chicken. Jowl rump fatback, biltong bacon t-bone turkey. Turkey pork loin boudin, tenderloin jerky beef ribs pastrami spare ribs biltong pork chop beef.",
+ longKeylongKeylongKeylongKeylongKeylongKey: "Pork belly boudin shoulder ribeye pork chop brisket biltong short ribs. Salami beef pork belly, t-bone sirloin meatloaf tail jowl spare ribs. Sirloin biltong bresaola cow turkey. Biltong fatback meatball, bresaola tail shankle turkey pancetta ham ribeye flank bacon jerky pork chop. Boudin sirloin shoulder, salami swine flank jerky t-bone pork chop pork beef tongue. Bresaola ribeye jerky andouille. Ribeye ground round sausage biltong beef ribs chuck, shank hamburger chicken short ribs spare ribs tenderloin meatloaf pork loin."
+ },
+
+ subArray: [1,2,3,4,5,6,7,8,9,10],
+ anotherString: "another string",
+ code: new Code("function() {}", {i:1})
+}
+
+// Number of objects
+var numberOfObjects = 10000;
+var bson = new BSON([Long, ObjectID, Binary, Code, DBRef, Symbol, Double, Timestamp, MaxKey, MinKey]);
+console.log("---------------------- 1")
+var s = new Date()
+// Object serialized
+for(var i = 0; i < numberOfObjects; i++) {
+ objectBSON = bson.serialize(object, null, true)
+}
+console.log("====================== " + (new Date().getTime() - s.getTime()) + " :: " + ((new Date().getTime() - s.getTime()))/numberOfObjects)
+
+console.log("---------------------- 2")
+var s = new Date()
+// Object serialized
+for(var i = 0; i < numberOfObjects; i++) {
+ bson.deserialize(objectBSON);
+}
+console.log("====================== " + (new Date().getTime() - s.getTime()) + " :: " + ((new Date().getTime() - s.getTime()))/numberOfObjects)
+
+// // Buffer With copies of the objectBSON
+// var data = new Buffer(objectBSON.length * numberOfObjects);
+// var index = 0;
+//
+// // Copy the buffer 1000 times to create a strea m of objects
+// for(var i = 0; i < numberOfObjects; i++) {
+// // Copy data
+// objectBSON.copy(data, index);
+// // Adjust index
+// index = index + objectBSON.length;
+// }
+//
+// // console.log("-----------------------------------------------------------------------------------")
+// // console.dir(objectBSON)
+//
+// var x, start, end, j
+// var objectBSON, objectJSON
+//
+// // Allocate the return array (avoid concatinating everything)
+// var results = new Array(numberOfObjects);
+//
+// console.log(COUNT + "x (objectBSON = BSON.serialize(object))")
+// start = new Date
+//
+// // var objects = BSON.deserializeStream(data, 0, numberOfObjects);
+// // console.log("----------------------------------------------------------------------------------- 0")
+// // var objects = BSON.deserialize(data);
+// // console.log("----------------------------------------------------------------------------------- 1")
+// // console.dir(objects)
+//
+// for (j=COUNT; --j>=0; ) {
+// var nextIndex = BSON.deserializeStream(data, 0, numberOfObjects, results, 0);
+// }
+//
+// end = new Date
+// var opsprsecond = COUNT / ((end - start)/1000);
+// console.log("bson size (bytes): ", objectBSON.length);
+// console.log("time = ", end - start, "ms -", COUNT / ((end - start)/1000), " ops/sec");
+// console.log("MB/s = " + ((opsprsecond*objectBSON.length)/1024));
+//
+// // console.dir(nextIndex)
+// // console.dir(results)
+
+
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp
new file mode 100644
index 0000000..42445d3
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/binding.gyp
@@ -0,0 +1,17 @@
+{
+ 'targets': [
+ {
+ 'target_name': 'bson',
+ 'sources': [ 'ext/bson.cc' ],
+ 'cflags!': [ '-fno-exceptions' ],
+ 'cflags_cc!': [ '-fno-exceptions' ],
+ 'conditions': [
+ ['OS=="mac"', {
+ 'xcode_settings': {
+ 'GCC_ENABLE_CPP_EXCEPTIONS': 'YES'
+ }
+ }]
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile
new file mode 100644
index 0000000..5c7ea72
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Makefile
@@ -0,0 +1,359 @@
+# We borrow heavily from the kernel build setup, though we are simpler since
+# we don't have Kconfig tweaking settings on us.
+
+# The implicit make rules have it looking for RCS files, among other things.
+# We instead explicitly write all the rules we care about.
+# It's even quicker (saves ~200ms) to pass -r on the command line.
+MAKEFLAGS=-r
+
+# The source directory tree.
+srcdir := ..
+abs_srcdir := $(abspath $(srcdir))
+
+# The name of the builddir.
+builddir_name ?= .
+
+# The V=1 flag on command line makes us verbosely print command lines.
+ifdef V
+ quiet=
+else
+ quiet=quiet_
+endif
+
+# Specify BUILDTYPE=Release on the command line for a release build.
+BUILDTYPE ?= Release
+
+# Directory all our build output goes into.
+# Note that this must be two directories beneath src/ for unit tests to pass,
+# as they reach into the src/ directory for data with relative paths.
+builddir ?= $(builddir_name)/$(BUILDTYPE)
+abs_builddir := $(abspath $(builddir))
+depsdir := $(builddir)/.deps
+
+# Object output directory.
+obj := $(builddir)/obj
+abs_obj := $(abspath $(obj))
+
+# We build up a list of every single one of the targets so we can slurp in the
+# generated dependency rule Makefiles in one pass.
+all_deps :=
+
+
+
+# C++ apps need to be linked with g++.
+#
+# Note: flock is used to seralize linking. Linking is a memory-intensive
+# process so running parallel links can often lead to thrashing. To disable
+# the serialization, override LINK via an envrionment variable as follows:
+#
+# export LINK=g++
+#
+# This will allow make to invoke N linker processes as specified in -jN.
+LINK ?= ./gyp-mac-tool flock $(builddir)/linker.lock $(CXX)
+
+CC.target ?= $(CC)
+CFLAGS.target ?= $(CFLAGS)
+CXX.target ?= $(CXX)
+CXXFLAGS.target ?= $(CXXFLAGS)
+LINK.target ?= $(LINK)
+LDFLAGS.target ?= $(LDFLAGS)
+AR.target ?= $(AR)
+ARFLAGS.target ?= crs
+
+# N.B.: the logic of which commands to run should match the computation done
+# in gyp's make.py where ARFLAGS.host etc. is computed.
+# TODO(evan): move all cross-compilation logic to gyp-time so we don't need
+# to replicate this environment fallback in make as well.
+CC.host ?= gcc
+CFLAGS.host ?=
+CXX.host ?= g++
+CXXFLAGS.host ?=
+LINK.host ?= g++
+LDFLAGS.host ?=
+AR.host ?= ar
+ARFLAGS.host := crs
+
+# Define a dir function that can handle spaces.
+# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions
+# "leading spaces cannot appear in the text of the first argument as written.
+# These characters can be put into the argument value by variable substitution."
+empty :=
+space := $(empty) $(empty)
+
+# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces
+replace_spaces = $(subst $(space),?,$1)
+unreplace_spaces = $(subst ?,$(space),$1)
+dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1)))
+
+# Flags to make gcc output dependency info. Note that you need to be
+# careful here to use the flags that ccache and distcc can understand.
+# We write to a dep file on the side first and then rename at the end
+# so we can't end up with a broken dep file.
+depfile = $(depsdir)/$(call replace_spaces,$@).d
+DEPFLAGS = -MMD -MF $(depfile).raw
+
+# We have to fixup the deps output in a few ways.
+# (1) the file output should mention the proper .o file.
+# ccache or distcc lose the path to the target, so we convert a rule of
+# the form:
+# foobar.o: DEP1 DEP2
+# into
+# path/to/foobar.o: DEP1 DEP2
+# (2) we want missing files not to cause us to fail to build.
+# We want to rewrite
+# foobar.o: DEP1 DEP2 \
+# DEP3
+# to
+# DEP1:
+# DEP2:
+# DEP3:
+# so if the files are missing, they're just considered phony rules.
+# We have to do some pretty insane escaping to get those backslashes
+# and dollar signs past make, the shell, and sed at the same time.
+# Doesn't work with spaces, but that's fine: .d files have spaces in
+# their names replaced with other characters.
+define fixup_dep
+# The depfile may not exist if the input file didn't have any #includes.
+touch $(depfile).raw
+# Fixup path as in (1).
+sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile)
+# Add extra rules as in (2).
+# We remove slashes and replace spaces with new lines;
+# remove blank lines;
+# delete the first line and append a colon to the remaining lines.
+sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\
+ grep -v '^$$' |\
+ sed -e 1d -e 's|$$|:|' \
+ >> $(depfile)
+rm $(depfile).raw
+endef
+
+# Command definitions:
+# - cmd_foo is the actual command to run;
+# - quiet_cmd_foo is the brief-output summary of the command.
+
+quiet_cmd_cc = CC($(TOOLSET)) $@
+cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_cxx = CXX($(TOOLSET)) $@
+cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+
+quiet_cmd_objc = CXX($(TOOLSET)) $@
+cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+quiet_cmd_objcxx = CXX($(TOOLSET)) $@
+cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# Commands for precompiled header files.
+quiet_cmd_pch_c = CXX($(TOOLSET)) $@
+cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_cc = CXX($(TOOLSET)) $@
+cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $<
+quiet_cmd_pch_m = CXX($(TOOLSET)) $@
+cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $<
+quiet_cmd_pch_mm = CXX($(TOOLSET)) $@
+cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $<
+
+# gyp-mac-tool is written next to the root Makefile by gyp.
+# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd
+# already.
+quiet_cmd_mac_tool = MACTOOL $(4) $<
+cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@"
+
+quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@
+cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4)
+
+quiet_cmd_infoplist = INFOPLIST $@
+cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@"
+
+quiet_cmd_touch = TOUCH $@
+cmd_touch = touch $@
+
+quiet_cmd_copy = COPY $@
+# send stderr to /dev/null to ignore messages when linking directories.
+cmd_copy = ln -f "$<" "$@" 2>/dev/null || (rm -rf "$@" && cp -af "$<" "$@")
+
+quiet_cmd_alink = LIBTOOL-STATIC $@
+cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool -static -o $@ $(filter %.o,$^)
+
+quiet_cmd_link = LINK($(TOOLSET)) $@
+cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): Find out and document the difference between shared_library and
+# loadable_module on mac.
+quiet_cmd_solink = SOLINK($(TOOLSET)) $@
+cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS)
+
+# TODO(thakis): The solink_module rule is likely wrong. Xcode seems to pass
+# -bundle -single_module here (for osmesa.so).
+quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@
+cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS)
+
+
+# Define an escape_quotes function to escape single quotes.
+# This allows us to handle quotes properly as long as we always use
+# use single quotes and escape_quotes.
+escape_quotes = $(subst ','\'',$(1))
+# This comment is here just to include a ' to unconfuse syntax highlighting.
+# Define an escape_vars function to escape '$' variable syntax.
+# This allows us to read/write command lines with shell variables (e.g.
+# $LD_LIBRARY_PATH), without triggering make substitution.
+escape_vars = $(subst $$,$$$$,$(1))
+# Helper that expands to a shell command to echo a string exactly as it is in
+# make. This uses printf instead of echo because printf's behaviour with respect
+# to escape sequences is more portable than echo's across different shells
+# (e.g., dash, bash).
+exact_echo = printf '%s\n' '$(call escape_quotes,$(1))'
+
+# Helper to compare the command we're about to run against the command
+# we logged the last time we ran the command. Produces an empty
+# string (false) when the commands match.
+# Tricky point: Make has no string-equality test function.
+# The kernel uses the following, but it seems like it would have false
+# positives, where one string reordered its arguments.
+# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
+# $(filter-out $(cmd_$@), $(cmd_$(1))))
+# We instead substitute each for the empty string into the other, and
+# say they're equal if both substitutions produce the empty string.
+# .d files contain ? instead of spaces, take that into account.
+command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\
+ $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1))))
+
+# Helper that is non-empty when a prerequisite changes.
+# Normally make does this implicitly, but we force rules to always run
+# so we can check their command lines.
+# $? -- new prerequisites
+# $| -- order-only dependencies
+prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?))
+
+# Helper that executes all postbuilds, and deletes the output file when done
+# if any of the postbuilds failed.
+define do_postbuilds
+ @E=0;\
+ for p in $(POSTBUILDS); do\
+ eval $$p;\
+ F=$$?;\
+ if [ $$F -ne 0 ]; then\
+ E=$$F;\
+ fi;\
+ done;\
+ if [ $$E -ne 0 ]; then\
+ rm -rf "$@";\
+ exit $$E;\
+ fi
+endef
+
+# do_cmd: run a command via the above cmd_foo names, if necessary.
+# Should always run for a given target to handle command-line changes.
+# Second argument, if non-zero, makes it do asm/C/C++ dependency munging.
+# Third argument, if non-zero, makes it do POSTBUILDS processing.
+# Note: We intentionally do NOT call dirx for depfile, since it contains ? for
+# spaces already and dirx strips the ? characters.
+define do_cmd
+$(if $(or $(command_changed),$(prereq_changed)),
+ @$(call exact_echo, $($(quiet)cmd_$(1)))
+ @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))"
+ $(if $(findstring flock,$(word 2,$(cmd_$1))),
+ @$(cmd_$(1))
+ @echo " $(quiet_cmd_$(1)): Finished",
+ @$(cmd_$(1))
+ )
+ @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile)
+ @$(if $(2),$(fixup_dep))
+ $(if $(and $(3), $(POSTBUILDS)),
+ $(call do_postbuilds)
+ )
+)
+endef
+
+# Declare the "all" target first so it is the default,
+# even though we don't have the deps yet.
+.PHONY: all
+all:
+
+# make looks for ways to re-generate included makefiles, but in our case, we
+# don't have a direct way. Explicitly telling make that it has nothing to do
+# for them makes it go faster.
+%.d: ;
+
+# Use FORCE_DO_CMD to force a target to run. Should be coupled with
+# do_cmd.
+.PHONY: FORCE_DO_CMD
+FORCE_DO_CMD:
+
+TOOLSET := target
+# Suffix rules, putting all outputs into $(obj).
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD
+ @$(call do_cmd,objc,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD
+ @$(call do_cmd,objcxx,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+# Try building from generated source, too.
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD
+ @$(call do_cmd,objc,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD
+ @$(call do_cmd,objcxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD
+ @$(call do_cmd,objc,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD
+ @$(call do_cmd,objcxx,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD
+ @$(call do_cmd,cc,1)
+
+
+ifeq ($(strip $(foreach prefix,$(NO_LOAD),\
+ $(findstring $(join ^,$(prefix)),\
+ $(join ^,bson.target.mk)))),)
+ include bson.target.mk
+endif
+
+quiet_cmd_regen_makefile = ACTION Regenerating $@
+cmd_regen_makefile = /Users/ck/.node-gyp/0.8.11/tools/gyp/gyp -fmake --ignore-environment "--toplevel-dir=." -I/Users/ck/coding/projects/js-bson/build/config.gypi -I/usr/local/lib/node_modules/node-gyp/addon.gypi -I/Users/ck/.node-gyp/0.8.11/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/ck/.node-gyp/0.8.11" "-Dmodule_root_dir=/Users/ck/coding/projects/js-bson" binding.gyp
+Makefile: $(srcdir)/../../../.node-gyp/0.8.11/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../../usr/local/lib/node_modules/node-gyp/addon.gypi
+ $(call do_cmd,regen_makefile)
+
+# "all" is a concatenation of the "all" targets from all the included
+# sub-makefiles. This is just here to clarify.
+all:
+
+# Add in dependency-tracking rules. $(all_deps) is the list of every single
+# target in our tree. Only consider the ones with .d (dependency) info:
+d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d))
+ifneq ($(d_files),)
+ include $(d_files)
+endif
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d
new file mode 100644
index 0000000..20963f4
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/bson.node.d
@@ -0,0 +1 @@
+cmd_Release/bson.node := ./gyp-mac-tool flock ./Release/linker.lock c++ -shared -Wl,-search_paths_first -mmacosx-version-min=10.5 -arch x86_64 -L./Release -install_name /usr/local/lib/bson.node -o Release/bson.node Release/obj.target/bson/ext/bson.o -undefined dynamic_lookup
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d
new file mode 100644
index 0000000..f224e00
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/.deps/Release/obj.target/bson/ext/bson.o.d
@@ -0,0 +1,34 @@
+cmd_Release/obj.target/bson/ext/bson.o := c++ '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_DARWIN_USE_64_BIT_INODE=1' -I/Users/ck/.node-gyp/0.8.11/src -I/Users/ck/.node-gyp/0.8.11/deps/uv/include -I/Users/ck/.node-gyp/0.8.11/deps/v8/include -Os -gdwarf-2 -mmacosx-version-min=10.5 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -fno-rtti -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/bson/ext/bson.o.d.raw -c -o Release/obj.target/bson/ext/bson.o ../ext/bson.cc
+Release/obj.target/bson/ext/bson.o: ../ext/bson.cc \
+ /Users/ck/.node-gyp/0.8.11/deps/v8/include/v8.h \
+ /Users/ck/.node-gyp/0.8.11/deps/v8/include/v8stdint.h \
+ /Users/ck/.node-gyp/0.8.11/src/node.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/uv.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/ares.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/ares_version.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/uv-unix.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/ngx-queue.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/ev.h \
+ /Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/eio.h \
+ /Users/ck/.node-gyp/0.8.11/src/node_object_wrap.h \
+ /Users/ck/.node-gyp/0.8.11/src/ev-emul.h \
+ /Users/ck/.node-gyp/0.8.11/src/eio-emul.h \
+ /Users/ck/.node-gyp/0.8.11/src/node_version.h \
+ /Users/ck/.node-gyp/0.8.11/src/node_buffer.h ../ext/bson.h
+../ext/bson.cc:
+/Users/ck/.node-gyp/0.8.11/deps/v8/include/v8.h:
+/Users/ck/.node-gyp/0.8.11/deps/v8/include/v8stdint.h:
+/Users/ck/.node-gyp/0.8.11/src/node.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/uv.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/ares.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/ares_version.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/uv-unix.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/ngx-queue.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/ev.h:
+/Users/ck/.node-gyp/0.8.11/deps/uv/include/uv-private/eio.h:
+/Users/ck/.node-gyp/0.8.11/src/node_object_wrap.h:
+/Users/ck/.node-gyp/0.8.11/src/ev-emul.h:
+/Users/ck/.node-gyp/0.8.11/src/eio-emul.h:
+/Users/ck/.node-gyp/0.8.11/src/node_version.h:
+/Users/ck/.node-gyp/0.8.11/src/node_buffer.h:
+../ext/bson.h:
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node
new file mode 100644
index 0000000..f8f0779
Binary files /dev/null and b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/bson.node differ
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/linker.lock b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/linker.lock
new file mode 100644
index 0000000..e69de29
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o
new file mode 100644
index 0000000..af87b6b
Binary files /dev/null and b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/Release/obj.target/bson/ext/bson.o differ
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/binding.Makefile b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/binding.Makefile
new file mode 100644
index 0000000..90bf824
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/binding.Makefile
@@ -0,0 +1,6 @@
+# This file is generated by gyp; do not edit.
+
+export builddir_name ?= build/./.
+.PHONY: all
+all:
+ $(MAKE) bson
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/bson.target.mk b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/bson.target.mk
new file mode 100644
index 0000000..f41c6bd
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/bson.target.mk
@@ -0,0 +1,145 @@
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := bson
+DEFS_Debug := \
+ '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_DARWIN_USE_64_BIT_INODE=1' \
+ '-DDEBUG' \
+ '-D_DEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+ -Os \
+ -gdwarf-2 \
+ -mmacosx-version-min=10.5 \
+ -arch x86_64 \
+ -Wall \
+ -Wendif-labels \
+ -W \
+ -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Debug := \
+ -fno-strict-aliasing
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fno-strict-aliasing
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Debug :=
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Debug :=
+
+INCS_Debug := \
+ -I/Users/ck/.node-gyp/0.8.11/src \
+ -I/Users/ck/.node-gyp/0.8.11/deps/uv/include \
+ -I/Users/ck/.node-gyp/0.8.11/deps/v8/include
+
+DEFS_Release := \
+ '-D_LARGEFILE_SOURCE' \
+ '-D_FILE_OFFSET_BITS=64' \
+ '-D_DARWIN_USE_64_BIT_INODE=1'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+ -Os \
+ -gdwarf-2 \
+ -mmacosx-version-min=10.5 \
+ -arch x86_64 \
+ -Wall \
+ -Wendif-labels \
+ -W \
+ -Wno-unused-parameter
+
+# Flags passed to only C files.
+CFLAGS_C_Release := \
+ -fno-strict-aliasing
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := \
+ -fno-rtti \
+ -fno-threadsafe-statics \
+ -fno-strict-aliasing
+
+# Flags passed to only ObjC files.
+CFLAGS_OBJC_Release :=
+
+# Flags passed to only ObjC++ files.
+CFLAGS_OBJCC_Release :=
+
+INCS_Release := \
+ -I/Users/ck/.node-gyp/0.8.11/src \
+ -I/Users/ck/.node-gyp/0.8.11/deps/uv/include \
+ -I/Users/ck/.node-gyp/0.8.11/deps/v8/include
+
+OBJS := \
+ $(obj).target/$(TARGET)/ext/bson.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))
+$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD
+ @$(call do_cmd,cxx,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+LDFLAGS_Debug := \
+ -Wl,-search_paths_first \
+ -mmacosx-version-min=10.5 \
+ -arch x86_64 \
+ -L$(builddir) \
+ -install_name /usr/local/lib/bson.node
+
+LDFLAGS_Release := \
+ -Wl,-search_paths_first \
+ -mmacosx-version-min=10.5 \
+ -arch x86_64 \
+ -L$(builddir) \
+ -install_name /usr/local/lib/bson.node
+
+LIBS := \
+ -undefined dynamic_lookup
+
+$(builddir)/bson.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(builddir)/bson.node: LIBS := $(LIBS)
+$(builddir)/bson.node: TOOLSET := $(TOOLSET)
+$(builddir)/bson.node: $(OBJS) FORCE_DO_CMD
+ $(call do_cmd,solink_module)
+
+all_deps += $(builddir)/bson.node
+# Add target alias
+.PHONY: bson
+bson: $(builddir)/bson.node
+
+# Short alias for building this executable.
+.PHONY: bson.node
+bson.node: $(builddir)/bson.node
+
+# Add executable to "all" target.
+.PHONY: all
+all: $(builddir)/bson.node
+
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/config.gypi b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/config.gypi
new file mode 100644
index 0000000..431cd3c
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/config.gypi
@@ -0,0 +1,28 @@
+# Do not edit. File was generated by node-gyp's "configure" step
+{
+ "target_defaults": {
+ "cflags": [],
+ "default_configuration": "Release",
+ "defines": [],
+ "include_dirs": [],
+ "libraries": []
+ },
+ "variables": {
+ "clang": 1,
+ "host_arch": "x64",
+ "node_install_npm": "true",
+ "node_install_waf": "true",
+ "node_prefix": "",
+ "node_shared_openssl": "false",
+ "node_shared_v8": "false",
+ "node_shared_zlib": "false",
+ "node_use_dtrace": "false",
+ "node_use_etw": "false",
+ "node_use_openssl": "true",
+ "target_arch": "x64",
+ "v8_no_strict_aliasing": 1,
+ "v8_use_snapshot": "true",
+ "nodedir": "/Users/ck/.node-gyp/0.8.11",
+ "copy_dev_lib": "true"
+ }
+}
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/gyp-mac-tool b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/gyp-mac-tool
new file mode 100644
index 0000000..22f8331
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/build/gyp-mac-tool
@@ -0,0 +1,210 @@
+#!/usr/bin/env python
+# Generated by gyp. Do not edit.
+# Copyright (c) 2012 Google Inc. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Utility functions to perform Xcode-style build steps.
+
+These functions are executed via gyp-mac-tool when using the Makefile generator.
+"""
+
+import fcntl
+import os
+import plistlib
+import re
+import shutil
+import string
+import subprocess
+import sys
+
+
+def main(args):
+ executor = MacTool()
+ exit_code = executor.Dispatch(args)
+ if exit_code is not None:
+ sys.exit(exit_code)
+
+
+class MacTool(object):
+ """This class performs all the Mac tooling steps. The methods can either be
+ executed directly, or dispatched from an argument list."""
+
+ def Dispatch(self, args):
+ """Dispatches a string command to a method."""
+ if len(args) < 1:
+ raise Exception("Not enough arguments")
+
+ method = "Exec%s" % self._CommandifyName(args[0])
+ return getattr(self, method)(*args[1:])
+
+ def _CommandifyName(self, name_string):
+ """Transforms a tool name like copy-info-plist to CopyInfoPlist"""
+ return name_string.title().replace('-', '')
+
+ def ExecCopyBundleResource(self, source, dest):
+ """Copies a resource file to the bundle/Resources directory, performing any
+ necessary compilation on each resource."""
+ extension = os.path.splitext(source)[1].lower()
+ if os.path.isdir(source):
+ # Copy tree.
+ if os.path.exists(dest):
+ shutil.rmtree(dest)
+ shutil.copytree(source, dest)
+ elif extension == '.xib':
+ return self._CopyXIBFile(source, dest)
+ elif extension == '.strings':
+ self._CopyStringsFile(source, dest)
+ else:
+ shutil.copyfile(source, dest)
+
+ def _CopyXIBFile(self, source, dest):
+ """Compiles a XIB file with ibtool into a binary plist in the bundle."""
+ tools_dir = os.environ.get('DEVELOPER_BIN_DIR', '/usr/bin')
+ args = [os.path.join(tools_dir, 'ibtool'), '--errors', '--warnings',
+ '--notices', '--output-format', 'human-readable-text', '--compile',
+ dest, source]
+ ibtool_section_re = re.compile(r'/\*.*\*/')
+ ibtool_re = re.compile(r'.*note:.*is clipping its content')
+ ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE)
+ current_section_header = None
+ for line in ibtoolout.stdout:
+ if ibtool_section_re.match(line):
+ current_section_header = line
+ elif not ibtool_re.match(line):
+ if current_section_header:
+ sys.stdout.write(current_section_header)
+ current_section_header = None
+ sys.stdout.write(line)
+ return ibtoolout.returncode
+
+ def _CopyStringsFile(self, source, dest):
+ """Copies a .strings file using iconv to reconvert the input into UTF-16."""
+ input_code = self._DetectInputEncoding(source) or "UTF-8"
+ fp = open(dest, 'w')
+ args = ['/usr/bin/iconv', '--from-code', input_code, '--to-code',
+ 'UTF-16', source]
+ subprocess.call(args, stdout=fp)
+ fp.close()
+
+ def _DetectInputEncoding(self, file_name):
+ """Reads the first few bytes from file_name and tries to guess the text
+ encoding. Returns None as a guess if it can't detect it."""
+ fp = open(file_name, 'rb')
+ try:
+ header = fp.read(3)
+ except e:
+ fp.close()
+ return None
+ fp.close()
+ if header.startswith("\xFE\xFF"):
+ return "UTF-16BE"
+ elif header.startswith("\xFF\xFE"):
+ return "UTF-16LE"
+ elif header.startswith("\xEF\xBB\xBF"):
+ return "UTF-8"
+ else:
+ return None
+
+ def ExecCopyInfoPlist(self, source, dest):
+ """Copies the |source| Info.plist to the destination directory |dest|."""
+ # Read the source Info.plist into memory.
+ fd = open(source, 'r')
+ lines = fd.read()
+ fd.close()
+
+ # Go through all the environment variables and replace them as variables in
+ # the file.
+ for key in os.environ:
+ if key.startswith('_'):
+ continue
+ evar = '${%s}' % key
+ lines = string.replace(lines, evar, os.environ[key])
+
+ # Write out the file with variables replaced.
+ fd = open(dest, 'w')
+ fd.write(lines)
+ fd.close()
+
+ # Now write out PkgInfo file now that the Info.plist file has been
+ # "compiled".
+ self._WritePkgInfo(dest)
+
+ def _WritePkgInfo(self, info_plist):
+ """This writes the PkgInfo file from the data stored in Info.plist."""
+ plist = plistlib.readPlist(info_plist)
+ if not plist:
+ return
+
+ # Only create PkgInfo for executable types.
+ package_type = plist['CFBundlePackageType']
+ if package_type != 'APPL':
+ return
+
+ # The format of PkgInfo is eight characters, representing the bundle type
+ # and bundle signature, each four characters. If that is missing, four
+ # '?' characters are used instead.
+ signature_code = plist.get('CFBundleSignature', '????')
+ if len(signature_code) != 4: # Wrong length resets everything, too.
+ signature_code = '?' * 4
+
+ dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo')
+ fp = open(dest, 'w')
+ fp.write('%s%s' % (package_type, signature_code))
+ fp.close()
+
+ def ExecFlock(self, lockfile, *cmd_list):
+ """Emulates the most basic behavior of Linux's flock(1)."""
+ # Rely on exception handling to report errors.
+ fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666)
+ fcntl.flock(fd, fcntl.LOCK_EX)
+ return subprocess.call(cmd_list)
+
+ def ExecFilterLibtool(self, *cmd_list):
+ """Calls libtool and filters out 'libtool: file: foo.o has no symbols'."""
+ libtool_re = re.compile(r'^libtool: file: .* has no symbols$')
+ libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE)
+ for line in libtoolout.stderr:
+ if not libtool_re.match(line):
+ sys.stderr.write(line)
+ return libtoolout.returncode
+
+ def ExecPackageFramework(self, framework, version):
+ """Takes a path to Something.framework and the Current version of that and
+ sets up all the symlinks."""
+ # Find the name of the binary based on the part before the ".framework".
+ binary = os.path.basename(framework).split('.')[0]
+
+ CURRENT = 'Current'
+ RESOURCES = 'Resources'
+ VERSIONS = 'Versions'
+
+ if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)):
+ # Binary-less frameworks don't seem to contain symlinks (see e.g.
+ # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle).
+ return
+
+ # Move into the framework directory to set the symlinks correctly.
+ pwd = os.getcwd()
+ os.chdir(framework)
+
+ # Set up the Current version.
+ self._Relink(version, os.path.join(VERSIONS, CURRENT))
+
+ # Set up the root symlinks.
+ self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary)
+ self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES)
+
+ # Back to where we were before!
+ os.chdir(pwd)
+
+ def _Relink(self, dest, link):
+ """Creates a symlink to |dest| named |link|. If |link| already exists,
+ it is overwritten."""
+ if os.path.lexists(link):
+ os.remove(link)
+ os.symlink(dest, link)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/Makefile b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/Makefile
new file mode 100644
index 0000000..435999e
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/Makefile
@@ -0,0 +1,28 @@
+NODE = node
+name = all
+JOBS = 1
+
+all:
+ rm -rf build .lock-wscript bson.node
+ node-waf configure build
+ cp -R ./build/Release/bson.node . || true
+
+all_debug:
+ rm -rf build .lock-wscript bson.node
+ node-waf --debug configure build
+ cp -R ./build/Release/bson.node . || true
+
+clang:
+ rm -rf build .lock-wscript bson.node
+ CXX=clang node-waf configure build
+ cp -R ./build/Release/bson.node . || true
+
+clang_debug:
+ rm -rf build .lock-wscript bson.node
+ CXX=clang node-waf --debug configure build
+ cp -R ./build/Release/bson.node . || true
+
+clean:
+ rm -rf build .lock-wscript bson.node
+
+.PHONY: all
\ No newline at end of file
diff --git a/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.cc b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.cc
new file mode 100644
index 0000000..01e4c28
--- /dev/null
+++ b/test/node_modules/mongoose/node_modules/mongodb/node_modules/bson/ext/bson.cc
@@ -0,0 +1,1020 @@
+//===========================================================================
+
+#include