mirror of
https://github.com/arnaucube/thoughts.git
synced 2026-02-07 03:36:49 +01:00
primer commit, server comença a funcionar
This commit is contained in:
13
node_modules/mongoose/.npmignore
generated
vendored
Normal file
13
node_modules/mongoose/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
lib-cov
|
||||
**.swp
|
||||
*.sw*
|
||||
*.orig
|
||||
.DS_Store
|
||||
node_modules/
|
||||
benchmarks/
|
||||
docs/
|
||||
test/
|
||||
Makefile
|
||||
CNAME
|
||||
index.html
|
||||
index.jade
|
||||
7
node_modules/mongoose/.travis.yml
generated
vendored
Normal file
7
node_modules/mongoose/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.8
|
||||
- 0.10
|
||||
services:
|
||||
- mongodb
|
||||
60
node_modules/mongoose/CONTRIBUTING.md
generated
vendored
Normal file
60
node_modules/mongoose/CONTRIBUTING.md
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
## Contributing to Mongoose
|
||||
|
||||
### STOP!
|
||||
|
||||
If you have a question about Mongoose (not a bug report) please post it to either [StackOverflow](http://stackoverflow.com/questions/tagged/mongoose), our [Google Group](http://groups.google.com/group/mongoose-orm), or on the #mongoosejs irc channel on freenode.
|
||||
|
||||
### 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).
|
||||
- Please describe the issue you are experiencing, along with any associated stack trace.
|
||||
- Please post code that reproduces the issue, the version of mongoose, node version, and mongodb version.
|
||||
- _The source of this project is written in javascript, not coffeescript, therefore your bug reports should be written in javascript_.
|
||||
- In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests.
|
||||
|
||||
### Requesting new features
|
||||
|
||||
- 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).
|
||||
- Please describe a use case for it
|
||||
- it would be ideal to include test cases as well
|
||||
- In general, adding a "+1" comment to an existing issue does little to help get it resolved. A better way is to submit a well documented pull request with clean code and passing tests.
|
||||
|
||||
### 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 (tests are in the [test](https://github.com/LearnBoost/mongoose/tree/master/test) directory).
|
||||
|
||||
### Running the tests
|
||||
- Open a terminal and navigate to the root of the project
|
||||
- execute `npm install` to install the necessary dependencies
|
||||
- execute `make test` to run the tests (we're using [mocha](http://visionmedia.github.com/mocha/))
|
||||
- or to execute a single test `T="-g 'some regexp that matches the test description'" make test`
|
||||
- any mocha flags can be specified with T="..."
|
||||
|
||||
### 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!
|
||||
|
||||
### Sharing your projects
|
||||
|
||||
All are welcome to share their creations which use mongoose on our [tumbler](http://mongoosejs.tumblr.com/). Just fill out the [simple submission form](http://mongoosejs.tumblr.com/submit).
|
||||
1738
node_modules/mongoose/History.md
generated
vendored
Normal file
1738
node_modules/mongoose/History.md
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
269
node_modules/mongoose/README.md
generated
vendored
Normal file
269
node_modules/mongoose/README.md
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
## What's Mongoose?
|
||||
|
||||
Mongoose is a [MongoDB](http://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment.
|
||||
|
||||
## Documentation
|
||||
|
||||
[mongoosejs.com](http://mongoosejs.com/)
|
||||
|
||||
## Try it live
|
||||
<a href="https://runnable.com/#learnboost/mongoose/code.js/launch" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a>
|
||||
|
||||
## Support
|
||||
|
||||
- [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose)
|
||||
- [bug reports](https://github.com/learnboost/mongoose/issues/)
|
||||
- [help forum](http://groups.google.com/group/mongoose-orm)
|
||||
- [MongoDB support](http://www.mongodb.org/display/DOCS/Technical+Support)
|
||||
- (irc) #mongoosejs on freenode
|
||||
|
||||
## Installation
|
||||
|
||||
First install [node.js](http://nodejs.org/) and [mongodb](http://www.mongodb.org/downloads).
|
||||
|
||||
$ npm install mongoose
|
||||
|
||||
## Plugins
|
||||
|
||||
Check out the [plugins search site](http://plugins.mongoosejs.com/) to see hundreds of related modules from the community.
|
||||
|
||||
## Contributors
|
||||
|
||||
View all 90+ [contributors](https://github.com/learnboost/mongoose/graphs/contributors).
|
||||
|
||||
## Get Involved
|
||||
|
||||
Stand up and be counted as a [contributor](https://github.com/LearnBoost/mongoose/blob/master/CONTRIBUTING.md) too!
|
||||
|
||||
## Overview
|
||||
|
||||
### 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)
|
||||
* [pseudo-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 [the docs](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
|
||||
|
||||
See the [docs](http://mongoosejs.com/docs/middleware.html) page.
|
||||
|
||||
#### 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
|
||||
}
|
||||
});
|
||||
|
||||
### 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.
|
||||
|
||||
## API Docs
|
||||
|
||||
Find the API docs [here](http://mongoosejs.com/docs/api.html), generated by [dox](http://github.com/visionmedia/dox).
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) 2010 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.
|
||||
42
node_modules/mongoose/examples/README.md
generated
vendored
Normal file
42
node_modules/mongoose/examples/README.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
This directory contains runnable sample mongoose programs.
|
||||
|
||||
To run:
|
||||
|
||||
- first install [Node.js](http://nodejs.org/)
|
||||
- from the command line, execute: `node example.js`, replacing "example.js" with the name of a program.
|
||||
|
||||
|
||||
Goal is to show:
|
||||
|
||||
- global schemas
|
||||
- GeoJSON schemas / use (with crs)
|
||||
- text search
|
||||
- storing schemas as json
|
||||
- lean querires
|
||||
- statics
|
||||
- methods and statics on subdocs
|
||||
- custom types
|
||||
- querybuilder
|
||||
- promises
|
||||
- express + mongoose
|
||||
- accessing driver collection, db
|
||||
- connecting to replica sets
|
||||
- connecting to sharded clusters
|
||||
- enabling a fail fast mode
|
||||
- on the fly schemas
|
||||
- storing files
|
||||
- map reduce
|
||||
- aggregation
|
||||
- advanced hooks
|
||||
- using $elemMatch to return a subset of an array
|
||||
- query casting
|
||||
- upserts
|
||||
- pagination
|
||||
- express + mongoose session handling
|
||||
- group by (use aggregation)
|
||||
- authentication
|
||||
- schema migration techniques
|
||||
- converting documents to plain objects (show transforms)
|
||||
- how to $unset
|
||||
|
||||
70
node_modules/mongoose/examples/doc-methods.js
generated
vendored
Normal file
70
node_modules/mongoose/examples/doc-methods.js
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Schema
|
||||
*/
|
||||
|
||||
var CharacterSchema = Schema({
|
||||
name: { type: String, required: true }
|
||||
, health: { type: Number, min: 0, max: 100 }
|
||||
})
|
||||
|
||||
/**
|
||||
* Methods
|
||||
*/
|
||||
|
||||
CharacterSchema.methods.attack = function () {
|
||||
console.log('%s is attacking', this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Character model
|
||||
*/
|
||||
|
||||
var Character = mongoose.model('Character', CharacterSchema);
|
||||
|
||||
/**
|
||||
* Connect to the database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
var dbname = 'mongoose-example-doc-methods-' + ((Math.random()*10000)|0);
|
||||
var uri = 'mongodb://localhost/' + dbname;
|
||||
|
||||
console.log('connecting to %s', uri);
|
||||
|
||||
mongoose.connect(uri, function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
example();
|
||||
})
|
||||
|
||||
/**
|
||||
* Use case
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Character.create({ name: 'Link', health: 100 }, function (err, link) {
|
||||
if (err) return done(err);
|
||||
console.log('found', link);
|
||||
link.attack(); // 'Link is attacking'
|
||||
done();
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
mongoose.connection.db.dropDatabase(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
}
|
||||
135
node_modules/mongoose/examples/population-across-three-collections.js
generated
vendored
Normal file
135
node_modules/mongoose/examples/population-across-three-collections.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
|
||||
var assert = require('assert')
|
||||
var mongoose = require('../');
|
||||
var Schema = mongoose.Schema;
|
||||
var ObjectId = mongoose.Types.ObjectId;
|
||||
|
||||
/**
|
||||
* Connect to the db
|
||||
*/
|
||||
|
||||
var dbname = 'testing_populateAdInfinitum_' + require('../lib/utils').random()
|
||||
mongoose.connect('localhost', dbname);
|
||||
mongoose.connection.on('error', function() {
|
||||
console.error('connection error', arguments);
|
||||
});
|
||||
|
||||
/**
|
||||
* Schemas
|
||||
*/
|
||||
|
||||
var user = new Schema({
|
||||
name: String,
|
||||
friends: [{
|
||||
type: Schema.ObjectId,
|
||||
ref: 'User'
|
||||
}]
|
||||
});
|
||||
var User = mongoose.model('User', user);
|
||||
|
||||
var blogpost = Schema({
|
||||
title: String,
|
||||
tags: [String],
|
||||
author: {
|
||||
type: Schema.ObjectId,
|
||||
ref: 'User'
|
||||
}
|
||||
})
|
||||
var BlogPost = mongoose.model('BlogPost', blogpost);
|
||||
|
||||
/**
|
||||
* example
|
||||
*/
|
||||
|
||||
mongoose.connection.on('open', function() {
|
||||
|
||||
/**
|
||||
* Generate data
|
||||
*/
|
||||
|
||||
var userIds = [new ObjectId, new ObjectId, new ObjectId, new ObjectId];
|
||||
var users = [];
|
||||
|
||||
users.push({
|
||||
_id: userIds[0],
|
||||
name: 'mary',
|
||||
friends: [userIds[1], userIds[2], userIds[3]]
|
||||
});
|
||||
users.push({
|
||||
_id: userIds[1],
|
||||
name: 'bob',
|
||||
friends: [userIds[0], userIds[2], userIds[3]]
|
||||
});
|
||||
users.push({
|
||||
_id: userIds[2],
|
||||
name: 'joe',
|
||||
friends: [userIds[0], userIds[1], userIds[3]]
|
||||
});
|
||||
users.push({
|
||||
_id: userIds[3],
|
||||
name: 'sally',
|
||||
friends: [userIds[0], userIds[1], userIds[2]]
|
||||
});
|
||||
|
||||
User.create(users, function(err, docs) {
|
||||
assert.ifError(err);
|
||||
|
||||
var blogposts = [];
|
||||
blogposts.push({
|
||||
title: 'blog 1',
|
||||
tags: ['fun', 'cool'],
|
||||
author: userIds[3]
|
||||
})
|
||||
blogposts.push({
|
||||
title: 'blog 2',
|
||||
tags: ['cool'],
|
||||
author: userIds[1]
|
||||
})
|
||||
blogposts.push({
|
||||
title: 'blog 3',
|
||||
tags: ['fun', 'odd'],
|
||||
author: userIds[2]
|
||||
})
|
||||
|
||||
BlogPost.create(blogposts, function(err, docs) {
|
||||
assert.ifError(err);
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
BlogPost
|
||||
.find({ tags: 'fun' })
|
||||
.lean()
|
||||
.populate('author')
|
||||
.exec(function(err, docs) {
|
||||
assert.ifError(err);
|
||||
|
||||
/**
|
||||
* Populate the populated documents
|
||||
*/
|
||||
|
||||
var opts = {
|
||||
path: 'author.friends',
|
||||
select: 'name',
|
||||
options: { limit: 2 }
|
||||
}
|
||||
|
||||
BlogPost.populate(docs, opts, function(err, docs) {
|
||||
assert.ifError(err);
|
||||
console.log('populated');
|
||||
var s = require('util').inspect(docs, { depth: null })
|
||||
console.log(s);
|
||||
done();
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
function done(err) {
|
||||
if (err) console.error(err.stack);
|
||||
mongoose.connection.db.dropDatabase(function() {
|
||||
mongoose.connection.close();
|
||||
});
|
||||
}
|
||||
95
node_modules/mongoose/examples/population-basic.js
generated
vendored
Normal file
95
node_modules/mongoose/examples/population-basic.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Console schema
|
||||
*/
|
||||
|
||||
var consoleSchema = Schema({
|
||||
name: String
|
||||
, manufacturer: String
|
||||
, released: Date
|
||||
})
|
||||
var Console = mongoose.model('Console', consoleSchema);
|
||||
|
||||
/**
|
||||
* Game schema
|
||||
*/
|
||||
|
||||
var gameSchema = Schema({
|
||||
name: String
|
||||
, developer: String
|
||||
, released: Date
|
||||
, consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
|
||||
})
|
||||
var Game = mongoose.model('Game', gameSchema);
|
||||
|
||||
/**
|
||||
* Connect to the console database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
mongoose.connect('mongodb://localhost/console', function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
createData();
|
||||
})
|
||||
|
||||
/**
|
||||
* Data generation
|
||||
*/
|
||||
|
||||
function createData () {
|
||||
Console.create({
|
||||
name: 'Nintendo 64'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'September 29, 1996'
|
||||
}, function (err, nintendo64) {
|
||||
if (err) return done(err);
|
||||
|
||||
Game.create({
|
||||
name: 'Legend of Zelda: Ocarina of Time'
|
||||
, developer: 'Nintendo'
|
||||
, released: new Date('November 21, 1998')
|
||||
, consoles: [nintendo64]
|
||||
}, function (err) {
|
||||
if (err) return done(err);
|
||||
example();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Game
|
||||
.findOne({ name: /^Legend of Zelda/ })
|
||||
.populate('consoles')
|
||||
.exec(function (err, ocinara) {
|
||||
if (err) return done(err);
|
||||
|
||||
console.log(
|
||||
'"%s" was released for the %s on %s'
|
||||
, ocinara.name
|
||||
, ocinara.consoles[0].name
|
||||
, ocinara.released.toLocaleDateString());
|
||||
|
||||
done();
|
||||
})
|
||||
}
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
Console.remove(function () {
|
||||
Game.remove(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
})
|
||||
}
|
||||
101
node_modules/mongoose/examples/population-of-existing-doc.js
generated
vendored
Normal file
101
node_modules/mongoose/examples/population-of-existing-doc.js
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Console schema
|
||||
*/
|
||||
|
||||
var consoleSchema = Schema({
|
||||
name: String
|
||||
, manufacturer: String
|
||||
, released: Date
|
||||
})
|
||||
var Console = mongoose.model('Console', consoleSchema);
|
||||
|
||||
/**
|
||||
* Game schema
|
||||
*/
|
||||
|
||||
var gameSchema = Schema({
|
||||
name: String
|
||||
, developer: String
|
||||
, released: Date
|
||||
, consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
|
||||
})
|
||||
var Game = mongoose.model('Game', gameSchema);
|
||||
|
||||
/**
|
||||
* Connect to the console database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
mongoose.connect('mongodb://localhost/console', function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
createData();
|
||||
})
|
||||
|
||||
/**
|
||||
* Data generation
|
||||
*/
|
||||
|
||||
function createData () {
|
||||
Console.create({
|
||||
name: 'Nintendo 64'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'September 29, 1996'
|
||||
}, function (err, nintendo64) {
|
||||
if (err) return done(err);
|
||||
|
||||
Game.create({
|
||||
name: 'Legend of Zelda: Ocarina of Time'
|
||||
, developer: 'Nintendo'
|
||||
, released: new Date('November 21, 1998')
|
||||
, consoles: [nintendo64]
|
||||
}, function (err) {
|
||||
if (err) return done(err);
|
||||
example();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Game
|
||||
.findOne({ name: /^Legend of Zelda/ })
|
||||
.exec(function (err, ocinara) {
|
||||
if (err) return done(err);
|
||||
|
||||
console.log('"%s" console _id: %s', ocinara.name, ocinara.consoles[0]);
|
||||
|
||||
// population of existing document
|
||||
ocinara.populate('consoles', function (err) {
|
||||
if (err) return done(err);
|
||||
|
||||
console.log(
|
||||
'"%s" was released for the %s on %s'
|
||||
, ocinara.name
|
||||
, ocinara.consoles[0].name
|
||||
, ocinara.released.toLocaleDateString());
|
||||
|
||||
done();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
Console.remove(function () {
|
||||
Game.remove(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
})
|
||||
}
|
||||
112
node_modules/mongoose/examples/population-of-multiple-existing-docs.js
generated
vendored
Normal file
112
node_modules/mongoose/examples/population-of-multiple-existing-docs.js
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Console schema
|
||||
*/
|
||||
|
||||
var consoleSchema = Schema({
|
||||
name: String
|
||||
, manufacturer: String
|
||||
, released: Date
|
||||
})
|
||||
var Console = mongoose.model('Console', consoleSchema);
|
||||
|
||||
/**
|
||||
* Game schema
|
||||
*/
|
||||
|
||||
var gameSchema = Schema({
|
||||
name: String
|
||||
, developer: String
|
||||
, released: Date
|
||||
, consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
|
||||
})
|
||||
var Game = mongoose.model('Game', gameSchema);
|
||||
|
||||
/**
|
||||
* Connect to the console database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
mongoose.connect('mongodb://localhost/console', function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
createData();
|
||||
})
|
||||
|
||||
/**
|
||||
* Data generation
|
||||
*/
|
||||
|
||||
function createData () {
|
||||
Console.create({
|
||||
name: 'Nintendo 64'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'September 29, 1996'
|
||||
}, {
|
||||
name: 'Super Nintendo'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'August 23, 1991'
|
||||
}, function (err, nintendo64, superNintendo) {
|
||||
if (err) return done(err);
|
||||
|
||||
Game.create({
|
||||
name: 'Legend of Zelda: Ocarina of Time'
|
||||
, developer: 'Nintendo'
|
||||
, released: new Date('November 21, 1998')
|
||||
, consoles: [nintendo64]
|
||||
}, {
|
||||
name: 'Mario Kart'
|
||||
, developer: 'Nintendo'
|
||||
, released: 'September 1, 1992'
|
||||
, consoles: [superNintendo]
|
||||
}, function (err) {
|
||||
if (err) return done(err);
|
||||
example();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Game
|
||||
.find({})
|
||||
.exec(function (err, games) {
|
||||
if (err) return done(err);
|
||||
|
||||
console.log('found %d games', games.length);
|
||||
|
||||
var options = { path: 'consoles', select: 'name released -_id' };
|
||||
Game.populate(games, options, function (err, games) {
|
||||
if (err) return done(err);
|
||||
|
||||
games.forEach(function (game) {
|
||||
console.log(
|
||||
'"%s" was released for the %s on %s'
|
||||
, game.name
|
||||
, game.consoles[0].name
|
||||
, game.released.toLocaleDateString());
|
||||
})
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
Console.remove(function () {
|
||||
Game.remove(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
})
|
||||
}
|
||||
124
node_modules/mongoose/examples/population-options.js
generated
vendored
Normal file
124
node_modules/mongoose/examples/population-options.js
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Console schema
|
||||
*/
|
||||
|
||||
var consoleSchema = Schema({
|
||||
name: String
|
||||
, manufacturer: String
|
||||
, released: Date
|
||||
})
|
||||
var Console = mongoose.model('Console', consoleSchema);
|
||||
|
||||
/**
|
||||
* Game schema
|
||||
*/
|
||||
|
||||
var gameSchema = Schema({
|
||||
name: String
|
||||
, developer: String
|
||||
, released: Date
|
||||
, consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
|
||||
})
|
||||
var Game = mongoose.model('Game', gameSchema);
|
||||
|
||||
/**
|
||||
* Connect to the console database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
mongoose.connect('mongodb://localhost/console', function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
createData();
|
||||
})
|
||||
|
||||
/**
|
||||
* Data generation
|
||||
*/
|
||||
|
||||
function createData () {
|
||||
Console.create({
|
||||
name: 'Nintendo 64'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'September 29, 1996'
|
||||
}, {
|
||||
name: 'Super Nintendo'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'August 23, 1991'
|
||||
}, {
|
||||
name: 'XBOX 360'
|
||||
, manufacturer: 'Microsoft'
|
||||
, released: 'November 22, 2005'
|
||||
}, function (err, nintendo64, superNintendo, xbox360) {
|
||||
if (err) return done(err);
|
||||
|
||||
Game.create({
|
||||
name: 'Legend of Zelda: Ocarina of Time'
|
||||
, developer: 'Nintendo'
|
||||
, released: new Date('November 21, 1998')
|
||||
, consoles: [nintendo64]
|
||||
}, {
|
||||
name: 'Mario Kart'
|
||||
, developer: 'Nintendo'
|
||||
, released: 'September 1, 1992'
|
||||
, consoles: [superNintendo]
|
||||
}, {
|
||||
name: 'Perfect Dark Zero'
|
||||
, developer: 'Rare'
|
||||
, released: 'November 17, 2005'
|
||||
, consoles: [xbox360]
|
||||
}, function (err) {
|
||||
if (err) return done(err);
|
||||
example();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Game
|
||||
.find({})
|
||||
.populate({
|
||||
path: 'consoles'
|
||||
, match: { manufacturer: 'Nintendo' }
|
||||
, select: 'name'
|
||||
, options: { comment: 'population' }
|
||||
})
|
||||
.exec(function (err, games) {
|
||||
if (err) return done(err);
|
||||
|
||||
games.forEach(function (game) {
|
||||
console.log(
|
||||
'"%s" was released for the %s on %s'
|
||||
, game.name
|
||||
, game.consoles.length ? game.consoles[0].name : '??'
|
||||
, game.released.toLocaleDateString());
|
||||
})
|
||||
|
||||
return done();
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up
|
||||
*/
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
Console.remove(function () {
|
||||
Game.remove(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
})
|
||||
}
|
||||
96
node_modules/mongoose/examples/population-plain-objects.js
generated
vendored
Normal file
96
node_modules/mongoose/examples/population-plain-objects.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var Schema = mongoose.Schema;
|
||||
|
||||
console.log('Running mongoose version %s', mongoose.version);
|
||||
|
||||
/**
|
||||
* Console schema
|
||||
*/
|
||||
|
||||
var consoleSchema = Schema({
|
||||
name: String
|
||||
, manufacturer: String
|
||||
, released: Date
|
||||
})
|
||||
var Console = mongoose.model('Console', consoleSchema);
|
||||
|
||||
/**
|
||||
* Game schema
|
||||
*/
|
||||
|
||||
var gameSchema = Schema({
|
||||
name: String
|
||||
, developer: String
|
||||
, released: Date
|
||||
, consoles: [{ type: Schema.Types.ObjectId, ref: 'Console' }]
|
||||
})
|
||||
var Game = mongoose.model('Game', gameSchema);
|
||||
|
||||
/**
|
||||
* Connect to the console database on localhost with
|
||||
* the default port (27017)
|
||||
*/
|
||||
|
||||
mongoose.connect('mongodb://localhost/console', function (err) {
|
||||
// if we failed to connect, abort
|
||||
if (err) throw err;
|
||||
|
||||
// we connected ok
|
||||
createData();
|
||||
})
|
||||
|
||||
/**
|
||||
* Data generation
|
||||
*/
|
||||
|
||||
function createData () {
|
||||
Console.create({
|
||||
name: 'Nintendo 64'
|
||||
, manufacturer: 'Nintendo'
|
||||
, released: 'September 29, 1996'
|
||||
}, function (err, nintendo64) {
|
||||
if (err) return done(err);
|
||||
|
||||
Game.create({
|
||||
name: 'Legend of Zelda: Ocarina of Time'
|
||||
, developer: 'Nintendo'
|
||||
, released: new Date('November 21, 1998')
|
||||
, consoles: [nintendo64]
|
||||
}, function (err) {
|
||||
if (err) return done(err);
|
||||
example();
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Population
|
||||
*/
|
||||
|
||||
function example () {
|
||||
Game
|
||||
.findOne({ name: /^Legend of Zelda/ })
|
||||
.populate('consoles')
|
||||
.lean() // just return plain objects, not documents wrapped by mongoose
|
||||
.exec(function (err, ocinara) {
|
||||
if (err) return done(err);
|
||||
|
||||
console.log(
|
||||
'"%s" was released for the %s on %s'
|
||||
, ocinara.name
|
||||
, ocinara.consoles[0].name
|
||||
, ocinara.released.toLocaleDateString());
|
||||
|
||||
done();
|
||||
})
|
||||
}
|
||||
|
||||
function done (err) {
|
||||
if (err) console.error(err);
|
||||
Console.remove(function () {
|
||||
Game.remove(function () {
|
||||
mongoose.disconnect();
|
||||
})
|
||||
})
|
||||
}
|
||||
102
node_modules/mongoose/examples/schema.js
generated
vendored
Normal file
102
node_modules/mongoose/examples/schema.js
generated
vendored
Normal file
@@ -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);
|
||||
7
node_modules/mongoose/index.js
generated
vendored
Normal file
7
node_modules/mongoose/index.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
/**
|
||||
* Export lib/mongoose
|
||||
*
|
||||
*/
|
||||
|
||||
module.exports = require('./lib/');
|
||||
188
node_modules/mongoose/lib/collection.js
generated
vendored
Normal file
188
node_modules/mongoose/lib/collection.js
generated
vendored
Normal file
@@ -0,0 +1,188 @@
|
||||
|
||||
/*!
|
||||
* 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) {
|
||||
if (undefined === opts) opts = {};
|
||||
if (undefined === opts.capped) opts.capped = {};
|
||||
|
||||
opts.bufferCommands = undefined === opts.bufferCommands
|
||||
? true
|
||||
: opts.bufferCommands;
|
||||
|
||||
if ('number' == typeof opts.capped) {
|
||||
opts.capped = { size: opts.capped };
|
||||
}
|
||||
|
||||
this.opts = opts;
|
||||
this.name = name;
|
||||
this.conn = conn;
|
||||
this.queue = [];
|
||||
this.buffer = this.opts.bufferCommands;
|
||||
|
||||
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 () {
|
||||
if (this.opts.bufferCommands) {
|
||||
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;
|
||||
711
node_modules/mongoose/lib/connection.js
generated
vendored
Normal file
711
node_modules/mongoose/lib/connection.js
generated
vendored
Normal file
@@ -0,0 +1,711 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var url = require('url')
|
||||
, utils = require('./utils')
|
||||
, EventEmitter = require('events').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
|
||||
* auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
|
||||
*
|
||||
* ####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
|
||||
* @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate
|
||||
* @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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Opens the connection 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
|
||||
* auth - options for authentication (see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate)
|
||||
* mongos - Boolean - if true, enables High Availability support for mongos
|
||||
*
|
||||
* ####Notes:
|
||||
*
|
||||
* _If connecting to multiple mongos servers, set the `mongos` option to true._
|
||||
*
|
||||
* conn.open('mongodb://mongosA:27501,mongosB:27501', { mongos: true }, cb);
|
||||
*
|
||||
* 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} 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
|
||||
* @see http://mongodb.github.com/node-mongodb-native/api-generated/db.html#authenticate
|
||||
* @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, self.options.auth, 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.
|
||||
*
|
||||
* Not typically needed by applications. Just talk to your collection through your model.
|
||||
*
|
||||
* @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_exports.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 (utils.isObject(schema) && !(schema instanceof Schema)) {
|
||||
schema = new Schema(schema);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of model names created on this connection.
|
||||
* @api public
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
Connection.prototype.modelNames = function () {
|
||||
return Object.keys(this.models);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
24
node_modules/mongoose/lib/connectionstate.js
generated
vendored
Normal file
24
node_modules/mongoose/lib/connectionstate.js
generated
vendored
Normal file
@@ -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;
|
||||
1726
node_modules/mongoose/lib/document.js
generated
vendored
Normal file
1726
node_modules/mongoose/lib/document.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
4
node_modules/mongoose/lib/drivers/SPEC.md
generated
vendored
Normal file
4
node_modules/mongoose/lib/drivers/SPEC.md
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
# Driver Spec
|
||||
|
||||
TODO
|
||||
8
node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
generated
vendored
Normal file
8
node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Binary = require('mongodb').BSONPure.Binary;
|
||||
|
||||
module.exports = exports = Binary;
|
||||
211
node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
generated
vendored
Normal file
211
node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
generated
vendored
Normal file
@@ -0,0 +1,211 @@
|
||||
|
||||
/*!
|
||||
* 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;
|
||||
|
||||
// always get a new collection in case the user changed host:port
|
||||
// of parent db instance when re-opening the connection.
|
||||
|
||||
if (!self.opts.capped.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 the name: '+ self.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.capped);
|
||||
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;
|
||||
310
node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
generated
vendored
Normal file
310
node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
generated
vendored
Normal file
@@ -0,0 +1,310 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var MongooseConnection = require('../../connection')
|
||||
, mongo = require('mongodb')
|
||||
, Db = mongo.Db
|
||||
, Server = mongo.Server
|
||||
, Mongos = mongo.Mongos
|
||||
, 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);
|
||||
this._listening = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expose the possible connection states.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
NativeConnection.STATES = STATES;
|
||||
|
||||
/*!
|
||||
* 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) {
|
||||
if (this.db) {
|
||||
mute(this);
|
||||
}
|
||||
|
||||
var server = new Server(this.host, this.port, this.options.server);
|
||||
this.db = new Db(this.name, server, this.options.db);
|
||||
|
||||
var self = this;
|
||||
this.db.open(function (err) {
|
||||
if (err) return fn(err);
|
||||
listen(self);
|
||||
fn();
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Register listeners for important events and bubble appropriately.
|
||||
*/
|
||||
|
||||
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')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/*!
|
||||
* Remove listeners registered in `listen`
|
||||
*/
|
||||
|
||||
function mute (conn) {
|
||||
if (!conn.db) throw new Error('missing db');
|
||||
conn.db.removeAllListeners("close");
|
||||
conn.db.removeAllListeners("error");
|
||||
conn.db.removeAllListeners("timeout");
|
||||
conn.db.removeAllListeners("open");
|
||||
conn.db.removeAllListeners("fullsetup");
|
||||
conn._listening = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (this.db) {
|
||||
mute(this);
|
||||
}
|
||||
|
||||
var servers = []
|
||||
, self = this;
|
||||
|
||||
this.hosts.forEach(function (server) {
|
||||
var host = server.host || server.ipc;
|
||||
var port = server.port || 27017;
|
||||
servers.push(new Server(host, port, self.options.server));
|
||||
})
|
||||
|
||||
var server = this.options.mongos
|
||||
? new Mongos(servers, this.options.mongos)
|
||||
: new ReplSetServers(servers, this.options.replset);
|
||||
this.db = new 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.auth || (o.auth = {});
|
||||
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 'authdb':
|
||||
if ('undefined' == typeof o.auth.authdb) {
|
||||
o.auth.authdb = opts[name];
|
||||
}
|
||||
break;
|
||||
case 'authSource':
|
||||
if ('undefined' == typeof o.auth.authSource) {
|
||||
o.auth.authSource = 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;
|
||||
29
node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
generated
vendored
Normal file
29
node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
generated
vendored
Normal file
@@ -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();
|
||||
};
|
||||
39
node_modules/mongoose/lib/error.js
generated
vendored
Normal file
39
node_modules/mongoose/lib/error.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
|
||||
/**
|
||||
* MongooseError constructor
|
||||
*
|
||||
* @param {String} msg Error message
|
||||
* @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')
|
||||
MongooseError.DivergentArrayError = require('./errors/divergentArray')
|
||||
35
node_modules/mongoose/lib/errors/cast.js
generated
vendored
Normal file
35
node_modules/mongoose/lib/errors/cast.js
generated
vendored
Normal file
@@ -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;
|
||||
40
node_modules/mongoose/lib/errors/divergentArray.js
generated
vendored
Normal file
40
node_modules/mongoose/lib/errors/divergentArray.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var MongooseError = require('../error');
|
||||
|
||||
/*!
|
||||
* DivergentArrayError constructor.
|
||||
*
|
||||
* @inherits MongooseError
|
||||
*/
|
||||
|
||||
function DivergentArrayError (paths) {
|
||||
var msg = 'For your own good, using `document.save()` to update an array '
|
||||
+ 'which was selected using an $elemMatch projection OR '
|
||||
+ 'populated using skip, limit, query conditions, or exclusion of '
|
||||
+ 'the _id field when the operation results in a $pop or $set of '
|
||||
+ 'the entire array is not supported. The following '
|
||||
+ 'path(s) would have been modified unsafely:\n'
|
||||
+ ' ' + paths.join('\n ') + '\n'
|
||||
+ 'Use Model.update() to update these arrays instead.'
|
||||
// TODO write up a docs page (FAQ) and link to it
|
||||
|
||||
MongooseError.call(this, msg);
|
||||
Error.captureStackTrace(this, arguments.callee);
|
||||
this.name = 'DivergentArrayError';
|
||||
};
|
||||
|
||||
/*!
|
||||
* Inherits from MongooseError.
|
||||
*/
|
||||
|
||||
DivergentArrayError.prototype.__proto__ = MongooseError.prototype;
|
||||
|
||||
/*!
|
||||
* exports
|
||||
*/
|
||||
|
||||
module.exports = DivergentArrayError;
|
||||
32
node_modules/mongoose/lib/errors/document.js
generated
vendored
Normal file
32
node_modules/mongoose/lib/errors/document.js
generated
vendored
Normal file
@@ -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;
|
||||
32
node_modules/mongoose/lib/errors/missingSchema.js
generated
vendored
Normal file
32
node_modules/mongoose/lib/errors/missingSchema.js
generated
vendored
Normal file
@@ -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;
|
||||
30
node_modules/mongoose/lib/errors/overwriteModel.js
generated
vendored
Normal file
30
node_modules/mongoose/lib/errors/overwriteModel.js
generated
vendored
Normal file
@@ -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;
|
||||
49
node_modules/mongoose/lib/errors/validation.js
generated
vendored
Normal file
49
node_modules/mongoose/lib/errors/validation.js
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
|
||||
/*!
|
||||
* 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 () {
|
||||
var ret = this.name + ': ';
|
||||
var msgs = [];
|
||||
|
||||
Object.keys(this.errors).forEach(function (key) {
|
||||
if (this == this.errors[key]) return;
|
||||
msgs.push(String(this.errors[key]));
|
||||
}, this)
|
||||
|
||||
return ret + msgs.join(', ');
|
||||
};
|
||||
|
||||
/*!
|
||||
* Inherits from MongooseError.
|
||||
*/
|
||||
|
||||
ValidationError.prototype.__proto__ = MongooseError.prototype;
|
||||
|
||||
/*!
|
||||
* Module exports
|
||||
*/
|
||||
|
||||
module.exports = exports = ValidationError;
|
||||
51
node_modules/mongoose/lib/errors/validator.js
generated
vendored
Normal file
51
node_modules/mongoose/lib/errors/validator.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var MongooseError = require('../error');
|
||||
|
||||
/**
|
||||
* Schema validator error
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {String} msg
|
||||
* @param {String|Number|any} val
|
||||
* @inherits MongooseError
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function ValidatorError (path, type, val) {
|
||||
var msg = type
|
||||
? '"' + type + '" '
|
||||
: '';
|
||||
|
||||
var message = 'Validator ' + msg + 'failed for path ' + path
|
||||
if (2 < arguments.length) message += ' with value `' + String(val) + '`';
|
||||
|
||||
MongooseError.call(this, message);
|
||||
Error.captureStackTrace(this, arguments.callee);
|
||||
this.name = 'ValidatorError';
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
this.value = val;
|
||||
};
|
||||
|
||||
/*!
|
||||
* toString helper
|
||||
*/
|
||||
|
||||
ValidatorError.prototype.toString = function () {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Inherits from MongooseError
|
||||
*/
|
||||
|
||||
ValidatorError.prototype.__proto__ = MongooseError.prototype;
|
||||
|
||||
/*!
|
||||
* exports
|
||||
*/
|
||||
|
||||
module.exports = ValidatorError;
|
||||
31
node_modules/mongoose/lib/errors/version.js
generated
vendored
Normal file
31
node_modules/mongoose/lib/errors/version.js
generated
vendored
Normal file
@@ -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;
|
||||
624
node_modules/mongoose/lib/index.js
generated
vendored
Normal file
624
node_modules/mongoose/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,624 @@
|
||||
'use strict';
|
||||
|
||||
/*!
|
||||
* 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')
|
||||
, pkg = require('../package.json')
|
||||
|
||||
/*!
|
||||
* Warn users if they are running an unstable release.
|
||||
*
|
||||
* Disable the warning by setting the MONGOOSE_DISABLE_STABILITY_WARNING
|
||||
* environment variable.
|
||||
*/
|
||||
|
||||
if (pkg.publishConfig && 'unstable' == pkg.publishConfig.tag) {
|
||||
if (!process.env.MONGOOSE_DISABLE_STABILITY_WARNING) {
|
||||
console.log('\u001b[33m');
|
||||
console.log('##############################################################');
|
||||
console.log('#');
|
||||
console.log('# !!! MONGOOSE WARNING !!!');
|
||||
console.log('#');
|
||||
console.log('# This is an UNSTABLE release of Mongoose.');
|
||||
console.log('# Unstable releases are available for preview/testing only.');
|
||||
console.log('# DO NOT run this in production.');
|
||||
console.log('#');
|
||||
console.log('##############################################################');
|
||||
console.log('\u001b[0m');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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`
|
||||
*
|
||||
* mongoose.set('debug', true) // enable logging collection methods + arguments to the console
|
||||
*
|
||||
* @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._
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* mongoose.connect('mongodb://user:pass@localhost:port/database');
|
||||
*
|
||||
* // replica sets
|
||||
* var uri = 'mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port';
|
||||
* mongoose.connect(uri);
|
||||
*
|
||||
* // with options
|
||||
* mongoose.connect(uri, options);
|
||||
*
|
||||
* // connecting to multiple mongos
|
||||
* var uri = 'mongodb://hostA:27501,hostB:27501';
|
||||
* var opts = { mongos: true };
|
||||
* mongoose.connect(uri, opts);
|
||||
*
|
||||
* @param {String} uri(s)
|
||||
* @param {Object} [options]
|
||||
* @param {Function} [callback]
|
||||
* @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_exports.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 ('string' == typeof schema) {
|
||||
collection = schema;
|
||||
schema = false;
|
||||
}
|
||||
|
||||
if (utils.isObject(schema) && !(schema instanceof Schema)) {
|
||||
schema = new Schema(schema);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of model names created on this instance of Mongoose.
|
||||
*
|
||||
* ####Note:
|
||||
*
|
||||
* _Does not include names of models created using `connection.model()`._
|
||||
*
|
||||
* @api public
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
Mongoose.prototype.modelNames = function () {
|
||||
var names = Object.keys(this.models);
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Mongoose Collection constructor
|
||||
*
|
||||
* @method Collection
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Collection = Collection;
|
||||
|
||||
/**
|
||||
* The Mongoose [Connection](#connection_Connection) constructor
|
||||
*
|
||||
* @method Connection
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Connection = Connection;
|
||||
|
||||
/**
|
||||
* The Mongoose version
|
||||
*
|
||||
* @property version
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.version = pkg.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();
|
||||
*
|
||||
* @method Mongoose
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Mongoose = Mongoose;
|
||||
|
||||
/**
|
||||
* The Mongoose [Schema](#schema_Schema) constructor
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var Schema = mongoose.Schema;
|
||||
* var CatSchema = new Schema(..);
|
||||
*
|
||||
* @method Schema
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Schema = Schema;
|
||||
|
||||
/**
|
||||
* The Mongoose [SchemaType](#schematype_SchemaType) constructor
|
||||
*
|
||||
* @method SchemaType
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.SchemaType = SchemaType;
|
||||
|
||||
/**
|
||||
* The various Mongoose SchemaTypes.
|
||||
*
|
||||
* ####Note:
|
||||
*
|
||||
* _Alias of mongoose.Schema.Types for backwards compatibility._
|
||||
*
|
||||
* @property SchemaTypes
|
||||
* @see Schema.SchemaTypes #schema_Schema.Types
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.SchemaTypes = Schema.Types;
|
||||
|
||||
/**
|
||||
* The Mongoose [VirtualType](#virtualtype_VirtualType) constructor
|
||||
*
|
||||
* @method VirtualType
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.VirtualType = VirtualType;
|
||||
|
||||
/**
|
||||
* The various Mongoose Types.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var array = mongoose.Types.Array;
|
||||
*
|
||||
* ####Types:
|
||||
*
|
||||
* - [ObjectId](#types-objectid-js)
|
||||
* - [Buffer](#types-buffer-js)
|
||||
* - [SubDocument](#types-embedded-js)
|
||||
* - [Array](#types-array-js)
|
||||
* - [DocumentArray](#types-documentarray-js)
|
||||
*
|
||||
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
|
||||
*
|
||||
* var ObjectId = mongoose.Types.ObjectId;
|
||||
* var id1 = new ObjectId;
|
||||
*
|
||||
* @property Types
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Types = Types;
|
||||
|
||||
/**
|
||||
* The Mongoose [Query](#query_Query) constructor.
|
||||
*
|
||||
* @method Query
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Query = Query;
|
||||
|
||||
/**
|
||||
* The Mongoose [Promise](#promise_Promise) constructor.
|
||||
*
|
||||
* @method Promise
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Promise = Promise;
|
||||
|
||||
/**
|
||||
* The Mongoose [Model](#model_Model) constructor.
|
||||
*
|
||||
* @method Model
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Model = Model;
|
||||
|
||||
/**
|
||||
* The Mongoose [Document](#document-js) constructor.
|
||||
*
|
||||
* @method Document
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Document = Document;
|
||||
|
||||
/**
|
||||
* The [MongooseError](#error_MongooseError) constructor.
|
||||
*
|
||||
* @method Error
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.Error = require('./error');
|
||||
|
||||
/**
|
||||
* The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses.
|
||||
*
|
||||
* @property mongo
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.mongo = require('mongodb');
|
||||
|
||||
/*!
|
||||
* The exports object is an instance of Mongoose.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var mongoose = module.exports = exports = new Mongoose;
|
||||
31
node_modules/mongoose/lib/internal.js
generated
vendored
Normal file
31
node_modules/mongoose/lib/internal.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*!
|
||||
* Dependencies
|
||||
*/
|
||||
|
||||
var StateMachine = require('./statemachine')
|
||||
var ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default')
|
||||
|
||||
module.exports = exports = InternalCache;
|
||||
|
||||
function InternalCache () {
|
||||
this.strictMode = undefined;
|
||||
this.selected = 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.populate = undefined; // what we want to populate in this doc
|
||||
this.populated = undefined;// the _ids that have been populated
|
||||
this.wasPopulated = false; // if this doc was the result of a population
|
||||
this.scope = undefined;
|
||||
this.activePaths = new ActiveRoster;
|
||||
|
||||
// embedded docs
|
||||
this.ownerDocument = undefined;
|
||||
this.fullPath = undefined;
|
||||
}
|
||||
2288
node_modules/mongoose/lib/model.js
generated
vendored
Normal file
2288
node_modules/mongoose/lib/model.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
70
node_modules/mongoose/lib/namedscope.js
generated
vendored
Normal file
70
node_modules/mongoose/lib/namedscope.js
generated
vendored
Normal file
@@ -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;
|
||||
231
node_modules/mongoose/lib/promise.js
generated
vendored
Normal file
231
node_modules/mongoose/lib/promise.js
generated
vendored
Normal file
@@ -0,0 +1,231 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
var MPromise = require('mpromise');
|
||||
|
||||
/**
|
||||
* Promise constructor.
|
||||
*
|
||||
* Promises are returned from executed queries. Example:
|
||||
*
|
||||
* var query = Candy.find({ bar: true });
|
||||
* var promise = query.exec();
|
||||
*
|
||||
* @param {Function} fn a function which will be called when the promise is resolved that accepts `fn(err, ...){}` as signature
|
||||
* @inherits mpromise https://github.com/aheckmann/mpromise
|
||||
* @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
|
||||
* @event `err`: Emits when the promise is rejected
|
||||
* @event `complete`: Emits when the promise is fulfilled
|
||||
* @api public
|
||||
*/
|
||||
|
||||
function Promise (fn) {
|
||||
MPromise.call(this, fn);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Inherit from mpromise
|
||||
*/
|
||||
|
||||
Promise.prototype = Object.create(MPromise.prototype, {
|
||||
constructor: {
|
||||
value: Promise
|
||||
, enumerable: false
|
||||
, writable: true
|
||||
, configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
/*!
|
||||
* Override event names for backward compatibility.
|
||||
*/
|
||||
|
||||
Promise.SUCCESS = 'complete';
|
||||
Promise.FAILURE = 'err';
|
||||
|
||||
/**
|
||||
* Adds `listener` to the `event`.
|
||||
*
|
||||
* If `event` is either the success or failure event and the event has already been emitted, the`listener` is called immediately and passed the results of the original emitted event.
|
||||
*
|
||||
* @see mpromise#on https://github.com/aheckmann/mpromise#on
|
||||
* @method on
|
||||
* @memberOf Promise
|
||||
* @param {String} event
|
||||
* @param {Function} listener
|
||||
* @return {Promise} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rejects this promise with `reason`.
|
||||
*
|
||||
* If the promise has already been fulfilled or rejected, not action is taken.
|
||||
*
|
||||
* @see mpromise#reject https://github.com/aheckmann/mpromise#reject
|
||||
* @method reject
|
||||
* @memberOf Promise
|
||||
* @param {Object|String|Error} reason
|
||||
* @return {Promise} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
/**
|
||||
* Rejects this promise with `err`.
|
||||
*
|
||||
* If the promise has already been fulfilled or rejected, not action is taken.
|
||||
*
|
||||
* Differs from [#reject](#promise_Promise-reject) by first casting `err` to an `Error` if it is not `instanceof Error`.
|
||||
*
|
||||
* @api public
|
||||
* @param {Error|String} err
|
||||
* @return {Promise} this
|
||||
*/
|
||||
|
||||
Promise.prototype.error = function (err) {
|
||||
if (!(err instanceof Error)) err = new Error(err);
|
||||
return this.reject(err);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves this promise to a rejected state if `err` is passed or a fulfilled state if no `err` is passed.
|
||||
*
|
||||
* If the promise has already been fulfilled or rejected, not action is taken.
|
||||
*
|
||||
* `err` will be cast to an Error if not already instanceof Error.
|
||||
*
|
||||
* _NOTE: overrides [mpromise#resolve](https://github.com/aheckmann/mpromise#resolve) to provide error casting._
|
||||
*
|
||||
* @param {Error} [err] error or null
|
||||
* @param {Object} [val] value to fulfill the promise with
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Promise.prototype.resolve = function (err, val) {
|
||||
if (err) return this.error(err);
|
||||
return this.fulfill(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single function as a listener to both err and complete.
|
||||
*
|
||||
* It will be executed with traditional node.js argument position when the promise is resolved.
|
||||
*
|
||||
* promise.addBack(function (err, args...) {
|
||||
* if (err) return handleError(err);
|
||||
* console.log('success');
|
||||
* })
|
||||
*
|
||||
* Alias of [mpromise#onResolve](https://github.com/aheckmann/mpromise#onresolve).
|
||||
*
|
||||
* @method addBack
|
||||
* @param {Function} listener
|
||||
* @return {Promise} this
|
||||
*/
|
||||
|
||||
Promise.prototype.addBack = Promise.prototype.onResolve;
|
||||
|
||||
/**
|
||||
* Fulfills this promise with passed arguments.
|
||||
*
|
||||
* Alias of [mpromise#fulfill](https://github.com/aheckmann/mpromise#fulfill).
|
||||
*
|
||||
* @method complete
|
||||
* @param {any} args
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Promise.prototype.complete = MPromise.prototype.fulfill;
|
||||
|
||||
/**
|
||||
* Adds a listener to the `complete` (success) event.
|
||||
*
|
||||
* Alias of [mpromise#onFulfill](https://github.com/aheckmann/mpromise#onfulfill).
|
||||
*
|
||||
* @method addCallback
|
||||
* @param {Function} listener
|
||||
* @return {Promise} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Promise.prototype.addCallback = Promise.prototype.onFulfill;
|
||||
|
||||
/**
|
||||
* Adds a listener to the `err` (rejected) event.
|
||||
*
|
||||
* Alias of [mpromise#onReject](https://github.com/aheckmann/mpromise#onreject).
|
||||
*
|
||||
* @method addErrback
|
||||
* @param {Function} listener
|
||||
* @return {Promise} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Promise.prototype.addErrback = Promise.prototype.onReject;
|
||||
|
||||
/**
|
||||
* Creates a new promise and returns it. If `onFulfill` or `onReject` are passed, they are added as SUCCESS/ERROR callbacks to this promise after the nextTick.
|
||||
*
|
||||
* Conforms to [promises/A+](https://github.com/promises-aplus/promises-spec) specification.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var promise = Meetups.find({ tags: 'javascript' }).select('_id').exec();
|
||||
* promise.then(function (meetups) {
|
||||
* var ids = meetups.map(function (m) {
|
||||
* return m._id;
|
||||
* });
|
||||
* return People.find({ meetups: { $in: ids }).exec();
|
||||
* }).then(function (people) {
|
||||
* if (people.length < 10000) {
|
||||
* throw new Error('Too few people!!!');
|
||||
* } else {
|
||||
* throw new Error('Still need more people!!!');
|
||||
* }
|
||||
* }).then(null, function (err) {
|
||||
* assert.ok(err instanceof Error);
|
||||
* });
|
||||
*
|
||||
* @see promises-A+ https://github.com/promises-aplus/promises-spec
|
||||
* @see mpromise#then https://github.com/aheckmann/mpromise#then
|
||||
* @method then
|
||||
* @memberOf Promise
|
||||
* @param {Function} onFulFill
|
||||
* @param {Function} onReject
|
||||
* @return {Promise} newPromise
|
||||
*/
|
||||
|
||||
/**
|
||||
* Signifies that this promise was the last in a chain of `then()s`: if a handler passed to the call to `then` which produced this promise throws, the exception will go uncaught.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var p = new Promise;
|
||||
* p.then(function(){ throw new Error('shucks') });
|
||||
* setTimeout(function () {
|
||||
* p.fulfill();
|
||||
* // error was caught and swallowed by the promise returned from
|
||||
* // p.then(). we either have to always register handlers on
|
||||
* // the returned promises or we can do the following...
|
||||
* }, 10);
|
||||
*
|
||||
* // this time we use .end() which prevents catching thrown errors
|
||||
* var p = new Promise;
|
||||
* var p2 = p.then(function(){ throw new Error('shucks') }).end(); // <--
|
||||
* setTimeout(function () {
|
||||
* p.fulfill(); // throws "shucks"
|
||||
* }, 10);
|
||||
*
|
||||
* @api public
|
||||
* @see mpromise#end https://github.com/aheckmann/mpromise#end
|
||||
* @method end
|
||||
* @memberOf Promise
|
||||
*/
|
||||
|
||||
/*!
|
||||
* expose
|
||||
*/
|
||||
|
||||
module.exports = Promise;
|
||||
2623
node_modules/mongoose/lib/query.js
generated
vendored
Normal file
2623
node_modules/mongoose/lib/query.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
35
node_modules/mongoose/lib/queryhelpers.js
generated
vendored
Normal file
35
node_modules/mongoose/lib/queryhelpers.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies
|
||||
*/
|
||||
|
||||
var utils = require('./utils')
|
||||
|
||||
/*!
|
||||
* Prepare a set of path options for query population.
|
||||
*
|
||||
* @param {Query} query
|
||||
* @param {Object} options
|
||||
* @return {Array}
|
||||
*/
|
||||
|
||||
exports.preparePopulationOptions = function preparePopulationOptions (query, options) {
|
||||
var pop = utils.object.vals(query.options.populate);
|
||||
|
||||
// lean options should trickle through all queries
|
||||
if (options.lean) pop.forEach(makeLean);
|
||||
|
||||
return pop;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Set each path query option to lean
|
||||
*
|
||||
* @param {Object} option
|
||||
*/
|
||||
|
||||
function makeLean (option) {
|
||||
option.options || (option.options = {});
|
||||
option.options.lean = true;
|
||||
}
|
||||
|
||||
336
node_modules/mongoose/lib/querystream.js
generated
vendored
Normal file
336
node_modules/mongoose/lib/querystream.js
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var Stream = require('stream').Stream
|
||||
var utils = require('./utils')
|
||||
var helpers = require('./queryhelpers')
|
||||
var K = function(k){ return k }
|
||||
|
||||
/**
|
||||
* Provides a Node.js 0.8 style [ReadStream](http://nodejs.org/docs/v0.8.21/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 0.8_ style write streams.
|
||||
*
|
||||
* Model.where('created').gte(twoWeeksAgo).stream().pipe(writeStream);
|
||||
*
|
||||
* ####Valid options
|
||||
*
|
||||
* - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data`.
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* // JSON.stringify all documents before emitting
|
||||
* var stream = Thing.find().stream({ transform: JSON.stringify });
|
||||
* 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._
|
||||
*
|
||||
* _NOTE: these streams are Node.js 0.8 style read streams which differ from Node.js 0.10 style. Node.js 0.10 streams are not well tested yet and are not guaranteed to work._
|
||||
*
|
||||
* @param {Query} query
|
||||
* @param {Object} [options]
|
||||
* @inherits NodeJS Stream http://nodejs.org/docs/v0.8.21/api/stream.html#stream_readable_stream
|
||||
* @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, options) {
|
||||
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;
|
||||
this._transform = options && 'function' == typeof options.transform
|
||||
? options.transform
|
||||
: K;
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
var opts = this.query.options;
|
||||
|
||||
if (!opts.populate) {
|
||||
return true === opts.lean
|
||||
? emit(this, doc)
|
||||
: createAndEmit(this, doc);
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var pop = helpers.preparePopulationOptions(self.query, self.query.options);
|
||||
|
||||
self.query.model.populate(doc, pop, function (err, doc) {
|
||||
if (err) return self.destroy(err);
|
||||
return true === opts.lean
|
||||
? emit(self, doc)
|
||||
: createAndEmit(self, doc);
|
||||
})
|
||||
}
|
||||
|
||||
function createAndEmit (self, doc) {
|
||||
var instance = new self.query.model(undefined, self._fields, true);
|
||||
instance.init(doc, function (err) {
|
||||
if (err) return self.destroy(err);
|
||||
emit(self, instance);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
* Emit a data event and manage the trampoline state
|
||||
*/
|
||||
|
||||
function emit (self, doc) {
|
||||
self.emit('data', self._transform(doc));
|
||||
|
||||
// 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])
|
||||
*
|
||||
* @method pipe
|
||||
* @memberOf QueryStream
|
||||
* @see NodeJS http://nodejs.org/api/stream.html
|
||||
* @api public
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Module exports
|
||||
*/
|
||||
|
||||
module.exports = exports = QueryStream;
|
||||
910
node_modules/mongoose/lib/schema.js
generated
vendored
Normal file
910
node_modules/mongoose/lib/schema.js
generated
vendored
Normal file
@@ -0,0 +1,910 @@
|
||||
/*!
|
||||
* 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
|
||||
* - [bufferCommands](/docs/guide.html#bufferCommands): 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
|
||||
* - `minimize`: bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - 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"
|
||||
*
|
||||
* ####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);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* 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
|
||||
, bufferCommands: 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 || '';
|
||||
var keys = Object.keys(obj);
|
||||
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
var key = keys[i];
|
||||
|
||||
if (null == obj[key]) {
|
||||
throw new TypeError('Invalid value for schema path `'+ prefix + key +'`');
|
||||
}
|
||||
|
||||
if (utils.isObject(obj[key]) && (!obj[key].constructor || 'Object' == obj[key].constructor.name) && (!obj[key].type || obj[key].type.type)) {
|
||||
if (Object.keys(obj[key]).length) {
|
||||
// nested object { last: { name: String }}
|
||||
this.nested[prefix + key] = true;
|
||||
this.add(obj[key], prefix + key + '.');
|
||||
} else {
|
||||
this.path(prefix + key, obj[key]); // mixed type
|
||||
}
|
||||
} else {
|
||||
this.path(prefix + key, obj[key]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 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, emit, _events, db, init, isNew, errors, schema, options, modelName, collection, _pres, _posts, toObject
|
||||
*
|
||||
* _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.collection =
|
||||
reserved.toObject =
|
||||
reserved.emit = // EventEmitter
|
||||
reserved._events = // EventEmitter
|
||||
reserved._pres = reserved._posts = 1 // hooks.js
|
||||
|
||||
/**
|
||||
* 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 && 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+\.|\.\d+$/.test(path) && getPositionalPath(this, path)) {
|
||||
return 'real';
|
||||
} else {
|
||||
return 'adhocOrUndefined'
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function getPositionalPath (self, path) {
|
||||
var subpaths = path.split(/\.(\d+)\.|\.(\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)) {
|
||||
if (val instanceof Types.Array) {
|
||||
// StringSchema, NumberSchema, etc
|
||||
val = val.caster;
|
||||
} else {
|
||||
val = undefined;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ignore if its just a position segment: path.0.subpath
|
||||
if (!/\D/.test(subpath)) continue;
|
||||
|
||||
if (!(val && val.schema)) {
|
||||
val = undefined;
|
||||
break;
|
||||
}
|
||||
|
||||
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.method('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];
|
||||
}
|
||||
|
||||
/**
|
||||
* The allowed index types
|
||||
*
|
||||
* @static indexTypes
|
||||
* @receiver Schema
|
||||
* @api public
|
||||
*/
|
||||
|
||||
var indexTypes = '2d 2dsphere hashed text'.split(' ');
|
||||
|
||||
Object.defineProperty(Schema, 'indexTypes', {
|
||||
get: function () { return indexTypes }
|
||||
, set: function () { throw new Error('Cannot overwrite Schema.indexTypes') }
|
||||
})
|
||||
|
||||
/**
|
||||
* Compiles indexes from fields and schema-level indexes
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Schema.prototype.indexes = function () {
|
||||
'use strict';
|
||||
|
||||
var indexes = []
|
||||
, seenSchemas = []
|
||||
collectIndexes(this);
|
||||
return indexes;
|
||||
|
||||
function collectIndexes (schema, prefix) {
|
||||
if (~seenSchemas.indexOf(schema)) return;
|
||||
seenSchemas.push(schema);
|
||||
|
||||
prefix = prefix || '';
|
||||
|
||||
var key, path, index, field, isObject, options, type;
|
||||
var keys = Object.keys(schema.paths);
|
||||
|
||||
for (var i = 0; i < keys.length; ++i) {
|
||||
key = keys[i];
|
||||
path = schema.paths[key];
|
||||
|
||||
if (path instanceof Types.DocumentArray) {
|
||||
collectIndexes(path.schema, key + '.');
|
||||
} else {
|
||||
index = path._index;
|
||||
|
||||
if (false !== index && null != index) {
|
||||
field = {};
|
||||
isObject = utils.isObject(index);
|
||||
options = isObject ? index : {};
|
||||
type = 'string' == typeof index ? index :
|
||||
isObject ? index.type :
|
||||
false;
|
||||
|
||||
if (type && ~Schema.indexTypes.indexOf(type)) {
|
||||
field[prefix + key] = type;
|
||||
} else {
|
||||
field[prefix + key] = 1;
|
||||
}
|
||||
|
||||
delete options.type;
|
||||
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 built-in Mongoose Schema Types.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var ObjectId = mongoose.Schema.Types.ObjectId;
|
||||
*
|
||||
* ####Types:
|
||||
*
|
||||
* - [String](#schema-string-js)
|
||||
* - [Number](#schema-number-js)
|
||||
* - [Boolean](#schema-boolean-js) | Bool
|
||||
* - [Array](#schema-array-js)
|
||||
* - [Buffer](#schema-buffer-js)
|
||||
* - [Date](#schema-date-js)
|
||||
* - [ObjectId](#schema-objectid-js) | Oid
|
||||
* - [Mixed](#schema-mixed-js)
|
||||
*
|
||||
* 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;
|
||||
|
||||
316
node_modules/mongoose/lib/schema/array.js
generated
vendored
Normal file
316
node_modules/mongoose/lib/schema/array.js
generated
vendored
Normal file
@@ -0,0 +1,316 @@
|
||||
/*!
|
||||
* 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')
|
||||
, utils = require('../utils')
|
||||
, isMongooseObject = 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 = utils.clone(cast); // do not alter user arguments
|
||||
delete castOptions.type;
|
||||
cast = cast.type;
|
||||
} else {
|
||||
cast = Mixed;
|
||||
}
|
||||
}
|
||||
|
||||
// support { type: 'String' }
|
||||
var name = 'string' == typeof cast
|
||||
? cast
|
||||
: cast.name;
|
||||
|
||||
var caster = name in Types
|
||||
? Types[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);
|
||||
}
|
||||
|
||||
function castArray (arr, self) {
|
||||
self || (self = this);
|
||||
|
||||
arr.forEach(function (v, i) {
|
||||
if (Array.isArray(v)) {
|
||||
castArray(v, self);
|
||||
} else {
|
||||
arr[i] = castToNumber.call(self, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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
|
||||
, '$options': String
|
||||
, '$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) {
|
||||
if (!Array.isArray(arr)) {
|
||||
var msg = 'Invalid $within $box argument. '
|
||||
+ 'Expected an array, received ' + arr;
|
||||
throw new TypeError(msg);
|
||||
}
|
||||
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);
|
||||
}
|
||||
})
|
||||
} else if (val.$geometry) {
|
||||
switch (val.$geometry.type) {
|
||||
case 'Polygon':
|
||||
case 'LineString':
|
||||
case 'Point':
|
||||
val.$geometry.coordinates.forEach(castArray);
|
||||
break;
|
||||
default:
|
||||
// ignore unknowns
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
, '$geoIntersects': function (val) {
|
||||
var geo = val.$geometry;
|
||||
if (!geo) return;
|
||||
|
||||
switch (val.$geometry.type) {
|
||||
case 'Polygon':
|
||||
case 'LineString':
|
||||
case 'Point':
|
||||
val.$geometry.coordinates.forEach(castArray);
|
||||
break;
|
||||
default:
|
||||
// ignore unknowns
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
, '$maxDistance': castToNumber
|
||||
};
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = SchemaArray;
|
||||
92
node_modules/mongoose/lib/schema/boolean.js
generated
vendored
Normal file
92
node_modules/mongoose/lib/schema/boolean.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
/*!
|
||||
* 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 (null === value) return value;
|
||||
if ('0' === value) return false;
|
||||
if ('true' === value) return true;
|
||||
if ('false' === value) 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;
|
||||
168
node_modules/mongoose/lib/schema/buffer.js
generated
vendored
Normal file
168
node_modules/mongoose/lib/schema/buffer.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype')
|
||||
, CastError = SchemaType.CastError
|
||||
, MongooseBuffer = require('../types').Buffer
|
||||
, Binary = MongooseBuffer.Binary
|
||||
, Query = require('../query')
|
||||
, utils = require('../utils')
|
||||
, Document
|
||||
|
||||
/**
|
||||
* 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, doc) {
|
||||
if (SchemaType._isRef(this, value, doc, true)) {
|
||||
return null != value;
|
||||
} else {
|
||||
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, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (null == value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (Buffer.isBuffer(value)) {
|
||||
return value;
|
||||
} else if (!utils.isObject(value)) {
|
||||
throw new CastError('buffer', value, this.path);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
var path = doc.$__fullPath(this.path);
|
||||
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
var pop = owner.populated(path, true);
|
||||
var ret = new pop.options.model(value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// documents
|
||||
if (value && value._id) {
|
||||
value = value._id;
|
||||
}
|
||||
|
||||
if (Buffer.isBuffer(value)) {
|
||||
if (!(value instanceof MongooseBuffer)) {
|
||||
value = new MongooseBuffer(value, [this.path, doc]);
|
||||
}
|
||||
|
||||
return value;
|
||||
} else if (value instanceof Binary) {
|
||||
var ret = new MongooseBuffer(value.value(true), [this.path, doc]);
|
||||
ret._subtype = value.sub_type;
|
||||
// do not override Binary subtypes. users set this
|
||||
// to whatever they want.
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (null === value) return value;
|
||||
|
||||
var type = typeof value;
|
||||
if ('string' == type || 'number' == type || Array.isArray(value)) {
|
||||
var ret = new MongooseBuffer(value, [this.path, doc]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
167
node_modules/mongoose/lib/schema/date.js
generated
vendored
Normal file
167
node_modules/mongoose/lib/schema/date.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
/*!
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype');
|
||||
var CastError = SchemaType.CastError;
|
||||
var utils = require('../utils');
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
SchemaDate.prototype.expires = function (when) {
|
||||
if (!this._index || 'Object' !== this._index.constructor.name) {
|
||||
this._index = {};
|
||||
}
|
||||
|
||||
this._index.expires = when;
|
||||
utils.expires(this._index);
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
189
node_modules/mongoose/lib/schema/documentarray.js
generated
vendored
Normal file
189
node_modules/mongoose/lib/schema/documentarray.js
generated
vendored
Normal file
@@ -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;
|
||||
41
node_modules/mongoose/lib/schema/embedded.js
generated
vendored
Normal file
41
node_modules/mongoose/lib/schema/embedded.js
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype')
|
||||
, CastError = SchemaType.CastError
|
||||
, errorMessages = require('../error').messages
|
||||
, utils = require('../utils')
|
||||
, Document
|
||||
|
||||
/**
|
||||
* EmbeddedDocument SchemaType constructor.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {Object} options
|
||||
* @inherits SchemaType
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function SchemaEmbedded (key, options, EmbeddedDoc, parentArray) {
|
||||
SchemaType.call(this, key, options, 'EmbeddedDocument');
|
||||
this.EmbeddedDoc = EmbeddedDoc;
|
||||
this.parentArray = parentArray;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Inherits from SchemaType.
|
||||
*/
|
||||
|
||||
SchemaEmbedded.prototype.__proto__ = SchemaType.prototype;
|
||||
|
||||
SchemaEmbedded.prototype.cast = function (value, doc, init) {
|
||||
return new this.EmbeddedDoc(value, this.parentArray);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = SchemaEmbedded;
|
||||
28
node_modules/mongoose/lib/schema/index.js
generated
vendored
Normal file
28
node_modules/mongoose/lib/schema/index.js
generated
vendored
Normal file
@@ -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;
|
||||
83
node_modules/mongoose/lib/schema/mixed.js
generated
vendored
Normal file
83
node_modules/mongoose/lib/schema/mixed.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype');
|
||||
var utils = require('../utils');
|
||||
|
||||
/**
|
||||
* Mixed SchemaType constructor.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Object} options
|
||||
* @inherits SchemaType
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function Mixed (path, options) {
|
||||
if (options && options.default) {
|
||||
var def = options.default;
|
||||
if (Array.isArray(def) && 0 === def.length) {
|
||||
// make sure empty array defaults are handled
|
||||
options.default = Array;
|
||||
} else if (!options.shared &&
|
||||
utils.isObject(def) &&
|
||||
0 === Object.keys(def).length) {
|
||||
// prevent odd "shared" objects between documents
|
||||
options.default = function () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
227
node_modules/mongoose/lib/schema/number.js
generated
vendored
Normal file
227
node_modules/mongoose/lib/schema/number.js
generated
vendored
Normal file
@@ -0,0 +1,227 @@
|
||||
/*!
|
||||
* Module requirements.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype')
|
||||
, CastError = SchemaType.CastError
|
||||
, utils = require('../utils')
|
||||
, Document
|
||||
|
||||
/**
|
||||
* 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, doc) {
|
||||
if (SchemaType._isRef(this, value, doc, true)) {
|
||||
return null != value;
|
||||
} else {
|
||||
return typeof value == 'number' || value instanceof Number;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a minimum 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
|
||||
* @return {SchemaType} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaNumber.prototype.min = function (value) {
|
||||
if (this.minValidator) {
|
||||
this.validators = this.validators.filter(function (v) {
|
||||
return 'min' != v[1];
|
||||
});
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
this.validators.push([this.minValidator = 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
|
||||
* @return {SchemaType} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaNumber.prototype.max = function (value) {
|
||||
if (this.maxValidator) {
|
||||
this.validators = this.validators.filter(function(v){
|
||||
return 'max' != v[1];
|
||||
});
|
||||
}
|
||||
|
||||
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, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (null == value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if ('number' == typeof value) {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('number', value, this.path);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
var path = doc.$__fullPath(this.path);
|
||||
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
var pop = owner.populated(path, true);
|
||||
var ret = new pop.options.model(value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
var val = value && value._id
|
||||
? value._id // documents
|
||||
: value;
|
||||
|
||||
if (!isNaN(val)){
|
||||
if (null === val) return val;
|
||||
if ('' === val) return null;
|
||||
if ('string' == typeof val) val = Number(val);
|
||||
if (val instanceof Number) return val
|
||||
if ('number' == typeof val) return val;
|
||||
if (val.toString && !Array.isArray(val) &&
|
||||
val.toString() == Number(val)) {
|
||||
return new Number(val)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
186
node_modules/mongoose/lib/schema/objectid.js
generated
vendored
Normal file
186
node_modules/mongoose/lib/schema/objectid.js
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype')
|
||||
, CastError = SchemaType.CastError
|
||||
, driver = global.MONGOOSE_DRIVER_PATH || './../drivers/node-mongodb-native'
|
||||
, oid = require('../types/objectid')
|
||||
, utils = require('../utils')
|
||||
, Document
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Adds an auto-generated ObjectId default if turnOn is true.
|
||||
* @param {Boolean} turnOn auto generated ObjectId defaults
|
||||
* @api public
|
||||
* @return {SchemaType} this
|
||||
*/
|
||||
|
||||
ObjectId.prototype.auto = function (turnOn) {
|
||||
if (turnOn) {
|
||||
this.default(defaultId);
|
||||
this.set(resetId)
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check required
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
ObjectId.prototype.checkRequired = function checkRequired (value, doc) {
|
||||
if (SchemaType._isRef(this, value, doc, true)) {
|
||||
return null != value;
|
||||
} else {
|
||||
return value instanceof oid;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Casts to ObjectId
|
||||
*
|
||||
* @param {Object} value
|
||||
* @param {Object} doc
|
||||
* @param {Boolean} init whether this is an initialization cast
|
||||
* @api private
|
||||
*/
|
||||
|
||||
ObjectId.prototype.cast = function (value, doc, init) {
|
||||
if (SchemaType._isRef(this, value, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (null == value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (value instanceof oid) {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('ObjectId', value, this.path);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
var path = doc.$__fullPath(this.path);
|
||||
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
var pop = owner.populated(path, true);
|
||||
var ret = new pop.options.model(value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function defaultId () {
|
||||
return new oid();
|
||||
};
|
||||
|
||||
function resetId (v) {
|
||||
this.$__._id = null;
|
||||
return v;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = ObjectId;
|
||||
312
node_modules/mongoose/lib/schema/string.js
generated
vendored
Normal file
312
node_modules/mongoose/lib/schema/string.js
generated
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var SchemaType = require('../schematype')
|
||||
, CastError = SchemaType.CastError
|
||||
, utils = require('../utils')
|
||||
, Document
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return {SchemaType} this
|
||||
* @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 this;
|
||||
}
|
||||
|
||||
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']);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return {SchemaType} this
|
||||
*/
|
||||
|
||||
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
|
||||
* @return {SchemaType} this
|
||||
*/
|
||||
|
||||
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
|
||||
* @return {SchemaType} this
|
||||
*/
|
||||
|
||||
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
|
||||
* @return {SchemaType} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaString.prototype.match = function match (regExp) {
|
||||
this.validators.push([function(v){
|
||||
return null != v && '' !== v
|
||||
? regExp.test(v)
|
||||
: true
|
||||
}, 'regexp']);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check required
|
||||
*
|
||||
* @param {String|null|undefined} value
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SchemaString.prototype.checkRequired = function checkRequired (value, doc) {
|
||||
if (SchemaType._isRef(this, value, doc, true)) {
|
||||
return null != value;
|
||||
} else {
|
||||
return (value instanceof String || typeof value == 'string') && value.length;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Casts to String
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SchemaString.prototype.cast = function (value, doc, init) {
|
||||
if (SchemaType._isRef(this, value, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (null == value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if ('string' == typeof value) {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('string', value, this.path);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
var path = doc.$__fullPath(this.path);
|
||||
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
var pop = owner.populated(path, true);
|
||||
var ret = new pop.options.model(value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value === null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if ('undefined' !== typeof value) {
|
||||
// handle documents being passed
|
||||
if (value._id && 'string' == typeof value._id) {
|
||||
return value._id;
|
||||
}
|
||||
if (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;
|
||||
34
node_modules/mongoose/lib/schemadefault.js
generated
vendored
Normal file
34
node_modules/mongoose/lib/schemadefault.js
generated
vendored
Normal file
@@ -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 });
|
||||
628
node_modules/mongoose/lib/schematype.js
generated
vendored
Normal file
628
node_modules/mongoose/lib/schematype.js
generated
vendored
Normal file
@@ -0,0 +1,628 @@
|
||||
/*!
|
||||
* 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, typeof m.aNumber) // 4.815162342 "number"
|
||||
*
|
||||
* @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({ loc: { type: [Number], index: 'hashed' })
|
||||
* var s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })
|
||||
* var s = new Schema({ loc: { type: [Number], index: { type: '2dsphere', sparse: 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|String} 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 (null == this._index || 'boolean' == typeof this._index) {
|
||||
this._index = {};
|
||||
} else if ('string' == typeof this._index) {
|
||||
this._index = { type: 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 (null == this._index || 'boolean' == typeof this._index) {
|
||||
this._index = {};
|
||||
} else if ('string' == typeof this._index) {
|
||||
this._index = { type: this._index };
|
||||
}
|
||||
|
||||
this._index.sparse = bool;
|
||||
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 TypeError('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 TypeError('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
|
||||
* @return {SchemaType} this
|
||||
* @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, this);
|
||||
}
|
||||
|
||||
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, scope, init)) {
|
||||
return init
|
||||
? value
|
||||
: this.cast(value, scope, init, priorVal);
|
||||
}
|
||||
|
||||
var v = value
|
||||
, setters = this.setters
|
||||
, len = setters.length
|
||||
|
||||
if (!len) {
|
||||
if (null === v || undefined === v) return v;
|
||||
return 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, scope, 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
|
||||
* @return {SchemaType} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaType.prototype.select = function select (val) {
|
||||
this.selected = !! val;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 (ok, msg, val) {
|
||||
if (err) return;
|
||||
if (ok === undefined || ok) {
|
||||
--count || fn(null);
|
||||
} else {
|
||||
fn(err = new ValidatorError(path, msg, val));
|
||||
}
|
||||
}
|
||||
|
||||
this.validators.forEach(function (v) {
|
||||
var validator = v[0]
|
||||
, message = v[1];
|
||||
|
||||
if (validator instanceof RegExp) {
|
||||
validate(validator.test(value), message, value);
|
||||
} else if ('function' === typeof validator) {
|
||||
if (2 === validator.length) {
|
||||
validator.call(scope, value, function (ok) {
|
||||
validate(ok, message, value);
|
||||
});
|
||||
} else {
|
||||
validate(validator.call(scope, value), message, value);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if value is a valid Reference.
|
||||
*
|
||||
* @param {SchemaType} self
|
||||
* @param {Object} value
|
||||
* @param {Document} doc
|
||||
* @param {Boolean} init
|
||||
* @return {Boolean}
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SchemaType._isRef = function (self, value, doc, init) {
|
||||
// fast path
|
||||
var ref = init && self.options && self.options.ref;
|
||||
|
||||
if (!ref && doc && doc.$__fullPath) {
|
||||
// checks for
|
||||
// - this populated with adhoc model and no ref was set in schema OR
|
||||
// - setting / pushing values after population
|
||||
var path = doc.$__fullPath(self.path);
|
||||
var owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
ref = owner.populated(path);
|
||||
}
|
||||
|
||||
if (ref) {
|
||||
if (null == value) return true;
|
||||
if (!Buffer.isBuffer(value) && // buffers are objects too
|
||||
'Binary' != value._bsontype // raw binary value from the db
|
||||
&& utils.isObject(value) // might have deselected _id in population query
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
module.exports = exports = SchemaType;
|
||||
|
||||
exports.CastError = CastError;
|
||||
|
||||
exports.ValidatorError = ValidatorError;
|
||||
179
node_modules/mongoose/lib/statemachine.js
generated
vendored
Normal file
179
node_modules/mongoose/lib/statemachine.js
generated
vendored
Normal file
@@ -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);
|
||||
}
|
||||
|
||||
679
node_modules/mongoose/lib/types/array.js
generated
vendored
Normal file
679
node_modules/mongoose/lib/types/array.js
generated
vendored
Normal file
@@ -0,0 +1,679 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var EmbeddedDocument = require('./embedded');
|
||||
var Document = require('../document');
|
||||
var ObjectId = require('./objectid');
|
||||
var utils = require('../utils');
|
||||
var isMongooseObject = utils.isMongooseObject;
|
||||
|
||||
/**
|
||||
* 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 owner = this._owner;
|
||||
var populated = false;
|
||||
var Model;
|
||||
|
||||
if (this._parent) {
|
||||
// if a populated array, we must cast to the same model
|
||||
// instance as specified in the original query.
|
||||
if (!owner) {
|
||||
owner = this._owner = this._parent.ownerDocument
|
||||
? this._parent.ownerDocument()
|
||||
: this._parent;
|
||||
}
|
||||
|
||||
populated = owner.populated(this._path, true);
|
||||
}
|
||||
|
||||
if (populated && null != value) {
|
||||
// cast to the populated Models schema
|
||||
var Model = populated.options.model;
|
||||
|
||||
// only objects are permitted so we can safely assume that
|
||||
// non-objects are to be interpreted as _id
|
||||
if (Buffer.isBuffer(value) ||
|
||||
value instanceof ObjectId || !utils.isObject(value)) {
|
||||
value = { _id: value };
|
||||
}
|
||||
|
||||
value = new Model(value);
|
||||
return this._schema.caster.cast(value, this._parent, true)
|
||||
}
|
||||
|
||||
return this._schema.caster.cast(value, this._parent, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.
|
||||
*
|
||||
* If no atomics exist, we return all array values after conversion.
|
||||
*
|
||||
* @return {Array}
|
||||
* @method $__getAtomics
|
||||
* @memberOf MongooseArray
|
||||
* @api private
|
||||
*/
|
||||
|
||||
MongooseArray.prototype.$__getAtomics = function () {
|
||||
var ret = [];
|
||||
var keys = Object.keys(this._atomics);
|
||||
var i = keys.length;
|
||||
|
||||
if (0 === i) {
|
||||
ret[0] = ['$set', this.toObject({ depopulate: 1 })];
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (i--) {
|
||||
var op = keys[i];
|
||||
var val = this._atomics[op];
|
||||
|
||||
// the atomic values which are arrays are not MongooseArrays. we
|
||||
// need to convert their elements as if they were MongooseArrays
|
||||
// to handle populated arrays versus DocumentArrays properly.
|
||||
if (isMongooseObject(val)) {
|
||||
val = val.toObject({ depopulate: 1 });
|
||||
} else if (Array.isArray(val)) {
|
||||
val = this.toObject.call(val, { depopulate: 1 });
|
||||
} else if (val.valueOf) {
|
||||
val = val.valueOf();
|
||||
}
|
||||
|
||||
if ('$addToSet' == op) {
|
||||
val = { $each: val }
|
||||
}
|
||||
|
||||
ret.push([op, val]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pulls items from the array atomically.
|
||||
*
|
||||
* ####Examples:
|
||||
*
|
||||
* doc.array.pull(ObjectId)
|
||||
* doc.array.pull({ _id: 'someId' })
|
||||
* doc.array.pull(36)
|
||||
* doc.array.pull('tag 1', 'tag 2')
|
||||
*
|
||||
* To remove a document from a subdocument array we may pass an object with a matching `_id`.
|
||||
*
|
||||
* doc.subdocs.push({ _id: 4815162342 })
|
||||
* doc.subdocs.pull({ _id: 4815162342 }) // removed
|
||||
*
|
||||
* Or we may passing the _id directly and let mongoose take care of it.
|
||||
*
|
||||
* doc.subdocs.push({ _id: 4815162342 })
|
||||
* doc.subdocs.pull(4815162342); // works
|
||||
*
|
||||
* @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;
|
||||
};
|
||||
|
||||
/**
|
||||
* Alias of [pull](#types_array_MongooseArray-pull)
|
||||
*
|
||||
* @see MongooseArray#pull #types_array_MongooseArray-pull
|
||||
* @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
|
||||
* @api public
|
||||
* @memberOf MongooseArray
|
||||
* @method remove
|
||||
*/
|
||||
|
||||
MongooseArray.prototype.remove = MongooseArray.prototype.pull;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
return this.map(function (doc) {
|
||||
return doc instanceof Document
|
||||
? doc.toObject(options)
|
||||
: doc
|
||||
});
|
||||
}
|
||||
|
||||
return this.slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
214
node_modules/mongoose/lib/types/buffer.js
generated
vendored
Normal file
214
node_modules/mongoose/lib/types/buffer.js
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
|
||||
/*!
|
||||
* 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)
|
||||
});
|
||||
}
|
||||
|
||||
buf._subtype = 0;
|
||||
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:
|
||||
*
|
||||
* var bson = require('bson')
|
||||
* bson.BSON_BINARY_SUBTYPE_DEFAULT
|
||||
* bson.BSON_BINARY_SUBTYPE_FUNCTION
|
||||
* bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
|
||||
* bson.BSON_BINARY_SUBTYPE_UUID
|
||||
* bson.BSON_BINARY_SUBTYPE_MD5
|
||||
* bson.BSON_BINARY_SUBTYPE_USER_DEFINED
|
||||
*
|
||||
* doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
|
||||
*
|
||||
* @see http://bsonspec.org/#/specification
|
||||
* @param {Hex} [subtype]
|
||||
* @return {Binary}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
MongooseBuffer.prototype.toObject = function (options) {
|
||||
var subtype = 'number' == typeof options
|
||||
? options
|
||||
: (this._subtype || 0x00);
|
||||
return new Binary(this, subtype);
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if this buffer is equals to `other` buffer
|
||||
*
|
||||
* @param {Buffer} other
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
MongooseBuffer.prototype.equals = function (other) {
|
||||
if (!Buffer.isBuffer(other)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.length !== other.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.length; ++i) {
|
||||
if (this[i] !== other[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
MongooseBuffer.Binary = Binary;
|
||||
|
||||
module.exports = MongooseBuffer;
|
||||
192
node_modules/mongoose/lib/types/documentarray.js
generated
vendored
Normal file
192
node_modules/mongoose/lib/types/documentarray.js
generated
vendored
Normal file
@@ -0,0 +1,192 @@
|
||||
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var MongooseArray = require('./array')
|
||||
, driver = global.MONGOOSE_DRIVER_PATH || '../drivers/node-mongodb-native'
|
||||
, ObjectId = require(driver + '/objectid')
|
||||
, ObjectIdSchema = require('../schema/objectid')
|
||||
, utils = require('../utils')
|
||||
, util = require('util')
|
||||
, Document = require('../document')
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
if (!(value.__parent && value.__parentArray)) {
|
||||
// value may have been created using array.create()
|
||||
value.__parent = this._parent;
|
||||
value.__parentArray = this;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// handle cast('string') or cast(ObjectId) etc.
|
||||
// only objects are permitted so we can safely assume that
|
||||
// non-objects are to be interpreted as _id
|
||||
if (Buffer.isBuffer(value) ||
|
||||
value instanceof ObjectId || !utils.isObject(value)) {
|
||||
value = { _id: 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
|
||||
, sid
|
||||
, _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 Document) {
|
||||
sid || (sid = String(id));
|
||||
if (sid == _id._id) return this[i];
|
||||
} else if (!(_id instanceof ObjectId)) {
|
||||
sid || (sid = String(id));
|
||||
if (sid == _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._
|
||||
*
|
||||
* @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion
|
||||
* @return {Array}
|
||||
* @api public
|
||||
*/
|
||||
|
||||
MongooseDocumentArray.prototype.toObject = function (options) {
|
||||
return this.map(function (doc) {
|
||||
return doc && doc.toObject(options) || 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;
|
||||
244
node_modules/mongoose/lib/types/embedded.js
generated
vendored
Normal file
244
node_modules/mongoose/lib/types/embedded.js
generated
vendored
Normal file
@@ -0,0 +1,244 @@
|
||||
/*!
|
||||
* 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, val, first) {
|
||||
if (!this.__parent) {
|
||||
var msg = 'Unable to invalidate a subdocument that has not been added to an array.'
|
||||
throw new Error(msg);
|
||||
}
|
||||
|
||||
var index = this.__parentArray.indexOf(this);
|
||||
var parentPath = this.__parentArray._path;
|
||||
var fullPath = [parentPath, index, path].join('.');
|
||||
|
||||
// sniffing arguments:
|
||||
// need to check if user passed a value to keep
|
||||
// our error message clean.
|
||||
if (2 < arguments.length) {
|
||||
this.__parent.invalidate(fullPath, err, val);
|
||||
} else {
|
||||
this.__parent.invalidate(fullPath, err);
|
||||
}
|
||||
|
||||
if (first)
|
||||
this.$__.validationError = this.ownerDocument().$__.validationError;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top level document of this sub-document.
|
||||
*
|
||||
* @return {Document}
|
||||
*/
|
||||
|
||||
EmbeddedDocument.prototype.ownerDocument = function () {
|
||||
if (this.$__.ownerDocument) {
|
||||
return this.$__.ownerDocument;
|
||||
}
|
||||
|
||||
var parent = this.__parent;
|
||||
if (!parent) return this;
|
||||
|
||||
while (parent.__parent) {
|
||||
parent = parent.__parent;
|
||||
}
|
||||
|
||||
return this.$__.ownerDocument = parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full path to this document. If optional `path` is passed, it is appended to the full path.
|
||||
*
|
||||
* @param {String} [path]
|
||||
* @return {String}
|
||||
* @api private
|
||||
* @method $__fullPath
|
||||
* @memberOf EmbeddedDocument
|
||||
*/
|
||||
|
||||
EmbeddedDocument.prototype.$__fullPath = function (path) {
|
||||
if (!this.$__.fullPath) {
|
||||
var parent = this;
|
||||
if (!parent.__parent) return path;
|
||||
|
||||
var paths = [];
|
||||
while (parent.__parent) {
|
||||
paths.unshift(parent.__parentArray._path);
|
||||
parent = parent.__parent;
|
||||
}
|
||||
|
||||
this.$__.fullPath = paths.join('.');
|
||||
|
||||
if (!this.$__.ownerDocument) {
|
||||
// optimization
|
||||
this.$__.ownerDocument = parent;
|
||||
}
|
||||
}
|
||||
|
||||
return path
|
||||
? this.$__.fullPath + '.' + path
|
||||
: this.$__.fullPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
13
node_modules/mongoose/lib/types/index.js
generated
vendored
Normal file
13
node_modules/mongoose/lib/types/index.js
generated
vendored
Normal file
@@ -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');
|
||||
43
node_modules/mongoose/lib/types/objectid.js
generated
vendored
Normal file
43
node_modules/mongoose/lib/types/objectid.js
generated
vendored
Normal file
@@ -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;
|
||||
671
node_modules/mongoose/lib/utils.js
generated
vendored
Normal file
671
node_modules/mongoose/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,671 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var ReadPref = require('mongodb').ReadPreference
|
||||
, ObjectId = require('./types/objectid')
|
||||
, cloneRegExp = require('regexp-clone')
|
||||
, sliced = require('sliced')
|
||||
, mpath = require('mpath')
|
||||
, ms = require('ms')
|
||||
, 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`.
|
||||
*
|
||||
* @deprecated remove in 4.x gh-1350
|
||||
*/
|
||||
|
||||
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`.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/*!
|
||||
* 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 (a instanceof RegExp && b instanceof RegExp) {
|
||||
return a.source == b.source &&
|
||||
a.ignoreCase == b.ignoreCase &&
|
||||
a.multiline == b.multiline &&
|
||||
a.global == b.global;
|
||||
}
|
||||
|
||||
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 (obj.constructor) {
|
||||
switch (obj.constructor.name) {
|
||||
case 'Object':
|
||||
return cloneObject(obj, options);
|
||||
case 'Date':
|
||||
return new obj.constructor(+obj);
|
||||
case 'RegExp':
|
||||
return cloneRegExp(obj);
|
||||
default:
|
||||
// ignore
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (obj instanceof ObjectId)
|
||||
return new ObjectId(obj.id);
|
||||
|
||||
if (!obj.constructor && exports.isObject(obj)) {
|
||||
// object created with Object.create(null)
|
||||
return cloneObject(obj, options);
|
||||
}
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Shallow copies defaults into options.
|
||||
*
|
||||
* @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
|
||||
* @api private
|
||||
* @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;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Converts arguments to ReadPrefs the driver
|
||||
* can understand.
|
||||
*
|
||||
* @TODO move this into the driver layer
|
||||
* @param {String|Array} pref
|
||||
* @param {Array} [tags]
|
||||
*/
|
||||
|
||||
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 = 'primaryPreferred';
|
||||
break;
|
||||
case 's':
|
||||
pref = 'secondary';
|
||||
break;
|
||||
case 'sp':
|
||||
pref = 'secondaryPreferred';
|
||||
break;
|
||||
case 'n':
|
||||
pref = 'nearest';
|
||||
break;
|
||||
}
|
||||
|
||||
return new ReadPref(pref, tags);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Populate options constructor
|
||||
*/
|
||||
|
||||
function PopulateOptions (path, select, match, options, model) {
|
||||
this.path = path;
|
||||
this.match = match;
|
||||
this.select = select;
|
||||
this.options = options;
|
||||
this.model = model;
|
||||
this._docs = {};
|
||||
}
|
||||
|
||||
// make it compatible with utils.clone
|
||||
PopulateOptions.prototype.constructor = Object;
|
||||
|
||||
// expose
|
||||
exports.PopulateOptions = PopulateOptions;
|
||||
|
||||
/*!
|
||||
* populate helper
|
||||
*/
|
||||
|
||||
exports.populate = function populate (path, select, model, match, options) {
|
||||
// The order of select/conditions args is opposite Model.find but
|
||||
// necessary to keep backward compatibility (select could be
|
||||
// an array, string, or object literal).
|
||||
|
||||
// might have passed an object specifying all arguments
|
||||
if (1 === arguments.length) {
|
||||
if (path instanceof PopulateOptions) {
|
||||
return [path];
|
||||
}
|
||||
|
||||
if (Array.isArray(path)) {
|
||||
return path.map(function(o){
|
||||
return exports.populate(o)[0];
|
||||
});
|
||||
}
|
||||
|
||||
if (exports.isObject(path)) {
|
||||
match = path.match;
|
||||
options = path.options;
|
||||
select = path.select;
|
||||
model = path.model;
|
||||
path = path.path;
|
||||
}
|
||||
} else if ('string' !== typeof model) {
|
||||
options = match;
|
||||
match = model;
|
||||
model = undefined;
|
||||
}
|
||||
|
||||
if ('string' != typeof path) {
|
||||
throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');
|
||||
}
|
||||
|
||||
var ret = [];
|
||||
var paths = path.split(' ');
|
||||
for (var i = 0; i < paths.length; ++i) {
|
||||
ret.push(new PopulateOptions(paths[i], select, match, options, model));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Return the value of `obj` at the given `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Object} obj
|
||||
*/
|
||||
|
||||
exports.getValue = function (path, obj, map) {
|
||||
return mpath.get(path, obj, '_doc', map);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Sets the value of `obj` at the given `path`.
|
||||
*
|
||||
* @param {String} path
|
||||
* @param {Anything} val
|
||||
* @param {Object} obj
|
||||
*/
|
||||
|
||||
exports.setValue = function (path, val, obj, map) {
|
||||
mpath.set(path, val, obj, '_doc', map);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns an array of values from object `o`.
|
||||
*
|
||||
* @param {Object} o
|
||||
* @return {Array}
|
||||
* @private
|
||||
*/
|
||||
|
||||
exports.object = {};
|
||||
exports.object.vals = function vals (o) {
|
||||
var keys = Object.keys(o)
|
||||
, i = keys.length
|
||||
, ret = [];
|
||||
|
||||
while (i--) {
|
||||
ret.push(o[keys[i]]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* @see exports.options
|
||||
*/
|
||||
|
||||
exports.object.shallowCopy = exports.options;
|
||||
|
||||
/*!
|
||||
* Safer helper for hasOwnProperty checks
|
||||
*
|
||||
* @param {Object} obj
|
||||
* @param {String} prop
|
||||
*/
|
||||
|
||||
exports.object.hasOwnProperty = function (obj, prop) {
|
||||
return Object.prototype.hasOwnProperty.call(obj, prop);
|
||||
}
|
||||
|
||||
/*!
|
||||
* Determine if `val` is null or undefined
|
||||
*
|
||||
* @return {Boolean}
|
||||
*/
|
||||
|
||||
exports.isNullOrUndefined = function (val) {
|
||||
return null == val
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
exports.array = {};
|
||||
|
||||
/*!
|
||||
* Flattens an array.
|
||||
*
|
||||
* [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]
|
||||
*
|
||||
* @param {Array} arr
|
||||
* @param {Function} [filter] If passed, will be invoked with each item in the array. If `filter` returns a falsey value, the item will not be included in the results.
|
||||
* @return {Array}
|
||||
* @private
|
||||
*/
|
||||
|
||||
exports.array.flatten = function flatten (arr, filter, ret) {
|
||||
ret || (ret = []);
|
||||
|
||||
arr.forEach(function (item) {
|
||||
if (Array.isArray(item)) {
|
||||
flatten(item, filter, ret);
|
||||
} else {
|
||||
if (!filter || filter(item)) {
|
||||
ret.push(item);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
103
node_modules/mongoose/lib/virtualtype.js
generated
vendored
Normal file
103
node_modules/mongoose/lib/virtualtype.js
generated
vendored
Normal file
@@ -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;
|
||||
2
node_modules/mongoose/node_modules/hooks/.npmignore
generated
vendored
Normal file
2
node_modules/mongoose/node_modules/hooks/.npmignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
**.swp
|
||||
node_modules
|
||||
9
node_modules/mongoose/node_modules/hooks/Makefile
generated
vendored
Normal file
9
node_modules/mongoose/node_modules/hooks/Makefile
generated
vendored
Normal file
@@ -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
|
||||
306
node_modules/mongoose/node_modules/hooks/README.md
generated
vendored
Normal file
306
node_modules/mongoose/node_modules/hooks/README.md
generated
vendored
Normal file
@@ -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
|
||||
134
node_modules/mongoose/node_modules/hooks/hooks.alt.js
generated
vendored
Normal file
134
node_modules/mongoose/node_modules/hooks/hooks.alt.js
generated
vendored
Normal file
@@ -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;
|
||||
}
|
||||
};
|
||||
161
node_modules/mongoose/node_modules/hooks/hooks.js
generated
vendored
Normal file
161
node_modules/mongoose/node_modules/hooks/hooks.js
generated
vendored
Normal file
@@ -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);
|
||||
};
|
||||
}
|
||||
68
node_modules/mongoose/node_modules/hooks/package.json
generated
vendored
Normal file
68
node_modules/mongoose/node_modules/hooks/package.json
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
691
node_modules/mongoose/node_modules/hooks/test.js
generated
vendored
Normal file
691
node_modules/mongoose/node_modules/hooks/test.js
generated
vendored
Normal file
@@ -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);
|
||||
});
|
||||
}
|
||||
};
|
||||
5
node_modules/mongoose/node_modules/mongodb/.travis.yml
generated
vendored
Normal file
5
node_modules/mongoose/node_modules/mongodb/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.6
|
||||
- 0.8
|
||||
- 0.10 # development version of 0.8, may be unstable
|
||||
23
node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md
generated
vendored
Normal file
23
node_modules/mongoose/node_modules/mongodb/CONTRIBUTING.md
generated
vendored
Normal file
@@ -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.
|
||||
201
node_modules/mongoose/node_modules/mongodb/LICENSE
generated
vendored
Normal file
201
node_modules/mongoose/node_modules/mongodb/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
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.
|
||||
28
node_modules/mongoose/node_modules/mongodb/Makefile
generated
vendored
Normal file
28
node_modules/mongoose/node_modules/mongodb/Makefile
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
NODE = node
|
||||
NPM = npm
|
||||
NODEUNIT = node_modules/nodeunit/bin/nodeunit
|
||||
DOX = node_modules/dox/bin/dox
|
||||
name = all
|
||||
|
||||
total: build_native
|
||||
|
||||
test_functional:
|
||||
node test/runner.js -t functional
|
||||
|
||||
test_ssl:
|
||||
node test/runner.js -t ssl
|
||||
|
||||
test_replicaset:
|
||||
node test/runner.js -t replicaset
|
||||
|
||||
test_sharded:
|
||||
node test/runner.js -t sharded
|
||||
|
||||
test_auth:
|
||||
node test/runner.js -t auth
|
||||
|
||||
generate_docs:
|
||||
$(NODE) dev/tools/build-docs.js
|
||||
make --directory=./docs/sphinx-docs --file=Makefile html
|
||||
|
||||
.PHONY: total
|
||||
421
node_modules/mongoose/node_modules/mongodb/Readme.md
generated
vendored
Normal file
421
node_modules/mongoose/node_modules/mongodb/Readme.md
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
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.
|
||||
|
||||
Live Examples
|
||||
============
|
||||
<a href="https://runnable.com/node-mongodb-native" target="_blank"><img src="https://runnable.com/external/styles/assets/runnablebtn.png" style="width:67px;height:25px;"></a>
|
||||
|
||||
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 MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
|
||||
var collection = db.collection('test_insert');
|
||||
collection.insert({a:2}, function(err, docs) {
|
||||
|
||||
collection.count(function(err, count) {
|
||||
console.log(format("count = %s", count));
|
||||
});
|
||||
|
||||
// Locate all the entries using find
|
||||
collection.find().toArray(function(err, results) {
|
||||
console.dir(results);
|
||||
// Let's close the db
|
||||
db.close();
|
||||
});
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
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:
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test'
|
||||
, {db: {native_parser: true}}, function(err, db) {})
|
||||
```
|
||||
|
||||
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 the extensive documentation [Documentation](http://mongodb.github.com/node-mongodb-native/)
|
||||
|
||||
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
|
||||
var MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
// Custom factory (need to provide a 12 byte array);
|
||||
CustomPKFactory = function() {}
|
||||
CustomPKFactory.prototype = new Object();
|
||||
CustomPKFactory.createPk = function() {
|
||||
return new ObjectID("aaaaaaaaaaaa");
|
||||
}
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
|
||||
db.dropDatabase(function(err, done) {
|
||||
|
||||
db.createCollection('test_custom_key', function(err, collection) {
|
||||
|
||||
collection.insert({'a':1}, function(err, docs) {
|
||||
|
||||
collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}).toArray(function(err, items) {
|
||||
console.dir(items);
|
||||
// Let's close the db
|
||||
db.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 MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
|
||||
var collection = db
|
||||
.collection('test')
|
||||
.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 MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
|
||||
db.collection('test').insert({hello: 'world'}, {w:1}, 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 MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
|
||||
db.collection('test').update({hi: 'here'}, {$set: {hi: 'there'}}, {w:1}, 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 MongoClient = require('mongodb').MongoClient
|
||||
, format = require('util').format;
|
||||
|
||||
MongoClient.connect('mongodb://127.0.0.1:27017/test', function(err, db) {
|
||||
if(err) throw err;
|
||||
db.collection('test').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.
|
||||
|
||||
1
node_modules/mongoose/node_modules/mongodb/index.js
generated
vendored
Executable file
1
node_modules/mongoose/node_modules/mongodb/index.js
generated
vendored
Executable file
@@ -0,0 +1 @@
|
||||
module.exports = require('./lib/mongodb');
|
||||
339
node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js
generated
vendored
Normal file
339
node_modules/mongoose/node_modules/mongodb/lib/mongodb/admin.js
generated
vendored
Normal file
@@ -0,0 +1,339 @@
|
||||
/*!
|
||||
* Module dependencies.
|
||||
*/
|
||||
var Collection = require('./collection').Collection,
|
||||
Cursor = require('./cursor').Cursor,
|
||||
DbCommand = require('./commands/db_command').DbCommand,
|
||||
utils = require('./utils');
|
||||
|
||||
/**
|
||||
* Allows the user to access the admin functionality of MongoDB
|
||||
*
|
||||
* @class Represents the Admin methods of MongoDB.
|
||||
* @param {Object} db Current db instance we wish to perform Admin operations on.
|
||||
* @return {Function} Constructor for Admin type.
|
||||
*/
|
||||
function Admin(db) {
|
||||
if(!(this instanceof Admin)) return new Admin(db);
|
||||
this.db = db;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the server information for the current
|
||||
* instance of the db client
|
||||
*
|
||||
* @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 buildInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.buildInfo = function(callback) {
|
||||
this.serverInfo(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the server information for the current
|
||||
* instance of the db client
|
||||
*
|
||||
* @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 serverInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api private
|
||||
*/
|
||||
Admin.prototype.serverInfo = function(callback) {
|
||||
this.db.executeDbAdminCommand({buildinfo:1}, function(err, doc) {
|
||||
if(err != null) return callback(err, null);
|
||||
return callback(null, doc.documents[0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve this db's server status.
|
||||
*
|
||||
* @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 serverStatus or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.serverStatus = function(callback) {
|
||||
var self = this;
|
||||
|
||||
this.db.executeDbAdminCommand({serverStatus: 1}, function(err, doc) {
|
||||
if(err == null && doc.documents[0].ok === 1) {
|
||||
callback(null, doc.documents[0]);
|
||||
} else {
|
||||
if(err) return callback(err, false);
|
||||
return callback(utils.toError(doc.documents[0]), false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the current profiling Level for MongoDB
|
||||
*
|
||||
* @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 profilingLevel or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.profilingLevel = function(callback) {
|
||||
var self = this;
|
||||
|
||||
this.db.executeDbAdminCommand({profile:-1}, function(err, doc) {
|
||||
doc = doc.documents[0];
|
||||
|
||||
if(err == null && doc.ok === 1) {
|
||||
var was = doc.was;
|
||||
if(was == 0) return callback(null, "off");
|
||||
if(was == 1) return callback(null, "slow_only");
|
||||
if(was == 2) return callback(null, "all");
|
||||
return callback(new Error("Error: illegal profiling level value " + was), null);
|
||||
} else {
|
||||
err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Ping the MongoDB server and retrieve results
|
||||
*
|
||||
* @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 ping or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.ping = function(options, callback) {
|
||||
// Unpack calls
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
callback = args.pop();
|
||||
|
||||
this.db.executeDbAdminCommand({ping: 1}, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate against MongoDB
|
||||
*
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {String} password The password for the authentication.
|
||||
* @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 authenticate or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.authenticate = function(username, password, callback) {
|
||||
this.db.authenticate(username, password, {authdb: 'admin'}, function(err, doc) {
|
||||
return callback(err, doc);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout current authenticated user
|
||||
*
|
||||
* @param {Object} [options] Optional parameters to the 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 results from logout or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.logout = function(callback) {
|
||||
this.db.logout({authdb: 'admin'}, function(err, doc) {
|
||||
return callback(err, doc);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a user to the MongoDB server, if the user exists it will
|
||||
* overwrite the current password
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {String} password The password for the authentication.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @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 addUser or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.addUser = function(username, password, options, callback) {
|
||||
var args = Array.prototype.slice.call(arguments, 2);
|
||||
callback = args.pop();
|
||||
options = args.length ? args.shift() : {};
|
||||
|
||||
options.dbName = 'admin';
|
||||
// Add user
|
||||
this.db.addUser(username, password, options, function(err, doc) {
|
||||
return callback(err, doc);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user from the MongoDB server
|
||||
*
|
||||
* Options
|
||||
* - **safe** {true | {w:n, wtimeout:n} | {fsync:true}, default:false}, executes with a getLastError command returning the results of the command on MongoDB.
|
||||
*
|
||||
* @param {String} username The user name for the authentication.
|
||||
* @param {Object} [options] additional options during update.
|
||||
* @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 removeUser or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.removeUser = function(username, options, callback) {
|
||||
var self = this;
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
callback = args.pop();
|
||||
options = args.length ? args.shift() : {};
|
||||
options.dbName = 'admin';
|
||||
|
||||
this.db.removeUser(username, options, function(err, doc) {
|
||||
return callback(err, doc);
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current profiling level of MongoDB
|
||||
*
|
||||
* @param {String} level The new profiling level (off, slow_only, all)
|
||||
* @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 setProfilingLevel or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.setProfilingLevel = function(level, callback) {
|
||||
var self = this;
|
||||
var command = {};
|
||||
var profile = 0;
|
||||
|
||||
if(level == "off") {
|
||||
profile = 0;
|
||||
} else if(level == "slow_only") {
|
||||
profile = 1;
|
||||
} else if(level == "all") {
|
||||
profile = 2;
|
||||
} else {
|
||||
return callback(new Error("Error: illegal profiling level value " + level));
|
||||
}
|
||||
|
||||
// Set up the profile number
|
||||
command['profile'] = profile;
|
||||
|
||||
this.db.executeDbAdminCommand(command, function(err, doc) {
|
||||
doc = doc.documents[0];
|
||||
|
||||
if(err == null && doc.ok === 1)
|
||||
return callback(null, level);
|
||||
return err != null ? callback(err, null) : callback(new Error("Error with profile command"), null);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrive the current profiling information for MongoDB
|
||||
*
|
||||
* @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 profilingInfo or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.profilingInfo = function(callback) {
|
||||
try {
|
||||
new Cursor(this.db, new Collection(this.db, DbCommand.SYSTEM_PROFILE_COLLECTION), {}, {}, {dbName: 'admin'}).toArray(function(err, items) {
|
||||
return callback(err, items);
|
||||
});
|
||||
} catch (err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a db command against the Admin database
|
||||
*
|
||||
* @param {Object} command A command object `{ping:1}`.
|
||||
* @param {Object} [options] Optional parameters to the command.
|
||||
* @param {Function} callback this will be called after executing this method. The command always return the whole result of the command as the second parameter.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.command = function(command, options, callback) {
|
||||
var self = this;
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
callback = args.pop();
|
||||
options = args.length ? args.shift() : {};
|
||||
|
||||
// Execute a command
|
||||
this.db.executeDbAdminCommand(command, options, function(err, doc) {
|
||||
// Ensure change before event loop executes
|
||||
return callback != null ? callback(err, doc) : null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an existing collection
|
||||
*
|
||||
* @param {String} collectionName The name of the collection to validate.
|
||||
* @param {Object} [options] Optional parameters to the 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 results from validateCollection or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.validateCollection = function(collectionName, options, callback) {
|
||||
var args = Array.prototype.slice.call(arguments, 1);
|
||||
callback = args.pop();
|
||||
options = args.length ? args.shift() : {};
|
||||
|
||||
var self = this;
|
||||
var command = {validate: collectionName};
|
||||
var keys = Object.keys(options);
|
||||
|
||||
// Decorate command with extra options
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
if(options.hasOwnProperty(keys[i])) {
|
||||
command[keys[i]] = options[keys[i]];
|
||||
}
|
||||
}
|
||||
|
||||
this.db.executeDbCommand(command, function(err, doc) {
|
||||
if(err != null) return callback(err, null);
|
||||
doc = doc.documents[0];
|
||||
|
||||
if(doc.ok === 0)
|
||||
return callback(new Error("Error with validate command"), null);
|
||||
if(doc.result != null && doc.result.constructor != String)
|
||||
return callback(new Error("Error with validation data"), null);
|
||||
if(doc.result != null && doc.result.match(/exception|corrupt/) != null)
|
||||
return callback(new Error("Error: invalid collection " + collectionName), null);
|
||||
if(doc.valid != null && !doc.valid)
|
||||
return callback(new Error("Error: invalid collection " + collectionName), null);
|
||||
|
||||
return callback(null, doc);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* List the available databases
|
||||
*
|
||||
* @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 listDatabases or null if an error occured.
|
||||
* @return {null} Returns no result
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.listDatabases = function(callback) {
|
||||
// Execute the listAllDatabases command
|
||||
this.db.executeDbAdminCommand({listDatabases:1}, {}, function(err, doc) {
|
||||
if(err != null) return callback(err, null);
|
||||
return callback(null, doc.documents[0]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get ReplicaSet status
|
||||
*
|
||||
* @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 replSetGetStatus or null if an error occured.
|
||||
* @return {null}
|
||||
* @api public
|
||||
*/
|
||||
Admin.prototype.replSetGetStatus = function(callback) {
|
||||
var self = this;
|
||||
|
||||
this.db.executeDbAdminCommand({replSetGetStatus:1}, function(err, doc) {
|
||||
if(err == null && doc.documents[0].ok === 1)
|
||||
return callback(null, doc.documents[0]);
|
||||
if(err) return callback(err, false);
|
||||
return callback(utils.toError(doc.documents[0]), false);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
exports.Admin = Admin;
|
||||
57
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js
generated
vendored
Normal file
57
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_cr.js
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
var DbCommand = require('../commands/db_command').DbCommand
|
||||
, utils = require('../utils');
|
||||
|
||||
var authenticate = function(db, username, password, authdb, options, callback) {
|
||||
var numberOfConnections = 0;
|
||||
var errorObject = null;
|
||||
|
||||
if(options['connection'] != null) {
|
||||
//if a connection was explicitly passed on options, then we have only one...
|
||||
numberOfConnections = 1;
|
||||
} else {
|
||||
// Get the amount of connections in the pool to ensure we have authenticated all comments
|
||||
numberOfConnections = db.serverConfig.allRawConnections().length;
|
||||
options['onAll'] = true;
|
||||
}
|
||||
|
||||
// Execute all four
|
||||
db._executeQueryCommand(DbCommand.createGetNonceCommand(db), options, function(err, result, connection) {
|
||||
// Execute on all the connections
|
||||
if(err == null) {
|
||||
// Nonce used to make authentication request with md5 hash
|
||||
var nonce = result.documents[0].nonce;
|
||||
// Execute command
|
||||
db._executeQueryCommand(DbCommand.createAuthenticationCommand(db, username, password, nonce, authdb), {connection:connection}, function(err, result) {
|
||||
// Count down
|
||||
numberOfConnections = numberOfConnections - 1;
|
||||
// Ensure we save any error
|
||||
if(err) {
|
||||
errorObject = err;
|
||||
} else if(result
|
||||
&& Array.isArray(result.documents)
|
||||
&& result.documents.length > 0
|
||||
&& (result.documents[0].err != null || result.documents[0].errmsg != null)) {
|
||||
errorObject = utils.toError(result.documents[0]);
|
||||
}
|
||||
|
||||
// Work around the case where the number of connections are 0
|
||||
if(numberOfConnections <= 0 && typeof callback == 'function') {
|
||||
var internalCallback = callback;
|
||||
callback = null;
|
||||
|
||||
if(errorObject == null
|
||||
&& result && Array.isArray(result.documents) && result.documents.length > 0
|
||||
&& result.documents[0].ok == 1) { // We authenticated correctly save the credentials
|
||||
db.serverConfig.auth.add('MONGODB-CR', db.databaseName, username, password, authdb);
|
||||
// Return callback
|
||||
internalCallback(errorObject, true);
|
||||
} else {
|
||||
internalCallback(errorObject, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.authenticate = authenticate;
|
||||
149
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js
generated
vendored
Normal file
149
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_gssapi.js
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
var DbCommand = require('../commands/db_command').DbCommand
|
||||
, utils = require('../utils')
|
||||
, format = require('util').format;
|
||||
|
||||
// Kerberos class
|
||||
var Kerberos = null;
|
||||
var MongoAuthProcess = null;
|
||||
// Try to grab the Kerberos class
|
||||
try {
|
||||
Kerberos = require('kerberos').Kerberos
|
||||
// Authentication process for Mongo
|
||||
MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
|
||||
} catch(err) {}
|
||||
|
||||
var authenticate = function(db, username, password, authdb, options, callback) {
|
||||
var numberOfConnections = 0;
|
||||
var errorObject = null;
|
||||
// We don't have the Kerberos library
|
||||
if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
|
||||
|
||||
if(options['connection'] != null) {
|
||||
//if a connection was explicitly passed on options, then we have only one...
|
||||
numberOfConnections = 1;
|
||||
} else {
|
||||
// Get the amount of connections in the pool to ensure we have authenticated all comments
|
||||
numberOfConnections = db.serverConfig.allRawConnections().length;
|
||||
options['onAll'] = true;
|
||||
}
|
||||
|
||||
// Grab all the connections
|
||||
var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
|
||||
var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
|
||||
var error = null;
|
||||
// Authenticate all connections
|
||||
for(var i = 0; i < numberOfConnections; i++) {
|
||||
|
||||
// Start Auth process for a connection
|
||||
GSSAPIInitialize(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
|
||||
// Adjust number of connections left to connect
|
||||
numberOfConnections = numberOfConnections - 1;
|
||||
// If we have an error save it
|
||||
if(err) error = err;
|
||||
|
||||
// We are done
|
||||
if(numberOfConnections == 0) {
|
||||
if(err) return callback(error, false);
|
||||
// We authenticated correctly save the credentials
|
||||
db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
|
||||
// Return valid callback
|
||||
return callback(null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize step
|
||||
var GSSAPIInitialize = function(db, username, password, authdb, gssapiServiceName, connection, callback) {
|
||||
// Create authenticator
|
||||
var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, gssapiServiceName);
|
||||
|
||||
// Perform initialization
|
||||
mongo_auth_process.init(username, password, function(err, context) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
// Perform the first step
|
||||
mongo_auth_process.transition('', function(err, payload) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
// Call the next db step
|
||||
MongoDBGSSAPIFirstStep(mongo_auth_process, payload, db, username, password, authdb, connection, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Perform first step against mongodb
|
||||
var MongoDBGSSAPIFirstStep = function(mongo_auth_process, payload, db, username, password, authdb, connection, callback) {
|
||||
// Build the sasl start command
|
||||
var command = {
|
||||
saslStart: 1
|
||||
, mechanism: 'GSSAPI'
|
||||
, payload: payload
|
||||
, autoAuthorize: 1
|
||||
};
|
||||
|
||||
// Execute first sasl step
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err, false);
|
||||
// Get the payload
|
||||
doc = doc.documents[0];
|
||||
var db_payload = doc.payload;
|
||||
|
||||
mongo_auth_process.transition(doc.payload, function(err, payload) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
// MongoDB API Second Step
|
||||
MongoDBGSSAPISecondStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
// Perform first step against mongodb
|
||||
var MongoDBGSSAPISecondStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
|
||||
// Build Authentication command to send to MongoDB
|
||||
var command = {
|
||||
saslContinue: 1
|
||||
, conversationId: doc.conversationId
|
||||
, payload: payload
|
||||
};
|
||||
|
||||
// Execute the command
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
// Get the result document
|
||||
doc = doc.documents[0];
|
||||
|
||||
// Call next transition for kerberos
|
||||
mongo_auth_process.transition(doc.payload, function(err, payload) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
// Call the last and third step
|
||||
MongoDBGSSAPIThirdStep(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var MongoDBGSSAPIThirdStep = function(mongo_auth_process, payload, doc, db, username, password, authdb, connection, callback) {
|
||||
// Build final command
|
||||
var command = {
|
||||
saslContinue: 1
|
||||
, conversationId: doc.conversationId
|
||||
, payload: payload
|
||||
};
|
||||
|
||||
// Let's finish the auth process against mongodb
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err, false);
|
||||
|
||||
mongo_auth_process.transition(null, function(err, payload) {
|
||||
if(err) return callback(err, false);
|
||||
callback(null, true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.authenticate = authenticate;
|
||||
66
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js
generated
vendored
Normal file
66
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_plain.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
var DbCommand = require('../commands/db_command').DbCommand
|
||||
, utils = require('../utils')
|
||||
, Binary = require('bson').Binary
|
||||
, format = require('util').format;
|
||||
|
||||
var authenticate = function(db, username, password, options, callback) {
|
||||
var numberOfConnections = 0;
|
||||
var errorObject = null;
|
||||
|
||||
if(options['connection'] != null) {
|
||||
//if a connection was explicitly passed on options, then we have only one...
|
||||
numberOfConnections = 1;
|
||||
} else {
|
||||
// Get the amount of connections in the pool to ensure we have authenticated all comments
|
||||
numberOfConnections = db.serverConfig.allRawConnections().length;
|
||||
options['onAll'] = true;
|
||||
}
|
||||
|
||||
// Create payload
|
||||
var payload = new Binary(format("\x00%s\x00%s", username, password));
|
||||
|
||||
// Let's start the sasl process
|
||||
var command = {
|
||||
saslStart: 1
|
||||
, mechanism: 'PLAIN'
|
||||
, payload: payload
|
||||
, autoAuthorize: 1
|
||||
};
|
||||
|
||||
// Grab all the connections
|
||||
var connections = options['connection'] != null ? [options['connection']] : db.serverConfig.allRawConnections();
|
||||
|
||||
// Authenticate all connections
|
||||
for(var i = 0; i < numberOfConnections; i++) {
|
||||
var connection = connections[i];
|
||||
// Execute first sasl step
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, result) {
|
||||
// Count down
|
||||
numberOfConnections = numberOfConnections - 1;
|
||||
|
||||
// Ensure we save any error
|
||||
if(err) {
|
||||
errorObject = err;
|
||||
} else if(result.documents[0].err != null || result.documents[0].errmsg != null){
|
||||
errorObject = utils.toError(result.documents[0]);
|
||||
}
|
||||
|
||||
// Work around the case where the number of connections are 0
|
||||
if(numberOfConnections <= 0 && typeof callback == 'function') {
|
||||
var internalCallback = callback;
|
||||
callback = null;
|
||||
|
||||
if(errorObject == null && result.documents[0].ok == 1) {
|
||||
// We authenticated correctly save the credentials
|
||||
db.serverConfig.auth.add('PLAIN', db.databaseName, username, password);
|
||||
// Return callback
|
||||
internalCallback(errorObject, true);
|
||||
} else {
|
||||
internalCallback(errorObject, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
exports.authenticate = authenticate;
|
||||
135
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js
generated
vendored
Normal file
135
node_modules/mongoose/node_modules/mongodb/lib/mongodb/auth/mongodb_sspi.js
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
var DbCommand = require('../commands/db_command').DbCommand
|
||||
, utils = require('../utils')
|
||||
, format = require('util').format;
|
||||
|
||||
// Kerberos class
|
||||
var Kerberos = null;
|
||||
var MongoAuthProcess = null;
|
||||
// Try to grab the Kerberos class
|
||||
try {
|
||||
Kerberos = require('kerberos').Kerberos
|
||||
// Authentication process for Mongo
|
||||
MongoAuthProcess = require('kerberos').processes.MongoAuthProcess
|
||||
} catch(err) {}
|
||||
|
||||
var authenticate = function(db, username, password, authdb, options, callback) {
|
||||
var numberOfConnections = 0;
|
||||
var errorObject = null;
|
||||
// We don't have the Kerberos library
|
||||
if(Kerberos == null) return callback(new Error("Kerberos library is not installed"));
|
||||
|
||||
if(options['connection'] != null) {
|
||||
//if a connection was explicitly passed on options, then we have only one...
|
||||
numberOfConnections = 1;
|
||||
} else {
|
||||
// Get the amount of connections in the pool to ensure we have authenticated all comments
|
||||
numberOfConnections = db.serverConfig.allRawConnections().length;
|
||||
options['onAll'] = true;
|
||||
}
|
||||
|
||||
// Set the sspi server name
|
||||
var gssapiServiceName = options['gssapiServiceName'] || 'mongodb';
|
||||
|
||||
// Grab all the connections
|
||||
var connections = db.serverConfig.allRawConnections();
|
||||
var error = null;
|
||||
|
||||
// Authenticate all connections
|
||||
for(var i = 0; i < numberOfConnections; i++) {
|
||||
// Start Auth process for a connection
|
||||
SSIPAuthenticate(db, username, password, authdb, gssapiServiceName, connections[i], function(err, result) {
|
||||
// Adjust number of connections left to connect
|
||||
numberOfConnections = numberOfConnections - 1;
|
||||
// If we have an error save it
|
||||
if(err) error = err;
|
||||
|
||||
// We are done
|
||||
if(numberOfConnections == 0) {
|
||||
if(err) return callback(err, false);
|
||||
// We authenticated correctly save the credentials
|
||||
db.serverConfig.auth.add('GSSAPI', db.databaseName, username, password, authdb, gssapiServiceName);
|
||||
// Return valid callback
|
||||
return callback(null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var SSIPAuthenticate = function(db, username, password, authdb, service_name, connection, callback) {
|
||||
// --------------------------------------------------------------
|
||||
// Async Version
|
||||
// --------------------------------------------------------------
|
||||
var command = {
|
||||
saslStart: 1
|
||||
, mechanism: 'GSSAPI'
|
||||
, payload: ''
|
||||
, autoAuthorize: 1
|
||||
};
|
||||
|
||||
// Create authenticator
|
||||
var mongo_auth_process = new MongoAuthProcess(connection.socketOptions.host, connection.socketOptions.port, service_name);
|
||||
|
||||
// Execute first sasl step
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err);
|
||||
doc = doc.documents[0];
|
||||
|
||||
mongo_auth_process.init(username, password, function(err) {
|
||||
if(err) return callback(err);
|
||||
|
||||
mongo_auth_process.transition(doc.payload, function(err, payload) {
|
||||
if(err) return callback(err);
|
||||
|
||||
// Perform the next step against mongod
|
||||
var command = {
|
||||
saslContinue: 1
|
||||
, conversationId: doc.conversationId
|
||||
, payload: payload
|
||||
};
|
||||
|
||||
// Execute the command
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err);
|
||||
doc = doc.documents[0];
|
||||
|
||||
mongo_auth_process.transition(doc.payload, function(err, payload) {
|
||||
if(err) return callback(err);
|
||||
|
||||
// Perform the next step against mongod
|
||||
var command = {
|
||||
saslContinue: 1
|
||||
, conversationId: doc.conversationId
|
||||
, payload: payload
|
||||
};
|
||||
|
||||
// Execute the command
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err);
|
||||
doc = doc.documents[0];
|
||||
|
||||
mongo_auth_process.transition(doc.payload, function(err, payload) {
|
||||
// Perform the next step against mongod
|
||||
var command = {
|
||||
saslContinue: 1
|
||||
, conversationId: doc.conversationId
|
||||
, payload: payload
|
||||
};
|
||||
|
||||
// Execute the command
|
||||
db._executeQueryCommand(DbCommand.createDbCommand(db, command, {}, '$external'), {connection:connection}, function(err, doc) {
|
||||
if(err) return callback(err);
|
||||
doc = doc.documents[0];
|
||||
|
||||
if(doc.done) return callback(null, true);
|
||||
callback(new Error("Authentication failed"), false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
exports.authenticate = authenticate;
|
||||
1730
node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js
generated
vendored
Normal file
1730
node_modules/mongoose/node_modules/mongodb/lib/mongodb/collection.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
29
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js
generated
vendored
Normal file
29
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/base_command.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
Base object used for common functionality
|
||||
**/
|
||||
var BaseCommand = exports.BaseCommand = function BaseCommand() {
|
||||
};
|
||||
|
||||
var id = 1;
|
||||
BaseCommand.prototype.getRequestId = function getRequestId() {
|
||||
if (!this.requestId) this.requestId = id++;
|
||||
return this.requestId;
|
||||
};
|
||||
|
||||
BaseCommand.prototype.setMongosReadPreference = function setMongosReadPreference(readPreference, tags) {}
|
||||
|
||||
BaseCommand.prototype.updateRequestId = function() {
|
||||
this.requestId = id++;
|
||||
return this.requestId;
|
||||
};
|
||||
|
||||
// OpCodes
|
||||
BaseCommand.OP_REPLY = 1;
|
||||
BaseCommand.OP_MSG = 1000;
|
||||
BaseCommand.OP_UPDATE = 2001;
|
||||
BaseCommand.OP_INSERT = 2002;
|
||||
BaseCommand.OP_GET_BY_OID = 2003;
|
||||
BaseCommand.OP_QUERY = 2004;
|
||||
BaseCommand.OP_GET_MORE = 2005;
|
||||
BaseCommand.OP_DELETE = 2006;
|
||||
BaseCommand.OP_KILL_CURSORS = 2007;
|
||||
245
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js
generated
vendored
Normal file
245
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/db_command.js
generated
vendored
Normal file
@@ -0,0 +1,245 @@
|
||||
var QueryCommand = require('./query_command').QueryCommand,
|
||||
InsertCommand = require('./insert_command').InsertCommand,
|
||||
inherits = require('util').inherits,
|
||||
utils = require('../utils'),
|
||||
crypto = require('crypto');
|
||||
|
||||
/**
|
||||
Db Command
|
||||
**/
|
||||
var DbCommand = exports.DbCommand = function(dbInstance, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
|
||||
QueryCommand.call(this);
|
||||
this.collectionName = collectionName;
|
||||
this.queryOptions = queryOptions;
|
||||
this.numberToSkip = numberToSkip;
|
||||
this.numberToReturn = numberToReturn;
|
||||
this.query = query;
|
||||
this.returnFieldSelector = returnFieldSelector;
|
||||
this.db = dbInstance;
|
||||
|
||||
if(this.db && this.db.slaveOk) {
|
||||
this.queryOptions |= QueryCommand.OPTS_SLAVE;
|
||||
}
|
||||
|
||||
// Make sure we don't get a null exception
|
||||
options = options == null ? {} : options;
|
||||
// Let us defined on a command basis if we want functions to be serialized or not
|
||||
if(options['serializeFunctions'] != null && options['serializeFunctions']) {
|
||||
this.serializeFunctions = true;
|
||||
}
|
||||
};
|
||||
|
||||
inherits(DbCommand, QueryCommand);
|
||||
|
||||
// Constants
|
||||
DbCommand.SYSTEM_NAMESPACE_COLLECTION = "system.namespaces";
|
||||
DbCommand.SYSTEM_INDEX_COLLECTION = "system.indexes";
|
||||
DbCommand.SYSTEM_PROFILE_COLLECTION = "system.profile";
|
||||
DbCommand.SYSTEM_USER_COLLECTION = "system.users";
|
||||
DbCommand.SYSTEM_COMMAND_COLLECTION = "$cmd";
|
||||
DbCommand.SYSTEM_JS_COLLECTION = "system.js";
|
||||
|
||||
// New commands
|
||||
DbCommand.NcreateIsMasterCommand = function(db, databaseName) {
|
||||
return new DbCommand(db, databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
|
||||
};
|
||||
|
||||
// Provide constructors for different db commands
|
||||
DbCommand.createIsMasterCommand = function(db) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'ismaster':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createCollectionInfoCommand = function(db, selector) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_NAMESPACE_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, 0, selector, null);
|
||||
};
|
||||
|
||||
DbCommand.createGetNonceCommand = function(db, options) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getnonce':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createAuthenticationCommand = function(db, username, password, nonce, authdb) {
|
||||
// Use node md5 generator
|
||||
var md5 = crypto.createHash('md5');
|
||||
// Generate keys used for authentication
|
||||
md5.update(username + ":mongo:" + password);
|
||||
var hash_password = md5.digest('hex');
|
||||
// Final key
|
||||
md5 = crypto.createHash('md5');
|
||||
md5.update(nonce + username + hash_password);
|
||||
var key = md5.digest('hex');
|
||||
// Creat selector
|
||||
var selector = {'authenticate':1, 'user':username, 'nonce':nonce, 'key':key};
|
||||
// Create db command
|
||||
return new DbCommand(db, authdb + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NONE, 0, -1, selector, null);
|
||||
};
|
||||
|
||||
DbCommand.createLogoutCommand = function(db) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'logout':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createCreateCollectionCommand = function(db, collectionName, options) {
|
||||
var selector = {'create':collectionName};
|
||||
// Modify the options to ensure correct behaviour
|
||||
for(var name in options) {
|
||||
if(options[name] != null && options[name].constructor != Function) selector[name] = options[name];
|
||||
}
|
||||
// Execute the command
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, selector, null);
|
||||
};
|
||||
|
||||
DbCommand.createDropCollectionCommand = function(db, collectionName) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'drop':collectionName}, null);
|
||||
};
|
||||
|
||||
DbCommand.createRenameCollectionCommand = function(db, fromCollectionName, toCollectionName, options) {
|
||||
var renameCollection = db.databaseName + "." + fromCollectionName;
|
||||
var toCollection = db.databaseName + "." + toCollectionName;
|
||||
var dropTarget = options && options.dropTarget ? options.dropTarget : false;
|
||||
return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'renameCollection':renameCollection, 'to':toCollection, 'dropTarget':dropTarget}, null);
|
||||
};
|
||||
|
||||
DbCommand.createGetLastErrorCommand = function(options, db) {
|
||||
|
||||
if (typeof db === 'undefined') {
|
||||
db = options;
|
||||
options = {};
|
||||
}
|
||||
// Final command
|
||||
var command = {'getlasterror':1};
|
||||
// If we have an options Object let's merge in the fields (fsync/wtimeout/w)
|
||||
if('object' === typeof options) {
|
||||
for(var name in options) {
|
||||
command[name] = options[name]
|
||||
}
|
||||
}
|
||||
|
||||
// Special case for w == 1, remove the w
|
||||
if(1 == command.w) {
|
||||
delete command.w;
|
||||
}
|
||||
|
||||
// Execute command
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command, null);
|
||||
};
|
||||
|
||||
DbCommand.createGetLastStatusCommand = DbCommand.createGetLastErrorCommand;
|
||||
|
||||
DbCommand.createGetPreviousErrorsCommand = function(db) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'getpreverror':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createResetErrorHistoryCommand = function(db) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reseterror':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createCreateIndexCommand = function(db, collectionName, fieldOrSpec, options) {
|
||||
var fieldHash = {};
|
||||
var indexes = [];
|
||||
var keys;
|
||||
|
||||
// Get all the fields accordingly
|
||||
if('string' == typeof fieldOrSpec) {
|
||||
// 'type'
|
||||
indexes.push(fieldOrSpec + '_' + 1);
|
||||
fieldHash[fieldOrSpec] = 1;
|
||||
|
||||
} else if(utils.isArray(fieldOrSpec)) {
|
||||
|
||||
fieldOrSpec.forEach(function(f) {
|
||||
if('string' == typeof f) {
|
||||
// [{location:'2d'}, 'type']
|
||||
indexes.push(f + '_' + 1);
|
||||
fieldHash[f] = 1;
|
||||
} else if(utils.isArray(f)) {
|
||||
// [['location', '2d'],['type', 1]]
|
||||
indexes.push(f[0] + '_' + (f[1] || 1));
|
||||
fieldHash[f[0]] = f[1] || 1;
|
||||
} else if(utils.isObject(f)) {
|
||||
// [{location:'2d'}, {type:1}]
|
||||
keys = Object.keys(f);
|
||||
keys.forEach(function(k) {
|
||||
indexes.push(k + '_' + f[k]);
|
||||
fieldHash[k] = f[k];
|
||||
});
|
||||
} else {
|
||||
// undefined (ignore)
|
||||
}
|
||||
});
|
||||
|
||||
} else if(utils.isObject(fieldOrSpec)) {
|
||||
// {location:'2d', type:1}
|
||||
keys = Object.keys(fieldOrSpec);
|
||||
keys.forEach(function(key) {
|
||||
indexes.push(key + '_' + fieldOrSpec[key]);
|
||||
fieldHash[key] = fieldOrSpec[key];
|
||||
});
|
||||
}
|
||||
|
||||
// Generate the index name
|
||||
var indexName = typeof options.name == 'string'
|
||||
? options.name
|
||||
: indexes.join("_");
|
||||
|
||||
var selector = {
|
||||
'ns': db.databaseName + "." + collectionName,
|
||||
'key': fieldHash,
|
||||
'name': indexName
|
||||
}
|
||||
|
||||
// Ensure we have a correct finalUnique
|
||||
var finalUnique = options == null || 'object' === typeof options
|
||||
? false
|
||||
: options;
|
||||
|
||||
// Set up options
|
||||
options = options == null || typeof options == 'boolean'
|
||||
? {}
|
||||
: options;
|
||||
|
||||
// Add all the options
|
||||
var keys = Object.keys(options);
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
selector[keys[i]] = options[keys[i]];
|
||||
}
|
||||
|
||||
if(selector['unique'] == null)
|
||||
selector['unique'] = finalUnique;
|
||||
|
||||
var name = db.databaseName + "." + DbCommand.SYSTEM_INDEX_COLLECTION;
|
||||
var cmd = new InsertCommand(db, name, false);
|
||||
return cmd.add(selector);
|
||||
};
|
||||
|
||||
DbCommand.logoutCommand = function(db, command_hash, options) {
|
||||
var dbName = options != null && options['authdb'] != null ? options['authdb'] : db.databaseName;
|
||||
return new DbCommand(db, dbName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
|
||||
}
|
||||
|
||||
DbCommand.createDropIndexCommand = function(db, collectionName, indexName) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'deleteIndexes':collectionName, 'index':indexName}, null);
|
||||
};
|
||||
|
||||
DbCommand.createReIndexCommand = function(db, collectionName) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'reIndex':collectionName}, null);
|
||||
};
|
||||
|
||||
DbCommand.createDropDatabaseCommand = function(db) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, {'dropDatabase':1}, null);
|
||||
};
|
||||
|
||||
DbCommand.createDbCommand = function(db, command_hash, options, auth_db) {
|
||||
var db_name = (auth_db ? auth_db : db.databaseName) + "." + DbCommand.SYSTEM_COMMAND_COLLECTION;
|
||||
return new DbCommand(db, db_name, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null, options);
|
||||
};
|
||||
|
||||
DbCommand.createAdminDbCommand = function(db, command_hash) {
|
||||
return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT, 0, -1, command_hash, null);
|
||||
};
|
||||
|
||||
DbCommand.createAdminDbCommandSlaveOk = function(db, command_hash) {
|
||||
return new DbCommand(db, "admin." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null);
|
||||
};
|
||||
|
||||
DbCommand.createDbSlaveOkCommand = function(db, command_hash, options) {
|
||||
return new DbCommand(db, db.databaseName + "." + DbCommand.SYSTEM_COMMAND_COLLECTION, QueryCommand.OPTS_NO_CURSOR_TIMEOUT | QueryCommand.OPTS_SLAVE, 0, -1, command_hash, null, options);
|
||||
};
|
||||
129
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js
generated
vendored
Normal file
129
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/delete_command.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits;
|
||||
|
||||
/**
|
||||
Insert Document Command
|
||||
**/
|
||||
var DeleteCommand = exports.DeleteCommand = function(db, collectionName, selector, flags) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
// Validate correctness off the selector
|
||||
var object = selector;
|
||||
if(Buffer.isBuffer(object)) {
|
||||
var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) {
|
||||
var error = new Error("delete raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.flags = flags;
|
||||
this.collectionName = collectionName;
|
||||
this.selector = selector;
|
||||
this.db = db;
|
||||
};
|
||||
|
||||
inherits(DeleteCommand, BaseCommand);
|
||||
|
||||
DeleteCommand.OP_DELETE = 2006;
|
||||
|
||||
/*
|
||||
struct {
|
||||
MsgHeader header; // standard message header
|
||||
int32 ZERO; // 0 - reserved for future use
|
||||
cstring fullCollectionName; // "dbname.collectionname"
|
||||
int32 ZERO; // 0 - reserved for future use
|
||||
mongo.BSON selector; // query object. See below for details.
|
||||
}
|
||||
*/
|
||||
DeleteCommand.prototype.toBinary = function(bsonSettings) {
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
if(!!~this.collectionName.indexOf("\x00")) {
|
||||
throw new Error("namespace cannot contain a null character");
|
||||
}
|
||||
|
||||
// Calculate total length of the document
|
||||
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.selector, false, true) + (4 * 4);
|
||||
|
||||
// Enforce maximum bson size
|
||||
if(!bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxBsonSize)
|
||||
throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
|
||||
|
||||
if(bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
|
||||
throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
|
||||
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index] = totalLengthOfCommand & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the request ID
|
||||
_command[_index + 3] = (this.requestId >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index] = this.requestId & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
// Write the op_code for the command
|
||||
_command[_index + 3] = (DeleteCommand.OP_DELETE >> 24) & 0xff;
|
||||
_command[_index + 2] = (DeleteCommand.OP_DELETE >> 16) & 0xff;
|
||||
_command[_index + 1] = (DeleteCommand.OP_DELETE >> 8) & 0xff;
|
||||
_command[_index] = DeleteCommand.OP_DELETE & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
|
||||
// Write the collection name to the command
|
||||
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Write the flags
|
||||
_command[_index + 3] = (this.flags >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.flags >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.flags >> 8) & 0xff;
|
||||
_command[_index] = this.flags & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
|
||||
// Serialize the selector
|
||||
// If we are passing a raw buffer, do minimal validation
|
||||
if(Buffer.isBuffer(this.selector)) {
|
||||
documentLength = this.selector.length;
|
||||
// Copy the data into the current buffer
|
||||
this.selector.copy(_command, _index);
|
||||
} else {
|
||||
documentLength = this.db.bson.serializeWithBufferAndIndex(this.selector, this.checkKeys, _command, _index) - _index + 1;
|
||||
}
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
return _command;
|
||||
};
|
||||
88
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js
generated
vendored
Normal file
88
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/get_more_command.js
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits,
|
||||
binaryutils = require('../utils');
|
||||
|
||||
/**
|
||||
Get More Document Command
|
||||
**/
|
||||
var GetMoreCommand = exports.GetMoreCommand = function(db, collectionName, numberToReturn, cursorId) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
this.collectionName = collectionName;
|
||||
this.numberToReturn = numberToReturn;
|
||||
this.cursorId = cursorId;
|
||||
this.db = db;
|
||||
};
|
||||
|
||||
inherits(GetMoreCommand, BaseCommand);
|
||||
|
||||
GetMoreCommand.OP_GET_MORE = 2005;
|
||||
|
||||
GetMoreCommand.prototype.toBinary = function() {
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
if(!!~this.collectionName.indexOf("\x00")) {
|
||||
throw new Error("namespace cannot contain a null character");
|
||||
}
|
||||
|
||||
// Calculate total length of the document
|
||||
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 8 + (4 * 4);
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index++] = totalLengthOfCommand & 0xff;
|
||||
_command[_index++] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index++] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index++] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
|
||||
// Write the request ID
|
||||
_command[_index++] = this.requestId & 0xff;
|
||||
_command[_index++] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index++] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index++] = (this.requestId >> 24) & 0xff;
|
||||
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
|
||||
// Write the op_code for the command
|
||||
_command[_index++] = GetMoreCommand.OP_GET_MORE & 0xff;
|
||||
_command[_index++] = (GetMoreCommand.OP_GET_MORE >> 8) & 0xff;
|
||||
_command[_index++] = (GetMoreCommand.OP_GET_MORE >> 16) & 0xff;
|
||||
_command[_index++] = (GetMoreCommand.OP_GET_MORE >> 24) & 0xff;
|
||||
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
|
||||
// Write the collection name to the command
|
||||
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Number of documents to return
|
||||
_command[_index++] = this.numberToReturn & 0xff;
|
||||
_command[_index++] = (this.numberToReturn >> 8) & 0xff;
|
||||
_command[_index++] = (this.numberToReturn >> 16) & 0xff;
|
||||
_command[_index++] = (this.numberToReturn >> 24) & 0xff;
|
||||
|
||||
// Encode the cursor id
|
||||
var low_bits = this.cursorId.getLowBits();
|
||||
// Encode low bits
|
||||
_command[_index++] = low_bits & 0xff;
|
||||
_command[_index++] = (low_bits >> 8) & 0xff;
|
||||
_command[_index++] = (low_bits >> 16) & 0xff;
|
||||
_command[_index++] = (low_bits >> 24) & 0xff;
|
||||
|
||||
var high_bits = this.cursorId.getHighBits();
|
||||
// Encode high bits
|
||||
_command[_index++] = high_bits & 0xff;
|
||||
_command[_index++] = (high_bits >> 8) & 0xff;
|
||||
_command[_index++] = (high_bits >> 16) & 0xff;
|
||||
_command[_index++] = (high_bits >> 24) & 0xff;
|
||||
// Return command
|
||||
return _command;
|
||||
};
|
||||
161
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js
generated
vendored
Normal file
161
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/insert_command.js
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits;
|
||||
|
||||
/**
|
||||
Insert Document Command
|
||||
**/
|
||||
var InsertCommand = exports.InsertCommand = function(db, collectionName, checkKeys, options) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
this.collectionName = collectionName;
|
||||
this.documents = [];
|
||||
this.checkKeys = checkKeys == null ? true : checkKeys;
|
||||
this.db = db;
|
||||
this.flags = 0;
|
||||
this.serializeFunctions = false;
|
||||
|
||||
// Ensure valid options hash
|
||||
options = options == null ? {} : options;
|
||||
|
||||
// Check if we have keepGoing set -> set flag if it's the case
|
||||
if(options['keepGoing'] != null && options['keepGoing']) {
|
||||
// This will finish inserting all non-index violating documents even if it returns an error
|
||||
this.flags = 1;
|
||||
}
|
||||
|
||||
// Check if we have keepGoing set -> set flag if it's the case
|
||||
if(options['continueOnError'] != null && options['continueOnError']) {
|
||||
// This will finish inserting all non-index violating documents even if it returns an error
|
||||
this.flags = 1;
|
||||
}
|
||||
|
||||
// Let us defined on a command basis if we want functions to be serialized or not
|
||||
if(options['serializeFunctions'] != null && options['serializeFunctions']) {
|
||||
this.serializeFunctions = true;
|
||||
}
|
||||
};
|
||||
|
||||
inherits(InsertCommand, BaseCommand);
|
||||
|
||||
// OpCodes
|
||||
InsertCommand.OP_INSERT = 2002;
|
||||
|
||||
InsertCommand.prototype.add = function(document) {
|
||||
if(Buffer.isBuffer(document)) {
|
||||
var object_size = document[0] | document[1] << 8 | document[2] << 16 | document[3] << 24;
|
||||
if(object_size != document.length) {
|
||||
var error = new Error("insert raw message size does not match message header size [" + document.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.documents.push(document);
|
||||
return this;
|
||||
};
|
||||
|
||||
/*
|
||||
struct {
|
||||
MsgHeader header; // standard message header
|
||||
int32 ZERO; // 0 - reserved for future use
|
||||
cstring fullCollectionName; // "dbname.collectionname"
|
||||
BSON[] documents; // one or more documents to insert into the collection
|
||||
}
|
||||
*/
|
||||
InsertCommand.prototype.toBinary = function(bsonSettings) {
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
if(!!~this.collectionName.indexOf("\x00")) {
|
||||
throw new Error("namespace cannot contain a null character");
|
||||
}
|
||||
|
||||
// Calculate total length of the document
|
||||
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + (4 * 4);
|
||||
// var docLength = 0
|
||||
for(var i = 0; i < this.documents.length; i++) {
|
||||
if(Buffer.isBuffer(this.documents[i])) {
|
||||
totalLengthOfCommand += this.documents[i].length;
|
||||
} else {
|
||||
// Calculate size of document
|
||||
totalLengthOfCommand += this.db.bson.calculateObjectSize(this.documents[i], this.serializeFunctions, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Enforce maximum bson size
|
||||
if(!bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxBsonSize)
|
||||
throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
|
||||
|
||||
if(bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
|
||||
throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
|
||||
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index] = totalLengthOfCommand & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the request ID
|
||||
_command[_index + 3] = (this.requestId >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index] = this.requestId & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
// Write the op_code for the command
|
||||
_command[_index + 3] = (InsertCommand.OP_INSERT >> 24) & 0xff;
|
||||
_command[_index + 2] = (InsertCommand.OP_INSERT >> 16) & 0xff;
|
||||
_command[_index + 1] = (InsertCommand.OP_INSERT >> 8) & 0xff;
|
||||
_command[_index] = InsertCommand.OP_INSERT & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write flags if any
|
||||
_command[_index + 3] = (this.flags >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.flags >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.flags >> 8) & 0xff;
|
||||
_command[_index] = this.flags & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the collection name to the command
|
||||
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Write all the bson documents to the buffer at the index offset
|
||||
for(var i = 0; i < this.documents.length; i++) {
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
var object = this.documents[i];
|
||||
|
||||
// Serialize the selector
|
||||
// If we are passing a raw buffer, do minimal validation
|
||||
if(Buffer.isBuffer(object)) {
|
||||
documentLength = object.length;
|
||||
// Copy the data into the current buffer
|
||||
object.copy(_command, _index);
|
||||
} else {
|
||||
// Serialize the document straight to the buffer
|
||||
documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
|
||||
}
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
}
|
||||
|
||||
return _command;
|
||||
};
|
||||
98
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js
generated
vendored
Normal file
98
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/kill_cursor_command.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits,
|
||||
binaryutils = require('../utils');
|
||||
|
||||
/**
|
||||
Insert Document Command
|
||||
**/
|
||||
var KillCursorCommand = exports.KillCursorCommand = function(db, cursorIds) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
this.cursorIds = cursorIds;
|
||||
this.db = db;
|
||||
};
|
||||
|
||||
inherits(KillCursorCommand, BaseCommand);
|
||||
|
||||
KillCursorCommand.OP_KILL_CURSORS = 2007;
|
||||
|
||||
/*
|
||||
struct {
|
||||
MsgHeader header; // standard message header
|
||||
int32 ZERO; // 0 - reserved for future use
|
||||
int32 numberOfCursorIDs; // number of cursorIDs in message
|
||||
int64[] cursorIDs; // array of cursorIDs to close
|
||||
}
|
||||
*/
|
||||
KillCursorCommand.prototype.toBinary = function() {
|
||||
// Calculate total length of the document
|
||||
var totalLengthOfCommand = 4 + 4 + (4 * 4) + (this.cursorIds.length * 8);
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index] = totalLengthOfCommand & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the request ID
|
||||
_command[_index + 3] = (this.requestId >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index] = this.requestId & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
// Write the op_code for the command
|
||||
_command[_index + 3] = (KillCursorCommand.OP_KILL_CURSORS >> 24) & 0xff;
|
||||
_command[_index + 2] = (KillCursorCommand.OP_KILL_CURSORS >> 16) & 0xff;
|
||||
_command[_index + 1] = (KillCursorCommand.OP_KILL_CURSORS >> 8) & 0xff;
|
||||
_command[_index] = KillCursorCommand.OP_KILL_CURSORS & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
|
||||
// Number of cursors to kill
|
||||
var numberOfCursors = this.cursorIds.length;
|
||||
_command[_index + 3] = (numberOfCursors >> 24) & 0xff;
|
||||
_command[_index + 2] = (numberOfCursors >> 16) & 0xff;
|
||||
_command[_index + 1] = (numberOfCursors >> 8) & 0xff;
|
||||
_command[_index] = numberOfCursors & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Encode all the cursors
|
||||
for(var i = 0; i < this.cursorIds.length; i++) {
|
||||
// Encode the cursor id
|
||||
var low_bits = this.cursorIds[i].getLowBits();
|
||||
// Encode low bits
|
||||
_command[_index + 3] = (low_bits >> 24) & 0xff;
|
||||
_command[_index + 2] = (low_bits >> 16) & 0xff;
|
||||
_command[_index + 1] = (low_bits >> 8) & 0xff;
|
||||
_command[_index] = low_bits & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
var high_bits = this.cursorIds[i].getHighBits();
|
||||
// Encode high bits
|
||||
_command[_index + 3] = (high_bits >> 24) & 0xff;
|
||||
_command[_index + 2] = (high_bits >> 16) & 0xff;
|
||||
_command[_index + 1] = (high_bits >> 8) & 0xff;
|
||||
_command[_index] = high_bits & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
}
|
||||
|
||||
return _command;
|
||||
};
|
||||
280
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js
generated
vendored
Normal file
280
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/query_command.js
generated
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits;
|
||||
|
||||
/**
|
||||
Insert Document Command
|
||||
**/
|
||||
var QueryCommand = exports.QueryCommand = function(db, collectionName, queryOptions, numberToSkip, numberToReturn, query, returnFieldSelector, options) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
// Validate correctness off the selector
|
||||
var object = query,
|
||||
object_size;
|
||||
if(Buffer.isBuffer(object)) {
|
||||
object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) {
|
||||
var error = new Error("query selector raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
object = returnFieldSelector;
|
||||
if(Buffer.isBuffer(object)) {
|
||||
object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) {
|
||||
var error = new Error("query fields raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we don't get a null exception
|
||||
options = options == null ? {} : options;
|
||||
// Set up options
|
||||
this.collectionName = collectionName;
|
||||
this.queryOptions = queryOptions;
|
||||
this.numberToSkip = numberToSkip;
|
||||
this.numberToReturn = numberToReturn;
|
||||
|
||||
// Ensure we have no null query
|
||||
query = query == null ? {} : query;
|
||||
// Wrap query in the $query parameter so we can add read preferences for mongos
|
||||
this.query = query;
|
||||
this.returnFieldSelector = returnFieldSelector;
|
||||
this.db = db;
|
||||
|
||||
// Force the slave ok flag to be set if we are not using primary read preference
|
||||
if(this.db && this.db.slaveOk) {
|
||||
this.queryOptions |= QueryCommand.OPTS_SLAVE;
|
||||
}
|
||||
|
||||
// Let us defined on a command basis if we want functions to be serialized or not
|
||||
if(options['serializeFunctions'] != null && options['serializeFunctions']) {
|
||||
this.serializeFunctions = true;
|
||||
}
|
||||
};
|
||||
|
||||
inherits(QueryCommand, BaseCommand);
|
||||
|
||||
QueryCommand.OP_QUERY = 2004;
|
||||
|
||||
/*
|
||||
* Adds the read prefrence to the current command
|
||||
*/
|
||||
QueryCommand.prototype.setMongosReadPreference = function(readPreference, tags) {
|
||||
// If we have readPreference set to true set to secondary prefered
|
||||
if(readPreference == true) {
|
||||
readPreference = 'secondaryPreferred';
|
||||
} else if(readPreference == 'false') {
|
||||
readPreference = 'primary';
|
||||
}
|
||||
|
||||
// Force the slave ok flag to be set if we are not using primary read preference
|
||||
if(readPreference != false && readPreference != 'primary') {
|
||||
this.queryOptions |= QueryCommand.OPTS_SLAVE;
|
||||
}
|
||||
|
||||
// Backward compatibility, ensure $query only set on read preference so 1.8.X works
|
||||
if((readPreference != null || tags != null) && this.query['$query'] == null) {
|
||||
this.query = {'$query': this.query};
|
||||
}
|
||||
|
||||
// If we have no readPreference set and no tags, check if the slaveOk bit is set
|
||||
if(readPreference == null && tags == null) {
|
||||
// If we have a slaveOk bit set the read preference for MongoS
|
||||
if(this.queryOptions & QueryCommand.OPTS_SLAVE) {
|
||||
this.query['$readPreference'] = {mode: 'secondary'}
|
||||
} else {
|
||||
this.query['$readPreference'] = {mode: 'primary'}
|
||||
}
|
||||
}
|
||||
|
||||
// Build read preference object
|
||||
if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
|
||||
this.query['$readPreference'] = readPreference.toObject();
|
||||
} else if(readPreference != null) {
|
||||
// Add the read preference
|
||||
this.query['$readPreference'] = {mode: readPreference};
|
||||
|
||||
// If we have tags let's add them
|
||||
if(tags != null) {
|
||||
this.query['$readPreference']['tags'] = tags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
struct {
|
||||
MsgHeader header; // standard message header
|
||||
int32 opts; // query options. See below for details.
|
||||
cstring fullCollectionName; // "dbname.collectionname"
|
||||
int32 numberToSkip; // number of documents to skip when returning results
|
||||
int32 numberToReturn; // number of documents to return in the first OP_REPLY
|
||||
BSON query ; // query object. See below for details.
|
||||
[ BSON returnFieldSelector; ] // OPTIONAL : selector indicating the fields to return. See below for details.
|
||||
}
|
||||
*/
|
||||
QueryCommand.prototype.toBinary = function(bsonSettings) {
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
if(!!~this.collectionName.indexOf("\x00")) {
|
||||
throw new Error("namespace cannot contain a null character");
|
||||
}
|
||||
|
||||
// Total length of the command
|
||||
var totalLengthOfCommand = 0;
|
||||
// Calculate total length of the document
|
||||
if(Buffer.isBuffer(this.query)) {
|
||||
totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.query.length + (4 * 4);
|
||||
} else {
|
||||
totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + 4 + this.db.bson.calculateObjectSize(this.query, this.serializeFunctions, true) + (4 * 4);
|
||||
}
|
||||
|
||||
// Calculate extra fields size
|
||||
if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
|
||||
if(Object.keys(this.returnFieldSelector).length > 0) {
|
||||
totalLengthOfCommand += this.db.bson.calculateObjectSize(this.returnFieldSelector, this.serializeFunctions, true);
|
||||
}
|
||||
} else if(Buffer.isBuffer(this.returnFieldSelector)) {
|
||||
totalLengthOfCommand += this.returnFieldSelector.length;
|
||||
}
|
||||
|
||||
// Enforce maximum bson size
|
||||
if(!bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxBsonSize)
|
||||
throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
|
||||
|
||||
if(bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
|
||||
throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
|
||||
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index] = totalLengthOfCommand & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the request ID
|
||||
_command[_index + 3] = (this.requestId >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index] = this.requestId & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
// Write the op_code for the command
|
||||
_command[_index + 3] = (QueryCommand.OP_QUERY >> 24) & 0xff;
|
||||
_command[_index + 2] = (QueryCommand.OP_QUERY >> 16) & 0xff;
|
||||
_command[_index + 1] = (QueryCommand.OP_QUERY >> 8) & 0xff;
|
||||
_command[_index] = QueryCommand.OP_QUERY & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write the query options
|
||||
_command[_index + 3] = (this.queryOptions >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.queryOptions >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.queryOptions >> 8) & 0xff;
|
||||
_command[_index] = this.queryOptions & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write the collection name to the command
|
||||
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Write the number of documents to skip
|
||||
_command[_index + 3] = (this.numberToSkip >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.numberToSkip >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.numberToSkip >> 8) & 0xff;
|
||||
_command[_index] = this.numberToSkip & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write the number of documents to return
|
||||
_command[_index + 3] = (this.numberToReturn >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.numberToReturn >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.numberToReturn >> 8) & 0xff;
|
||||
_command[_index] = this.numberToReturn & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
var object = this.query;
|
||||
|
||||
// Serialize the selector
|
||||
if(Buffer.isBuffer(object)) {
|
||||
documentLength = object.length;
|
||||
// Copy the data into the current buffer
|
||||
object.copy(_command, _index);
|
||||
} else {
|
||||
// Serialize the document straight to the buffer
|
||||
documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
|
||||
}
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Push field selector if available
|
||||
if(this.returnFieldSelector != null && !(Buffer.isBuffer(this.returnFieldSelector))) {
|
||||
if(Object.keys(this.returnFieldSelector).length > 0) {
|
||||
var documentLength = this.db.bson.serializeWithBufferAndIndex(this.returnFieldSelector, this.checkKeys, _command, _index, this.serializeFunctions) - _index + 1;
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
}
|
||||
} if(this.returnFieldSelector != null && Buffer.isBuffer(this.returnFieldSelector)) {
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
var object = this.returnFieldSelector;
|
||||
|
||||
// Serialize the selector
|
||||
documentLength = object.length;
|
||||
// Copy the data into the current buffer
|
||||
object.copy(_command, _index);
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
}
|
||||
|
||||
// Return finished command
|
||||
return _command;
|
||||
};
|
||||
|
||||
// Constants
|
||||
QueryCommand.OPTS_NONE = 0;
|
||||
QueryCommand.OPTS_TAILABLE_CURSOR = 2;
|
||||
QueryCommand.OPTS_SLAVE = 4;
|
||||
QueryCommand.OPTS_OPLOG_REPLY = 8;
|
||||
QueryCommand.OPTS_NO_CURSOR_TIMEOUT = 16;
|
||||
QueryCommand.OPTS_AWAIT_DATA = 32;
|
||||
QueryCommand.OPTS_EXHAUST = 64;
|
||||
QueryCommand.OPTS_PARTIAL = 128;
|
||||
189
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js
generated
vendored
Normal file
189
node_modules/mongoose/node_modules/mongodb/lib/mongodb/commands/update_command.js
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
var BaseCommand = require('./base_command').BaseCommand,
|
||||
inherits = require('util').inherits;
|
||||
|
||||
/**
|
||||
Update Document Command
|
||||
**/
|
||||
var UpdateCommand = exports.UpdateCommand = function(db, collectionName, spec, document, options) {
|
||||
BaseCommand.call(this);
|
||||
|
||||
var object = spec;
|
||||
if(Buffer.isBuffer(object)) {
|
||||
var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) {
|
||||
var error = new Error("update spec raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
var object = document;
|
||||
if(Buffer.isBuffer(object)) {
|
||||
var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) {
|
||||
var error = new Error("update document raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
error.name = 'MongoError';
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
this.collectionName = collectionName;
|
||||
this.spec = spec;
|
||||
this.document = document;
|
||||
this.db = db;
|
||||
this.serializeFunctions = false;
|
||||
this.checkKeys = typeof options.checkKeys != 'boolean' ? false : options.checkKeys;
|
||||
|
||||
// Generate correct flags
|
||||
var db_upsert = 0;
|
||||
var db_multi_update = 0;
|
||||
db_upsert = options != null && options['upsert'] != null ? (options['upsert'] == true ? 1 : 0) : db_upsert;
|
||||
db_multi_update = options != null && options['multi'] != null ? (options['multi'] == true ? 1 : 0) : db_multi_update;
|
||||
|
||||
// Flags
|
||||
this.flags = parseInt(db_multi_update.toString() + db_upsert.toString(), 2);
|
||||
// Let us defined on a command basis if we want functions to be serialized or not
|
||||
if(options['serializeFunctions'] != null && options['serializeFunctions']) {
|
||||
this.serializeFunctions = true;
|
||||
}
|
||||
};
|
||||
|
||||
inherits(UpdateCommand, BaseCommand);
|
||||
|
||||
UpdateCommand.OP_UPDATE = 2001;
|
||||
|
||||
/*
|
||||
struct {
|
||||
MsgHeader header; // standard message header
|
||||
int32 ZERO; // 0 - reserved for future use
|
||||
cstring fullCollectionName; // "dbname.collectionname"
|
||||
int32 flags; // bit vector. see below
|
||||
BSON spec; // the query to select the document
|
||||
BSON document; // the document data to update with or insert
|
||||
}
|
||||
*/
|
||||
UpdateCommand.prototype.toBinary = function(bsonSettings) {
|
||||
// Validate that we are not passing 0x00 in the colletion name
|
||||
if(!!~this.collectionName.indexOf("\x00")) {
|
||||
throw new Error("namespace cannot contain a null character");
|
||||
}
|
||||
|
||||
// Calculate total length of the document
|
||||
var totalLengthOfCommand = 4 + Buffer.byteLength(this.collectionName) + 1 + 4 + this.db.bson.calculateObjectSize(this.spec, false, true) +
|
||||
this.db.bson.calculateObjectSize(this.document, this.serializeFunctions, true) + (4 * 4);
|
||||
|
||||
// Enforce maximum bson size
|
||||
if(!bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxBsonSize)
|
||||
throw new Error("Document exceeds maximum allowed bson size of " + bsonSettings.maxBsonSize + " bytes");
|
||||
|
||||
if(bsonSettings.disableDriverBSONSizeCheck
|
||||
&& totalLengthOfCommand > bsonSettings.maxMessageSizeBytes)
|
||||
throw new Error("Command exceeds maximum message size of " + bsonSettings.maxMessageSizeBytes + " bytes");
|
||||
|
||||
// Let's build the single pass buffer command
|
||||
var _index = 0;
|
||||
var _command = new Buffer(totalLengthOfCommand);
|
||||
// Write the header information to the buffer
|
||||
_command[_index + 3] = (totalLengthOfCommand >> 24) & 0xff;
|
||||
_command[_index + 2] = (totalLengthOfCommand >> 16) & 0xff;
|
||||
_command[_index + 1] = (totalLengthOfCommand >> 8) & 0xff;
|
||||
_command[_index] = totalLengthOfCommand & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write the request ID
|
||||
_command[_index + 3] = (this.requestId >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.requestId >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.requestId >> 8) & 0xff;
|
||||
_command[_index] = this.requestId & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
// Write the op_code for the command
|
||||
_command[_index + 3] = (UpdateCommand.OP_UPDATE >> 24) & 0xff;
|
||||
_command[_index + 2] = (UpdateCommand.OP_UPDATE >> 16) & 0xff;
|
||||
_command[_index + 1] = (UpdateCommand.OP_UPDATE >> 8) & 0xff;
|
||||
_command[_index] = UpdateCommand.OP_UPDATE & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Write zero
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
_command[_index++] = 0;
|
||||
|
||||
// Write the collection name to the command
|
||||
_index = _index + _command.write(this.collectionName, _index, 'utf8') + 1;
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Write the update flags
|
||||
_command[_index + 3] = (this.flags >> 24) & 0xff;
|
||||
_command[_index + 2] = (this.flags >> 16) & 0xff;
|
||||
_command[_index + 1] = (this.flags >> 8) & 0xff;
|
||||
_command[_index] = this.flags & 0xff;
|
||||
// Adjust index
|
||||
_index = _index + 4;
|
||||
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
var object = this.spec;
|
||||
|
||||
// Serialize the selector
|
||||
// If we are passing a raw buffer, do minimal validation
|
||||
if(Buffer.isBuffer(object)) {
|
||||
var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
documentLength = object.length;
|
||||
// Copy the data into the current buffer
|
||||
object.copy(_command, _index);
|
||||
} else {
|
||||
documentLength = this.db.bson.serializeWithBufferAndIndex(object, this.checkKeys, _command, _index, false) - _index + 1;
|
||||
}
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
// Document binary length
|
||||
var documentLength = 0
|
||||
var object = this.document;
|
||||
|
||||
// Serialize the document
|
||||
// If we are passing a raw buffer, do minimal validation
|
||||
if(Buffer.isBuffer(object)) {
|
||||
var object_size = object[0] | object[1] << 8 | object[2] << 16 | object[3] << 24;
|
||||
if(object_size != object.length) throw new Error("raw message size does not match message header size [" + object.length + "] != [" + object_size + "]");
|
||||
documentLength = object.length;
|
||||
// Copy the data into the current buffer
|
||||
object.copy(_command, _index);
|
||||
} else {
|
||||
documentLength = this.db.bson.serializeWithBufferAndIndex(object, false, _command, _index, this.serializeFunctions) - _index + 1;
|
||||
}
|
||||
|
||||
// Write the length to the document
|
||||
_command[_index + 3] = (documentLength >> 24) & 0xff;
|
||||
_command[_index + 2] = (documentLength >> 16) & 0xff;
|
||||
_command[_index + 1] = (documentLength >> 8) & 0xff;
|
||||
_command[_index] = documentLength & 0xff;
|
||||
// Update index in buffer
|
||||
_index = _index + documentLength;
|
||||
// Add terminating 0 for the object
|
||||
_command[_index - 1] = 0;
|
||||
|
||||
return _command;
|
||||
};
|
||||
|
||||
// Constants
|
||||
UpdateCommand.DB_UPSERT = 0;
|
||||
UpdateCommand.DB_MULTI_UPDATE = 1;
|
||||
442
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js
generated
vendored
Normal file
442
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/base.js
generated
vendored
Normal file
@@ -0,0 +1,442 @@
|
||||
var EventEmitter = require('events').EventEmitter
|
||||
, inherits = require('util').inherits
|
||||
, mongodb_cr_authenticate = require('../auth/mongodb_cr.js').authenticate
|
||||
, mongodb_gssapi_authenticate = require('../auth/mongodb_gssapi.js').authenticate
|
||||
, mongodb_sspi_authenticate = require('../auth/mongodb_sspi.js').authenticate;
|
||||
|
||||
var id = 0;
|
||||
|
||||
/**
|
||||
* Internal class for callback storage
|
||||
* @ignore
|
||||
*/
|
||||
var CallbackStore = function() {
|
||||
// Make class an event emitter
|
||||
EventEmitter.call(this);
|
||||
// Add a info about call variable
|
||||
this._notReplied = {};
|
||||
this.id = id++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
inherits(CallbackStore, EventEmitter);
|
||||
|
||||
CallbackStore.prototype.notRepliedToIds = function() {
|
||||
return Object.keys(this._notReplied);
|
||||
}
|
||||
|
||||
CallbackStore.prototype.callbackInfo = function(id) {
|
||||
return this._notReplied[id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class for holding non-executed commands
|
||||
* @ignore
|
||||
*/
|
||||
var NonExecutedOperationStore = function(config) {
|
||||
this.config = config;
|
||||
this.commands = {
|
||||
read: []
|
||||
, write_reads: []
|
||||
, write: []
|
||||
};
|
||||
}
|
||||
|
||||
NonExecutedOperationStore.prototype.write = function(op) {
|
||||
this.commands.write.push(op);
|
||||
}
|
||||
|
||||
NonExecutedOperationStore.prototype.read_from_writer = function(op) {
|
||||
this.commands.write_reads.push(op);
|
||||
}
|
||||
|
||||
NonExecutedOperationStore.prototype.read = function(op) {
|
||||
this.commands.read.push(op);
|
||||
}
|
||||
|
||||
NonExecutedOperationStore.prototype.execute_queries = function(executeInsertCommand) {
|
||||
var connection = this.config.checkoutReader();
|
||||
if(connection == null || connection instanceof Error) return;
|
||||
|
||||
// Write out all the queries
|
||||
while(this.commands.read.length > 0) {
|
||||
// Get the next command
|
||||
var command = this.commands.read.shift();
|
||||
command.options.connection = connection;
|
||||
// Execute the next command
|
||||
command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
|
||||
}
|
||||
}
|
||||
|
||||
NonExecutedOperationStore.prototype.execute_writes = function() {
|
||||
var connection = this.config.checkoutWriter();
|
||||
if(connection == null || connection instanceof Error) return;
|
||||
|
||||
// Write out all the queries to the primary
|
||||
while(this.commands.write_reads.length > 0) {
|
||||
// Get the next command
|
||||
var command = this.commands.write_reads.shift();
|
||||
command.options.connection = connection;
|
||||
// Execute the next command
|
||||
command.executeQueryCommand(command.db, command.db_command, command.options, command.callback);
|
||||
}
|
||||
|
||||
// Execute all write operations
|
||||
while(this.commands.write.length > 0) {
|
||||
// Get the next command
|
||||
var command = this.commands.write.shift();
|
||||
// Set the connection
|
||||
command.options.connection = connection;
|
||||
// Execute the next command
|
||||
command.executeInsertCommand(command.db, command.db_command, command.options, command.callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class for authentication storage
|
||||
* @ignore
|
||||
*/
|
||||
var AuthStore = function() {
|
||||
this._auths = [];
|
||||
}
|
||||
|
||||
AuthStore.prototype.add = function(authMechanism, dbName, username, password, authdbName, gssapiServiceName) {
|
||||
// Check for duplicates
|
||||
if(!this.contains(dbName)) {
|
||||
// Base config
|
||||
var config = {
|
||||
'username':username
|
||||
, 'password':password
|
||||
, 'db': dbName
|
||||
, 'authMechanism': authMechanism
|
||||
, 'gssapiServiceName': gssapiServiceName
|
||||
};
|
||||
|
||||
// Add auth source if passed in
|
||||
if(typeof authdbName == 'string') {
|
||||
config['authdb'] = authdbName;
|
||||
}
|
||||
|
||||
// Push the config
|
||||
this._auths.push(config);
|
||||
}
|
||||
}
|
||||
|
||||
AuthStore.prototype.contains = function(dbName) {
|
||||
for(var i = 0; i < this._auths.length; i++) {
|
||||
if(this._auths[i].db == dbName) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthStore.prototype.remove = function(dbName) {
|
||||
var newAuths = [];
|
||||
|
||||
// Filter out all the login details
|
||||
for(var i = 0; i < this._auths.length; i++) {
|
||||
if(this._auths[i].db != dbName) newAuths.push(this._auths[i]);
|
||||
}
|
||||
|
||||
// Set the filtered list
|
||||
this._auths = newAuths;
|
||||
}
|
||||
|
||||
AuthStore.prototype.get = function(index) {
|
||||
return this._auths[index];
|
||||
}
|
||||
|
||||
AuthStore.prototype.length = function() {
|
||||
return this._auths.length;
|
||||
}
|
||||
|
||||
AuthStore.prototype.toArray = function() {
|
||||
return this._auths.slice(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal class for storing db references
|
||||
* @ignore
|
||||
*/
|
||||
var DbStore = function() {
|
||||
this._dbs = [];
|
||||
}
|
||||
|
||||
DbStore.prototype.add = function(db) {
|
||||
var found = false;
|
||||
|
||||
// Only add if it does not exist already
|
||||
for(var i = 0; i < this._dbs.length; i++) {
|
||||
if(db.databaseName == this._dbs[i].databaseName) found = true;
|
||||
}
|
||||
|
||||
// Only add if it does not already exist
|
||||
if(!found) {
|
||||
this._dbs.push(db);
|
||||
}
|
||||
}
|
||||
|
||||
DbStore.prototype.reset = function() {
|
||||
this._dbs = [];
|
||||
}
|
||||
|
||||
DbStore.prototype.fetch = function(databaseName) {
|
||||
// Only add if it does not exist already
|
||||
for(var i = 0; i < this._dbs.length; i++) {
|
||||
if(databaseName == this._dbs[i].databaseName)
|
||||
return this._dbs[i];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
DbStore.prototype.emit = function(event, message, object, reset, filterDb, rethrow_if_no_listeners) {
|
||||
var emitted = false;
|
||||
|
||||
// Emit the events
|
||||
for(var i = 0; i < this._dbs.length; i++) {
|
||||
if(this._dbs[i].listeners(event).length > 0) {
|
||||
if(filterDb == null || filterDb.databaseName !== this._dbs[i].databaseName
|
||||
|| filterDb.tag !== this._dbs[i].tag) {
|
||||
this._dbs[i].emit(event, message, object == null ? this._dbs[i] : object);
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Emit error message
|
||||
if(message
|
||||
&& event == 'error'
|
||||
&& !emitted
|
||||
&& rethrow_if_no_listeners
|
||||
&& object && object.db) {
|
||||
process.nextTick(function() {
|
||||
object.db.emit(event, message, null);
|
||||
})
|
||||
}
|
||||
|
||||
// Not emitted and we have enabled rethrow, let process.uncaughtException
|
||||
// deal with the issue
|
||||
if(!emitted && rethrow_if_no_listeners) {
|
||||
throw message;
|
||||
}
|
||||
}
|
||||
|
||||
var Base = function Base() {
|
||||
EventEmitter.call(this);
|
||||
|
||||
// Callback store is part of connection specification
|
||||
if(Base._callBackStore == null) {
|
||||
Base._callBackStore = new CallbackStore();
|
||||
}
|
||||
|
||||
// Create a new callback store
|
||||
this._callBackStore = new CallbackStore();
|
||||
// All commands not being executed
|
||||
this._commandsStore = new NonExecutedOperationStore(this);
|
||||
// Create a new auth store
|
||||
this.auth = new AuthStore();
|
||||
// Contains all the dbs attached to this server config
|
||||
this._dbStore = new DbStore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
inherits(Base, EventEmitter);
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Base.prototype._apply_auths = function(db, callback) {
|
||||
_apply_auths_serially(this, db, this.auth.toArray(), callback);
|
||||
}
|
||||
|
||||
var _apply_auths_serially = function(self, db, auths, callback) {
|
||||
if(auths.length == 0) return callback(null, null);
|
||||
// Get the first auth
|
||||
var auth = auths.shift();
|
||||
var connections = self.allRawConnections();
|
||||
var connectionsLeft = connections.length;
|
||||
var options = {};
|
||||
|
||||
if(auth.authMechanism == 'GSSAPI') {
|
||||
// We have the kerberos library, execute auth process
|
||||
if(process.platform == 'win32') {
|
||||
mongodb_sspi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
|
||||
} else {
|
||||
mongodb_gssapi_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
|
||||
}
|
||||
} else if(auth.authMechanism == 'MONGODB-CR') {
|
||||
mongodb_cr_authenticate(db, auth.username, auth.password, auth.authdb, options, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all the errors
|
||||
* @ignore
|
||||
*/
|
||||
Base.prototype.__executeAllCallbacksWithError = function(err) {
|
||||
// Check all callbacks
|
||||
var keys = Object.keys(this._callBackStore._notReplied);
|
||||
// For each key check if it's a callback that needs to be returned
|
||||
for(var j = 0; j < keys.length; j++) {
|
||||
var info = this._callBackStore._notReplied[keys[j]];
|
||||
// Execute callback with error
|
||||
this._callBackStore.emit(keys[j], err, null);
|
||||
// Remove the key
|
||||
delete this._callBackStore._notReplied[keys[j]];
|
||||
// Force cleanup _events, node.js seems to set it as a null value
|
||||
if(this._callBackStore._events) {
|
||||
delete this._callBackStore._events[keys[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire all the errors
|
||||
* @ignore
|
||||
*/
|
||||
Base.prototype.__executeAllServerSpecificErrorCallbacks = function(host, port, err) {
|
||||
// Check all callbacks
|
||||
var keys = Object.keys(this._callBackStore._notReplied);
|
||||
// For each key check if it's a callback that needs to be returned
|
||||
for(var j = 0; j < keys.length; j++) {
|
||||
var info = this._callBackStore._notReplied[keys[j]];
|
||||
|
||||
if(info.connection) {
|
||||
// Unpack the connection settings
|
||||
var _host = info.connection.socketOptions.host;
|
||||
var _port = info.connection.socketOptions.port;
|
||||
// If the server matches execute the callback with the error
|
||||
if(_port == port && _host == host) {
|
||||
this._callBackStore.emit(keys[j], err, null);
|
||||
// Remove the key
|
||||
delete this._callBackStore._notReplied[keys[j]];
|
||||
// Force cleanup _events, node.js seems to set it as a null value
|
||||
if(this._callBackStore._events) {
|
||||
delete this._callBackStore._events[keys[j]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._registerHandler = function(db_command, raw, connection, exhaust, callback) {
|
||||
// Check if we have exhausted
|
||||
if(typeof exhaust == 'function') {
|
||||
callback = exhaust;
|
||||
exhaust = false;
|
||||
}
|
||||
|
||||
// Add the callback to the list of handlers
|
||||
this._callBackStore.once(db_command.getRequestId(), callback);
|
||||
// Add the information about the reply
|
||||
this._callBackStore._notReplied[db_command.getRequestId().toString()] = {start: new Date().getTime(), 'raw': raw, connection:connection, exhaust:exhaust};
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-Register a handler, on the cursor id f.ex
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._reRegisterHandler = function(newId, object, callback) {
|
||||
// Add the callback to the list of handlers
|
||||
this._callBackStore.once(newId, object.callback.listener);
|
||||
// Add the information about the reply
|
||||
this._callBackStore._notReplied[newId] = object.info;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._callHandler = function(id, document, err) {
|
||||
var self = this;
|
||||
|
||||
// If there is a callback peform it
|
||||
if(this._callBackStore.listeners(id).length >= 1) {
|
||||
// Get info object
|
||||
var info = this._callBackStore._notReplied[id];
|
||||
// Delete the current object
|
||||
delete this._callBackStore._notReplied[id];
|
||||
// Call the handle directly don't emit
|
||||
var callback = this._callBackStore.listeners(id)[0].listener;
|
||||
// Remove the listeners
|
||||
this._callBackStore.removeAllListeners(id);
|
||||
// Force key deletion because it nulling it not deleting in 0.10.X
|
||||
if(this._callBackStore._events) {
|
||||
delete this._callBackStore._events[id];
|
||||
}
|
||||
|
||||
try {
|
||||
// Execute the callback if one was provided
|
||||
if(typeof callback == 'function') callback(err, document, info.connection);
|
||||
} catch(err) {
|
||||
self._emitAcrossAllDbInstances(self, null, "error", err, self, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._hasHandler = function(id) {
|
||||
return this._callBackStore.listeners(id).length >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._removeHandler = function(id) {
|
||||
// Remove the information
|
||||
if(this._callBackStore._notReplied[id] != null) delete this._callBackStore._notReplied[id];
|
||||
// Remove the callback if it's registered
|
||||
this._callBackStore.removeAllListeners(id);
|
||||
// Force cleanup _events, node.js seems to set it as a null value
|
||||
if(this._callBackStore._events) {
|
||||
delete this._callBackStore._events[id];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._findHandler = function(id) {
|
||||
var info = this._callBackStore._notReplied[id];
|
||||
// Return the callback
|
||||
return {info:info, callback:(this._callBackStore.listeners(id).length >= 1) ? this._callBackStore.listeners(id)[0] : null}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @ignore
|
||||
* @api private
|
||||
*/
|
||||
Base.prototype._emitAcrossAllDbInstances = function(server, filterDb, event, message, object, resetConnection, rethrow_if_no_listeners) {
|
||||
if(resetConnection) {
|
||||
for(var i = 0; i < this._dbStore._dbs.length; i++) {
|
||||
if(typeof this._dbStore._dbs[i].openCalled != 'undefined')
|
||||
this._dbStore._dbs[i].openCalled = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fire event
|
||||
this._dbStore.emit(event, message, object, resetConnection, filterDb, rethrow_if_no_listeners);
|
||||
}
|
||||
|
||||
exports.Base = Base;
|
||||
507
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js
generated
vendored
Normal file
507
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection.js
generated
vendored
Normal file
@@ -0,0 +1,507 @@
|
||||
var utils = require('./connection_utils'),
|
||||
inherits = require('util').inherits,
|
||||
net = require('net'),
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
inherits = require('util').inherits,
|
||||
binaryutils = require('../utils'),
|
||||
tls = require('tls');
|
||||
|
||||
var Connection = exports.Connection = function(id, socketOptions) {
|
||||
// Set up event emitter
|
||||
EventEmitter.call(this);
|
||||
// Store all socket options
|
||||
this.socketOptions = socketOptions ? socketOptions : {host:'localhost', port:27017, domainSocket:false};
|
||||
// Set keep alive default if not overriden
|
||||
if(this.socketOptions.keepAlive == null && (process.platform !== "sunos" || process.platform !== "win32")) this.socketOptions.keepAlive = 100;
|
||||
// Id for the connection
|
||||
this.id = id;
|
||||
// State of the connection
|
||||
this.connected = false;
|
||||
// Set if this is a domain socket
|
||||
this.domainSocket = this.socketOptions.domainSocket;
|
||||
|
||||
//
|
||||
// Connection parsing state
|
||||
//
|
||||
this.maxBsonSize = socketOptions.maxBsonSize ? socketOptions.maxBsonSize : Connection.DEFAULT_MAX_BSON_SIZE;
|
||||
this.maxMessageSizeBytes = socketOptions.maxMessageSizeBytes ? socketOptions.maxMessageSizeBytes : Connection.DEFAULT_MAX_MESSAGE_SIZE;
|
||||
// Contains the current message bytes
|
||||
this.buffer = null;
|
||||
// Contains the current message size
|
||||
this.sizeOfMessage = 0;
|
||||
// Contains the readIndex for the messaage
|
||||
this.bytesRead = 0;
|
||||
// Contains spill over bytes from additional messages
|
||||
this.stubBuffer = 0;
|
||||
|
||||
// Just keeps list of events we allow
|
||||
this.eventHandlers = {error:[], parseError:[], poolReady:[], message:[], close:[], timeout:[], end:[]};
|
||||
|
||||
// Just keeps list of events we allow
|
||||
resetHandlers(this, false);
|
||||
// Bson object
|
||||
this.maxBsonSettings = {
|
||||
disableDriverBSONSizeCheck: this.socketOptions['disableDriverBSONSizeCheck'] || false
|
||||
, maxBsonSize: this.maxBsonSize
|
||||
, maxMessageSizeBytes: this.maxMessageSizeBytes
|
||||
}
|
||||
}
|
||||
|
||||
// Set max bson size
|
||||
Connection.DEFAULT_MAX_BSON_SIZE = 1024 * 1024 * 4;
|
||||
// Set default to max bson to avoid overflow or bad guesses
|
||||
Connection.DEFAULT_MAX_MESSAGE_SIZE = Connection.DEFAULT_MAX_BSON_SIZE;
|
||||
|
||||
// Inherit event emitter so we can emit stuff wohoo
|
||||
inherits(Connection, EventEmitter);
|
||||
|
||||
Connection.prototype.start = function() {
|
||||
var self = this;
|
||||
|
||||
// If we have a normal connection
|
||||
if(this.socketOptions.ssl) {
|
||||
// Create new connection instance
|
||||
if(this.domainSocket) {
|
||||
this.connection = net.createConnection(this.socketOptions.host);
|
||||
} else {
|
||||
this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
|
||||
}
|
||||
if(this.logger != null && this.logger.doDebug){
|
||||
this.logger.debug("opened connection", this.socketOptions);
|
||||
}
|
||||
// Set options on the socket
|
||||
this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
|
||||
// Work around for 0.4.X
|
||||
if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
|
||||
// Set keep alive if defined
|
||||
if(process.version.indexOf("v0.4") == -1) {
|
||||
if(this.socketOptions.keepAlive > 0) {
|
||||
this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
|
||||
} else {
|
||||
this.connection.setKeepAlive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the driver should validate the certificate
|
||||
var validate_certificates = this.socketOptions.sslValidate == true ? true : false;
|
||||
|
||||
// Create options for the tls connection
|
||||
var tls_options = {
|
||||
socket: this.connection
|
||||
, rejectUnauthorized: false
|
||||
}
|
||||
|
||||
// If we wish to validate the certificate we have provided a ca store
|
||||
if(validate_certificates) {
|
||||
tls_options.ca = this.socketOptions.sslCA;
|
||||
}
|
||||
|
||||
// If we have a certificate to present
|
||||
if(this.socketOptions.sslCert) {
|
||||
tls_options.cert = this.socketOptions.sslCert;
|
||||
tls_options.key = this.socketOptions.sslKey;
|
||||
}
|
||||
|
||||
// If the driver has been provided a private key password
|
||||
if(this.socketOptions.sslPass) {
|
||||
tls_options.passphrase = this.socketOptions.sslPass;
|
||||
}
|
||||
|
||||
// Contains the cleartext stream
|
||||
var cleartext = null;
|
||||
// Attempt to establish a TLS connection to the server
|
||||
try {
|
||||
cleartext = tls.connect(this.socketOptions.port, this.socketOptions.host, tls_options, function() {
|
||||
// If we have a ssl certificate validation error return an error
|
||||
if(cleartext.authorizationError && validate_certificates) {
|
||||
// Emit an error
|
||||
return self.emit("error", cleartext.authorizationError, self, {ssl:true});
|
||||
}
|
||||
|
||||
// Connect to the server
|
||||
connectHandler(self)();
|
||||
})
|
||||
} catch(err) {
|
||||
return self.emit("error", "SSL connection failed", self, {ssl:true});
|
||||
}
|
||||
|
||||
// Save the output stream
|
||||
this.writeSteam = cleartext;
|
||||
|
||||
// Set up data handler for the clear stream
|
||||
cleartext.on("data", createDataHandler(this));
|
||||
// Do any handling of end event of the stream
|
||||
cleartext.on("end", endHandler(this));
|
||||
cleartext.on("error", errorHandler(this));
|
||||
|
||||
// Handle any errors
|
||||
this.connection.on("error", errorHandler(this));
|
||||
// Handle timeout
|
||||
this.connection.on("timeout", timeoutHandler(this));
|
||||
// Handle drain event
|
||||
this.connection.on("drain", drainHandler(this));
|
||||
// Handle the close event
|
||||
this.connection.on("close", closeHandler(this));
|
||||
} else {
|
||||
// Create new connection instance
|
||||
if(this.domainSocket) {
|
||||
this.connection = net.createConnection(this.socketOptions.host);
|
||||
} else {
|
||||
this.connection = net.createConnection(this.socketOptions.port, this.socketOptions.host);
|
||||
}
|
||||
if(this.logger != null && this.logger.doDebug){
|
||||
this.logger.debug("opened connection", this.socketOptions);
|
||||
}
|
||||
|
||||
// Set options on the socket
|
||||
this.connection.setTimeout(this.socketOptions.connectTimeoutMS != null ? this.socketOptions.connectTimeoutMS : this.socketOptions.timeout);
|
||||
// Work around for 0.4.X
|
||||
if(process.version.indexOf("v0.4") == -1) this.connection.setNoDelay(this.socketOptions.noDelay);
|
||||
// Set keep alive if defined
|
||||
if(process.version.indexOf("v0.4") == -1) {
|
||||
if(this.socketOptions.keepAlive > 0) {
|
||||
this.connection.setKeepAlive(true, this.socketOptions.keepAlive);
|
||||
} else {
|
||||
this.connection.setKeepAlive(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Set up write stream
|
||||
this.writeSteam = this.connection;
|
||||
// Add handlers
|
||||
this.connection.on("error", errorHandler(this));
|
||||
// Add all handlers to the socket to manage it
|
||||
this.connection.on("connect", connectHandler(this));
|
||||
// this.connection.on("end", endHandler(this));
|
||||
this.connection.on("data", createDataHandler(this));
|
||||
this.connection.on("timeout", timeoutHandler(this));
|
||||
this.connection.on("drain", drainHandler(this));
|
||||
this.connection.on("close", closeHandler(this));
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the sockets are live
|
||||
Connection.prototype.isConnected = function() {
|
||||
return this.connected && !this.connection.destroyed && this.connection.writable && this.connection.readable;
|
||||
}
|
||||
|
||||
// Write the data out to the socket
|
||||
Connection.prototype.write = function(command, callback) {
|
||||
try {
|
||||
// If we have a list off commands to be executed on the same socket
|
||||
if(Array.isArray(command)) {
|
||||
for(var i = 0; i < command.length; i++) {
|
||||
try {
|
||||
// Pass in the bson validation settings (validate early)
|
||||
var binaryCommand = command[i].toBinary(this.maxBsonSettings)
|
||||
|
||||
if(this.logger != null && this.logger.doDebug)
|
||||
this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
|
||||
|
||||
this.writeSteam.write(binaryCommand);
|
||||
} catch(err) {
|
||||
return callback(err, null);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
// Pass in the bson validation settings (validate early)
|
||||
var binaryCommand = command.toBinary(this.maxBsonSettings)
|
||||
|
||||
if(this.logger != null && this.logger.doDebug)
|
||||
this.logger.debug("writing command to mongodb", {binary: binaryCommand, json: command[i]});
|
||||
|
||||
this.writeSteam.write(binaryCommand);
|
||||
} catch(err) {
|
||||
return callback(err, null)
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
if(typeof callback === 'function') callback(err);
|
||||
}
|
||||
}
|
||||
|
||||
// Force the closure of the connection
|
||||
Connection.prototype.close = function() {
|
||||
// clear out all the listeners
|
||||
resetHandlers(this, true);
|
||||
// Add a dummy error listener to catch any weird last moment errors (and ignore them)
|
||||
this.connection.on("error", function() {})
|
||||
// destroy connection
|
||||
this.connection.destroy();
|
||||
if(this.logger != null && this.logger.doDebug){
|
||||
this.logger.debug("closed connection", this.connection);
|
||||
}
|
||||
}
|
||||
|
||||
// Reset all handlers
|
||||
var resetHandlers = function(self, clearListeners) {
|
||||
self.eventHandlers = {error:[], connect:[], close:[], end:[], timeout:[], parseError:[], message:[]};
|
||||
|
||||
// If we want to clear all the listeners
|
||||
if(clearListeners && self.connection != null) {
|
||||
var keys = Object.keys(self.eventHandlers);
|
||||
// Remove all listeners
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
self.connection.removeAllListeners(keys[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Handlers
|
||||
//
|
||||
|
||||
// Connect handler
|
||||
var connectHandler = function(self) {
|
||||
return function(data) {
|
||||
// Set connected
|
||||
self.connected = true;
|
||||
// Now that we are connected set the socket timeout
|
||||
self.connection.setTimeout(self.socketOptions.socketTimeoutMS != null ? self.socketOptions.socketTimeoutMS : self.socketOptions.timeout);
|
||||
// Emit the connect event with no error
|
||||
self.emit("connect", null, self);
|
||||
}
|
||||
}
|
||||
|
||||
var createDataHandler = exports.Connection.createDataHandler = function(self) {
|
||||
// We need to handle the parsing of the data
|
||||
// and emit the messages when there is a complete one
|
||||
return function(data) {
|
||||
// Parse until we are done with the data
|
||||
while(data.length > 0) {
|
||||
// If we still have bytes to read on the current message
|
||||
if(self.bytesRead > 0 && self.sizeOfMessage > 0) {
|
||||
// Calculate the amount of remaining bytes
|
||||
var remainingBytesToRead = self.sizeOfMessage - self.bytesRead;
|
||||
// Check if the current chunk contains the rest of the message
|
||||
if(remainingBytesToRead > data.length) {
|
||||
// Copy the new data into the exiting buffer (should have been allocated when we know the message size)
|
||||
data.copy(self.buffer, self.bytesRead);
|
||||
// Adjust the number of bytes read so it point to the correct index in the buffer
|
||||
self.bytesRead = self.bytesRead + data.length;
|
||||
|
||||
// Reset state of buffer
|
||||
data = new Buffer(0);
|
||||
} else {
|
||||
// Copy the missing part of the data into our current buffer
|
||||
data.copy(self.buffer, self.bytesRead, 0, remainingBytesToRead);
|
||||
// Slice the overflow into a new buffer that we will then re-parse
|
||||
data = data.slice(remainingBytesToRead);
|
||||
|
||||
// Emit current complete message
|
||||
try {
|
||||
var emitBuffer = self.buffer;
|
||||
// Reset state of buffer
|
||||
self.buffer = null;
|
||||
self.sizeOfMessage = 0;
|
||||
self.bytesRead = 0;
|
||||
self.stubBuffer = null;
|
||||
// Emit the buffer
|
||||
self.emit("message", emitBuffer, self);
|
||||
} catch(err) {
|
||||
var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
|
||||
sizeOfMessage:self.sizeOfMessage,
|
||||
bytesRead:self.bytesRead,
|
||||
stubBuffer:self.stubBuffer}};
|
||||
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
|
||||
// We got a parse Error fire it off then keep going
|
||||
self.emit("parseError", errorObject, self);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Stub buffer is kept in case we don't get enough bytes to determine the
|
||||
// size of the message (< 4 bytes)
|
||||
if(self.stubBuffer != null && self.stubBuffer.length > 0) {
|
||||
|
||||
// If we have enough bytes to determine the message size let's do it
|
||||
if(self.stubBuffer.length + data.length > 4) {
|
||||
// Prepad the data
|
||||
var newData = new Buffer(self.stubBuffer.length + data.length);
|
||||
self.stubBuffer.copy(newData, 0);
|
||||
data.copy(newData, self.stubBuffer.length);
|
||||
// Reassign for parsing
|
||||
data = newData;
|
||||
|
||||
// Reset state of buffer
|
||||
self.buffer = null;
|
||||
self.sizeOfMessage = 0;
|
||||
self.bytesRead = 0;
|
||||
self.stubBuffer = null;
|
||||
|
||||
} else {
|
||||
|
||||
// Add the the bytes to the stub buffer
|
||||
var newStubBuffer = new Buffer(self.stubBuffer.length + data.length);
|
||||
// Copy existing stub buffer
|
||||
self.stubBuffer.copy(newStubBuffer, 0);
|
||||
// Copy missing part of the data
|
||||
data.copy(newStubBuffer, self.stubBuffer.length);
|
||||
// Exit parsing loop
|
||||
data = new Buffer(0);
|
||||
}
|
||||
} else {
|
||||
if(data.length > 4) {
|
||||
// Retrieve the message size
|
||||
var sizeOfMessage = binaryutils.decodeUInt32(data, 0);
|
||||
// If we have a negative sizeOfMessage emit error and return
|
||||
if(sizeOfMessage < 0 || sizeOfMessage > self.maxBsonSize) {
|
||||
var errorObject = {err:"socketHandler", trace:'', bin:self.buffer, parseState:{
|
||||
sizeOfMessage: sizeOfMessage,
|
||||
bytesRead: self.bytesRead,
|
||||
stubBuffer: self.stubBuffer}};
|
||||
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
|
||||
// We got a parse Error fire it off then keep going
|
||||
self.emit("parseError", errorObject, self);
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure that the size of message is larger than 0 and less than the max allowed
|
||||
if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage > data.length) {
|
||||
self.buffer = new Buffer(sizeOfMessage);
|
||||
// Copy all the data into the buffer
|
||||
data.copy(self.buffer, 0);
|
||||
// Update bytes read
|
||||
self.bytesRead = data.length;
|
||||
// Update sizeOfMessage
|
||||
self.sizeOfMessage = sizeOfMessage;
|
||||
// Ensure stub buffer is null
|
||||
self.stubBuffer = null;
|
||||
// Exit parsing loop
|
||||
data = new Buffer(0);
|
||||
|
||||
} else if(sizeOfMessage > 4 && sizeOfMessage < self.maxBsonSize && sizeOfMessage == data.length) {
|
||||
try {
|
||||
var emitBuffer = data;
|
||||
// Reset state of buffer
|
||||
self.buffer = null;
|
||||
self.sizeOfMessage = 0;
|
||||
self.bytesRead = 0;
|
||||
self.stubBuffer = null;
|
||||
// Exit parsing loop
|
||||
data = new Buffer(0);
|
||||
// Emit the message
|
||||
self.emit("message", emitBuffer, self);
|
||||
} catch (err) {
|
||||
var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
|
||||
sizeOfMessage:self.sizeOfMessage,
|
||||
bytesRead:self.bytesRead,
|
||||
stubBuffer:self.stubBuffer}};
|
||||
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
|
||||
// We got a parse Error fire it off then keep going
|
||||
self.emit("parseError", errorObject, self);
|
||||
}
|
||||
} else if(sizeOfMessage <= 4 || sizeOfMessage > self.maxBsonSize) {
|
||||
var errorObject = {err:"socketHandler", trace:null, bin:data, parseState:{
|
||||
sizeOfMessage:sizeOfMessage,
|
||||
bytesRead:0,
|
||||
buffer:null,
|
||||
stubBuffer:null}};
|
||||
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
|
||||
// We got a parse Error fire it off then keep going
|
||||
self.emit("parseError", errorObject, self);
|
||||
|
||||
// Clear out the state of the parser
|
||||
self.buffer = null;
|
||||
self.sizeOfMessage = 0;
|
||||
self.bytesRead = 0;
|
||||
self.stubBuffer = null;
|
||||
// Exit parsing loop
|
||||
data = new Buffer(0);
|
||||
|
||||
} else {
|
||||
try {
|
||||
var emitBuffer = data.slice(0, sizeOfMessage);
|
||||
// Reset state of buffer
|
||||
self.buffer = null;
|
||||
self.sizeOfMessage = 0;
|
||||
self.bytesRead = 0;
|
||||
self.stubBuffer = null;
|
||||
// Copy rest of message
|
||||
data = data.slice(sizeOfMessage);
|
||||
// Emit the message
|
||||
self.emit("message", emitBuffer, self);
|
||||
} catch (err) {
|
||||
var errorObject = {err:"socketHandler", trace:err, bin:self.buffer, parseState:{
|
||||
sizeOfMessage:sizeOfMessage,
|
||||
bytesRead:self.bytesRead,
|
||||
stubBuffer:self.stubBuffer}};
|
||||
if(self.logger != null && self.logger.doError) self.logger.error("parseError", errorObject);
|
||||
// We got a parse Error fire it off then keep going
|
||||
self.emit("parseError", errorObject, self);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// Create a buffer that contains the space for the non-complete message
|
||||
self.stubBuffer = new Buffer(data.length)
|
||||
// Copy the data to the stub buffer
|
||||
data.copy(self.stubBuffer, 0);
|
||||
// Exit parsing loop
|
||||
data = new Buffer(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var endHandler = function(self) {
|
||||
return function() {
|
||||
// Set connected to false
|
||||
self.connected = false;
|
||||
// Emit end event
|
||||
self.emit("end", {err: 'connection received Fin packet from [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
|
||||
}
|
||||
}
|
||||
|
||||
var timeoutHandler = function(self) {
|
||||
return function() {
|
||||
// Set connected to false
|
||||
self.connected = false;
|
||||
// Emit timeout event
|
||||
self.emit("timeout", {err: 'connection to [' + self.socketOptions.host + ':' + self.socketOptions.port + '] timed out'}, self);
|
||||
}
|
||||
}
|
||||
|
||||
var drainHandler = function(self) {
|
||||
return function() {
|
||||
}
|
||||
}
|
||||
|
||||
var errorHandler = function(self) {
|
||||
return function(err) {
|
||||
self.connection.destroy();
|
||||
// Set connected to false
|
||||
self.connected = false;
|
||||
// Emit error
|
||||
self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
|
||||
}
|
||||
}
|
||||
|
||||
var closeHandler = function(self) {
|
||||
return function(hadError) {
|
||||
// If we have an error during the connection phase
|
||||
if(hadError && !self.connected) {
|
||||
// Set disconnected
|
||||
self.connected = false;
|
||||
// Emit error
|
||||
self.emit("error", {err: 'failed to connect to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
|
||||
} else {
|
||||
// Set disconnected
|
||||
self.connected = false;
|
||||
// Emit close
|
||||
self.emit("close", {err: 'connection closed to [' + self.socketOptions.host + ':' + self.socketOptions.port + ']'}, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Some basic defaults
|
||||
Connection.DEFAULT_PORT = 27017;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
295
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js
generated
vendored
Normal file
295
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_pool.js
generated
vendored
Normal file
@@ -0,0 +1,295 @@
|
||||
var utils = require('./connection_utils'),
|
||||
inherits = require('util').inherits,
|
||||
net = require('net'),
|
||||
timers = require('timers'),
|
||||
EventEmitter = require('events').EventEmitter,
|
||||
inherits = require('util').inherits,
|
||||
MongoReply = require("../responses/mongo_reply").MongoReply,
|
||||
Connection = require("./connection").Connection;
|
||||
|
||||
// Set processor, setImmediate if 0.10 otherwise nextTick
|
||||
var processor = require('../utils').processor();
|
||||
|
||||
var ConnectionPool = exports.ConnectionPool = function(host, port, poolSize, bson, socketOptions) {
|
||||
if(typeof host !== 'string') {
|
||||
throw new Error("host must be specified [" + host + "]");
|
||||
}
|
||||
|
||||
// Set up event emitter
|
||||
EventEmitter.call(this);
|
||||
|
||||
// Keep all options for the socket in a specific collection allowing the user to specify the
|
||||
// Wished upon socket connection parameters
|
||||
this.socketOptions = typeof socketOptions === 'object' ? socketOptions : {};
|
||||
this.socketOptions.host = host;
|
||||
this.socketOptions.port = port;
|
||||
this.socketOptions.domainSocket = false;
|
||||
this.bson = bson;
|
||||
// PoolSize is always + 1 for special reserved "measurment" socket (like ping, stats etc)
|
||||
this.poolSize = poolSize;
|
||||
this.minPoolSize = Math.floor(this.poolSize / 2) + 1;
|
||||
|
||||
// Check if the host is a socket
|
||||
if(host.match(/^\//)) {
|
||||
this.socketOptions.domainSocket = true;
|
||||
} else if(typeof port === 'string') {
|
||||
try {
|
||||
port = parseInt(port, 10);
|
||||
} catch(err) {
|
||||
new Error("port must be specified or valid integer[" + port + "]");
|
||||
}
|
||||
} else if(typeof port !== 'number') {
|
||||
throw new Error("port must be specified [" + port + "]");
|
||||
}
|
||||
|
||||
// Set default settings for the socket options
|
||||
utils.setIntegerParameter(this.socketOptions, 'timeout', 0);
|
||||
// Delay before writing out the data to the server
|
||||
utils.setBooleanParameter(this.socketOptions, 'noDelay', true);
|
||||
// Delay before writing out the data to the server
|
||||
utils.setIntegerParameter(this.socketOptions, 'keepAlive', 0);
|
||||
// Set the encoding of the data read, default is binary == null
|
||||
utils.setStringParameter(this.socketOptions, 'encoding', null);
|
||||
// Allows you to set a throttling bufferSize if you need to stop overflows
|
||||
utils.setIntegerParameter(this.socketOptions, 'bufferSize', 0);
|
||||
|
||||
// Internal structures
|
||||
this.openConnections = [];
|
||||
// Assign connection id's
|
||||
this.connectionId = 0;
|
||||
|
||||
// Current index for selection of pool connection
|
||||
this.currentConnectionIndex = 0;
|
||||
// The pool state
|
||||
this._poolState = 'disconnected';
|
||||
// timeout control
|
||||
this._timeout = false;
|
||||
// Time to wait between connections for the pool
|
||||
this._timeToWait = 10;
|
||||
}
|
||||
|
||||
inherits(ConnectionPool, EventEmitter);
|
||||
|
||||
ConnectionPool.prototype.setMaxBsonSize = function(maxBsonSize) {
|
||||
if(maxBsonSize == null){
|
||||
maxBsonSize = Connection.DEFAULT_MAX_BSON_SIZE;
|
||||
}
|
||||
|
||||
for(var i = 0; i < this.openConnections.length; i++) {
|
||||
this.openConnections[i].maxBsonSize = maxBsonSize;
|
||||
this.openConnections[i].maxBsonSettings.maxBsonSize = maxBsonSize;
|
||||
}
|
||||
}
|
||||
|
||||
ConnectionPool.prototype.setMaxMessageSizeBytes = function(maxMessageSizeBytes) {
|
||||
if(maxMessageSizeBytes == null){
|
||||
maxMessageSizeBytes = Connection.DEFAULT_MAX_MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
for(var i = 0; i < this.openConnections.length; i++) {
|
||||
this.openConnections[i].maxMessageSizeBytes = maxMessageSizeBytes;
|
||||
this.openConnections[i].maxBsonSettings.maxMessageSizeBytes = maxMessageSizeBytes;
|
||||
}
|
||||
}
|
||||
|
||||
// Start a function
|
||||
var _connect = function(_self) {
|
||||
// return new function() {
|
||||
// Create a new connection instance
|
||||
var connection = new Connection(_self.connectionId++, _self.socketOptions);
|
||||
// Set logger on pool
|
||||
connection.logger = _self.logger;
|
||||
// Connect handler
|
||||
connection.on("connect", function(err, connection) {
|
||||
// Add connection to list of open connections
|
||||
_self.openConnections.push(connection);
|
||||
// If the number of open connections is equal to the poolSize signal ready pool
|
||||
if(_self.openConnections.length === _self.poolSize && _self._poolState !== 'disconnected') {
|
||||
// Set connected
|
||||
_self._poolState = 'connected';
|
||||
// Emit pool ready
|
||||
_self.emit("poolReady");
|
||||
} else if(_self.openConnections.length < _self.poolSize) {
|
||||
// Wait a little bit of time to let the close event happen if the server closes the connection
|
||||
// so we don't leave hanging connections around
|
||||
if(typeof _self._timeToWait == 'number') {
|
||||
setTimeout(function() {
|
||||
// If we are still connecting (no close events fired in between start another connection)
|
||||
if(_self._poolState == 'connecting') {
|
||||
_connect(_self);
|
||||
}
|
||||
}, _self._timeToWait);
|
||||
} else {
|
||||
processor(function() {
|
||||
// If we are still connecting (no close events fired in between start another connection)
|
||||
if(_self._poolState == 'connecting') {
|
||||
_connect(_self);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var numberOfErrors = 0
|
||||
|
||||
// Error handler
|
||||
connection.on("error", function(err, connection, error_options) {
|
||||
numberOfErrors++;
|
||||
// If we are already disconnected ignore the event
|
||||
if(_self._poolState != 'disconnected' && _self.listeners("error").length > 0) {
|
||||
_self.emit("error", err, connection, error_options);
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
connection.close();
|
||||
// Set pool as disconnected
|
||||
_self._poolState = 'disconnected';
|
||||
// Stop the pool
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
// Close handler
|
||||
connection.on("close", function() {
|
||||
// If we are already disconnected ignore the event
|
||||
if(_self._poolState !== 'disconnected' && _self.listeners("close").length > 0) {
|
||||
_self.emit("close");
|
||||
}
|
||||
|
||||
// Set disconnected
|
||||
_self._poolState = 'disconnected';
|
||||
// Stop
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
// Timeout handler
|
||||
connection.on("timeout", function(err, connection) {
|
||||
// If we are already disconnected ignore the event
|
||||
if(_self._poolState !== 'disconnected' && _self.listeners("timeout").length > 0) {
|
||||
_self.emit("timeout", err);
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
connection.close();
|
||||
// Set disconnected
|
||||
_self._poolState = 'disconnected';
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
// Parse error, needs a complete shutdown of the pool
|
||||
connection.on("parseError", function() {
|
||||
// If we are already disconnected ignore the event
|
||||
if(_self._poolState !== 'disconnected' && _self.listeners("parseError").length > 0) {
|
||||
_self.emit("parseError", new Error("parseError occured"));
|
||||
}
|
||||
|
||||
// Set disconnected
|
||||
_self._poolState = 'disconnected';
|
||||
_self.stop();
|
||||
});
|
||||
|
||||
connection.on("message", function(message) {
|
||||
_self.emit("message", message);
|
||||
});
|
||||
|
||||
// Start connection in the next tick
|
||||
connection.start();
|
||||
// }();
|
||||
}
|
||||
|
||||
|
||||
// Start method, will throw error if no listeners are available
|
||||
// Pass in an instance of the listener that contains the api for
|
||||
// finding callbacks for a given message etc.
|
||||
ConnectionPool.prototype.start = function() {
|
||||
var markerDate = new Date().getTime();
|
||||
var self = this;
|
||||
|
||||
if(this.listeners("poolReady").length == 0) {
|
||||
throw "pool must have at least one listener ready that responds to the [poolReady] event";
|
||||
}
|
||||
|
||||
// Set pool state to connecting
|
||||
this._poolState = 'connecting';
|
||||
this._timeout = false;
|
||||
|
||||
_connect(self);
|
||||
}
|
||||
|
||||
// Restart a connection pool (on a close the pool might be in a wrong state)
|
||||
ConnectionPool.prototype.restart = function() {
|
||||
// Close all connections
|
||||
this.stop(false);
|
||||
// Now restart the pool
|
||||
this.start();
|
||||
}
|
||||
|
||||
// Stop the connections in the pool
|
||||
ConnectionPool.prototype.stop = function(removeListeners) {
|
||||
removeListeners = removeListeners == null ? true : removeListeners;
|
||||
// Set disconnected
|
||||
this._poolState = 'disconnected';
|
||||
|
||||
// Clear all listeners if specified
|
||||
if(removeListeners) {
|
||||
this.removeAllEventListeners();
|
||||
}
|
||||
|
||||
// Close all connections
|
||||
for(var i = 0; i < this.openConnections.length; i++) {
|
||||
this.openConnections[i].close();
|
||||
}
|
||||
|
||||
// Clean up
|
||||
this.openConnections = [];
|
||||
}
|
||||
|
||||
// Check the status of the connection
|
||||
ConnectionPool.prototype.isConnected = function() {
|
||||
// return this._poolState === 'connected';
|
||||
return this.openConnections.length > 0 && this.openConnections[0].isConnected();
|
||||
}
|
||||
|
||||
// Checkout a connection from the pool for usage, or grab a specific pool instance
|
||||
ConnectionPool.prototype.checkoutConnection = function(id) {
|
||||
var index = (this.currentConnectionIndex++ % (this.openConnections.length));
|
||||
var connection = this.openConnections[index];
|
||||
return connection;
|
||||
}
|
||||
|
||||
ConnectionPool.prototype.getAllConnections = function() {
|
||||
return this.openConnections;
|
||||
}
|
||||
|
||||
// Remove all non-needed event listeners
|
||||
ConnectionPool.prototype.removeAllEventListeners = function() {
|
||||
this.removeAllListeners("close");
|
||||
this.removeAllListeners("error");
|
||||
this.removeAllListeners("timeout");
|
||||
this.removeAllListeners("connect");
|
||||
this.removeAllListeners("end");
|
||||
this.removeAllListeners("parseError");
|
||||
this.removeAllListeners("message");
|
||||
this.removeAllListeners("poolReady");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
23
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js
generated
vendored
Normal file
23
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/connection_utils.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
exports.setIntegerParameter = function(object, field, defaultValue) {
|
||||
if(object[field] == null) {
|
||||
object[field] = defaultValue;
|
||||
} else if(typeof object[field] !== "number" && object[field] !== parseInt(object[field], 10)) {
|
||||
throw "object field [" + field + "] must be a numeric integer value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
|
||||
}
|
||||
}
|
||||
|
||||
exports.setBooleanParameter = function(object, field, defaultValue) {
|
||||
if(object[field] == null) {
|
||||
object[field] = defaultValue;
|
||||
} else if(typeof object[field] !== "boolean") {
|
||||
throw "object field [" + field + "] must be a boolean value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
|
||||
}
|
||||
}
|
||||
|
||||
exports.setStringParameter = function(object, field, defaultValue) {
|
||||
if(object[field] == null) {
|
||||
object[field] = defaultValue;
|
||||
} else if(typeof object[field] !== "string") {
|
||||
throw "object field [" + field + "] must be a string value, attempted to set to [" + object[field] + "] type of [" + typeof object[field] + "]";
|
||||
}
|
||||
}
|
||||
524
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js
generated
vendored
Normal file
524
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/mongos.js
generated
vendored
Normal file
@@ -0,0 +1,524 @@
|
||||
var ReadPreference = require('./read_preference').ReadPreference
|
||||
, Base = require('./base').Base
|
||||
, Server = require('./server').Server
|
||||
, format = require('util').format
|
||||
, timers = require('timers')
|
||||
, inherits = require('util').inherits;
|
||||
|
||||
// Set processor, setImmediate if 0.10 otherwise nextTick
|
||||
var processor = require('../utils').processor();
|
||||
|
||||
/**
|
||||
* Mongos constructor provides a connection to a mongos proxy including failover to additional servers
|
||||
*
|
||||
* Options
|
||||
* - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
|
||||
* - **ha** {Boolean, default:true}, turn on high availability, attempts to reconnect to down proxies
|
||||
* - **haInterval** {Number, default:2000}, time between each replicaset status check.
|
||||
*
|
||||
* @class Represents a Mongos connection with failover to backup proxies
|
||||
* @param {Array} list of mongos server objects
|
||||
* @param {Object} [options] additional options for the mongos connection
|
||||
*/
|
||||
var Mongos = function Mongos(servers, options) {
|
||||
// Set up basic
|
||||
if(!(this instanceof Mongos))
|
||||
return new Mongos(servers, options);
|
||||
|
||||
// Set up event emitter
|
||||
Base.call(this);
|
||||
|
||||
// Throw error on wrong setup
|
||||
if(servers == null || !Array.isArray(servers) || servers.length == 0)
|
||||
throw new Error("At least one mongos proxy must be in the array");
|
||||
|
||||
// Ensure we have at least an empty options object
|
||||
this.options = options == null ? {} : options;
|
||||
// Set default connection pool options
|
||||
this.socketOptions = this.options.socketOptions != null ? this.options.socketOptions : {};
|
||||
// Enabled ha
|
||||
this.haEnabled = this.options['ha'] == null ? true : this.options['ha'];
|
||||
this._haInProgress = false;
|
||||
// How often are we checking for new servers in the replicaset
|
||||
this.mongosStatusCheckInterval = this.options['haInterval'] == null ? 1000 : this.options['haInterval'];
|
||||
// Save all the server connections
|
||||
this.servers = servers;
|
||||
// Servers we need to attempt reconnect with
|
||||
this.downServers = {};
|
||||
// Servers that are up
|
||||
this.upServers = {};
|
||||
// Up servers by ping time
|
||||
this.upServersByUpTime = {};
|
||||
// Emit open setup
|
||||
this.emitOpen = this.options.emitOpen || true;
|
||||
// Just contains the current lowest ping time and server
|
||||
this.lowestPingTimeServer = null;
|
||||
this.lowestPingTime = 0;
|
||||
// Connection timeout
|
||||
this._connectTimeoutMS = this.socketOptions.connectTimeoutMS
|
||||
? this.socketOptions.connectTimeoutMS
|
||||
: 1000;
|
||||
|
||||
// Add options to servers
|
||||
for(var i = 0; i < this.servers.length; i++) {
|
||||
var server = this.servers[i];
|
||||
server._callBackStore = this._callBackStore;
|
||||
server.auto_reconnect = false;
|
||||
// Default empty socket options object
|
||||
var socketOptions = {host: server.host, port: server.port};
|
||||
// If a socket option object exists clone it
|
||||
if(this.socketOptions != null) {
|
||||
var keys = Object.keys(this.socketOptions);
|
||||
for(var k = 0; k < keys.length;k++) socketOptions[keys[i]] = this.socketOptions[keys[i]];
|
||||
}
|
||||
|
||||
// Set socket options
|
||||
server.socketOptions = socketOptions;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
inherits(Mongos, Base);
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.isMongos = function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.connect = function(db, options, callback) {
|
||||
if('function' === typeof options) callback = options, options = {};
|
||||
if(options == null) options = {};
|
||||
if(!('function' === typeof callback)) callback = null;
|
||||
var self = this;
|
||||
|
||||
// Keep reference to parent
|
||||
this.db = db;
|
||||
// Set server state to connecting
|
||||
this._serverState = 'connecting';
|
||||
// Number of total servers that need to initialized (known servers)
|
||||
this._numberOfServersLeftToInitialize = this.servers.length;
|
||||
// Connect handler
|
||||
var connectHandler = function(_server) {
|
||||
return function(err, result) {
|
||||
self._numberOfServersLeftToInitialize = self._numberOfServersLeftToInitialize - 1;
|
||||
|
||||
// Add the server to the list of servers that are up
|
||||
if(!err) {
|
||||
self.upServers[format("%s:%s", _server.host, _server.port)] = _server;
|
||||
}
|
||||
|
||||
// We are done connecting
|
||||
if(self._numberOfServersLeftToInitialize == 0) {
|
||||
// Start ha function if it exists
|
||||
if(self.haEnabled) {
|
||||
// Setup the ha process
|
||||
if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
|
||||
self._replicasetTimeoutId = setInterval(self.mongosCheckFunction, self.mongosStatusCheckInterval);
|
||||
}
|
||||
|
||||
// Set the mongos to connected
|
||||
self._serverState = "connected";
|
||||
|
||||
// Emit the open event
|
||||
if(self.emitOpen)
|
||||
self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
|
||||
|
||||
self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
|
||||
// Callback
|
||||
callback(null, self.db);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Error handler
|
||||
var errorOrCloseHandler = function(_server) {
|
||||
return function(err, result) {
|
||||
// Execute all the callbacks with errors
|
||||
self.__executeAllCallbacksWithError(err);
|
||||
// Check if we have the server
|
||||
var found = false;
|
||||
|
||||
// Get the server name
|
||||
var server_name = format("%s:%s", _server.host, _server.port);
|
||||
// Add the downed server
|
||||
self.downServers[server_name] = _server;
|
||||
// Remove the current server from the list
|
||||
delete self.upServers[server_name];
|
||||
|
||||
// Emit close across all the attached db instances
|
||||
if(Object.keys(self.upServers).length == 0) {
|
||||
self._emitAcrossAllDbInstances(self, null, "close", new Error("mongos disconnected, no valid proxies contactable over tcp"), null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mongo function
|
||||
this.mongosCheckFunction = function() {
|
||||
// Set as not waiting for check event
|
||||
self._haInProgress = true;
|
||||
|
||||
// Servers down
|
||||
var numberOfServersLeft = Object.keys(self.downServers).length;
|
||||
|
||||
// Check downed servers
|
||||
if(numberOfServersLeft > 0) {
|
||||
for(var name in self.downServers) {
|
||||
// Pop a downed server
|
||||
var downServer = self.downServers[name];
|
||||
// Set up the connection options for a Mongos
|
||||
var options = {
|
||||
auto_reconnect: false,
|
||||
returnIsMasterResults: true,
|
||||
slaveOk: true,
|
||||
poolSize: downServer.poolSize,
|
||||
socketOptions: {
|
||||
connectTimeoutMS: self._connectTimeoutMS,
|
||||
socketTimeoutMS: self._socketTimeoutMS
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new server object
|
||||
var newServer = new Server(downServer.host, downServer.port, options);
|
||||
// Setup the connection function
|
||||
var connectFunction = function(_db, _server, _options, _callback) {
|
||||
return function() {
|
||||
// Attempt to connect
|
||||
_server.connect(_db, _options, function(err, result) {
|
||||
numberOfServersLeft = numberOfServersLeft - 1;
|
||||
|
||||
if(err) {
|
||||
return _callback(err, _server);
|
||||
} else {
|
||||
// Set the new server settings
|
||||
_server._callBackStore = self._callBackStore;
|
||||
|
||||
// Add server event handlers
|
||||
_server.on("close", errorOrCloseHandler(_server));
|
||||
_server.on("timeout", errorOrCloseHandler(_server));
|
||||
_server.on("error", errorOrCloseHandler(_server));
|
||||
|
||||
// Get a read connection
|
||||
var _connection = _server.checkoutReader();
|
||||
// Get the start time
|
||||
var startTime = new Date().getTime();
|
||||
|
||||
// Execute ping command to mark each server with the expected times
|
||||
self.db.command({ping:1}
|
||||
, {failFast:true, connection:_connection}, function(err, result) {
|
||||
// Get the start time
|
||||
var endTime = new Date().getTime();
|
||||
// Mark the server with the ping time
|
||||
_server.runtimeStats['pingMs'] = endTime - startTime;
|
||||
// Execute any waiting reads
|
||||
self._commandsStore.execute_writes();
|
||||
self._commandsStore.execute_queries();
|
||||
// Callback
|
||||
return _callback(null, _server);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to connect to the database
|
||||
connectFunction(self.db, newServer, options, function(err, _server) {
|
||||
// If we have an error
|
||||
if(err) {
|
||||
self.downServers[format("%s:%s", _server.host, _server.port)] = _server;
|
||||
}
|
||||
|
||||
// Connection function
|
||||
var connectionFunction = function(_auth, _connection, _callback) {
|
||||
var pending = _auth.length();
|
||||
|
||||
for(var j = 0; j < pending; j++) {
|
||||
// Get the auth object
|
||||
var _auth = _auth.get(j);
|
||||
// Unpack the parameter
|
||||
var username = _auth.username;
|
||||
var password = _auth.password;
|
||||
var options = {
|
||||
authMechanism: _auth.authMechanism
|
||||
, authSource: _auth.authdb
|
||||
, connection: _connection
|
||||
};
|
||||
|
||||
// If we have changed the service name
|
||||
if(_auth.gssapiServiceName)
|
||||
options.gssapiServiceName = _auth.gssapiServiceName;
|
||||
|
||||
// Hold any error
|
||||
var _error = null;
|
||||
// Authenticate against the credentials
|
||||
self.db.authenticate(username, password, options, function(err, result) {
|
||||
_error = err != null ? err : _error;
|
||||
// Adjust the pending authentication
|
||||
pending = pending - 1;
|
||||
// Finished up
|
||||
if(pending == 0) _callback(_error ? _error : null, _error ? false : true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Run auths against the connections
|
||||
if(self.auth.length() > 0) {
|
||||
var connections = _server.allRawConnections();
|
||||
var pendingAuthConn = connections.length;
|
||||
|
||||
// No connections we are done
|
||||
if(connections.length == 0) {
|
||||
// Set ha done
|
||||
if(numberOfServersLeft == 0) {
|
||||
self._haInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Final error object
|
||||
var finalError = null;
|
||||
// Go over all the connections
|
||||
for(var j = 0; j < connections.length; j++) {
|
||||
|
||||
// Execute against all the connections
|
||||
connectionFunction(self.auth, connections[j], function(err, result) {
|
||||
// Pending authentication
|
||||
pendingAuthConn = pendingAuthConn - 1 ;
|
||||
|
||||
// Save error if any
|
||||
finalError = err ? err : finalError;
|
||||
|
||||
// If we are done let's finish up
|
||||
if(pendingAuthConn == 0) {
|
||||
// Set ha done
|
||||
if(numberOfServersLeft == 0) {
|
||||
self._haInProgress = false;
|
||||
}
|
||||
|
||||
if(!err) {
|
||||
add_server(self, _server);
|
||||
}
|
||||
|
||||
// Execute any waiting reads
|
||||
self._commandsStore.execute_writes();
|
||||
self._commandsStore.execute_queries();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if(!err) {
|
||||
add_server(self, _server);
|
||||
}
|
||||
|
||||
// Set ha done
|
||||
if(numberOfServersLeft == 0) {
|
||||
self._haInProgress = false;
|
||||
// Execute any waiting reads
|
||||
self._commandsStore.execute_writes();
|
||||
self._commandsStore.execute_queries();
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
} else {
|
||||
self._haInProgress = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Connect all the server instances
|
||||
for(var i = 0; i < this.servers.length; i++) {
|
||||
// Get the connection
|
||||
var server = this.servers[i];
|
||||
server.mongosInstance = this;
|
||||
// Add server event handlers
|
||||
server.on("close", errorOrCloseHandler(server));
|
||||
server.on("timeout", errorOrCloseHandler(server));
|
||||
server.on("error", errorOrCloseHandler(server));
|
||||
|
||||
// Configuration
|
||||
var options = {
|
||||
slaveOk: true,
|
||||
poolSize: server.poolSize,
|
||||
socketOptions: { connectTimeoutMS: self._connectTimeoutMS },
|
||||
returnIsMasterResults: true
|
||||
}
|
||||
|
||||
// Connect the instance
|
||||
server.connect(self.db, options, connectHandler(server));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* Add a server to the list of up servers and sort them by ping time
|
||||
*/
|
||||
var add_server = function(self, _server) {
|
||||
var server_key = format("%s:%s", _server.host, _server.port);
|
||||
// Push to list of valid server
|
||||
self.upServers[server_key] = _server;
|
||||
// Remove the server from the list of downed servers
|
||||
delete self.downServers[server_key];
|
||||
|
||||
// Sort the keys by ping time
|
||||
var keys = Object.keys(self.upServers);
|
||||
var _upServersSorted = {};
|
||||
var _upServers = []
|
||||
|
||||
// Get all the servers
|
||||
for(var name in self.upServers) {
|
||||
_upServers.push(self.upServers[name]);
|
||||
}
|
||||
|
||||
// Sort all the server
|
||||
_upServers.sort(function(a, b) {
|
||||
return a.runtimeStats['pingMs'] > b.runtimeStats['pingMs'];
|
||||
});
|
||||
|
||||
// Rebuild the upServer
|
||||
for(var i = 0; i < _upServers.length; i++) {
|
||||
_upServersSorted[format("%s:%s", _upServers[i].host, _upServers[i].port)] = _upServers[i];
|
||||
}
|
||||
|
||||
// Set the up servers
|
||||
self.upServers = _upServersSorted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* Just return the currently picked active connection
|
||||
*/
|
||||
Mongos.prototype.allServerInstances = function() {
|
||||
return this.servers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Always ourselves
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.setReadPreference = function() {}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.allRawConnections = function() {
|
||||
// Neeed to build a complete list of all raw connections, start with master server
|
||||
var allConnections = [];
|
||||
// Get all connected connections
|
||||
for(var name in this.upServers) {
|
||||
allConnections = allConnections.concat(this.upServers[name].allRawConnections());
|
||||
}
|
||||
// Return all the conections
|
||||
return allConnections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.isConnected = function() {
|
||||
return Object.keys(this.upServers).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.isAutoReconnect = function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.canWrite = Mongos.prototype.isConnected;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.canRead = Mongos.prototype.isConnected;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.isDestroyed = function() {
|
||||
return this._serverState == 'destroyed';
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.checkoutWriter = function() {
|
||||
// Checkout a writer
|
||||
var keys = Object.keys(this.upServers);
|
||||
// console.dir("============================ checkoutWriter :: " + keys.length)
|
||||
if(keys.length == 0) return null;
|
||||
// console.log("=============== checkoutWriter :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
|
||||
return this.upServers[keys[0]].checkoutWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.checkoutReader = function(read) {
|
||||
// console.log("=============== checkoutReader :: read :: " + read);
|
||||
// If read is set to null default to primary
|
||||
read = read || 'primary'
|
||||
// If we have a read preference object unpack it
|
||||
if(read != null && typeof read == 'object' && read['_type'] == 'ReadPreference') {
|
||||
// Validate if the object is using a valid mode
|
||||
if(!read.isValid()) throw new Error("Illegal readPreference mode specified, " + read.mode);
|
||||
} else if(!ReadPreference.isValid(read)) {
|
||||
throw new Error("Illegal readPreference mode specified, " + read);
|
||||
}
|
||||
|
||||
// Checkout a writer
|
||||
var keys = Object.keys(this.upServers);
|
||||
if(keys.length == 0) return null;
|
||||
// console.log("=============== checkoutReader :: " + this.upServers[keys[0]].checkoutWriter().socketOptions.port)
|
||||
// console.dir(this._commandsStore.commands)
|
||||
return this.upServers[keys[0]].checkoutWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
Mongos.prototype.close = function(callback) {
|
||||
var self = this;
|
||||
// Set server status as disconnected
|
||||
this._serverState = 'destroyed';
|
||||
// Number of connections to close
|
||||
var numberOfConnectionsToClose = self.servers.length;
|
||||
// If we have a ha process running kill it
|
||||
if(self._replicasetTimeoutId != null) clearInterval(self._replicasetTimeoutId);
|
||||
self._replicasetTimeoutId = null;
|
||||
|
||||
// Emit close event
|
||||
processor(function() {
|
||||
self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
|
||||
});
|
||||
|
||||
// Close all the up servers
|
||||
for(var name in this.upServers) {
|
||||
this.upServers[name].close(function(err, result) {
|
||||
numberOfConnectionsToClose = numberOfConnectionsToClose - 1;
|
||||
|
||||
// Callback if we have one defined
|
||||
if(numberOfConnectionsToClose == 0 && typeof callback == 'function') {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
* Return the used state
|
||||
*/
|
||||
Mongos.prototype._isUsed = function() {
|
||||
return this._used;
|
||||
}
|
||||
|
||||
exports.Mongos = Mongos;
|
||||
67
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js
generated
vendored
Normal file
67
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/read_preference.js
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* A class representation of the Read Preference.
|
||||
*
|
||||
* Read Preferences
|
||||
* - **ReadPreference.PRIMARY**, Read from primary only. All operations produce an error (throw an exception where applicable) if primary is unavailable. Cannot be combined with tags (This is the default.).
|
||||
* - **ReadPreference.PRIMARY_PREFERRED**, Read from primary if available, otherwise a secondary.
|
||||
* - **ReadPreference.SECONDARY**, Read from secondary if available, otherwise error.
|
||||
* - **ReadPreference.SECONDARY_PREFERRED**, Read from a secondary if available, otherwise read from the primary.
|
||||
* - **ReadPreference.NEAREST**, All modes read from among the nearest candidates, but unlike other modes, NEAREST will include both the primary and all secondaries in the random selection.
|
||||
*
|
||||
* @class Represents a Read Preference.
|
||||
* @param {String} the read preference type
|
||||
* @param {Object} tags
|
||||
* @return {ReadPreference}
|
||||
*/
|
||||
var ReadPreference = function(mode, tags) {
|
||||
if(!(this instanceof ReadPreference))
|
||||
return new ReadPreference(mode, tags);
|
||||
this._type = 'ReadPreference';
|
||||
this.mode = mode;
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReadPreference.isValid = function(_mode) {
|
||||
return (_mode == ReadPreference.PRIMARY || _mode == ReadPreference.PRIMARY_PREFERRED
|
||||
|| _mode == ReadPreference.SECONDARY || _mode == ReadPreference.SECONDARY_PREFERRED
|
||||
|| _mode == ReadPreference.NEAREST
|
||||
|| _mode == true || _mode == false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReadPreference.prototype.isValid = function(mode) {
|
||||
var _mode = typeof mode == 'string' ? mode : this.mode;
|
||||
return ReadPreference.isValid(_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReadPreference.prototype.toObject = function() {
|
||||
var object = {mode:this.mode};
|
||||
|
||||
if(this.tags != null) {
|
||||
object['tags'] = this.tags;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReadPreference.PRIMARY = 'primary';
|
||||
ReadPreference.PRIMARY_PREFERRED = 'primaryPreferred';
|
||||
ReadPreference.SECONDARY = 'secondary';
|
||||
ReadPreference.SECONDARY_PREFERRED = 'secondaryPreferred';
|
||||
ReadPreference.NEAREST = 'nearest'
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
exports.ReadPreference = ReadPreference;
|
||||
407
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js
generated
vendored
Normal file
407
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/ha.js
generated
vendored
Normal file
@@ -0,0 +1,407 @@
|
||||
var DbCommand = require('../../commands/db_command').DbCommand
|
||||
, format = require('util').format;
|
||||
|
||||
var HighAvailabilityProcess = function(replset, options) {
|
||||
this.replset = replset;
|
||||
this.options = options;
|
||||
this.server = null;
|
||||
this.state = HighAvailabilityProcess.INIT;
|
||||
this.selectedIndex = 0;
|
||||
}
|
||||
|
||||
HighAvailabilityProcess.INIT = 'init';
|
||||
HighAvailabilityProcess.RUNNING = 'running';
|
||||
HighAvailabilityProcess.STOPPED = 'stopped';
|
||||
|
||||
HighAvailabilityProcess.prototype.start = function() {
|
||||
var self = this;
|
||||
if(this.replset._state
|
||||
&& Object.keys(this.replset._state.addresses).length == 0) {
|
||||
if(this.server) this.server.close();
|
||||
this.state = HighAvailabilityProcess.STOPPED;
|
||||
return;
|
||||
}
|
||||
|
||||
if(this.server) this.server.close();
|
||||
// Start the running
|
||||
this._haProcessInProcess = false;
|
||||
this.state = HighAvailabilityProcess.RUNNING;
|
||||
|
||||
// Get all possible reader servers
|
||||
var candidate_servers = this.replset._state.getAllReadServers();
|
||||
if(candidate_servers.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Select a candidate server for the connection
|
||||
var server = candidate_servers[this.selectedIndex % candidate_servers.length];
|
||||
this.selectedIndex = this.selectedIndex + 1;
|
||||
|
||||
// Unpack connection options
|
||||
var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
|
||||
var socketTimeoutMS = self.options.socketTimeoutMS || 30000;
|
||||
|
||||
// Just ensure we don't have a full cycle dependency
|
||||
var Db = require('../../db').Db
|
||||
var Server = require('../server').Server;
|
||||
|
||||
// Set up a new server instance
|
||||
var newServer = new Server(server.host, server.port, {
|
||||
auto_reconnect: false
|
||||
, returnIsMasterResults: true
|
||||
, poolSize: 1
|
||||
, socketOptions: {
|
||||
connectTimeoutMS: connectTimeoutMS,
|
||||
socketTimeoutMS: socketTimeoutMS,
|
||||
keepAlive: 100
|
||||
}
|
||||
, ssl: this.options.ssl
|
||||
, sslValidate: this.options.sslValidate
|
||||
, sslCA: this.options.sslCA
|
||||
, sslCert: this.options.sslCert
|
||||
, sslKey: this.options.sslKey
|
||||
, sslPass: this.options.sslPass
|
||||
});
|
||||
|
||||
// Create new dummy db for app
|
||||
self.db = new Db('local', newServer, {w:1});
|
||||
|
||||
// Set up the event listeners
|
||||
newServer.once("error", _handle(this, newServer));
|
||||
newServer.once("close", _handle(this, newServer));
|
||||
newServer.once("timeout", _handle(this, newServer));
|
||||
newServer.name = format("%s:%s", server.host, server.port);
|
||||
|
||||
// Let's attempt a connection over here
|
||||
newServer.connect(self.db, function(err, result, _server) {
|
||||
if(self.state == HighAvailabilityProcess.STOPPED) {
|
||||
_server.close();
|
||||
}
|
||||
|
||||
if(err) {
|
||||
// Close the server
|
||||
_server.close();
|
||||
// Check if we can even do HA (is there anything running)
|
||||
if(Object.keys(self.replset._state.addresses).length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's boot the ha timeout settings
|
||||
setTimeout(function() {
|
||||
self.start();
|
||||
}, self.options.haInterval);
|
||||
} else {
|
||||
self.server = _server;
|
||||
// Let's boot the ha timeout settings
|
||||
setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
HighAvailabilityProcess.prototype.stop = function() {
|
||||
this.state = HighAvailabilityProcess.STOPPED;
|
||||
if(this.server) this.server.close();
|
||||
}
|
||||
|
||||
var _timeoutHandle = function(self) {
|
||||
return function() {
|
||||
if(self.state == HighAvailabilityProcess.STOPPED) {
|
||||
// Stop all server instances
|
||||
for(var name in self.replset._state.addresses) {
|
||||
self.replset._state.addresses[name].close();
|
||||
delete self.replset._state.addresses[name];
|
||||
}
|
||||
|
||||
// Finished pinging
|
||||
return;
|
||||
}
|
||||
|
||||
// If the server is connected
|
||||
if(self.server.isConnected() && !self._haProcessInProcess) {
|
||||
// Start HA process
|
||||
self._haProcessInProcess = true;
|
||||
// Execute is master command
|
||||
self.db._executeQueryCommand(DbCommand.createIsMasterCommand(self.db),
|
||||
{failFast:true, connection: self.server.checkoutReader()}
|
||||
, function(err, res) {
|
||||
if(err) {
|
||||
self.server.close();
|
||||
return setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
|
||||
// Master document
|
||||
var master = res.documents[0];
|
||||
var hosts = master.hosts || [];
|
||||
var reconnect_servers = [];
|
||||
var state = self.replset._state;
|
||||
|
||||
// We are in recovery mode, let's remove the current server
|
||||
if(!master.ismaster
|
||||
&& !master.secondary
|
||||
&& state.addresses[master.me]) {
|
||||
self.server.close();
|
||||
state.addresses[master.me].close();
|
||||
delete state.secondaries[master.me];
|
||||
return setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
|
||||
// For all the hosts let's check that we have connections
|
||||
for(var i = 0; i < hosts.length; i++) {
|
||||
var host = hosts[i];
|
||||
// Check if we need to reconnect to a server
|
||||
if(state.addresses[host] == null) {
|
||||
reconnect_servers.push(host);
|
||||
} else if(state.addresses[host] && !state.addresses[host].isConnected()) {
|
||||
state.addresses[host].close();
|
||||
delete state.secondaries[host];
|
||||
reconnect_servers.push(host);
|
||||
}
|
||||
|
||||
if((master.primary && state.master == null)
|
||||
|| (master.primary && state.master.name != master.primary)) {
|
||||
|
||||
// Locate the primary and set it
|
||||
if(state.addresses[master.primary]) {
|
||||
if(state.master) state.master.close();
|
||||
delete state.secondaries[master.primary];
|
||||
state.master = state.addresses[master.primary];
|
||||
}
|
||||
|
||||
// Set up the changes
|
||||
if(state.master != null && state.master.isMasterDoc != null) {
|
||||
state.master.isMasterDoc.ismaster = true;
|
||||
state.master.isMasterDoc.secondary = false;
|
||||
} else if(state.master != null) {
|
||||
state.master.isMasterDoc = master;
|
||||
state.master.isMasterDoc.ismaster = true;
|
||||
state.master.isMasterDoc.secondary = false;
|
||||
}
|
||||
|
||||
// Execute any waiting commands (queries or writes)
|
||||
self.replset._commandsStore.execute_queries();
|
||||
self.replset._commandsStore.execute_writes();
|
||||
}
|
||||
}
|
||||
|
||||
// Let's reconnect to any server needed
|
||||
if(reconnect_servers.length > 0) {
|
||||
_reconnect_servers(self, reconnect_servers);
|
||||
} else {
|
||||
self._haProcessInProcess = false
|
||||
return setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
});
|
||||
} else if(!self.server.isConnected()) {
|
||||
setTimeout(function() {
|
||||
return self.start();
|
||||
}, self.options.haInterval);
|
||||
} else {
|
||||
setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _reconnect_servers = function(self, reconnect_servers) {
|
||||
if(reconnect_servers.length == 0) {
|
||||
self._haProcessInProcess = false
|
||||
return setTimeout(_timeoutHandle(self), self.options.haInterval);
|
||||
}
|
||||
|
||||
// Unpack connection options
|
||||
var connectTimeoutMS = self.options.connectTimeoutMS || 10000;
|
||||
var socketTimeoutMS = self.options.socketTimeoutMS || 30000;
|
||||
|
||||
// Server class
|
||||
var Db = require('../../db').Db
|
||||
var Server = require('../server').Server;
|
||||
// Get the host
|
||||
var host = reconnect_servers.shift();
|
||||
// Split it up
|
||||
var _host = host.split(":")[0];
|
||||
var _port = parseInt(host.split(":")[1], 10);
|
||||
|
||||
// Set up a new server instance
|
||||
var newServer = new Server(_host, _port, {
|
||||
auto_reconnect: false
|
||||
, returnIsMasterResults: true
|
||||
, poolSize: self.options.poolSize
|
||||
, socketOptions: {
|
||||
connectTimeoutMS: connectTimeoutMS,
|
||||
socketTimeoutMS: socketTimeoutMS
|
||||
}
|
||||
, ssl: self.options.ssl
|
||||
, sslValidate: self.options.sslValidate
|
||||
, sslCA: self.options.sslCA
|
||||
, sslCert: self.options.sslCert
|
||||
, sslKey: self.options.sslKey
|
||||
, sslPass: self.options.sslPass
|
||||
});
|
||||
|
||||
// Create new dummy db for app
|
||||
var db = new Db('local', newServer, {w:1});
|
||||
var state = self.replset._state;
|
||||
|
||||
// Set up the event listeners
|
||||
newServer.once("error", _repl_set_handler("error", self.replset, newServer));
|
||||
newServer.once("close", _repl_set_handler("close", self.replset, newServer));
|
||||
newServer.once("timeout", _repl_set_handler("timeout", self.replset, newServer));
|
||||
|
||||
// Set shared state
|
||||
newServer.name = host;
|
||||
newServer._callBackStore = self.replset._callBackStore;
|
||||
newServer.replicasetInstance = self.replset;
|
||||
newServer.enableRecordQueryStats(self.replset.recordQueryStats);
|
||||
|
||||
// Let's attempt a connection over here
|
||||
newServer.connect(db, function(err, result, _server) {
|
||||
if(self.state == HighAvailabilityProcess.STOPPED) {
|
||||
_server.close();
|
||||
}
|
||||
|
||||
// If we connected let's check what kind of server we have
|
||||
if(!err) {
|
||||
_apply_auths(self, db, _server, function(err, result) {
|
||||
if(err) {
|
||||
_server.close();
|
||||
// Process the next server
|
||||
return setTimeout(function() {
|
||||
_reconnect_servers(self, reconnect_servers);
|
||||
}, self.options.haInterval);
|
||||
}
|
||||
var doc = _server.isMasterDoc;
|
||||
// Fire error on any unknown callbacks for this server
|
||||
self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
|
||||
|
||||
if(doc.ismaster) {
|
||||
if(state.secondaries[doc.me]) {
|
||||
delete state.secondaries[doc.me];
|
||||
}
|
||||
|
||||
// Override any server in list of addresses
|
||||
state.addresses[doc.me] = _server;
|
||||
// Set server as master
|
||||
state.master = _server;
|
||||
// Execute any waiting writes
|
||||
self.replset._commandsStore.execute_writes();
|
||||
} else if(doc.secondary) {
|
||||
state.secondaries[doc.me] = _server;
|
||||
// Override any server in list of addresses
|
||||
state.addresses[doc.me] = _server;
|
||||
// Execute any waiting reads
|
||||
self.replset._commandsStore.execute_queries();
|
||||
} else {
|
||||
_server.close();
|
||||
}
|
||||
|
||||
// Set any tags on the instance server
|
||||
_server.name = doc.me;
|
||||
_server.tags = doc.tags;
|
||||
// Process the next server
|
||||
setTimeout(function() {
|
||||
_reconnect_servers(self, reconnect_servers);
|
||||
}, self.options.haInterval);
|
||||
});
|
||||
} else {
|
||||
_server.close();
|
||||
self.replset.__executeAllServerSpecificErrorCallbacks(_server.socketOptions.host, _server.socketOptions.port, err);
|
||||
|
||||
setTimeout(function() {
|
||||
_reconnect_servers(self, reconnect_servers);
|
||||
}, self.options.haInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var _apply_auths = function(self, _db, _server, _callback) {
|
||||
if(self.replset.auth.length() == 0) return _callback(null);
|
||||
// Apply any authentication needed
|
||||
if(self.replset.auth.length() > 0) {
|
||||
var pending = self.replset.auth.length();
|
||||
var connections = _server.allRawConnections();
|
||||
var pendingAuthConn = connections.length;
|
||||
|
||||
// Connection function
|
||||
var connectionFunction = function(_auth, _connection, __callback) {
|
||||
var pending = _auth.length();
|
||||
|
||||
for(var j = 0; j < pending; j++) {
|
||||
// Get the auth object
|
||||
var _auth = _auth.get(j);
|
||||
// Unpack the parameter
|
||||
var username = _auth.username;
|
||||
var password = _auth.password;
|
||||
var options = {
|
||||
authMechanism: _auth.authMechanism
|
||||
, authSource: _auth.authdb
|
||||
, connection: _connection
|
||||
};
|
||||
|
||||
// If we have changed the service name
|
||||
if(_auth.gssapiServiceName)
|
||||
options.gssapiServiceName = _auth.gssapiServiceName;
|
||||
|
||||
// Hold any error
|
||||
var _error = null;
|
||||
|
||||
// Authenticate against the credentials
|
||||
_db.authenticate(username, password, options, function(err, result) {
|
||||
_error = err != null ? err : _error;
|
||||
// Adjust the pending authentication
|
||||
pending = pending - 1;
|
||||
// Finished up
|
||||
if(pending == 0) __callback(_error ? _error : null, _error ? false : true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Final error object
|
||||
var finalError = null;
|
||||
// Iterate over all the connections
|
||||
for(var i = 0; i < connections.length; i++) {
|
||||
connectionFunction(self.replset.auth, connections[i], function(err, result) {
|
||||
// Pending authentication
|
||||
pendingAuthConn = pendingAuthConn - 1 ;
|
||||
|
||||
// Save error if any
|
||||
finalError = err ? err : finalError;
|
||||
|
||||
// If we are done let's finish up
|
||||
if(pendingAuthConn == 0) {
|
||||
_callback(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _handle = function(self, server) {
|
||||
return function(err) {
|
||||
server.close();
|
||||
}
|
||||
}
|
||||
|
||||
var _repl_set_handler = function(event, self, server) {
|
||||
var ReplSet = require('./repl_set').ReplSet;
|
||||
|
||||
return function(err, doc) {
|
||||
server.close();
|
||||
|
||||
// The event happened to a primary
|
||||
// Remove it from play
|
||||
if(self._state.isPrimary(server)) {
|
||||
self._state.master == null;
|
||||
self._serverState = ReplSet.REPLSET_READ_ONLY;
|
||||
} else if(self._state.isSecondary(server)) {
|
||||
delete self._state.secondaries[server.name];
|
||||
}
|
||||
|
||||
// Unpack variables
|
||||
var host = server.socketOptions.host;
|
||||
var port = server.socketOptions.port;
|
||||
|
||||
// Fire error on any unknown callbacks
|
||||
self.__executeAllServerSpecificErrorCallbacks(host, port, err);
|
||||
}
|
||||
}
|
||||
|
||||
exports.HighAvailabilityProcess = HighAvailabilityProcess;
|
||||
126
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js
generated
vendored
Normal file
126
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/options.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
var PingStrategy = require('./strategies/ping_strategy').PingStrategy
|
||||
, StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
|
||||
, ReadPreference = require('../read_preference').ReadPreference;
|
||||
|
||||
var Options = function(options) {
|
||||
options = options || {};
|
||||
this._options = options;
|
||||
this.ha = options.ha || true;
|
||||
this.haInterval = options.haInterval || 2000;
|
||||
this.reconnectWait = options.reconnectWait || 1000;
|
||||
this.retries = options.retries || 30;
|
||||
this.rs_name = options.rs_name;
|
||||
this.socketOptions = options.socketOptions || {};
|
||||
this.readPreference = options.readPreference;
|
||||
this.readSecondary = options.read_secondary;
|
||||
this.poolSize = options.poolSize == null ? 5 : options.poolSize;
|
||||
this.strategy = options.strategy || 'ping';
|
||||
this.secondaryAcceptableLatencyMS = options.secondaryAcceptableLatencyMS || 15;
|
||||
this.connectArbiter = options.connectArbiter || false;
|
||||
this.connectWithNoPrimary = options.connectWithNoPrimary || false;
|
||||
this.logger = options.logger;
|
||||
this.ssl = options.ssl || false;
|
||||
this.sslValidate = options.sslValidate || false;
|
||||
this.sslCA = options.sslCA;
|
||||
this.sslCert = options.sslCert;
|
||||
this.sslKey = options.sslKey;
|
||||
this.sslPass = options.sslPass;
|
||||
this.emitOpen = options.emitOpen || true;
|
||||
}
|
||||
|
||||
Options.prototype.init = function() {
|
||||
if(this.sslValidate && (!Array.isArray(this.sslCA) || this.sslCA.length == 0)) {
|
||||
throw new Error("The driver expects an Array of CA certificates in the sslCA parameter when enabling sslValidate");
|
||||
}
|
||||
|
||||
// Make sure strategy is one of the two allowed
|
||||
if(this.strategy != null && (this.strategy != 'ping' && this.strategy != 'statistical' && this.strategy != 'none'))
|
||||
throw new Error("Only ping or statistical strategies allowed");
|
||||
|
||||
if(this.strategy == null) this.strategy = 'ping';
|
||||
|
||||
// Set logger if strategy exists
|
||||
if(this.strategyInstance) this.strategyInstance.logger = this.logger;
|
||||
|
||||
// Unpack read Preference
|
||||
var readPreference = this.readPreference;
|
||||
// Validate correctness of Read preferences
|
||||
if(readPreference != null) {
|
||||
if(readPreference != ReadPreference.PRIMARY && readPreference != ReadPreference.PRIMARY_PREFERRED
|
||||
&& readPreference != ReadPreference.SECONDARY && readPreference != ReadPreference.SECONDARY_PREFERRED
|
||||
&& readPreference != ReadPreference.NEAREST && typeof readPreference != 'object' && readPreference['_type'] != 'ReadPreference') {
|
||||
throw new Error("Illegal readPreference mode specified, " + readPreference);
|
||||
}
|
||||
|
||||
this.readPreference = readPreference;
|
||||
} else {
|
||||
this.readPreference = null;
|
||||
}
|
||||
|
||||
// Ensure read_secondary is set correctly
|
||||
if(this.readSecondary != null)
|
||||
this.readSecondary = this.readPreference == ReadPreference.PRIMARY
|
||||
|| this.readPreference == false
|
||||
|| this.readPreference == null ? false : true;
|
||||
|
||||
// Ensure correct slave set
|
||||
if(this.readSecondary) this.slaveOk = true;
|
||||
|
||||
// Set up logger if any set
|
||||
this.logger = this.logger != null
|
||||
&& (typeof this.logger.debug == 'function')
|
||||
&& (typeof this.logger.error == 'function')
|
||||
&& (typeof this.logger.debug == 'function')
|
||||
? this.logger : {error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}};
|
||||
|
||||
// Connection timeout
|
||||
this.connectTimeoutMS = this.socketOptions.connectTimeoutMS
|
||||
? this.socketOptions.connectTimeoutMS
|
||||
: 1000;
|
||||
|
||||
// Socket connection timeout
|
||||
this.socketTimeoutMS = this.socketOptions.socketTimeoutMS
|
||||
? this.socketOptions.socketTimeoutMS
|
||||
: 30000;
|
||||
}
|
||||
|
||||
Options.prototype.decorateAndClean = function(servers, callBackStore) {
|
||||
var self = this;
|
||||
|
||||
// var de duplicate list
|
||||
var uniqueServers = {};
|
||||
// De-duplicate any servers in the seed list
|
||||
for(var i = 0; i < servers.length; i++) {
|
||||
var server = servers[i];
|
||||
// If server does not exist set it
|
||||
if(uniqueServers[server.host + ":" + server.port] == null) {
|
||||
uniqueServers[server.host + ":" + server.port] = server;
|
||||
}
|
||||
}
|
||||
|
||||
// Let's set the deduplicated list of servers
|
||||
var finalServers = [];
|
||||
// Add the servers
|
||||
for(var key in uniqueServers) {
|
||||
finalServers.push(uniqueServers[key]);
|
||||
}
|
||||
|
||||
finalServers.forEach(function(server) {
|
||||
// Ensure no server has reconnect on
|
||||
server.options.auto_reconnect = false;
|
||||
// Set up ssl options
|
||||
server.ssl = self.ssl;
|
||||
server.sslValidate = self.sslValidate;
|
||||
server.sslCA = self.sslCA;
|
||||
server.sslCert = self.sslCert;
|
||||
server.sslKey = self.sslKey;
|
||||
server.sslPass = self.sslPass;
|
||||
server.poolSize = self.poolSize;
|
||||
// Set callback store
|
||||
server._callBackStore = callBackStore;
|
||||
});
|
||||
|
||||
return finalServers;
|
||||
}
|
||||
|
||||
exports.Options = Options;
|
||||
799
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js
generated
vendored
Normal file
799
node_modules/mongoose/node_modules/mongodb/lib/mongodb/connection/repl_set/repl_set.js
generated
vendored
Normal file
@@ -0,0 +1,799 @@
|
||||
var ReadPreference = require('../read_preference').ReadPreference
|
||||
, DbCommand = require('../../commands/db_command').DbCommand
|
||||
, inherits = require('util').inherits
|
||||
, format = require('util').format
|
||||
, timers = require('timers')
|
||||
, Server = require('../server').Server
|
||||
, utils = require('../../utils')
|
||||
, PingStrategy = require('./strategies/ping_strategy').PingStrategy
|
||||
, StatisticsStrategy = require('./strategies/statistics_strategy').StatisticsStrategy
|
||||
, Options = require('./options').Options
|
||||
, ReplSetState = require('./repl_set_state').ReplSetState
|
||||
, HighAvailabilityProcess = require('./ha').HighAvailabilityProcess
|
||||
, Base = require('../base').Base;
|
||||
|
||||
const STATE_STARTING_PHASE_1 = 0;
|
||||
const STATE_PRIMARY = 1;
|
||||
const STATE_SECONDARY = 2;
|
||||
const STATE_RECOVERING = 3;
|
||||
const STATE_FATAL_ERROR = 4;
|
||||
const STATE_STARTING_PHASE_2 = 5;
|
||||
const STATE_UNKNOWN = 6;
|
||||
const STATE_ARBITER = 7;
|
||||
const STATE_DOWN = 8;
|
||||
const STATE_ROLLBACK = 9;
|
||||
|
||||
// Set processor, setImmediate if 0.10 otherwise nextTick
|
||||
var processor = require('../../utils').processor();
|
||||
|
||||
/**
|
||||
* ReplSet constructor provides replicaset functionality
|
||||
*
|
||||
* Options
|
||||
* - **ha** {Boolean, default:true}, turn on high availability.
|
||||
* - **haInterval** {Number, default:2000}, time between each replicaset status check.
|
||||
* - **reconnectWait** {Number, default:1000}, time to wait in miliseconds before attempting reconnect.
|
||||
* - **retries** {Number, default:30}, number of times to attempt a replicaset reconnect.
|
||||
* - **rs_name** {String}, the name of the replicaset to connect to.
|
||||
* - **socketOptions** {Object, default:null}, an object containing socket options to use (noDelay:(boolean), keepAlive:(number), connectTimeoutMS:(number), socketTimeoutMS:(number))
|
||||
* - **readPreference** {String}, the prefered read preference (ReadPreference.PRIMARY, ReadPreference.PRIMARY_PREFERRED, ReadPreference.SECONDARY, ReadPreference.SECONDARY_PREFERRED, ReadPreference.NEAREST).
|
||||
* - **strategy** {String, default:'ping'}, selection strategy for reads choose between (ping, statistical and none, default is ping)
|
||||
* - **secondaryAcceptableLatencyMS** {Number, default:15}, sets the range of servers to pick when using NEAREST (lowest ping ms + the latency fence, ex: range of 1 to (1 + 15) ms)
|
||||
* - **connectWithNoPrimary** {Boolean, default:false}, sets if the driver should connect even if no primary is available
|
||||
* - **connectArbiter** {Boolean, default:false}, sets if the driver should connect to arbiters or not.
|
||||
* - **logger** {Object, default:null}, an object representing a logger that you want to use, needs to support functions debug, log, error **({error:function(message, object) {}, log:function(message, object) {}, debug:function(message, object) {}})**.
|
||||
* - **poolSize** {Number, default:5}, number of connections in the connection pool for each server instance, set to 5 as default for legacy reasons.
|
||||
* - **ssl** {Boolean, default:false}, use ssl connection (needs to have a mongod server with ssl support)
|
||||
* - **sslValidate** {Boolean, default:false}, validate mongod server certificate against ca (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* - **sslCA** {Array, default:null}, Array of valid certificates either as Buffers or Strings (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* - **sslCert** {Buffer/String, default:null}, String or buffer containing the certificate we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* - **sslKey** {Buffer/String, default:null}, String or buffer containing the certificate private key we wish to present (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
* - **sslPass** {Buffer/String, default:null}, String or buffer containing the certificate password (needs to have a mongod server with ssl support, 2.4 or higher)
|
||||
*
|
||||
* @class Represents a
|
||||
Replicaset Configuration
|
||||
* @param {Array} list of server objects participating in the replicaset.
|
||||
* @param {Object} [options] additional options for the replicaset connection.
|
||||
*/
|
||||
var ReplSet = exports.ReplSet = function(servers, options) {
|
||||
// Set up basic
|
||||
if(!(this instanceof ReplSet))
|
||||
return new ReplSet(servers, options);
|
||||
|
||||
// Set up event emitter
|
||||
Base.call(this);
|
||||
|
||||
// Ensure we have a list of servers
|
||||
if(!Array.isArray(servers)) throw Error("The parameter must be an array of servers and contain at least one server");
|
||||
// Ensure no Mongos's
|
||||
for(var i = 0; i < servers.length; i++) {
|
||||
if(!(servers[i] instanceof Server)) throw new Error("list of servers must be of type Server");
|
||||
}
|
||||
|
||||
// Save the options
|
||||
this.options = new Options(options);
|
||||
// Ensure basic validation of options
|
||||
this.options.init();
|
||||
|
||||
// Server state
|
||||
this._serverState = ReplSet.REPLSET_DISCONNECTED;
|
||||
// Add high availability process
|
||||
this._haProcess = new HighAvailabilityProcess(this, this.options);
|
||||
|
||||
|
||||
// Let's iterate over all the provided server objects and decorate them
|
||||
this.servers = this.options.decorateAndClean(servers, this._callBackStore);
|
||||
// Throw error if no seed servers
|
||||
if(this.servers.length == 0) throw new Error("No valid seed servers in the array");
|
||||
|
||||
// Let's set up our strategy object for picking secondaries
|
||||
if(this.options.strategy == 'ping') {
|
||||
// Create a new instance
|
||||
this.strategyInstance = new PingStrategy(this, this.options.secondaryAcceptableLatencyMS);
|
||||
} else if(this.options.strategy == 'statistical') {
|
||||
// Set strategy as statistical
|
||||
this.strategyInstance = new StatisticsStrategy(this);
|
||||
// Add enable query information
|
||||
this.enableRecordQueryStats(true);
|
||||
}
|
||||
|
||||
this.emitOpen = this.options.emitOpen || true;
|
||||
// Set up a clean state
|
||||
this._state = new ReplSetState();
|
||||
// Current round robin selected server
|
||||
this._currentServerChoice = 0;
|
||||
// Ensure up the server callbacks
|
||||
for(var i = 0; i < this.servers.length; i++) {
|
||||
this.servers[i]._callBackStore = this._callBackStore;
|
||||
this.servers[i].name = format("%s:%s", this.servers[i].host, this.servers[i].port)
|
||||
this.servers[i].replicasetInstance = this;
|
||||
this.servers[i].options.auto_reconnect = false;
|
||||
this.servers[i].inheritReplSetOptionsFrom(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
inherits(ReplSet, Base);
|
||||
|
||||
// Replicaset states
|
||||
ReplSet.REPLSET_CONNECTING = 'connecting';
|
||||
ReplSet.REPLSET_DISCONNECTED = 'disconnected';
|
||||
ReplSet.REPLSET_CONNECTED = 'connected';
|
||||
ReplSet.REPLSET_RECONNECTING = 'reconnecting';
|
||||
ReplSet.REPLSET_DESTROYED = 'destroyed';
|
||||
ReplSet.REPLSET_READ_ONLY = 'readonly';
|
||||
|
||||
ReplSet.prototype.isAutoReconnect = function() {
|
||||
return true;
|
||||
}
|
||||
|
||||
ReplSet.prototype.canWrite = function() {
|
||||
return this._state.master && this._state.master.isConnected();
|
||||
}
|
||||
|
||||
ReplSet.prototype.canRead = function(read) {
|
||||
if((read == ReadPreference.PRIMARY
|
||||
|| read == null || read == false) && (this._state.master == null || !this._state.master.isConnected())) return false;
|
||||
return Object.keys(this._state.secondaries).length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.enableRecordQueryStats = function(enable) {
|
||||
// Set the global enable record query stats
|
||||
this.recordQueryStats = enable;
|
||||
|
||||
// Enable all the servers
|
||||
for(var i = 0; i < this.servers.length; i++) {
|
||||
this.servers[i].enableRecordQueryStats(enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.setReadPreference = function(preference) {
|
||||
this.options.readPreference = preference;
|
||||
}
|
||||
|
||||
ReplSet.prototype.connect = function(parent, options, callback) {
|
||||
if(this._serverState != ReplSet.REPLSET_DISCONNECTED)
|
||||
return callback(new Error("in process of connection"));
|
||||
|
||||
// If no callback throw
|
||||
if(!(typeof callback == 'function'))
|
||||
throw new Error("cannot call ReplSet.prototype.connect with no callback function");
|
||||
|
||||
var self = this;
|
||||
// Save db reference
|
||||
this.options.db = parent;
|
||||
// Set replicaset as connecting
|
||||
this._serverState = ReplSet.REPLSET_CONNECTING
|
||||
// Copy all the servers to our list of seeds
|
||||
var candidateServers = this.servers.slice(0);
|
||||
// Pop the first server
|
||||
var server = candidateServers.pop();
|
||||
server.name = format("%s:%s", server.host, server.port);
|
||||
// Set up the options
|
||||
var opts = {
|
||||
returnIsMasterResults: true,
|
||||
eventReceiver: server
|
||||
}
|
||||
|
||||
// Register some event listeners
|
||||
this.once("fullsetup", function(err, db, replset) {
|
||||
// Set state to connected
|
||||
self._serverState = ReplSet.REPLSET_CONNECTED;
|
||||
// Stop any process running
|
||||
if(self._haProcess) self._haProcess.stop();
|
||||
// Start the HA process
|
||||
self._haProcess.start();
|
||||
|
||||
// Emit fullsetup
|
||||
processor(function() {
|
||||
if(self.emitOpen)
|
||||
self._emitAcrossAllDbInstances(self, null, "open", null, null, null);
|
||||
|
||||
self._emitAcrossAllDbInstances(self, null, "fullsetup", null, null, null);
|
||||
});
|
||||
|
||||
// If we have a strategy defined start it
|
||||
if(self.strategyInstance) {
|
||||
self.strategyInstance.start();
|
||||
}
|
||||
|
||||
// Finishing up the call
|
||||
callback(err, db, replset);
|
||||
});
|
||||
|
||||
// Errors
|
||||
this.once("connectionError", function(err, result) {
|
||||
callback(err, result);
|
||||
});
|
||||
|
||||
// Attempt to connect to the server
|
||||
server.connect(this.options.db, opts, _connectHandler(this, candidateServers, server));
|
||||
}
|
||||
|
||||
ReplSet.prototype.close = function(callback) {
|
||||
var self = this;
|
||||
// Set as destroyed
|
||||
this._serverState = ReplSet.REPLSET_DESTROYED;
|
||||
// Stop the ha
|
||||
this._haProcess.stop();
|
||||
|
||||
// If we have a strategy stop it
|
||||
if(this.strategyInstance) {
|
||||
this.strategyInstance.stop();
|
||||
}
|
||||
|
||||
// Kill all servers available
|
||||
for(var name in this._state.addresses) {
|
||||
this._state.addresses[name].close();
|
||||
}
|
||||
|
||||
// Clean out the state
|
||||
this._state = new ReplSetState();
|
||||
|
||||
// Emit close event
|
||||
processor(function() {
|
||||
self._emitAcrossAllDbInstances(self, null, "close", null, null, true)
|
||||
});
|
||||
|
||||
// Callback
|
||||
if(typeof callback == 'function')
|
||||
return callback(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new server for the `replset` based on `host`.
|
||||
*
|
||||
* @param {String} host - host:port pair (localhost:27017)
|
||||
* @param {ReplSet} replset - the ReplSet instance
|
||||
* @return {Server}
|
||||
* @ignore
|
||||
*/
|
||||
var createServer = function(self, host, options) {
|
||||
// copy existing socket options to new server
|
||||
var socketOptions = {}
|
||||
if(options.socketOptions) {
|
||||
var keys = Object.keys(options.socketOptions);
|
||||
for(var k = 0; k < keys.length; k++) {
|
||||
socketOptions[keys[k]] = options.socketOptions[keys[k]];
|
||||
}
|
||||
}
|
||||
|
||||
var parts = host.split(/:/);
|
||||
if(1 === parts.length) {
|
||||
parts[1] = Connection.DEFAULT_PORT;
|
||||
}
|
||||
|
||||
socketOptions.host = parts[0];
|
||||
socketOptions.port = parseInt(parts[1], 10);
|
||||
|
||||
var serverOptions = {
|
||||
readPreference: options.readPreference,
|
||||
socketOptions: socketOptions,
|
||||
poolSize: options.poolSize,
|
||||
logger: options.logger,
|
||||
auto_reconnect: false,
|
||||
ssl: options.ssl,
|
||||
sslValidate: options.sslValidate,
|
||||
sslCA: options.sslCA,
|
||||
sslCert: options.sslCert,
|
||||
sslKey: options.sslKey,
|
||||
sslPass: options.sslPass
|
||||
}
|
||||
|
||||
var server = new Server(socketOptions.host, socketOptions.port, serverOptions);
|
||||
// Set up shared state
|
||||
server._callBackStore = self._callBackStore;
|
||||
server.replicasetInstance = self;
|
||||
server.enableRecordQueryStats(self.recordQueryStats);
|
||||
// Set up event handlers
|
||||
server.on("close", _handler("close", self, server));
|
||||
server.on("error", _handler("error", self, server));
|
||||
server.on("timeout", _handler("timeout", self, server));
|
||||
return server;
|
||||
}
|
||||
|
||||
var _handler = function(event, self, server) {
|
||||
return function(err, doc) {
|
||||
// The event happened to a primary
|
||||
// Remove it from play
|
||||
if(self._state.isPrimary(server)) {
|
||||
var current_master = self._state.master;
|
||||
self._state.master = null;
|
||||
self._serverState = ReplSet.REPLSET_READ_ONLY;
|
||||
|
||||
if(current_master != null) {
|
||||
// Unpack variables
|
||||
var host = current_master.socketOptions.host;
|
||||
var port = current_master.socketOptions.port;
|
||||
|
||||
// Fire error on any unknown callbacks
|
||||
self.__executeAllServerSpecificErrorCallbacks(host, port, err);
|
||||
}
|
||||
} else if(self._state.isSecondary(server)) {
|
||||
delete self._state.secondaries[server.name];
|
||||
}
|
||||
|
||||
// If there is no more connections left and the setting is not destroyed
|
||||
// set to disconnected
|
||||
if(Object.keys(self._state.addresses).length == 0
|
||||
&& self._serverState != ReplSet.REPLSET_DESTROYED) {
|
||||
self._serverState = ReplSet.REPLSET_DISCONNECTED;
|
||||
|
||||
// Emit close across all the attached db instances
|
||||
self._dbStore.emit("close", new Error("replicaset disconnected, no valid servers contactable over tcp"), null, true);
|
||||
}
|
||||
|
||||
// Unpack variables
|
||||
var host = server.socketOptions.host;
|
||||
var port = server.socketOptions.port;
|
||||
|
||||
// Fire error on any unknown callbacks
|
||||
self.__executeAllServerSpecificErrorCallbacks(host, port, err);
|
||||
}
|
||||
}
|
||||
|
||||
var locateNewServers = function(self, state, candidateServers, ismaster) {
|
||||
// Retrieve the host
|
||||
var hosts = ismaster.hosts;
|
||||
// In candidate servers
|
||||
var inCandidateServers = function(name, candidateServers) {
|
||||
for(var i = 0; i < candidateServers.length; i++) {
|
||||
if(candidateServers[i].name == name) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// New servers
|
||||
var newServers = [];
|
||||
if(Array.isArray(hosts)) {
|
||||
// Let's go over all the hosts
|
||||
for(var i = 0; i < hosts.length; i++) {
|
||||
if(!state.contains(hosts[i])
|
||||
&& !inCandidateServers(hosts[i], candidateServers)) {
|
||||
newServers.push(createServer(self, hosts[i], self.options));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return list of possible new servers
|
||||
return newServers;
|
||||
}
|
||||
|
||||
var _connectHandler = function(self, candidateServers, instanceServer) {
|
||||
return function(err, doc) {
|
||||
// If we have an error add to the list
|
||||
if(err) {
|
||||
self._state.errors[instanceServer.name] = instanceServer;
|
||||
} else {
|
||||
delete self._state.errors[instanceServer.name];
|
||||
}
|
||||
|
||||
if(!err) {
|
||||
var ismaster = doc.documents[0]
|
||||
|
||||
// Error the server if
|
||||
if(!ismaster.ismaster
|
||||
&& !ismaster.secondary) {
|
||||
self._state.errors[instanceServer.name] = instanceServer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// No error let's analyse the ismaster command
|
||||
if(!err && self._state.errors[instanceServer.name] == null) {
|
||||
var ismaster = doc.documents[0]
|
||||
|
||||
// If no replicaset name exists set the current one
|
||||
if(self.options.rs_name == null) {
|
||||
self.options.rs_name = ismaster.setName;
|
||||
}
|
||||
|
||||
// If we have a member that is not part of the set let's finish up
|
||||
if(typeof ismaster.setName == 'string' && ismaster.setName != self.options.rs_name) {
|
||||
return self.emit("connectionError", new Error("Replicaset name " + ismaster.setName + " does not match specified name " + self.options.rs_name));
|
||||
}
|
||||
|
||||
// Add the error handlers
|
||||
instanceServer.on("close", _handler("close", self, instanceServer));
|
||||
instanceServer.on("error", _handler("error", self, instanceServer));
|
||||
instanceServer.on("timeout", _handler("timeout", self, instanceServer));
|
||||
|
||||
// Set any tags on the instance server
|
||||
instanceServer.name = ismaster.me;
|
||||
instanceServer.tags = ismaster.tags;
|
||||
|
||||
// Add the server to the list
|
||||
self._state.addServer(instanceServer, ismaster);
|
||||
|
||||
// Check if we have more servers to add (only check when done with initial set)
|
||||
if(candidateServers.length == 0) {
|
||||
// Get additional new servers that are not currently in set
|
||||
var new_servers = locateNewServers(self, self._state, candidateServers, ismaster);
|
||||
|
||||
// Locate any new servers that have not errored out yet
|
||||
for(var i = 0; i < new_servers.length; i++) {
|
||||
if(self._state.errors[new_servers[i].name] == null) {
|
||||
candidateServers.push(new_servers[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the candidate server list is empty and no valid servers
|
||||
if(candidateServers.length == 0 &&
|
||||
!self._state.hasValidServers()) {
|
||||
return self.emit("connectionError", new Error("No valid replicaset instance servers found"));
|
||||
} else if(candidateServers.length == 0) {
|
||||
if(!self.options.connectWithNoPrimary && (self._state.master == null || !self._state.master.isConnected())) {
|
||||
return self.emit("connectionError", new Error("No primary found in set"));
|
||||
}
|
||||
return self.emit("fullsetup", null, self.options.db, self);
|
||||
}
|
||||
|
||||
// Let's connect the next server
|
||||
var nextServer = candidateServers.pop();
|
||||
|
||||
// Set up the options
|
||||
var opts = {
|
||||
returnIsMasterResults: true,
|
||||
eventReceiver: nextServer
|
||||
}
|
||||
|
||||
// Attempt to connect to the server
|
||||
nextServer.connect(self.options.db, opts, _connectHandler(self, candidateServers, nextServer));
|
||||
}
|
||||
}
|
||||
|
||||
ReplSet.prototype.isDestroyed = function() {
|
||||
return this._serverState == ReplSet.REPLSET_DESTROYED;
|
||||
}
|
||||
|
||||
ReplSet.prototype.isConnected = function(read) {
|
||||
var isConnected = false;
|
||||
|
||||
if(read == null || read == ReadPreference.PRIMARY || read == false)
|
||||
isConnected = this._state.master != null && this._state.master.isConnected();
|
||||
|
||||
if((read == ReadPreference.PRIMARY_PREFERRED || read == ReadPreference.SECONDARY_PREFERRED || read == ReadPreference.NEAREST)
|
||||
&& ((this._state.master != null && this._state.master.isConnected())
|
||||
|| (this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0))) {
|
||||
isConnected = true;
|
||||
} else if(read == ReadPreference.SECONDARY) {
|
||||
isConnected = this._state && this._state.secondaries && Object.keys(this._state.secondaries).length > 0;
|
||||
}
|
||||
|
||||
// No valid connection return false
|
||||
return isConnected;
|
||||
}
|
||||
|
||||
ReplSet.prototype.isMongos = function() {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReplSet.prototype.checkoutWriter = function() {
|
||||
if(this._state.master) return this._state.master.checkoutWriter();
|
||||
return new Error("no writer connection available");
|
||||
}
|
||||
|
||||
ReplSet.prototype.processIsMaster = function(_server, _ismaster) {
|
||||
// Server in recovery mode, remove it from available servers
|
||||
if(!_ismaster.ismaster && !_ismaster.secondary) {
|
||||
// Locate the actual server
|
||||
var server = this._state.addresses[_server.name];
|
||||
// Close the server, simulating the closing of the connection
|
||||
// to get right removal semantics
|
||||
if(server) server.close();
|
||||
// Execute any callback errors
|
||||
_handler(null, this, server)(new Error("server is in recovery mode"));
|
||||
}
|
||||
}
|
||||
|
||||
ReplSet.prototype.allRawConnections = function() {
|
||||
var connections = [];
|
||||
|
||||
for(var name in this._state.addresses) {
|
||||
connections = connections.concat(this._state.addresses[name].allRawConnections());
|
||||
}
|
||||
|
||||
return connections;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.allServerInstances = function() {
|
||||
var self = this;
|
||||
// If no state yet return empty
|
||||
if(!self._state) return [];
|
||||
// Close all the servers (concatenate entire list of servers first for ease)
|
||||
var allServers = self._state.master != null ? [self._state.master] : [];
|
||||
|
||||
// Secondary keys
|
||||
var keys = Object.keys(self._state.secondaries);
|
||||
// Add all secondaries
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
allServers.push(self._state.secondaries[keys[i]]);
|
||||
}
|
||||
|
||||
// Return complete list of all servers
|
||||
return allServers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
ReplSet.prototype.checkoutReader = function(readPreference, tags) {
|
||||
var connection = null;
|
||||
|
||||
// If we have a read preference object unpack it
|
||||
if(typeof readPreference == 'object' && readPreference['_type'] == 'ReadPreference') {
|
||||
// Validate if the object is using a valid mode
|
||||
if(!readPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + readPreference.mode);
|
||||
// Set the tag
|
||||
tags = readPreference.tags;
|
||||
readPreference = readPreference.mode;
|
||||
} else if(typeof readPreference == 'object' && readPreference['_type'] != 'ReadPreference') {
|
||||
return new Error("read preferences must be either a string or an instance of ReadPreference");
|
||||
}
|
||||
|
||||
// Set up our read Preference, allowing us to override the readPreference
|
||||
var finalReadPreference = readPreference != null ? readPreference : this.options.readPreference;
|
||||
|
||||
// Ensure we unpack a reference
|
||||
if(finalReadPreference != null && typeof finalReadPreference == 'object' && finalReadPreference['_type'] == 'ReadPreference') {
|
||||
// Validate if the object is using a valid mode
|
||||
if(!finalReadPreference.isValid()) throw new Error("Illegal readPreference mode specified, " + finalReadPreference.mode);
|
||||
// Set the tag
|
||||
tags = finalReadPreference.tags;
|
||||
readPreference = finalReadPreference.mode;
|
||||
}
|
||||
|
||||
// Finalize the read preference setup
|
||||
finalReadPreference = finalReadPreference == true ? ReadPreference.SECONDARY_PREFERRED : finalReadPreference;
|
||||
finalReadPreference = finalReadPreference == null ? ReadPreference.PRIMARY : finalReadPreference;
|
||||
|
||||
// If we are reading from a primary
|
||||
if(finalReadPreference == 'primary') {
|
||||
// If we provide a tags set send an error
|
||||
if(typeof tags == 'object' && tags != null) {
|
||||
return new Error("PRIMARY cannot be combined with tags");
|
||||
}
|
||||
|
||||
// If we provide a tags set send an error
|
||||
if(this._state.master == null) {
|
||||
return new Error("No replica set primary available for query with ReadPreference PRIMARY");
|
||||
}
|
||||
|
||||
// Checkout a writer
|
||||
return this.checkoutWriter();
|
||||
}
|
||||
|
||||
// If we have specified to read from a secondary server grab a random one and read
|
||||
// from it, otherwise just pass the primary connection
|
||||
if((this.options.readSecondary || finalReadPreference == ReadPreference.SECONDARY_PREFERRED || finalReadPreference == ReadPreference.SECONDARY) && Object.keys(this._state.secondaries).length > 0) {
|
||||
// If we have tags, look for servers matching the specific tag
|
||||
if(this.strategyInstance != null) {
|
||||
// Only pick from secondaries
|
||||
var _secondaries = [];
|
||||
for(var key in this._state.secondaries) {
|
||||
_secondaries.push(this._state.secondaries[key]);
|
||||
}
|
||||
|
||||
if(finalReadPreference == ReadPreference.SECONDARY) {
|
||||
// Check out the nearest from only the secondaries
|
||||
connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
|
||||
} else {
|
||||
connection = this.strategyInstance.checkoutConnection(tags, _secondaries);
|
||||
// No candidate servers that match the tags, error
|
||||
if(connection == null || connection instanceof Error) {
|
||||
// No secondary server avilable, attemp to checkout a primary server
|
||||
connection = this.checkoutWriter();
|
||||
// If no connection return an error
|
||||
if(connection == null || connection instanceof Error) {
|
||||
return new Error("No replica set members available for query");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(tags != null && typeof tags == 'object') {
|
||||
// Get connection
|
||||
connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
|
||||
// No candidate servers that match the tags, error
|
||||
if(connection == null) {
|
||||
return new Error("No replica set members available for query");
|
||||
}
|
||||
} else {
|
||||
connection = _roundRobin(this, tags);
|
||||
}
|
||||
} else if(finalReadPreference == ReadPreference.PRIMARY_PREFERRED) {
|
||||
// Check if there is a primary available and return that if possible
|
||||
connection = this.checkoutWriter();
|
||||
// If no connection available checkout a secondary
|
||||
if(connection == null || connection instanceof Error) {
|
||||
// If we have tags, look for servers matching the specific tag
|
||||
if(tags != null && typeof tags == 'object') {
|
||||
// Get connection
|
||||
connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
|
||||
// No candidate servers that match the tags, error
|
||||
if(connection == null) {
|
||||
return new Error("No replica set members available for query");
|
||||
}
|
||||
} else {
|
||||
connection = _roundRobin(this, tags);
|
||||
}
|
||||
}
|
||||
} else if(finalReadPreference == ReadPreference.SECONDARY_PREFERRED) {
|
||||
// If we have tags, look for servers matching the specific tag
|
||||
if(this.strategyInstance != null) {
|
||||
connection = this.strategyInstance.checkoutConnection(tags);
|
||||
|
||||
// No candidate servers that match the tags, error
|
||||
if(connection == null || connection instanceof Error) {
|
||||
// No secondary server avilable, attemp to checkout a primary server
|
||||
connection = this.checkoutWriter();
|
||||
// If no connection return an error
|
||||
if(connection == null || connection instanceof Error) {
|
||||
var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
|
||||
return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
|
||||
}
|
||||
}
|
||||
} else if(tags != null && typeof tags == 'object') {
|
||||
// Get connection
|
||||
connection = _pickFromTags(this, tags);// = function(self, readPreference, tags) {
|
||||
// No candidate servers that match the tags, error
|
||||
if(connection == null) {
|
||||
// No secondary server avilable, attemp to checkout a primary server
|
||||
connection = this.checkoutWriter();
|
||||
// If no connection return an error
|
||||
if(connection == null || connection instanceof Error) {
|
||||
var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
|
||||
return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance != null) {
|
||||
connection = this.strategyInstance.checkoutConnection(tags);
|
||||
} else if(finalReadPreference == ReadPreference.NEAREST && this.strategyInstance == null) {
|
||||
return new Error("A strategy for calculating nearness must be enabled such as ping or statistical");
|
||||
} else if(finalReadPreference == ReadPreference.SECONDARY && Object.keys(this._state.secondaries).length == 0) {
|
||||
if(tags != null && typeof tags == 'object') {
|
||||
var preferenceName = finalReadPreference == ReadPreference.SECONDARY ? 'secondary' : finalReadPreference;
|
||||
return new Error("No replica set member available for query with ReadPreference " + preferenceName + " and tags " + JSON.stringify(tags));
|
||||
} else {
|
||||
return new Error("No replica set secondary available for query with ReadPreference SECONDARY");
|
||||
}
|
||||
} else {
|
||||
connection = this.checkoutWriter();
|
||||
}
|
||||
|
||||
// Return the connection
|
||||
return connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
var _pickFromTags = function(self, tags) {
|
||||
// If we have an array or single tag selection
|
||||
var tagObjects = Array.isArray(tags) ? tags : [tags];
|
||||
// Iterate over all tags until we find a candidate server
|
||||
for(var _i = 0; _i < tagObjects.length; _i++) {
|
||||
// Grab a tag object
|
||||
var tagObject = tagObjects[_i];
|
||||
// Matching keys
|
||||
var matchingKeys = Object.keys(tagObject);
|
||||
// Match all the servers that match the provdided tags
|
||||
var keys = Object.keys(self._state.secondaries);
|
||||
var candidateServers = [];
|
||||
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
var server = self._state.secondaries[keys[i]];
|
||||
// If we have tags match
|
||||
if(server.tags != null) {
|
||||
var matching = true;
|
||||
// Ensure we have all the values
|
||||
for(var j = 0; j < matchingKeys.length; j++) {
|
||||
if(server.tags[matchingKeys[j]] != tagObject[matchingKeys[j]]) {
|
||||
matching = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a match add it to the list of matching servers
|
||||
if(matching) {
|
||||
candidateServers.push(server);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a candidate server return
|
||||
if(candidateServers.length > 0) {
|
||||
if(self.strategyInstance) return self.strategyInstance.checkoutConnection(tags, candidateServers);
|
||||
// Set instance to return
|
||||
return candidateServers[Math.floor(Math.random() * candidateServers.length)].checkoutReader();
|
||||
}
|
||||
}
|
||||
|
||||
// No connection found
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pick a secondary using round robin
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
function _roundRobin (replset, tags) {
|
||||
var keys = Object.keys(replset._state.secondaries);
|
||||
// Update index
|
||||
replset._currentServerChoice = replset._currentServerChoice + 1;
|
||||
// Pick a server
|
||||
var key = keys[replset._currentServerChoice % keys.length];
|
||||
|
||||
var conn = null != replset._state.secondaries[key]
|
||||
? replset._state.secondaries[key].checkoutReader()
|
||||
: null;
|
||||
|
||||
// If connection is null fallback to first available secondary
|
||||
if(null == conn) {
|
||||
conn = pickFirstConnectedSecondary(replset, tags);
|
||||
}
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
var pickFirstConnectedSecondary = function pickFirstConnectedSecondary(self, tags) {
|
||||
var keys = Object.keys(self._state.secondaries);
|
||||
var connection;
|
||||
|
||||
// Find first available reader if any
|
||||
for(var i = 0; i < keys.length; i++) {
|
||||
connection = self._state.secondaries[keys[i]].checkoutReader();
|
||||
if(connection) return connection;
|
||||
}
|
||||
|
||||
// If we still have a null, read from primary if it's not secondary only
|
||||
if(self._readPreference == ReadPreference.SECONDARY_PREFERRED) {
|
||||
connection = self._state.master.checkoutReader();
|
||||
if(connection) return connection;
|
||||
}
|
||||
|
||||
var preferenceName = self._readPreference == ReadPreference.SECONDARY_PREFERRED
|
||||
? 'secondary'
|
||||
: self._readPreference;
|
||||
|
||||
return new Error("No replica set member available for query with ReadPreference "
|
||||
+ preferenceName + " and tags " + JSON.stringify(tags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of secondaries
|
||||
* @ignore
|
||||
*/
|
||||
Object.defineProperty(ReplSet.prototype, "secondaries", {enumerable: true
|
||||
, get: function() {
|
||||
return utils.objectToArray(this._state.secondaries);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Get list of secondaries
|
||||
* @ignore
|
||||
*/
|
||||
Object.defineProperty(ReplSet.prototype, "arbiters", {enumerable: true
|
||||
, get: function() {
|
||||
return utils.objectToArray(this._state.arbiters);
|
||||
}
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user