arnaucube
arnaucube/thoughtsPublic Self-hosted repository
thoughts/node_modules/mongoose/lib/index.js
node_modules/mongoose/lib/index.jsRaw
  1'use strict';
  2
  3/*!
  4 * Module dependencies.
  5 */
  6
  7var Schema = require('./schema')
  8  , SchemaType = require('./schematype')
  9  , VirtualType = require('./virtualtype')
 10  , SchemaTypes = Schema.Types
 11  , SchemaDefaults = require('./schemadefault')
 12  , Types = require('./types')
 13  , Query = require('./query')
 14  , Promise = require('./promise')
 15  , Model = require('./model')
 16  , Document = require('./document')
 17  , utils = require('./utils')
 18  , format = utils.toCollectionName
 19  , mongodb = require('mongodb')
 20  , pkg = require('../package.json')
 21
 22/*!
 23 * Warn users if they are running an unstable release.
 24 *
 25 * Disable the warning by setting the MONGOOSE_DISABLE_STABILITY_WARNING
 26 * environment variable.
 27 */
 28
 29if (pkg.publishConfig && 'unstable' == pkg.publishConfig.tag) {
 30  if (!process.env.MONGOOSE_DISABLE_STABILITY_WARNING) {
 31    console.log('\u001b[33m');
 32    console.log('##############################################################');
 33    console.log('#');
 34    console.log('#   !!! MONGOOSE WARNING !!!');
 35    console.log('#');
 36    console.log('#   This is an UNSTABLE release of Mongoose.');
 37    console.log('#   Unstable releases are available for preview/testing only.');
 38    console.log('#   DO NOT run this in production.');
 39    console.log('#');
 40    console.log('##############################################################');
 41    console.log('\u001b[0m');
 42  }
 43}
 44
 45/**
 46 * Mongoose constructor.
 47 *
 48 * The exports object of the `mongoose` module is an instance of this class.
 49 * Most apps will only use this one instance.
 50 *
 51 * @api public
 52 */
 53
 54function Mongoose () {
 55  this.connections = [];
 56  this.plugins = [];
 57  this.models = {};
 58  this.modelSchemas = {};
 59  this.options = {};
 60  this.createConnection(); // default connection
 61};
 62
 63/**
 64 * Sets mongoose options
 65 *
 66 * ####Example:
 67 *
 68 *     mongoose.set('test', value) // sets the 'test' option to `value`
 69 *
 70 *     mongoose.set('debug', true) // enable logging collection methods + arguments to the console
 71 *
 72 * @param {String} key
 73 * @param {String} value
 74 * @api public
 75 */
 76
 77Mongoose.prototype.set = function (key, value) {
 78  if (arguments.length == 1)
 79    return this.options[key];
 80  this.options[key] = value;
 81  return this;
 82};
 83
 84/**
 85 * Gets mongoose options
 86 *
 87 * ####Example:
 88 *
 89 *     mongoose.get('test') // returns the 'test' value
 90 *
 91 * @param {String} key
 92 * @method get
 93 * @api public
 94 */
 95
 96Mongoose.prototype.get = Mongoose.prototype.set;
 97
 98/*!
 99 * ReplSet connection string check.
100 */
101
102var rgxReplSet = /^.+,.+$/;
103
104/**
105 * Creates a Connection instance.
106 *
107 * Each `connection` instance maps to a single database. This method is helpful when mangaging multiple db connections.
108 *
109 * 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.
110 *
111 * _Options passed take precedence over options included in connection strings._
112 *
113 * ####Example:
114 *
115 *     // with mongodb:// URI
116 *     db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
117 *
118 *     // and options
119 *     var opts = { db: { native_parser: true }}
120 *     db = mongoose.createConnection('mongodb://user:pass@localhost:port/database', opts);
121 *
122 *     // replica sets
123 *     db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port');
124 *
125 *     // and options
126 *     var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
127 *     db = mongoose.createConnection('mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port', opts);
128 *
129 *     // with [host, database_name[, port] signature
130 *     db = mongoose.createConnection('localhost', 'database', port)
131 *
132 *     // and options
133 *     var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
134 *     db = mongoose.createConnection('localhost', 'database', port, opts)
135 *
136 *     // initialize now, connect later
137 *     db = mongoose.createConnection();
138 *     db.open('localhost', 'database', port, [opts]);
139 *
140 * @param {String} [uri] a mongodb:// URI
141 * @param {Object} [options] options to pass to the driver
142 * @see Connection#open #connection_Connection-open
143 * @see Connection#openSet #connection_Connection-openSet
144 * @return {Connection} the created Connection object
145 * @api public
146 */
147
148Mongoose.prototype.createConnection = function () {
149  var conn = new Connection(this);
150  this.connections.push(conn);
151
152  if (arguments.length) {
153    if (rgxReplSet.test(arguments[0])) {
154      conn.openSet.apply(conn, arguments);
155    } else {
156      conn.open.apply(conn, arguments);
157    }
158  }
159
160  return conn;
161};
162
163/**
164 * Opens the default mongoose connection.
165 *
166 * If arguments are passed, they are proxied to either [Connection#open](#connection_Connection-open) or [Connection#openSet](#connection_Connection-openSet) appropriately.
167 *
168 * _Options passed take precedence over options included in connection strings._
169 *
170 * ####Example:
171 *
172 *     mongoose.connect('mongodb://user:pass@localhost:port/database');
173 *
174 *     // replica sets
175 *     var uri = 'mongodb://user:pass@localhost:port/database,mongodb://anotherhost:port,mongodb://yetanother:port';
176 *     mongoose.connect(uri);
177 *
178 *     // with options
179 *     mongoose.connect(uri, options);
180 *
181 *     // connecting to multiple mongos
182 *     var uri = 'mongodb://hostA:27501,hostB:27501';
183 *     var opts = { mongos: true };
184 *     mongoose.connect(uri, opts);
185 *
186 * @param {String} uri(s)
187 * @param {Object} [options]
188 * @param {Function} [callback]
189 * @see Mongoose#createConnection #index_Mongoose-createConnection
190 * @api public
191 * @return {Mongoose} this
192 */
193
194Mongoose.prototype.connect = function () {
195  var conn = this.connection;
196
197  if (rgxReplSet.test(arguments[0])) {
198    conn.openSet.apply(conn, arguments);
199  } else {
200    conn.open.apply(conn, arguments);
201  }
202
203  return this;
204};
205
206/**
207 * Disconnects all connections.
208 *
209 * @param {Function} [fn] called after all connection close.
210 * @return {Mongoose} this
211 * @api public
212 */
213
214Mongoose.prototype.disconnect = function (fn) {
215  var count = this.connections.length
216    , error
217
218  this.connections.forEach(function(conn){
219    conn.close(function(err){
220      if (error) return;
221
222      if (err) {
223        error = err;
224        if (fn) return fn(err);
225        throw err;
226      }
227
228      if (fn)
229        --count || fn();
230    });
231  });
232  return this;
233};
234
235/**
236 * Defines a model or retrieves it.
237 *
238 * Models defined on the `mongoose` instance are available to all connection created by the same `mongoose` instance.
239 *
240 * ####Example:
241 *
242 *     var mongoose = require('mongoose');
243 *
244 *     // define an Actor model with this mongoose instance
245 *     mongoose.model('Actor', new Schema({ name: String }));
246 *
247 *     // create a new connection
248 *     var conn = mongoose.createConnection(..);
249 *
250 *     // retrieve the Actor model
251 *     var Actor = conn.model('Actor');
252 *
253 * _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._
254 *
255 * ####Example:
256 *
257 *     var schema = new Schema({ name: String }, { collection: 'actor' });
258 *
259 *     // or
260 *
261 *     schema.set('collection', 'actor');
262 *
263 *     // or
264 *
265 *     var collectionName = 'actor'
266 *     var M = mongoose.model('Actor', schema, collectionName)
267 *
268 * @param {String} name model name
269 * @param {Schema} [schema]
270 * @param {String} [collection] name (optional, induced from model name)
271 * @param {Boolean} [skipInit] whether to skip initialization (defaults to false)
272 * @api public
273 */
274
275Mongoose.prototype.model = function (name, schema, collection, skipInit) {
276  if ('string' == typeof schema) {
277    collection = schema;
278    schema = false;
279  }
280
281  if (utils.isObject(schema) && !(schema instanceof Schema)) {
282    schema = new Schema(schema);
283  }
284
285  if ('boolean' === typeof collection) {
286    skipInit = collection;
287    collection = null;
288  }
289
290  // handle internal options from connection.model()
291  var options;
292  if (skipInit && utils.isObject(skipInit)) {
293    options = skipInit;
294    skipInit = true;
295  } else {
296    options = {};
297  }
298
299  // look up schema for the collection. this might be a
300  // default schema like system.indexes stored in SchemaDefaults.
301  if (!this.modelSchemas[name]) {
302    if (!schema && name in SchemaDefaults) {
303      schema = SchemaDefaults[name];
304    }
305
306    if (schema) {
307      // cache it so we only apply plugins once
308      this.modelSchemas[name] = schema;
309      this._applyPlugins(schema);
310    } else {
311      throw new mongoose.Error.MissingSchemaError(name);
312    }
313  }
314
315  var model;
316  var sub;
317
318  // connection.model() may be passing a different schema for
319  // an existing model name. in this case don't read from cache.
320  if (this.models[name] && false !== options.cache) {
321    if (schema instanceof Schema && schema != this.models[name].schema) {
322      throw new mongoose.Error.OverwriteModelError(name);
323    }
324
325    if (collection) {
326      // subclass current model with alternate collection
327      model = this.models[name];
328      schema = model.prototype.schema;
329      sub = model.__subclass(this.connection, schema, collection);
330      // do not cache the sub model
331      return sub;
332    }
333
334    return this.models[name];
335  }
336
337  // ensure a schema exists
338  if (!schema) {
339    schema = this.modelSchemas[name];
340    if (!schema) {
341      throw new mongoose.Error.MissingSchemaError(name);
342    }
343  }
344
345  if (!collection) {
346    collection = schema.get('collection') || format(name);
347  }
348
349  var connection = options.connection || this.connection;
350  model = Model.compile(name, schema, collection, connection, this);
351
352  if (!skipInit) {
353    model.init();
354  }
355
356  if (false === options.cache) {
357    return model;
358  }
359
360  return this.models[name] = model;
361}
362
363/**
364 * Returns an array of model names created on this instance of Mongoose.
365 *
366 * ####Note:
367 *
368 * _Does not include names of models created using `connection.model()`._
369 *
370 * @api public
371 * @return {Array}
372 */
373
374Mongoose.prototype.modelNames = function () {
375  var names = Object.keys(this.models);
376  return names;
377}
378
379/**
380 * Applies global plugins to `schema`.
381 *
382 * @param {Schema} schema
383 * @api private
384 */
385
386Mongoose.prototype._applyPlugins = function (schema) {
387  for (var i = 0, l = this.plugins.length; i < l; i++) {
388    schema.plugin(this.plugins[i][0], this.plugins[i][1]);
389  }
390}
391
392/**
393 * Declares a global plugin executed on all Schemas.
394 *
395 * Equivalent to calling `.plugin(fn)` on each Schema you create.
396 *
397 * @param {Function} fn plugin callback
398 * @param {Object} [opts] optional options
399 * @return {Mongoose} this
400 * @see plugins ./plugins.html
401 * @api public
402 */
403
404Mongoose.prototype.plugin = function (fn, opts) {
405  this.plugins.push([fn, opts]);
406  return this;
407};
408
409/**
410 * The default connection of the mongoose module.
411 *
412 * ####Example:
413 *
414 *     var mongoose = require('mongoose');
415 *     mongoose.connect(...);
416 *     mongoose.connection.on('error', cb);
417 *
418 * This is the connection used by default for every model created using [mongoose.model](#index_Mongoose-model).
419 *
420 * @property connection
421 * @return {Connection}
422 * @api public
423 */
424
425Mongoose.prototype.__defineGetter__('connection', function(){
426  return this.connections[0];
427});
428
429/*!
430 * Driver depentend APIs
431 */
432
433var driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
434
435/*!
436 * Connection
437 */
438
439var Connection = require(driver + '/connection');
440
441/*!
442 * Collection
443 */
444
445var Collection = require(driver + '/collection');
446
447/**
448 * The Mongoose Collection constructor
449 *
450 * @method Collection
451 * @api public
452 */
453
454Mongoose.prototype.Collection = Collection;
455
456/**
457 * The Mongoose [Connection](#connection_Connection) constructor
458 *
459 * @method Connection
460 * @api public
461 */
462
463Mongoose.prototype.Connection = Connection;
464
465/**
466 * The Mongoose version
467 *
468 * @property version
469 * @api public
470 */
471
472Mongoose.prototype.version = pkg.version;
473
474/**
475 * The Mongoose constructor
476 *
477 * The exports of the mongoose module is an instance of this class.
478 *
479 * ####Example:
480 *
481 *     var mongoose = require('mongoose');
482 *     var mongoose2 = new mongoose.Mongoose();
483 *
484 * @method Mongoose
485 * @api public
486 */
487
488Mongoose.prototype.Mongoose = Mongoose;
489
490/**
491 * The Mongoose [Schema](#schema_Schema) constructor
492 *
493 * ####Example:
494 *
495 *     var mongoose = require('mongoose');
496 *     var Schema = mongoose.Schema;
497 *     var CatSchema = new Schema(..);
498 *
499 * @method Schema
500 * @api public
501 */
502
503Mongoose.prototype.Schema = Schema;
504
505/**
506 * The Mongoose [SchemaType](#schematype_SchemaType) constructor
507 *
508 * @method SchemaType
509 * @api public
510 */
511
512Mongoose.prototype.SchemaType = SchemaType;
513
514/**
515 * The various Mongoose SchemaTypes.
516 *
517 * ####Note:
518 *
519 * _Alias of mongoose.Schema.Types for backwards compatibility._
520 *
521 * @property SchemaTypes
522 * @see Schema.SchemaTypes #schema_Schema.Types
523 * @api public
524 */
525
526Mongoose.prototype.SchemaTypes = Schema.Types;
527
528/**
529 * The Mongoose [VirtualType](#virtualtype_VirtualType) constructor
530 *
531 * @method VirtualType
532 * @api public
533 */
534
535Mongoose.prototype.VirtualType = VirtualType;
536
537/**
538 * The various Mongoose Types.
539 *
540 * ####Example:
541 *
542 *     var mongoose = require('mongoose');
543 *     var array = mongoose.Types.Array;
544 *
545 * ####Types:
546 *
547 * - [ObjectId](#types-objectid-js)
548 * - [Buffer](#types-buffer-js)
549 * - [SubDocument](#types-embedded-js)
550 * - [Array](#types-array-js)
551 * - [DocumentArray](#types-documentarray-js)
552 *
553 * Using this exposed access to the `ObjectId` type, we can construct ids on demand.
554 *
555 *     var ObjectId = mongoose.Types.ObjectId;
556 *     var id1 = new ObjectId;
557 *
558 * @property Types
559 * @api public
560 */
561
562Mongoose.prototype.Types = Types;
563
564/**
565 * The Mongoose [Query](#query_Query) constructor.
566 *
567 * @method Query
568 * @api public
569 */
570
571Mongoose.prototype.Query = Query;
572
573/**
574 * The Mongoose [Promise](#promise_Promise) constructor.
575 *
576 * @method Promise
577 * @api public
578 */
579
580Mongoose.prototype.Promise = Promise;
581
582/**
583 * The Mongoose [Model](#model_Model) constructor.
584 *
585 * @method Model
586 * @api public
587 */
588
589Mongoose.prototype.Model = Model;
590
591/**
592 * The Mongoose [Document](#document-js) constructor.
593 *
594 * @method Document
595 * @api public
596 */
597
598Mongoose.prototype.Document = Document;
599
600/**
601 * The [MongooseError](#error_MongooseError) constructor.
602 *
603 * @method Error
604 * @api public
605 */
606
607Mongoose.prototype.Error = require('./error');
608
609/**
610 * The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses.
611 *
612 * @property mongo
613 * @api public
614 */
615
616Mongoose.prototype.mongo = require('mongodb');
617
618/*!
619 * The exports object is an instance of Mongoose.
620 *
621 * @api public
622 */
623
624var mongoose = module.exports = exports = new Mongoose;