Cleanup
This commit is contained in:
61
node_modules/mongoose/lib/aggregate.js
generated
vendored
61
node_modules/mongoose/lib/aggregate.js
generated
vendored
@@ -7,7 +7,9 @@
|
||||
const AggregationCursor = require('./cursor/AggregationCursor');
|
||||
const Query = require('./query');
|
||||
const applyGlobalMaxTimeMS = require('./helpers/query/applyGlobalMaxTimeMS');
|
||||
const getConstructorName = require('./helpers/getConstructorName');
|
||||
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
||||
const stringifyFunctionOperators = require('./helpers/aggregate/stringifyFunctionOperators');
|
||||
const util = require('util');
|
||||
const utils = require('./utils');
|
||||
const read = Query.prototype.read;
|
||||
@@ -124,7 +126,7 @@ Aggregate.prototype.model = function(model) {
|
||||
* aggregate.append({ $project: { field: 1 }}, { $limit: 2 });
|
||||
*
|
||||
* // or pass an array
|
||||
* var pipeline = [{ $match: { daw: 'Logic Audio X' }} ];
|
||||
* const pipeline = [{ $match: { daw: 'Logic Audio X' }} ];
|
||||
* aggregate.append(pipeline);
|
||||
*
|
||||
* @param {Object} ops operator(s) to append
|
||||
@@ -470,7 +472,7 @@ Aggregate.prototype.sortByCount = function(arg) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends new custom $lookup operator(s) to this aggregate pipeline.
|
||||
* Appends new custom $lookup operator to this aggregate pipeline.
|
||||
*
|
||||
* ####Examples:
|
||||
*
|
||||
@@ -478,8 +480,7 @@ Aggregate.prototype.sortByCount = function(arg) {
|
||||
*
|
||||
* @see $lookup https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/#pipe._S_lookup
|
||||
* @param {Object} options to $lookup as described in the above link
|
||||
* @return {Aggregate}
|
||||
* @api public
|
||||
* @return {Aggregate}* @api public
|
||||
*/
|
||||
|
||||
Aggregate.prototype.lookup = function(options) {
|
||||
@@ -522,7 +523,7 @@ Aggregate.prototype.graphLookup = function(options) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Appends new custom $sample operator(s) to this aggregate pipeline.
|
||||
* Appends new custom $sample operator to this aggregate pipeline.
|
||||
*
|
||||
* ####Examples:
|
||||
*
|
||||
@@ -562,7 +563,7 @@ Aggregate.prototype.sort = function(arg) {
|
||||
|
||||
const sort = {};
|
||||
|
||||
if (arg.constructor.name === 'Object') {
|
||||
if (getConstructorName(arg) === 'Object') {
|
||||
const desc = ['desc', 'descending', -1];
|
||||
Object.keys(arg).forEach(function(field) {
|
||||
// If sorting by text score, skip coercing into 1/-1
|
||||
@@ -792,7 +793,7 @@ Aggregate.prototype.session = function(session) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option
|
||||
* const agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option
|
||||
* agg.options; // `{ allowDiskUse: true }`
|
||||
*
|
||||
* @param {Object} options keys to merge into current options
|
||||
@@ -819,7 +820,7 @@ Aggregate.prototype.option = function(value) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec();
|
||||
* const cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec();
|
||||
* cursor.eachAsync(function(doc, i) {
|
||||
* // use doc
|
||||
* });
|
||||
@@ -909,6 +910,32 @@ Aggregate.prototype.facet = function(options) {
|
||||
return this.append({ $facet: options });
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for [Atlas Text Search](https://docs.atlas.mongodb.com/reference/atlas-search/tutorial/)'s
|
||||
* `$search` stage.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* Model.aggregate().
|
||||
* search({
|
||||
* text: {
|
||||
* query: 'baseball',
|
||||
* path: 'plot'
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Output: [{ plot: '...', title: '...' }]
|
||||
*
|
||||
* @param {Object} $search options
|
||||
* @return {Aggregate} this
|
||||
* @see $search https://docs.atlas.mongodb.com/reference/atlas-search/tutorial/
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Aggregate.prototype.search = function(options) {
|
||||
return this.append({ $search: options });
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current pipeline
|
||||
*
|
||||
@@ -933,7 +960,7 @@ Aggregate.prototype.pipeline = function() {
|
||||
* aggregate.exec(callback);
|
||||
*
|
||||
* // Because a promise is returned, the `callback` is optional.
|
||||
* var promise = aggregate.exec();
|
||||
* const promise = aggregate.exec();
|
||||
* promise.then(..);
|
||||
*
|
||||
* @see Promise #promise_Promise
|
||||
@@ -956,8 +983,8 @@ Aggregate.prototype.exec = function(callback) {
|
||||
}
|
||||
|
||||
return promiseOrCallback(callback, cb => {
|
||||
|
||||
prepareDiscriminatorPipeline(this);
|
||||
stringifyFunctionOperators(this._pipeline);
|
||||
|
||||
model.hooks.execPre('aggregate', this, error => {
|
||||
if (error) {
|
||||
@@ -1027,7 +1054,7 @@ Aggregate.prototype.catch = function(reject) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an asyncIterator for use with [`for/await/of` loops](http://bit.ly/async-iterators)
|
||||
* Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js
|
||||
* You do not need to call this function explicitly, the JavaScript runtime
|
||||
* will call it for you.
|
||||
*
|
||||
@@ -1056,9 +1083,7 @@ if (Symbol.asyncIterator != null) {
|
||||
return this.cursor({ useMongooseAggCursor: true }).
|
||||
exec().
|
||||
transformNull().
|
||||
map(doc => {
|
||||
return doc == null ? { done: true } : { value: doc, done: false };
|
||||
});
|
||||
_transformForAsyncIterator();
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1114,6 +1139,14 @@ function prepareDiscriminatorPipeline(aggregate) {
|
||||
originalPipeline[0].$geoNear.query =
|
||||
originalPipeline[0].$geoNear.query || {};
|
||||
originalPipeline[0].$geoNear.query[discriminatorKey] = discriminatorValue;
|
||||
} else if (originalPipeline[0] && originalPipeline[0].$search) {
|
||||
if (originalPipeline[1] && originalPipeline[1].$match != null) {
|
||||
originalPipeline[1].$match[discriminatorKey] = originalPipeline[1].$match[discriminatorKey] || discriminatorValue;
|
||||
} else {
|
||||
const match = {};
|
||||
match[discriminatorKey] = discriminatorValue;
|
||||
originalPipeline.splice(1, 0, { $match: match });
|
||||
}
|
||||
} else {
|
||||
const match = {};
|
||||
match[discriminatorKey] = discriminatorValue;
|
||||
|
||||
27
node_modules/mongoose/lib/browser.js
generated
vendored
27
node_modules/mongoose/lib/browser.js
generated
vendored
@@ -48,9 +48,9 @@ exports.Error = require('./error/index');
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var Schema = mongoose.Schema;
|
||||
* var CatSchema = new Schema(..);
|
||||
* const mongoose = require('mongoose');
|
||||
* const Schema = mongoose.Schema;
|
||||
* const CatSchema = new Schema(..);
|
||||
*
|
||||
* @method Schema
|
||||
* @api public
|
||||
@@ -63,21 +63,24 @@ exports.Schema = require('./schema');
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var array = mongoose.Types.Array;
|
||||
* const mongoose = require('mongoose');
|
||||
* const 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)
|
||||
* - [Array](/docs/schematypes.html#arrays)
|
||||
* - [Buffer](/docs/schematypes.html#buffers)
|
||||
* - [Embedded](/docs/schematypes.html#schemas)
|
||||
* - [DocumentArray](/docs/api/documentarraypath.html)
|
||||
* - [Decimal128](/docs/api.html#mongoose_Mongoose-Decimal128)
|
||||
* - [ObjectId](/docs/schematypes.html#objectids)
|
||||
* - [Map](/docs/schematypes.html#maps)
|
||||
* - [Subdocument](/docs/schematypes.html#schemas)
|
||||
*
|
||||
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
|
||||
*
|
||||
* var ObjectId = mongoose.Types.ObjectId;
|
||||
* var id1 = new ObjectId;
|
||||
* const ObjectId = mongoose.Types.ObjectId;
|
||||
* const id1 = new ObjectId;
|
||||
*
|
||||
* @property Types
|
||||
* @api public
|
||||
|
||||
8
node_modules/mongoose/lib/cast.js
generated
vendored
8
node_modules/mongoose/lib/cast.js
generated
vendored
@@ -9,6 +9,8 @@ const StrictModeError = require('./error/strict');
|
||||
const Types = require('./schema/index');
|
||||
const castTextSearch = require('./schema/operators/text');
|
||||
const get = require('./helpers/get');
|
||||
const getConstructorName = require('./helpers/getConstructorName');
|
||||
const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
|
||||
const isOperator = require('./helpers/query/isOperator');
|
||||
const util = require('util');
|
||||
const isObject = require('./helpers/isObject');
|
||||
@@ -42,6 +44,10 @@ module.exports = function cast(schema, obj, options, context) {
|
||||
delete obj._bsontype;
|
||||
}
|
||||
|
||||
if (schema != null && schema.discriminators != null && obj[schema.options.discriminatorKey] != null) {
|
||||
schema = getSchemaDiscriminatorByValue(schema, obj[schema.options.discriminatorKey]) || schema;
|
||||
}
|
||||
|
||||
const paths = Object.keys(obj);
|
||||
let i = paths.length;
|
||||
let _keys;
|
||||
@@ -262,7 +268,7 @@ module.exports = function cast(schema, obj, options, context) {
|
||||
}
|
||||
} else if (val == null) {
|
||||
continue;
|
||||
} else if (val.constructor.name === 'Object') {
|
||||
} else if (getConstructorName(val) === 'Object') {
|
||||
any$conditionals = Object.keys(val).some(isOperator);
|
||||
|
||||
if (!any$conditionals) {
|
||||
|
||||
9
node_modules/mongoose/lib/cast/boolean.js
generated
vendored
9
node_modules/mongoose/lib/cast/boolean.js
generated
vendored
@@ -14,16 +14,17 @@ const CastError = require('../error/cast');
|
||||
*/
|
||||
|
||||
module.exports = function castBoolean(value, path) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (module.exports.convertToTrue.has(value)) {
|
||||
return true;
|
||||
}
|
||||
if (module.exports.convertToFalse.has(value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new CastError('boolean', value, path);
|
||||
};
|
||||
|
||||
|
||||
69
node_modules/mongoose/lib/collection.js
generated
vendored
69
node_modules/mongoose/lib/collection.js
generated
vendored
@@ -27,10 +27,6 @@ function Collection(name, conn, opts) {
|
||||
opts.capped = {};
|
||||
}
|
||||
|
||||
opts.bufferCommands = undefined === opts.bufferCommands
|
||||
? true
|
||||
: opts.bufferCommands;
|
||||
|
||||
if (typeof opts.capped === 'number') {
|
||||
opts.capped = { size: opts.capped };
|
||||
}
|
||||
@@ -40,7 +36,7 @@ function Collection(name, conn, opts) {
|
||||
this.collectionName = name;
|
||||
this.conn = conn;
|
||||
this.queue = [];
|
||||
this.buffer = this.opts.bufferCommands;
|
||||
this.buffer = true;
|
||||
this.emitter = new EventEmitter();
|
||||
|
||||
if (STATES.connected === this.conn.readyState) {
|
||||
@@ -93,7 +89,7 @@ Collection.prototype.onOpen = function() {
|
||||
*/
|
||||
|
||||
Collection.prototype.onClose = function(force) {
|
||||
if (this.opts.bufferCommands && !force) {
|
||||
if (this._shouldBufferCommands() && !force) {
|
||||
this.buffer = true;
|
||||
}
|
||||
};
|
||||
@@ -112,6 +108,23 @@ Collection.prototype.addQueue = function(name, args) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes a queued method
|
||||
*
|
||||
* @param {String} name name of the method to queue
|
||||
* @param {Array} args arguments to pass to the method when executed
|
||||
* @api private
|
||||
*/
|
||||
|
||||
Collection.prototype.removeQueue = function(name, args) {
|
||||
const index = this.queue.findIndex(v => v[0] === name && v[1] === args);
|
||||
if (index === -1) {
|
||||
return false;
|
||||
}
|
||||
this.queue.splice(index, 1);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes all queued methods and clears the queue.
|
||||
*
|
||||
@@ -128,7 +141,7 @@ Collection.prototype.doQueue = function() {
|
||||
}
|
||||
this.queue = [];
|
||||
const _this = this;
|
||||
process.nextTick(function() {
|
||||
immediate(function() {
|
||||
_this.emitter.emit('queue');
|
||||
});
|
||||
return this;
|
||||
@@ -147,7 +160,7 @@ Collection.prototype.ensureIndex = function() {
|
||||
*/
|
||||
|
||||
Collection.prototype.createIndex = function() {
|
||||
throw new Error('Collection#ensureIndex unimplemented by driver');
|
||||
throw new Error('Collection#createIndex unimplemented by driver');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -262,6 +275,46 @@ Collection.prototype.watch = function() {
|
||||
throw new Error('Collection#watch unimplemented by driver');
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
Collection.prototype._shouldBufferCommands = function _shouldBufferCommands() {
|
||||
const opts = this.opts;
|
||||
|
||||
if (opts.bufferCommands != null) {
|
||||
return opts.bufferCommands;
|
||||
}
|
||||
if (opts && opts.schemaUserProvidedOptions != null && opts.schemaUserProvidedOptions.bufferCommands != null) {
|
||||
return opts.schemaUserProvidedOptions.bufferCommands;
|
||||
}
|
||||
|
||||
return this.conn._shouldBufferCommands();
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
Collection.prototype._getBufferTimeoutMS = function _getBufferTimeoutMS() {
|
||||
const conn = this.conn;
|
||||
const opts = this.opts;
|
||||
|
||||
if (opts.bufferTimeoutMS != null) {
|
||||
return opts.bufferTimeoutMS;
|
||||
}
|
||||
if (opts && opts.schemaUserProvidedOptions != null && opts.schemaUserProvidedOptions.bufferTimeoutMS != null) {
|
||||
return opts.schemaUserProvidedOptions.bufferTimeoutMS;
|
||||
}
|
||||
if (conn.config.bufferTimeoutMS != null) {
|
||||
return conn.config.bufferTimeoutMS;
|
||||
}
|
||||
if (conn.base != null && conn.base.get('bufferTimeoutMS') != null) {
|
||||
return conn.base.get('bufferTimeoutMS');
|
||||
}
|
||||
return 10000;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
521
node_modules/mongoose/lib/connection.js
generated
vendored
521
node_modules/mongoose/lib/connection.js
generated
vendored
@@ -22,7 +22,8 @@ const utils = require('./utils');
|
||||
|
||||
const parseConnectionString = require('mongodb/lib/core').parseConnectionString;
|
||||
|
||||
let id = 0;
|
||||
const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
|
||||
const sessionNewDocuments = require('./helpers/symbols').sessionNewDocuments;
|
||||
|
||||
/*!
|
||||
* A list of authentication mechanisms that don't require a password for authentication.
|
||||
@@ -57,7 +58,7 @@ function Connection(base) {
|
||||
this.base = base;
|
||||
this.collections = {};
|
||||
this.models = {};
|
||||
this.config = { autoIndex: true };
|
||||
this.config = {};
|
||||
this.replica = false;
|
||||
this.options = null;
|
||||
this.otherDbs = []; // FIXME: To be replaced with relatedDbs
|
||||
@@ -67,7 +68,12 @@ function Connection(base) {
|
||||
this._closeCalled = false;
|
||||
this._hasOpened = false;
|
||||
this.plugins = [];
|
||||
this.id = id++;
|
||||
if (typeof base === 'undefined' || !base.connections.length) {
|
||||
this.id = 0;
|
||||
} else {
|
||||
this.id = base.connections.length;
|
||||
}
|
||||
this._queue = [];
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -113,11 +119,6 @@ Object.defineProperty(Connection.prototype, 'readyState', {
|
||||
db.readyState = val;
|
||||
}
|
||||
|
||||
// loop over relatedDbs on this connection and change their state
|
||||
for (const k in this.relatedDbs) {
|
||||
this.relatedDbs[k].readyState = val;
|
||||
}
|
||||
|
||||
if (STATES.connected === val) {
|
||||
this._hasOpened = true;
|
||||
}
|
||||
@@ -140,6 +141,10 @@ Object.defineProperty(Connection.prototype, 'readyState', {
|
||||
*/
|
||||
|
||||
Connection.prototype.get = function(key) {
|
||||
if (this.config.hasOwnProperty(key)) {
|
||||
return this.config[key];
|
||||
}
|
||||
|
||||
return get(this.options, key);
|
||||
};
|
||||
|
||||
@@ -164,6 +169,11 @@ Connection.prototype.get = function(key) {
|
||||
*/
|
||||
|
||||
Connection.prototype.set = function(key, val) {
|
||||
if (this.config.hasOwnProperty(key)) {
|
||||
this.config[key] = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
this.options = this.options || {};
|
||||
this.options[key] = val;
|
||||
return val;
|
||||
@@ -349,6 +359,18 @@ Object.defineProperty(Connection.prototype, 'pass', {
|
||||
|
||||
Connection.prototype.db;
|
||||
|
||||
/**
|
||||
* The MongoClient instance this connection uses to talk to MongoDB. Mongoose automatically sets this property
|
||||
* when the connection is opened.
|
||||
*
|
||||
* @property client
|
||||
* @memberOf Connection
|
||||
* @instance
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Connection.prototype.client;
|
||||
|
||||
/**
|
||||
* A hash of the global options that are associated with this connection
|
||||
*
|
||||
@@ -417,6 +439,77 @@ Connection.prototype.startSession = _wrapConnHelper(function startSession(option
|
||||
cb(null, session);
|
||||
});
|
||||
|
||||
/**
|
||||
* _Requires MongoDB >= 3.6.0._ Executes the wrapped async function
|
||||
* in a transaction. Mongoose will commit the transaction if the
|
||||
* async function executes successfully and attempt to retry if
|
||||
* there was a retriable error.
|
||||
*
|
||||
* Calls the MongoDB driver's [`session.withTransaction()`](http://mongodb.github.io/node-mongodb-native/3.5/api/ClientSession.html#withTransaction),
|
||||
* but also handles resetting Mongoose document state as shown below.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* const doc = new Person({ name: 'Will Riker' });
|
||||
* await db.transaction(async function setRank(session) {
|
||||
* doc.rank = 'Captain';
|
||||
* await doc.save({ session });
|
||||
* doc.isNew; // false
|
||||
*
|
||||
* // Throw an error to abort the transaction
|
||||
* throw new Error('Oops!');
|
||||
* },{ readPreference: 'primary' }).catch(() => {});
|
||||
*
|
||||
* // true, `transaction()` reset the document's state because the
|
||||
* // transaction was aborted.
|
||||
* doc.isNew;
|
||||
*
|
||||
* @method transaction
|
||||
* @param {Function} fn Function to execute in a transaction
|
||||
* @param {mongodb.TransactionOptions} [options] Optional settings for the transaction
|
||||
* @return {Promise<Any>} promise that is fulfilled if Mongoose successfully committed the transaction, or rejects if the transaction was aborted or if Mongoose failed to commit the transaction. If fulfilled, the promise resolves to a MongoDB command result.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Connection.prototype.transaction = function transaction(fn, options) {
|
||||
return this.startSession().then(session => {
|
||||
session[sessionNewDocuments] = new Map();
|
||||
return session.withTransaction(() => fn(session), options).
|
||||
then(res => {
|
||||
delete session[sessionNewDocuments];
|
||||
return res;
|
||||
}).
|
||||
catch(err => {
|
||||
// If transaction was aborted, we need to reset newly
|
||||
// inserted documents' `isNew`.
|
||||
for (const doc of session[sessionNewDocuments].keys()) {
|
||||
const state = session[sessionNewDocuments].get(doc);
|
||||
if (state.hasOwnProperty('isNew')) {
|
||||
doc.isNew = state.isNew;
|
||||
}
|
||||
if (state.hasOwnProperty('versionKey')) {
|
||||
doc.set(doc.schema.options.versionKey, state.versionKey);
|
||||
}
|
||||
|
||||
for (const path of state.modifiedPaths) {
|
||||
doc.$__.activePaths.paths[path] = 'modify';
|
||||
doc.$__.activePaths.states.modify[path] = true;
|
||||
}
|
||||
|
||||
for (const path of state.atomics.keys()) {
|
||||
const val = doc.$__getValue(path);
|
||||
if (val == null) {
|
||||
continue;
|
||||
}
|
||||
val[arrayAtomicsSymbol] = state.atomics.get(path);
|
||||
}
|
||||
}
|
||||
delete session[sessionNewDocuments];
|
||||
throw err;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for `dropCollection()`. Will delete the given collection, including
|
||||
* all documents and indexes.
|
||||
@@ -476,20 +569,36 @@ function _wrapConnHelper(fn) {
|
||||
// as long as `mongoose.connect()` is called on the same tick.
|
||||
// Re: gh-8534
|
||||
immediate(() => {
|
||||
if (this.readyState === STATES.connecting) {
|
||||
this.once('open', function() {
|
||||
fn.apply(this, argsWithoutCb.concat([cb]));
|
||||
});
|
||||
if (this.readyState === STATES.connecting && this._shouldBufferCommands()) {
|
||||
this._queue.push({ fn: fn, ctx: this, args: argsWithoutCb.concat([cb]) });
|
||||
} else if (this.readyState === STATES.disconnected && this.db == null) {
|
||||
cb(disconnectedError);
|
||||
} else {
|
||||
fn.apply(this, argsWithoutCb.concat([cb]));
|
||||
try {
|
||||
fn.apply(this, argsWithoutCb.concat([cb]));
|
||||
} catch (err) {
|
||||
return cb(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
Connection.prototype._shouldBufferCommands = function _shouldBufferCommands() {
|
||||
if (this.config.bufferCommands != null) {
|
||||
return this.config.bufferCommands;
|
||||
}
|
||||
if (this.base.get('bufferCommands') != null) {
|
||||
return this.base.get('bufferCommands');
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* error
|
||||
*
|
||||
@@ -521,6 +630,11 @@ Connection.prototype.error = function(err, callback) {
|
||||
Connection.prototype.onOpen = function() {
|
||||
this.readyState = STATES.connected;
|
||||
|
||||
for (const d of this._queue) {
|
||||
d.fn.apply(d.ctx, d.args);
|
||||
}
|
||||
this._queue = [];
|
||||
|
||||
// avoid having the collection subscribe to our event emitter
|
||||
// to prevent 0.3 warning
|
||||
for (const i in this.collections) {
|
||||
@@ -538,6 +652,7 @@ Connection.prototype.onOpen = function() {
|
||||
* @param {String} uri The URI to connect with.
|
||||
* @param {Object} [options] Passed on to http://mongodb.github.io/node-mongodb-native/2.2/api/MongoClient.html#connect
|
||||
* @param {Boolean} [options.bufferCommands=true] Mongoose specific option. Set to false to [disable buffering](http://mongoosejs.com/docs/faq.html#callback_never_executes) on all models associated with this connection.
|
||||
* @param {Number} [options.bufferTimeoutMS=10000] Mongoose specific option. If `bufferCommands` is true, Mongoose will throw an error after `bufferTimeoutMS` if the operation is still buffered.
|
||||
* @param {String} [options.dbName] The name of the database we want to use. If not provided, use database name from connection string.
|
||||
* @param {String} [options.user] username for authentication, equivalent to `options.auth.user`. Maintained for backwards compatibility.
|
||||
* @param {String} [options.pass] password for authentication, equivalent to `options.auth.password`. Maintained for backwards compatibility.
|
||||
@@ -547,25 +662,22 @@ Connection.prototype.onOpen = function() {
|
||||
* @param {Number} [options.heartbeatFrequencyMS] If `useUnifiedTopology = true`, the MongoDB driver sends a heartbeat every `heartbeatFrequencyMS` to check on the status of the connection. A heartbeat is subject to `serverSelectionTimeoutMS`, so the MongoDB driver will retry failed heartbeats for up to 30 seconds by default. Mongoose only emits a `'disconnected'` event after a heartbeat has failed, so you may want to decrease this setting to reduce the time between when your server goes down and when Mongoose emits `'disconnected'`. We recommend you do **not** set this setting below 1000, too many heartbeats can lead to performance degradation.
|
||||
* @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
|
||||
* @param {Boolean} [options.useNewUrlParser=false] False by default. Set to `true` to opt in to the MongoDB driver's new URL parser logic.
|
||||
* @param {Boolean} [options.useCreateIndex=true] Mongoose-specific option. If `true`, this connection will use [`createIndex()` instead of `ensureIndex()`](/docs/deprecations.html#ensureindex) for automatic index builds via [`Model.init()`](/docs/api.html#model_Model.init).
|
||||
* @param {Boolean} [options.useCreateIndex=false] Mongoose-specific option. If `true`, this connection will use [`createIndex()` instead of `ensureIndex()`](/docs/deprecations.html#ensureindex) for automatic index builds via [`Model.init()`](/docs/api.html#model_Model.init).
|
||||
* @param {Boolean} [options.useFindAndModify=true] True by default. Set to `false` to make `findOneAndUpdate()` and `findOneAndRemove()` use native `findOneAndUpdate()` rather than `findAndModify()`.
|
||||
* @param {Number} [options.reconnectTries=30] If you're connected to a single server or mongos proxy (as opposed to a replica set), the MongoDB driver will try to reconnect every `reconnectInterval` milliseconds for `reconnectTries` times, and give up afterward. When the driver gives up, the mongoose connection emits a `reconnectFailed` event. This option does nothing for replica set connections.
|
||||
* @param {Number} [options.reconnectInterval=1000] See `reconnectTries` option above.
|
||||
* @param {Class} [options.promiseLibrary] Sets the [underlying driver's promise library](http://mongodb.github.io/node-mongodb-native/3.1/api/MongoClient.html).
|
||||
* @param {Number} [options.poolSize=5] The maximum number of sockets the MongoDB driver will keep open for this connection. By default, `poolSize` is 5. Keep in mind that, as of MongoDB 3.4, MongoDB only allows one operation per socket at a time, so you may want to increase this if you find you have a few slow queries that are blocking faster queries from proceeding. See [Slow Trains in MongoDB and Node.js](http://thecodebarbarian.com/slow-trains-in-mongodb-and-nodejs).
|
||||
* @param {Number} [options.bufferMaxEntries] This option does nothing if `useUnifiedTopology` is set. The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set `bufferCommands` to `false` on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.
|
||||
* @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
|
||||
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
||||
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
||||
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
||||
* @param {Function} [callback]
|
||||
* @returns {Connection} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Connection.prototype.openUri = function(uri, options, callback) {
|
||||
this.readyState = STATES.connecting;
|
||||
this._closeCalled = false;
|
||||
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = null;
|
||||
@@ -590,11 +702,32 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
||||
typeof callback + '"');
|
||||
}
|
||||
|
||||
if (this.readyState === STATES.connecting || this.readyState === STATES.connected) {
|
||||
if (this._connectionString !== uri) {
|
||||
throw new MongooseError('Can\'t call `openUri()` on an active connection with ' +
|
||||
'different connection strings. Make sure you aren\'t calling `mongoose.connect()` ' +
|
||||
'multiple times. See: https://mongoosejs.com/docs/connections.html#multiple_connections');
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.$initialConnection = this.$initialConnection.then(
|
||||
() => callback(null, this),
|
||||
err => callback(err)
|
||||
);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
this._connectionString = uri;
|
||||
this.readyState = STATES.connecting;
|
||||
this._closeCalled = false;
|
||||
|
||||
const Promise = PromiseProvider.get();
|
||||
const _this = this;
|
||||
|
||||
if (options) {
|
||||
options = utils.clone(options);
|
||||
|
||||
const autoIndex = options.config && options.config.autoIndex != null ?
|
||||
options.config.autoIndex :
|
||||
options.autoIndex;
|
||||
@@ -631,7 +764,9 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
||||
delete options.pass;
|
||||
|
||||
if (options.bufferCommands != null) {
|
||||
options.bufferMaxEntries = 0;
|
||||
if (options.bufferMaxEntries == null) {
|
||||
options.bufferMaxEntries = 0;
|
||||
}
|
||||
this.config.bufferCommands = options.bufferCommands;
|
||||
delete options.bufferCommands;
|
||||
}
|
||||
@@ -694,132 +829,18 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
||||
});
|
||||
});
|
||||
|
||||
const _handleReconnect = () => {
|
||||
// If we aren't disconnected, we assume this reconnect is due to a
|
||||
// socket timeout. If there's no activity on a socket for
|
||||
// `socketTimeoutMS`, the driver will attempt to reconnect and emit
|
||||
// this event.
|
||||
if (_this.readyState !== STATES.connected) {
|
||||
_this.readyState = STATES.connected;
|
||||
_this.emit('reconnect');
|
||||
_this.emit('reconnected');
|
||||
}
|
||||
};
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const client = new mongodb.MongoClient(uri, options);
|
||||
_this.client = client;
|
||||
client.connect(function(error) {
|
||||
client.setMaxListeners(0);
|
||||
client.connect((error) => {
|
||||
if (error) {
|
||||
_this.readyState = STATES.disconnected;
|
||||
return reject(error);
|
||||
}
|
||||
|
||||
const db = dbName != null ? client.db(dbName) : client.db();
|
||||
_this.db = db;
|
||||
|
||||
// `useUnifiedTopology` events
|
||||
const type = get(db, 's.topology.s.description.type', '');
|
||||
if (options.useUnifiedTopology) {
|
||||
if (type === 'Single') {
|
||||
const server = Array.from(db.s.topology.s.servers.values())[0];
|
||||
|
||||
server.s.topology.on('serverHeartbeatSucceeded', () => {
|
||||
_handleReconnect();
|
||||
});
|
||||
server.s.pool.on('reconnect', () => {
|
||||
_handleReconnect();
|
||||
});
|
||||
client.on('serverDescriptionChanged', ev => {
|
||||
const newDescription = ev.newDescription;
|
||||
if (newDescription.type === 'Standalone') {
|
||||
_handleReconnect();
|
||||
} else {
|
||||
_this.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
} else if (type.startsWith('ReplicaSet')) {
|
||||
client.on('topologyDescriptionChanged', ev => {
|
||||
// Emit disconnected if we've lost connectivity to _all_ servers
|
||||
// in the replica set.
|
||||
const description = ev.newDescription;
|
||||
const servers = Array.from(ev.newDescription.servers.values());
|
||||
const allServersDisconnected = description.type === 'ReplicaSetNoPrimary' &&
|
||||
servers.reduce((cur, d) => cur || d.type === 'Unknown', false);
|
||||
if (_this.readyState === STATES.connected && allServersDisconnected) {
|
||||
// Implicitly emits 'disconnected'
|
||||
_this.readyState = STATES.disconnected;
|
||||
} else if (_this.readyState === STATES.disconnected && !allServersDisconnected) {
|
||||
_handleReconnect();
|
||||
}
|
||||
});
|
||||
|
||||
db.on('close', function() {
|
||||
const type = get(db, 's.topology.s.description.type', '');
|
||||
if (type !== 'ReplicaSetWithPrimary') {
|
||||
// Implicitly emits 'disconnected'
|
||||
_this.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Backwards compat for mongoose 4.x
|
||||
db.on('reconnect', function() {
|
||||
_handleReconnect();
|
||||
});
|
||||
db.s.topology.on('reconnectFailed', function() {
|
||||
_this.emit('reconnectFailed');
|
||||
});
|
||||
|
||||
if (!options.useUnifiedTopology) {
|
||||
db.s.topology.on('left', function(data) {
|
||||
_this.emit('left', data);
|
||||
});
|
||||
}
|
||||
db.s.topology.on('joined', function(data) {
|
||||
_this.emit('joined', data);
|
||||
});
|
||||
db.s.topology.on('fullsetup', function(data) {
|
||||
_this.emit('fullsetup', data);
|
||||
});
|
||||
if (get(db, 's.topology.s.coreTopology.s.pool') != null) {
|
||||
db.s.topology.s.coreTopology.s.pool.on('attemptReconnect', function() {
|
||||
_this.emit('attemptReconnect');
|
||||
});
|
||||
}
|
||||
if (!options.useUnifiedTopology || !type.startsWith('ReplicaSet')) {
|
||||
db.on('close', function() {
|
||||
// Implicitly emits 'disconnected'
|
||||
_this.readyState = STATES.disconnected;
|
||||
});
|
||||
}
|
||||
|
||||
if (!options.useUnifiedTopology) {
|
||||
client.on('left', function() {
|
||||
if (_this.readyState === STATES.connected &&
|
||||
get(db, 's.topology.s.coreTopology.s.replicaSetState.topologyType') === 'ReplicaSetNoPrimary') {
|
||||
_this.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
db.on('timeout', function() {
|
||||
_this.emit('timeout');
|
||||
});
|
||||
|
||||
delete _this.then;
|
||||
delete _this.catch;
|
||||
_this.readyState = STATES.connected;
|
||||
|
||||
for (const i in _this.collections) {
|
||||
if (utils.object.hasOwnProperty(_this.collections, i)) {
|
||||
_this.collections[i].onOpen();
|
||||
}
|
||||
}
|
||||
_setClient(_this, client, options, dbName);
|
||||
|
||||
resolve(_this);
|
||||
_this.emit('open');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -827,17 +848,22 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
||||
this.$initialConnection = Promise.all([promise, parsePromise]).
|
||||
then(res => res[0]).
|
||||
catch(err => {
|
||||
this.readyState = STATES.disconnected;
|
||||
if (err != null && err.name === 'MongoServerSelectionError') {
|
||||
err = serverSelectionError.assimilateError(err);
|
||||
}
|
||||
|
||||
if (this.listeners('error').length > 0) {
|
||||
process.nextTick(() => this.emit('error', err));
|
||||
immediate(() => this.emit('error', err));
|
||||
}
|
||||
throw err;
|
||||
});
|
||||
this.then = function(resolve, reject) {
|
||||
return this.$initialConnection.then(resolve, reject);
|
||||
return this.$initialConnection.then(() => {
|
||||
if (typeof resolve === 'function') {
|
||||
return resolve(_this);
|
||||
}
|
||||
}, reject);
|
||||
};
|
||||
this.catch = function(reject) {
|
||||
return this.$initialConnection.catch(reject);
|
||||
@@ -853,6 +879,126 @@ Connection.prototype.openUri = function(uri, options, callback) {
|
||||
return this;
|
||||
};
|
||||
|
||||
function _setClient(conn, client, options, dbName) {
|
||||
const db = dbName != null ? client.db(dbName) : client.db();
|
||||
conn.db = db;
|
||||
conn.client = client;
|
||||
conn._closeCalled = client._closeCalled;
|
||||
|
||||
const _handleReconnect = () => {
|
||||
// If we aren't disconnected, we assume this reconnect is due to a
|
||||
// socket timeout. If there's no activity on a socket for
|
||||
// `socketTimeoutMS`, the driver will attempt to reconnect and emit
|
||||
// this event.
|
||||
if (conn.readyState !== STATES.connected) {
|
||||
conn.readyState = STATES.connected;
|
||||
conn.emit('reconnect');
|
||||
conn.emit('reconnected');
|
||||
conn.onOpen();
|
||||
}
|
||||
};
|
||||
|
||||
// `useUnifiedTopology` events
|
||||
const type = get(db, 's.topology.s.description.type', '');
|
||||
if (options.useUnifiedTopology) {
|
||||
if (type === 'Single') {
|
||||
const server = Array.from(db.s.topology.s.servers.values())[0];
|
||||
server.s.topology.on('serverHeartbeatSucceeded', () => {
|
||||
_handleReconnect();
|
||||
});
|
||||
server.s.pool.on('reconnect', () => {
|
||||
_handleReconnect();
|
||||
});
|
||||
client.on('serverDescriptionChanged', ev => {
|
||||
const newDescription = ev.newDescription;
|
||||
if (newDescription.type === 'Standalone') {
|
||||
_handleReconnect();
|
||||
} else {
|
||||
conn.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
} else if (type.startsWith('ReplicaSet')) {
|
||||
client.on('topologyDescriptionChanged', ev => {
|
||||
// Emit disconnected if we've lost connectivity to _all_ servers
|
||||
// in the replica set.
|
||||
const description = ev.newDescription;
|
||||
const servers = Array.from(ev.newDescription.servers.values());
|
||||
const allServersDisconnected = description.type === 'ReplicaSetNoPrimary' &&
|
||||
servers.reduce((cur, d) => cur || d.type === 'Unknown', false);
|
||||
if (conn.readyState === STATES.connected && allServersDisconnected) {
|
||||
// Implicitly emits 'disconnected'
|
||||
conn.readyState = STATES.disconnected;
|
||||
} else if (conn.readyState === STATES.disconnected && !allServersDisconnected) {
|
||||
_handleReconnect();
|
||||
}
|
||||
});
|
||||
|
||||
client.on('close', function() {
|
||||
const type = get(db, 's.topology.s.description.type', '');
|
||||
if (type !== 'ReplicaSetWithPrimary') {
|
||||
// Implicitly emits 'disconnected'
|
||||
conn.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Backwards compat for mongoose 4.x
|
||||
db.s.topology.on('reconnectFailed', function() {
|
||||
conn.emit('reconnectFailed');
|
||||
});
|
||||
|
||||
if (!options.useUnifiedTopology) {
|
||||
client.on('reconnect', function() {
|
||||
_handleReconnect();
|
||||
});
|
||||
|
||||
db.s.topology.on('left', function(data) {
|
||||
conn.emit('left', data);
|
||||
});
|
||||
}
|
||||
db.s.topology.on('joined', function(data) {
|
||||
conn.emit('joined', data);
|
||||
});
|
||||
db.s.topology.on('fullsetup', function(data) {
|
||||
conn.emit('fullsetup', data);
|
||||
});
|
||||
if (get(db, 's.topology.s.coreTopology.s.pool') != null) {
|
||||
db.s.topology.s.coreTopology.s.pool.on('attemptReconnect', function() {
|
||||
conn.emit('attemptReconnect');
|
||||
});
|
||||
}
|
||||
if (!options.useUnifiedTopology) {
|
||||
client.on('close', function() {
|
||||
// Implicitly emits 'disconnected'
|
||||
conn.readyState = STATES.disconnected;
|
||||
});
|
||||
} else if (!type.startsWith('ReplicaSet')) {
|
||||
client.on('close', function() {
|
||||
// Implicitly emits 'disconnected'
|
||||
conn.readyState = STATES.disconnected;
|
||||
});
|
||||
}
|
||||
|
||||
if (!options.useUnifiedTopology) {
|
||||
client.on('left', function() {
|
||||
if (conn.readyState === STATES.connected &&
|
||||
get(db, 's.topology.s.coreTopology.s.replicaSetState.topologyType') === 'ReplicaSetNoPrimary') {
|
||||
conn.readyState = STATES.disconnected;
|
||||
}
|
||||
});
|
||||
|
||||
client.on('timeout', function() {
|
||||
conn.emit('timeout');
|
||||
});
|
||||
}
|
||||
|
||||
delete conn.then;
|
||||
delete conn.catch;
|
||||
|
||||
conn.onOpen();
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -896,11 +1042,25 @@ Connection.prototype.close = function(force, callback) {
|
||||
*/
|
||||
Connection.prototype._close = function(force, callback) {
|
||||
const _this = this;
|
||||
const closeCalled = this._closeCalled;
|
||||
this._closeCalled = true;
|
||||
if (this.client != null) {
|
||||
this.client._closeCalled = true;
|
||||
}
|
||||
|
||||
switch (this.readyState) {
|
||||
case STATES.disconnected:
|
||||
callback();
|
||||
if (closeCalled) {
|
||||
callback();
|
||||
} else {
|
||||
this.doClose(force, function(err) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
_this.onClose(force);
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
case STATES.connected:
|
||||
@@ -962,7 +1122,11 @@ Connection.prototype.onClose = function(force) {
|
||||
*/
|
||||
|
||||
Connection.prototype.collection = function(name, options) {
|
||||
options = options ? utils.clone(options) : {};
|
||||
const defaultOptions = {
|
||||
autoIndex: this.config.autoIndex != null ? this.config.autoIndex : this.base.options.autoIndex,
|
||||
autoCreate: this.config.autoCreate != null ? this.config.autoCreate : this.base.options.autoCreate
|
||||
};
|
||||
options = Object.assign({}, defaultOptions, options ? utils.clone(options) : {});
|
||||
options.$wasForceClosed = this.$wasForceClosed;
|
||||
if (!(name in this.collections)) {
|
||||
this.collections[name] = new Collection(name, this, options);
|
||||
@@ -997,17 +1161,17 @@ Connection.prototype.plugin = function(fn, opts) {
|
||||
/**
|
||||
* Defines or retrieves a model.
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var db = mongoose.createConnection(..);
|
||||
* const mongoose = require('mongoose');
|
||||
* const db = mongoose.createConnection(..);
|
||||
* db.model('Venue', new Schema(..));
|
||||
* var Ticket = db.model('Ticket', new Schema(..));
|
||||
* var Venue = db.model('Venue');
|
||||
* const Ticket = db.model('Ticket', new Schema(..));
|
||||
* const 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' });
|
||||
* const schema = new Schema({ name: String }, { collection: 'actor' });
|
||||
*
|
||||
* // or
|
||||
*
|
||||
@@ -1015,18 +1179,20 @@ Connection.prototype.plugin = function(fn, opts) {
|
||||
*
|
||||
* // or
|
||||
*
|
||||
* var collectionName = 'actor'
|
||||
* var M = conn.model('Actor', schema, collectionName)
|
||||
* const collectionName = 'actor'
|
||||
* const M = conn.model('Actor', schema, collectionName)
|
||||
*
|
||||
* @param {String|Function} name the model name or class extending Model
|
||||
* @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
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.overwriteModels=false] If true, overwrite existing models with the same name to avoid `OverwriteModelError`
|
||||
* @see Mongoose#model #index_Mongoose-model
|
||||
* @return {Model} The compiled model
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Connection.prototype.model = function(name, schema, collection) {
|
||||
Connection.prototype.model = function(name, schema, collection, options) {
|
||||
if (!(this instanceof Connection)) {
|
||||
throw new MongooseError('`connection.model()` should not be run with ' +
|
||||
'`new`. If you are doing `new db.model(foo)(bar)`, use ' +
|
||||
@@ -1053,7 +1219,9 @@ Connection.prototype.model = function(name, schema, collection) {
|
||||
'schema or a POJO');
|
||||
}
|
||||
|
||||
if (this.models[name] && !collection) {
|
||||
const defaultOptions = { cache: false, overwriteModels: this.base.options.overwriteModels };
|
||||
const opts = Object.assign(defaultOptions, options, { connection: this });
|
||||
if (this.models[name] && !collection && opts.overwriteModels !== true) {
|
||||
// model exists but we are not subclassing with custom collection
|
||||
if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
|
||||
throw new MongooseError.OverwriteModelError(name);
|
||||
@@ -1061,7 +1229,6 @@ Connection.prototype.model = function(name, schema, collection) {
|
||||
return this.models[name];
|
||||
}
|
||||
|
||||
const opts = { cache: false, connection: this };
|
||||
let model;
|
||||
|
||||
if (schema && schema.instanceOfSchema) {
|
||||
@@ -1146,6 +1313,8 @@ Connection.prototype.deleteModel = function(name) {
|
||||
delete this.models[name];
|
||||
delete this.collections[collectionName];
|
||||
delete this.base.modelSchemas[name];
|
||||
|
||||
this.emit('deleteModel', model);
|
||||
} else if (name instanceof RegExp) {
|
||||
const pattern = name;
|
||||
const names = this.modelNames();
|
||||
@@ -1267,6 +1436,57 @@ Connection.prototype.optionsProvideAuthenticationData = function(options) {
|
||||
((options.pass) || this.authMechanismDoesNotRequirePassword());
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the [MongoDB driver `MongoClient`](http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html) instance
|
||||
* that this connection uses to talk to MongoDB.
|
||||
*
|
||||
* ####Example:
|
||||
* const conn = await mongoose.createConnection('mongodb://localhost:27017/test');
|
||||
*
|
||||
* conn.getClient(); // MongoClient { ... }
|
||||
*
|
||||
* @api public
|
||||
* @return {MongoClient}
|
||||
*/
|
||||
|
||||
Connection.prototype.getClient = function getClient() {
|
||||
return this.client;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the [MongoDB driver `MongoClient`](http://mongodb.github.io/node-mongodb-native/3.5/api/MongoClient.html) instance
|
||||
* that this connection uses to talk to MongoDB. This is useful if you already have a MongoClient instance, and want to
|
||||
* reuse it.
|
||||
*
|
||||
* ####Example:
|
||||
* const client = await mongodb.MongoClient.connect('mongodb://localhost:27017/test');
|
||||
*
|
||||
* const conn = mongoose.createConnection().setClient(client);
|
||||
*
|
||||
* conn.getClient(); // MongoClient { ... }
|
||||
* conn.readyState; // 1, means 'CONNECTED'
|
||||
*
|
||||
* @api public
|
||||
* @return {Connection} this
|
||||
*/
|
||||
|
||||
Connection.prototype.setClient = function setClient(client) {
|
||||
if (!(client instanceof mongodb.MongoClient)) {
|
||||
throw new MongooseError('Must call `setClient()` with an instance of MongoClient');
|
||||
}
|
||||
if (this.client != null || this.readyState !== STATES.disconnected) {
|
||||
throw new MongooseError('Cannot call `setClient()` on a connection that is already connected.');
|
||||
}
|
||||
if (!client.isConnected()) {
|
||||
throw new MongooseError('Cannot call `setClient()` with a MongoClient that is not connected.');
|
||||
}
|
||||
|
||||
this._connectionString = client.s.url;
|
||||
_setClient(this, client, { useUnifiedTopology: client.s.options.useUnifiedTopology }, client.s.options.dbName);
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Switches to a different database using the same connection pool.
|
||||
*
|
||||
@@ -1277,6 +1497,7 @@ Connection.prototype.optionsProvideAuthenticationData = function(options) {
|
||||
* @param {String} name The database name
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.useCache=false] If true, cache results so calling `useDb()` multiple times with the same name only creates 1 connection object.
|
||||
* @param {Boolean} [options.noListener=false] If true, the connection object will not make the db listen to events on the original connection. See [issue #9961](https://github.com/Automattic/mongoose/issues/9961).
|
||||
* @return {Connection} New Connection Object
|
||||
* @api public
|
||||
*/
|
||||
|
||||
84
node_modules/mongoose/lib/cursor/AggregationCursor.js
generated
vendored
84
node_modules/mongoose/lib/cursor/AggregationCursor.js
generated
vendored
@@ -8,7 +8,9 @@ const MongooseError = require('../error/mongooseError');
|
||||
const Readable = require('stream').Readable;
|
||||
const promiseOrCallback = require('../helpers/promiseOrCallback');
|
||||
const eachAsync = require('../helpers/cursor/eachAsync');
|
||||
const immediate = require('../helpers/immediate');
|
||||
const util = require('util');
|
||||
const utils = require('../../lib/utils');
|
||||
|
||||
/**
|
||||
* An AggregationCursor is a concurrency primitive for processing aggregation
|
||||
@@ -35,7 +37,14 @@ const util = require('util');
|
||||
*/
|
||||
|
||||
function AggregationCursor(agg) {
|
||||
Readable.call(this, { objectMode: true });
|
||||
const streamOpts = { objectMode: true };
|
||||
// for node < 12 we will emit 'close' event after 'end'
|
||||
if (utils.nodeMajorVersion() >= 12) {
|
||||
// set autoDestroy=true because on node 12 it's by default false
|
||||
// gh-10902 need autoDestroy to destroy correctly and emit 'close' event for node >= 12
|
||||
streamOpts.autoDestroy = true;
|
||||
}
|
||||
Readable.call(this, streamOpts);
|
||||
|
||||
this.cursor = null;
|
||||
this.agg = agg;
|
||||
@@ -85,13 +94,10 @@ AggregationCursor.prototype._read = function() {
|
||||
if (error) {
|
||||
return _this.emit('error', error);
|
||||
}
|
||||
setTimeout(function() {
|
||||
// on node >= 14 streams close automatically (gh-8834)
|
||||
const isNotClosedAutomatically = !_this.destroyed;
|
||||
if (isNotClosedAutomatically) {
|
||||
_this.emit('close');
|
||||
}
|
||||
}, 0);
|
||||
// for node >= 12 the autoDestroy will emit the 'close' event
|
||||
if (utils.nodeMajorVersion() < 12) {
|
||||
_this.on('end', () => _this.emit('close'));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -125,7 +131,7 @@ if (Symbol.asyncIterator != null) {
|
||||
* on('data', function(doc) { console.log(doc.foo); });
|
||||
*
|
||||
* // Or map documents returned by `.next()`
|
||||
* var cursor = Thing.find({ name: /^hello/ }).
|
||||
* const cursor = Thing.find({ name: /^hello/ }).
|
||||
* cursor().
|
||||
* map(function (doc) {
|
||||
* doc.foo = "bar";
|
||||
@@ -221,6 +227,56 @@ AggregationCursor.prototype.eachAsync = function(fn, opts, callback) {
|
||||
return eachAsync(function(cb) { return _next(_this, cb); }, fn, opts, callback);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js
|
||||
* You do not need to call this function explicitly, the JavaScript runtime
|
||||
* will call it for you.
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* // Async iterator without explicitly calling `cursor()`. Mongoose still
|
||||
* // creates an AggregationCursor instance internally.
|
||||
* const agg = Model.aggregate([{ $match: { age: { $gte: 25 } } }]);
|
||||
* for await (const doc of agg) {
|
||||
* console.log(doc.name);
|
||||
* }
|
||||
*
|
||||
* // You can also use an AggregationCursor instance for async iteration
|
||||
* const cursor = Model.aggregate([{ $match: { age: { $gte: 25 } } }]).cursor();
|
||||
* for await (const doc of cursor) {
|
||||
* console.log(doc.name);
|
||||
* }
|
||||
*
|
||||
* Node.js 10.x supports async iterators natively without any flags. You can
|
||||
* enable async iterators in Node.js 8.x using the [`--harmony_async_iteration` flag](https://github.com/tc39/proposal-async-iteration/issues/117#issuecomment-346695187).
|
||||
*
|
||||
* **Note:** This function is not set if `Symbol.asyncIterator` is undefined. If
|
||||
* `Symbol.asyncIterator` is undefined, that means your Node.js version does not
|
||||
* support async iterators.
|
||||
*
|
||||
* @method Symbol.asyncIterator
|
||||
* @memberOf AggregationCursor
|
||||
* @instance
|
||||
* @api public
|
||||
*/
|
||||
|
||||
if (Symbol.asyncIterator != null) {
|
||||
AggregationCursor.prototype[Symbol.asyncIterator] = function() {
|
||||
return this.transformNull()._transformForAsyncIterator();
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
AggregationCursor.prototype._transformForAsyncIterator = function() {
|
||||
if (this._transforms.indexOf(_transformForAsyncIterator) === -1) {
|
||||
this.map(_transformForAsyncIterator);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -233,6 +289,14 @@ AggregationCursor.prototype.transformNull = function(val) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function _transformForAsyncIterator(doc) {
|
||||
return doc == null ? { done: true } : { value: doc, done: false };
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a [cursor flag](http://mongodb.github.io/node-mongodb-native/2.2/api/Cursor.html#addCursorFlag).
|
||||
* Useful for setting the `noCursorTimeout` and `tailable` flags.
|
||||
@@ -284,7 +348,7 @@ function _next(ctx, cb) {
|
||||
}
|
||||
|
||||
if (ctx._error) {
|
||||
return process.nextTick(function() {
|
||||
return immediate(function() {
|
||||
callback(ctx._error);
|
||||
});
|
||||
}
|
||||
|
||||
235
node_modules/mongoose/lib/cursor/QueryCursor.js
generated
vendored
235
node_modules/mongoose/lib/cursor/QueryCursor.js
generated
vendored
@@ -8,7 +8,9 @@ const Readable = require('stream').Readable;
|
||||
const promiseOrCallback = require('../helpers/promiseOrCallback');
|
||||
const eachAsync = require('../helpers/cursor/eachAsync');
|
||||
const helpers = require('../queryhelpers');
|
||||
const immediate = require('../helpers/immediate');
|
||||
const util = require('util');
|
||||
const utils = require('../../lib/utils');
|
||||
|
||||
/**
|
||||
* A QueryCursor is a concurrency primitive for processing query results
|
||||
@@ -16,8 +18,8 @@ const util = require('util');
|
||||
* in addition to several other mechanisms for loading documents from MongoDB
|
||||
* one at a time.
|
||||
*
|
||||
* QueryCursors execute the model's pre find hooks, but **not** the model's
|
||||
* post find hooks.
|
||||
* QueryCursors execute the model's pre `find` hooks before loading any documents
|
||||
* from MongoDB, and the model's post `find` hooks after loading each document.
|
||||
*
|
||||
* Unless you're an advanced user, do **not** instantiate this class directly.
|
||||
* Use [`Query#cursor()`](/docs/api.html#query_Query-cursor) instead.
|
||||
@@ -33,7 +35,14 @@ const util = require('util');
|
||||
*/
|
||||
|
||||
function QueryCursor(query, options) {
|
||||
Readable.call(this, { objectMode: true });
|
||||
const streamOpts = { objectMode: true };
|
||||
// for node < 12 we will emit 'close' event after 'end'
|
||||
if (utils.nodeMajorVersion() >= 12) {
|
||||
// set autoDestroy=true because on node 12 it's by default false
|
||||
// gh-10902 need autoDestroy to destroy correctly and emit 'close' event for node >= 12
|
||||
streamOpts.autoDestroy = true;
|
||||
}
|
||||
Readable.call(this, streamOpts);
|
||||
|
||||
this.cursor = null;
|
||||
this.query = query;
|
||||
@@ -54,11 +63,18 @@ function QueryCursor(query, options) {
|
||||
if (this.options.batchSize) {
|
||||
this.options.cursor = options.cursor || {};
|
||||
this.options.cursor.batchSize = options.batchSize;
|
||||
|
||||
// Max out the number of documents we'll populate in parallel at 5000.
|
||||
this.options._populateBatchSize = Math.min(this.options.batchSize, 5000);
|
||||
}
|
||||
model.collection.find(query._conditions, this.options, function(err, cursor) {
|
||||
if (_this._error) {
|
||||
cursor.close(function() {});
|
||||
if (cursor != null) {
|
||||
cursor.close(function() {});
|
||||
}
|
||||
_this.emit('cursor', null);
|
||||
_this.listeners('error').length > 0 && _this.emit('error', _this._error);
|
||||
return;
|
||||
}
|
||||
if (err) {
|
||||
return _this.emit('error', err);
|
||||
@@ -87,13 +103,10 @@ QueryCursor.prototype._read = function() {
|
||||
if (error) {
|
||||
return _this.emit('error', error);
|
||||
}
|
||||
setTimeout(function() {
|
||||
// on node >= 14 streams close automatically (gh-8834)
|
||||
const isNotClosedAutomatically = !_this.destroyed;
|
||||
if (isNotClosedAutomatically) {
|
||||
_this.emit('close');
|
||||
}
|
||||
}, 0);
|
||||
// for node >= 12 the autoDestroy will emit the 'close' event
|
||||
if (utils.nodeMajorVersion() < 12) {
|
||||
_this.on('end', () => _this.emit('close'));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -118,7 +131,7 @@ QueryCursor.prototype._read = function() {
|
||||
* on('data', function(doc) { console.log(doc.foo); });
|
||||
*
|
||||
* // Or map documents returned by `.next()`
|
||||
* var cursor = Thing.find({ name: /^hello/ }).
|
||||
* const cursor = Thing.find({ name: /^hello/ }).
|
||||
* cursor().
|
||||
* map(function (doc) {
|
||||
* doc.foo = "bar";
|
||||
@@ -270,6 +283,61 @@ QueryCursor.prototype.transformNull = function(val) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
QueryCursor.prototype._transformForAsyncIterator = function() {
|
||||
if (this._transforms.indexOf(_transformForAsyncIterator) === -1) {
|
||||
this.map(_transformForAsyncIterator);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js).
|
||||
* You do not need to call this function explicitly, the JavaScript runtime
|
||||
* will call it for you.
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* // Works without using `cursor()`
|
||||
* for await (const doc of Model.find([{ $sort: { name: 1 } }])) {
|
||||
* console.log(doc.name);
|
||||
* }
|
||||
*
|
||||
* // Can also use `cursor()`
|
||||
* for await (const doc of Model.find([{ $sort: { name: 1 } }]).cursor()) {
|
||||
* console.log(doc.name);
|
||||
* }
|
||||
*
|
||||
* Node.js 10.x supports async iterators natively without any flags. You can
|
||||
* enable async iterators in Node.js 8.x using the [`--harmony_async_iteration` flag](https://github.com/tc39/proposal-async-iteration/issues/117#issuecomment-346695187).
|
||||
*
|
||||
* **Note:** This function is not if `Symbol.asyncIterator` is undefined. If
|
||||
* `Symbol.asyncIterator` is undefined, that means your Node.js version does not
|
||||
* support async iterators.
|
||||
*
|
||||
* @method Symbol.asyncIterator
|
||||
* @memberOf Query
|
||||
* @instance
|
||||
* @api public
|
||||
*/
|
||||
|
||||
if (Symbol.asyncIterator != null) {
|
||||
QueryCursor.prototype[Symbol.asyncIterator] = function() {
|
||||
return this.transformNull()._transformForAsyncIterator();
|
||||
};
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function _transformForAsyncIterator(doc) {
|
||||
return doc == null ? { done: true } : { value: doc, done: false };
|
||||
}
|
||||
|
||||
/*!
|
||||
* Get the next doc from the underlying cursor and mongooseify it
|
||||
* (populate, etc.)
|
||||
@@ -289,46 +357,132 @@ function _next(ctx, cb) {
|
||||
}
|
||||
|
||||
if (ctx._error) {
|
||||
return process.nextTick(function() {
|
||||
return immediate(function() {
|
||||
callback(ctx._error);
|
||||
});
|
||||
}
|
||||
|
||||
if (ctx.cursor) {
|
||||
return ctx.cursor.next(function(error, doc) {
|
||||
if (error) {
|
||||
return callback(error);
|
||||
}
|
||||
if (!doc) {
|
||||
return callback(null, null);
|
||||
}
|
||||
|
||||
const opts = ctx.query._mongooseOptions;
|
||||
if (!opts.populate) {
|
||||
return opts.lean ?
|
||||
callback(null, doc) :
|
||||
_create(ctx, doc, null, callback);
|
||||
}
|
||||
|
||||
const pop = helpers.preparePopulationOptionsMQ(ctx.query,
|
||||
if (ctx.query._mongooseOptions.populate && !ctx._pop) {
|
||||
ctx._pop = helpers.preparePopulationOptionsMQ(ctx.query,
|
||||
ctx.query._mongooseOptions);
|
||||
pop.__noPromise = true;
|
||||
ctx.query.model.populate(doc, pop, function(err, doc) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
ctx._pop.__noPromise = true;
|
||||
}
|
||||
if (ctx.query._mongooseOptions.populate && ctx.options._populateBatchSize > 1) {
|
||||
if (ctx._batchDocs && ctx._batchDocs.length) {
|
||||
// Return a cached populated doc
|
||||
return _nextDoc(ctx, ctx._batchDocs.shift(), ctx._pop, callback);
|
||||
} else if (ctx._batchExhausted) {
|
||||
// Internal cursor reported no more docs. Act the same here
|
||||
return callback(null, null);
|
||||
} else {
|
||||
// Request as many docs as batchSize, to populate them also in batch
|
||||
ctx._batchDocs = [];
|
||||
return ctx.cursor.next(_onNext.bind({ ctx, callback }));
|
||||
}
|
||||
} else {
|
||||
return ctx.cursor.next(function(error, doc) {
|
||||
if (error) {
|
||||
return callback(error);
|
||||
}
|
||||
return opts.lean ?
|
||||
callback(null, doc) :
|
||||
_create(ctx, doc, pop, callback);
|
||||
if (!doc) {
|
||||
return callback(null, null);
|
||||
}
|
||||
|
||||
if (!ctx.query._mongooseOptions.populate) {
|
||||
return _nextDoc(ctx, doc, null, callback);
|
||||
}
|
||||
|
||||
ctx.query.model.populate(doc, ctx._pop, function(err, doc) {
|
||||
if (err) {
|
||||
return callback(err);
|
||||
}
|
||||
return _nextDoc(ctx, doc, ctx._pop, callback);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
ctx.once('cursor', function() {
|
||||
ctx.once('cursor', function(cursor) {
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
_next(ctx, cb);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function _onNext(error, doc) {
|
||||
if (error) {
|
||||
return this.callback(error);
|
||||
}
|
||||
if (!doc) {
|
||||
this.ctx._batchExhausted = true;
|
||||
return _populateBatch.call(this);
|
||||
}
|
||||
|
||||
this.ctx._batchDocs.push(doc);
|
||||
|
||||
if (this.ctx._batchDocs.length < this.ctx.options._populateBatchSize) {
|
||||
// If both `batchSize` and `_populateBatchSize` are huge, calling `next()` repeatedly may
|
||||
// cause a stack overflow. So make sure we clear the stack regularly.
|
||||
if (this.ctx._batchDocs.length > 0 && this.ctx._batchDocs.length % 1000 === 0) {
|
||||
return immediate(() => this.ctx.cursor.next(_onNext.bind(this)));
|
||||
}
|
||||
this.ctx.cursor.next(_onNext.bind(this));
|
||||
} else {
|
||||
_populateBatch.call(this);
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function _populateBatch() {
|
||||
if (!this.ctx._batchDocs.length) {
|
||||
return this.callback(null, null);
|
||||
}
|
||||
const _this = this;
|
||||
this.ctx.query.model.populate(this.ctx._batchDocs, this.ctx._pop, function(err) {
|
||||
if (err) {
|
||||
return _this.callback(err);
|
||||
}
|
||||
|
||||
_nextDoc(_this.ctx, _this.ctx._batchDocs.shift(), _this.ctx._pop, _this.callback);
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function _nextDoc(ctx, doc, pop, callback) {
|
||||
if (ctx.query._mongooseOptions.lean) {
|
||||
return ctx.model.hooks.execPost('find', ctx.query, [[doc]], err => {
|
||||
if (err != null) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, doc);
|
||||
});
|
||||
}
|
||||
|
||||
_create(ctx, doc, pop, (err, doc) => {
|
||||
if (err != null) {
|
||||
return callback(err);
|
||||
}
|
||||
ctx.model.hooks.execPost('find', ctx.query, [[doc]], err => {
|
||||
if (err != null) {
|
||||
return callback(err);
|
||||
}
|
||||
callback(null, doc);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -337,7 +491,10 @@ function _waitForCursor(ctx, cb) {
|
||||
if (ctx.cursor) {
|
||||
return cb();
|
||||
}
|
||||
ctx.once('cursor', function() {
|
||||
ctx.once('cursor', function(cursor) {
|
||||
if (cursor == null) {
|
||||
return;
|
||||
}
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
1154
node_modules/mongoose/lib/document.js
generated
vendored
1154
node_modules/mongoose/lib/document.js
generated
vendored
File diff suppressed because it is too large
Load Diff
3
node_modules/mongoose/lib/drivers/browser/index.js
generated
vendored
3
node_modules/mongoose/lib/drivers/browser/index.js
generated
vendored
@@ -8,6 +8,9 @@ exports.Binary = require('./binary');
|
||||
exports.Collection = function() {
|
||||
throw new Error('Cannot create a collection from browser library');
|
||||
};
|
||||
exports.getConnection = () => function() {
|
||||
throw new Error('Cannot create a connection from browser library');
|
||||
};
|
||||
exports.Decimal128 = require('./decimal128');
|
||||
exports.ObjectId = require('./objectid');
|
||||
exports.ReadPreference = require('./ReadPreference');
|
||||
|
||||
160
node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
generated
vendored
160
node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
generated
vendored
@@ -7,7 +7,9 @@
|
||||
const MongooseCollection = require('../../collection');
|
||||
const MongooseError = require('../../error/mongooseError');
|
||||
const Collection = require('mongodb').Collection;
|
||||
const ObjectId = require('./objectid');
|
||||
const get = require('../../helpers/get');
|
||||
const getConstructorName = require('../../helpers/getConstructorName');
|
||||
const sliced = require('sliced');
|
||||
const stream = require('stream');
|
||||
const util = require('util');
|
||||
@@ -21,9 +23,11 @@ const util = require('util');
|
||||
* @api private
|
||||
*/
|
||||
|
||||
function NativeCollection(name, options) {
|
||||
function NativeCollection(name, conn, options) {
|
||||
this.collection = null;
|
||||
this.Promise = options.Promise || Promise;
|
||||
this.modelName = options.modelName;
|
||||
delete options.modelName;
|
||||
this._closed = false;
|
||||
MongooseCollection.apply(this, arguments);
|
||||
}
|
||||
@@ -54,6 +58,7 @@ NativeCollection.prototype.onOpen = function() {
|
||||
|
||||
if (_this.opts.autoCreate === false) {
|
||||
_this.collection = _this.conn.db.collection(_this.name);
|
||||
MongooseCollection.prototype.onOpen.call(_this);
|
||||
return _this.collection;
|
||||
}
|
||||
|
||||
@@ -127,6 +132,7 @@ function iter(i) {
|
||||
const _this = this;
|
||||
const debug = get(_this, 'conn.base.options.debug');
|
||||
const lastArg = arguments[arguments.length - 1];
|
||||
const opId = new ObjectId();
|
||||
|
||||
// If user force closed, queueing will hang forever. See #5664
|
||||
if (this.conn.$wasForceClosed) {
|
||||
@@ -140,22 +146,77 @@ function iter(i) {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.buffer) {
|
||||
let _args = args;
|
||||
let callback = null;
|
||||
if (this._shouldBufferCommands() && this.buffer) {
|
||||
if (syncCollectionMethods[i]) {
|
||||
throw new Error('Collection method ' + i + ' is synchronous');
|
||||
}
|
||||
|
||||
this.conn.emit('buffer', {
|
||||
_id: opId,
|
||||
modelName: _this.modelName,
|
||||
collectionName: _this.name,
|
||||
method: i,
|
||||
args: args
|
||||
});
|
||||
|
||||
let callback;
|
||||
let _args;
|
||||
let promise = null;
|
||||
let timeout = null;
|
||||
if (typeof lastArg === 'function') {
|
||||
this.addQueue(i, args);
|
||||
callback = function collectionOperationCallback() {
|
||||
if (timeout != null) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
return lastArg.apply(this, arguments);
|
||||
};
|
||||
_args = args.slice(0, args.length - 1).concat([callback]);
|
||||
} else {
|
||||
promise = new this.Promise((resolve, reject) => {
|
||||
callback = function collectionOperationCallback(err, res) {
|
||||
if (timeout != null) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
if (err != null) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(res);
|
||||
};
|
||||
_args = args.concat([callback]);
|
||||
this.addQueue(i, _args);
|
||||
});
|
||||
}
|
||||
|
||||
const bufferTimeoutMS = this._getBufferTimeoutMS();
|
||||
timeout = setTimeout(() => {
|
||||
const removed = this.removeQueue(i, _args);
|
||||
if (removed) {
|
||||
const message = 'Operation `' + this.name + '.' + i + '()` buffering timed out after ' +
|
||||
bufferTimeoutMS + 'ms';
|
||||
const err = new MongooseError(message);
|
||||
this.conn.emit('buffer-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, error: err });
|
||||
callback(err);
|
||||
}
|
||||
}, bufferTimeoutMS);
|
||||
|
||||
if (typeof lastArg === 'function') {
|
||||
this.addQueue(i, _args);
|
||||
return;
|
||||
}
|
||||
return new this.Promise((resolve, reject) => {
|
||||
this.addQueue(i, [].concat(args).concat([(err, res) => {
|
||||
if (err != null) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(res);
|
||||
}]));
|
||||
});
|
||||
|
||||
return promise;
|
||||
} else if (!syncCollectionMethods[i] && typeof lastArg === 'function') {
|
||||
callback = function collectionOperationCallback(err, res) {
|
||||
if (err != null) {
|
||||
_this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, error: err });
|
||||
} else {
|
||||
_this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: _this.name, method: i, result: res });
|
||||
}
|
||||
return lastArg.apply(this, arguments);
|
||||
};
|
||||
_args = args.slice(0, args.length - 1).concat([callback]);
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
@@ -165,18 +226,45 @@ function iter(i) {
|
||||
} else if (debug instanceof stream.Writable) {
|
||||
this.$printToStream(_this.name, i, args, debug);
|
||||
} else {
|
||||
this.$print(_this.name, i, args, typeof debug.color === 'undefined' ? true : debug.color);
|
||||
const color = debug.color == null ? true : debug.color;
|
||||
const shell = debug.shell == null ? false : debug.shell;
|
||||
this.$print(_this.name, i, args, color, shell);
|
||||
}
|
||||
}
|
||||
|
||||
this.conn.emit('operation-start', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, params: _args });
|
||||
|
||||
try {
|
||||
return collection[i].apply(collection, args);
|
||||
if (collection == null) {
|
||||
const message = 'Cannot call `' + this.name + '.' + i + '()` before initial connection ' +
|
||||
'is complete if `bufferCommands = false`. Make sure you `await mongoose.connect()` if ' +
|
||||
'you have `bufferCommands = false`.';
|
||||
throw new MongooseError(message);
|
||||
}
|
||||
const ret = collection[i].apply(collection, _args);
|
||||
if (ret != null && typeof ret.then === 'function') {
|
||||
return ret.then(
|
||||
res => {
|
||||
this.conn.emit('operation-end', { _id: opId, modelName: this.modelName, collectionName: this.name, method: i, result: res });
|
||||
return res;
|
||||
},
|
||||
err => {
|
||||
this.conn.emit('operation-end', { _id: opId, modelName: this.modelName, collectionName: this.name, method: i, error: err });
|
||||
throw err;
|
||||
}
|
||||
);
|
||||
}
|
||||
return ret;
|
||||
} catch (error) {
|
||||
// Collection operation may throw because of max bson size, catch it here
|
||||
// See gh-3906
|
||||
if (args.length > 0 &&
|
||||
typeof args[args.length - 1] === 'function') {
|
||||
args[args.length - 1](error);
|
||||
if (typeof callback === 'function') {
|
||||
callback(error);
|
||||
} else {
|
||||
this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
|
||||
}
|
||||
if (typeof lastArg === 'function') {
|
||||
lastArg(error);
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
@@ -206,13 +294,13 @@ for (const key of Object.keys(Collection.prototype)) {
|
||||
* @method $print
|
||||
*/
|
||||
|
||||
NativeCollection.prototype.$print = function(name, i, args, color) {
|
||||
NativeCollection.prototype.$print = function(name, i, args, color, shell) {
|
||||
const moduleName = color ? '\x1B[0;36mMongoose:\x1B[0m ' : 'Mongoose: ';
|
||||
const functionCall = [name, i].join('.');
|
||||
const _args = [];
|
||||
for (let j = args.length - 1; j >= 0; --j) {
|
||||
if (this.$format(args[j]) || _args.length) {
|
||||
_args.unshift(this.$format(args[j], color));
|
||||
_args.unshift(this.$format(args[j], color, shell));
|
||||
}
|
||||
}
|
||||
const params = '(' + _args.join(', ') + ')';
|
||||
@@ -247,10 +335,10 @@ NativeCollection.prototype.$printToStream = function(name, i, args, stream) {
|
||||
* @method $format
|
||||
*/
|
||||
|
||||
NativeCollection.prototype.$format = function(arg, color) {
|
||||
NativeCollection.prototype.$format = function(arg, color, shell) {
|
||||
const type = typeof arg;
|
||||
if (type === 'function' || type === 'undefined') return '';
|
||||
return format(arg, false, color);
|
||||
return format(arg, false, color, shell);
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -272,10 +360,14 @@ function map(o) {
|
||||
function formatObjectId(x, key) {
|
||||
x[key] = inspectable('ObjectId("' + x[key].toHexString() + '")');
|
||||
}
|
||||
function formatDate(x, key) {
|
||||
x[key] = inspectable('new Date("' + x[key].toUTCString() + '")');
|
||||
function formatDate(x, key, shell) {
|
||||
if (shell) {
|
||||
x[key] = inspectable('ISODate("' + x[key].toUTCString() + '")');
|
||||
} else {
|
||||
x[key] = inspectable('new Date("' + x[key].toUTCString() + '")');
|
||||
}
|
||||
}
|
||||
function format(obj, sub, color) {
|
||||
function format(obj, sub, color, shell) {
|
||||
if (obj && typeof obj.toBSON === 'function') {
|
||||
obj = obj.toBSON();
|
||||
}
|
||||
@@ -285,14 +377,15 @@ function format(obj, sub, color) {
|
||||
|
||||
const clone = require('../../helpers/clone');
|
||||
let x = clone(obj, { transform: false });
|
||||
const constructorName = getConstructorName(x);
|
||||
|
||||
if (x.constructor.name === 'Binary') {
|
||||
if (constructorName === 'Binary') {
|
||||
x = 'BinData(' + x.sub_type + ', "' + x.toString('base64') + '")';
|
||||
} else if (x.constructor.name === 'ObjectID') {
|
||||
} else if (constructorName === 'ObjectID') {
|
||||
x = inspectable('ObjectId("' + x.toHexString() + '")');
|
||||
} else if (x.constructor.name === 'Date') {
|
||||
} else if (constructorName === 'Date') {
|
||||
x = inspectable('new Date("' + x.toUTCString() + '")');
|
||||
} else if (x.constructor.name === 'Object') {
|
||||
} else if (constructorName === 'Object') {
|
||||
const keys = Object.keys(x);
|
||||
const numKeys = keys.length;
|
||||
let key;
|
||||
@@ -311,16 +404,17 @@ function format(obj, sub, color) {
|
||||
error = _error;
|
||||
}
|
||||
}
|
||||
if (x[key].constructor.name === 'Binary') {
|
||||
const _constructorName = getConstructorName(x[key]);
|
||||
if (_constructorName === 'Binary') {
|
||||
x[key] = 'BinData(' + x[key].sub_type + ', "' +
|
||||
x[key].buffer.toString('base64') + '")';
|
||||
} else if (x[key].constructor.name === 'Object') {
|
||||
} else if (_constructorName === 'Object') {
|
||||
x[key] = format(x[key], true);
|
||||
} else if (x[key].constructor.name === 'ObjectID') {
|
||||
} else if (_constructorName === 'ObjectID') {
|
||||
formatObjectId(x, key);
|
||||
} else if (x[key].constructor.name === 'Date') {
|
||||
formatDate(x, key);
|
||||
} else if (x[key].constructor.name === 'ClientSession') {
|
||||
} else if (_constructorName === 'Date') {
|
||||
formatDate(x, key, shell);
|
||||
} else if (_constructorName === 'ClientSession') {
|
||||
x[key] = inspectable('ClientSession("' +
|
||||
get(x[key], 'id.id.buffer', '').toString('hex') + '")');
|
||||
} else if (Array.isArray(x[key])) {
|
||||
|
||||
72
node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
generated
vendored
72
node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
generated
vendored
@@ -6,6 +6,8 @@
|
||||
|
||||
const MongooseConnection = require('../../connection');
|
||||
const STATES = require('../../connectionstate');
|
||||
const immediate = require('../../helpers/immediate');
|
||||
const setTimeout = require('../../helpers/timers').setTimeout;
|
||||
|
||||
/**
|
||||
* A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation.
|
||||
@@ -38,16 +40,20 @@ NativeConnection.prototype.__proto__ = MongooseConnection.prototype;
|
||||
* Returns a new connection object, with the new db. If you set the `useCache`
|
||||
* option, `useDb()` will cache connections by `name`.
|
||||
*
|
||||
* **Note:** Calling `close()` on a `useDb()` connection will close the base connection as well.
|
||||
*
|
||||
* @param {String} name The database name
|
||||
* @param {Object} [options]
|
||||
* @param {Boolean} [options.useCache=false] If true, cache results so calling `useDb()` multiple times with the same name only creates 1 connection object.
|
||||
* @param {Boolean} [options.noListener=false] If true, the new connection object won't listen to any events on the base connection. This is better for memory usage in cases where you're calling `useDb()` for every request.
|
||||
* @return {Connection} New Connection Object
|
||||
* @api public
|
||||
*/
|
||||
|
||||
NativeConnection.prototype.useDb = function(name, options) {
|
||||
// Return immediately if cached
|
||||
if (options && options.useCache && this.relatedDbs[name]) {
|
||||
options = options || {};
|
||||
if (options.useCache && this.relatedDbs[name]) {
|
||||
return this.relatedDbs[name];
|
||||
}
|
||||
|
||||
@@ -58,7 +64,7 @@ NativeConnection.prototype.useDb = function(name, options) {
|
||||
newConn.collections = {};
|
||||
newConn.models = {};
|
||||
newConn.replica = this.replica;
|
||||
newConn.config = Object.assign({}, this.base.connection.config, newConn.config);
|
||||
newConn.config = Object.assign({}, this.config, newConn.config);
|
||||
newConn.name = this.name;
|
||||
newConn.options = this.options;
|
||||
newConn._readyState = this._readyState;
|
||||
@@ -90,16 +96,24 @@ NativeConnection.prototype.useDb = function(name, options) {
|
||||
|
||||
function wireup() {
|
||||
newConn.client = _this.client;
|
||||
newConn.db = _this.client.db(name);
|
||||
const _opts = {};
|
||||
if (options.hasOwnProperty('noListener')) {
|
||||
_opts.noListener = options.noListener;
|
||||
}
|
||||
newConn.db = _this.client.db(name, _opts);
|
||||
newConn.onOpen();
|
||||
// setup the events appropriately
|
||||
listen(newConn);
|
||||
if (options.noListener !== true) {
|
||||
listen(newConn);
|
||||
}
|
||||
}
|
||||
|
||||
newConn.name = name;
|
||||
|
||||
// push onto the otherDbs stack, this is used when state changes
|
||||
this.otherDbs.push(newConn);
|
||||
if (options.noListener !== true) {
|
||||
this.otherDbs.push(newConn);
|
||||
}
|
||||
newConn.otherDbs.push(this);
|
||||
|
||||
// push onto the relatedDbs cache, this is used when state changes
|
||||
@@ -116,13 +130,16 @@ NativeConnection.prototype.useDb = function(name, options) {
|
||||
*/
|
||||
|
||||
function listen(conn) {
|
||||
if (conn.db._listening) {
|
||||
if (conn._listening) {
|
||||
return;
|
||||
}
|
||||
conn.db._listening = true;
|
||||
conn._listening = true;
|
||||
|
||||
conn.db.on('close', function(force) {
|
||||
if (conn._closeCalled) return;
|
||||
conn.client.on('close', function(force) {
|
||||
if (conn._closeCalled) {
|
||||
return;
|
||||
}
|
||||
conn._closeCalled = conn.client._closeCalled;
|
||||
|
||||
// the driver never emits an `open` event. auto_reconnect still
|
||||
// emits a `close` event but since we never get another
|
||||
@@ -134,26 +151,30 @@ function listen(conn) {
|
||||
}
|
||||
conn.onClose(force);
|
||||
});
|
||||
conn.db.on('error', function(err) {
|
||||
conn.client.on('error', function(err) {
|
||||
conn.emit('error', err);
|
||||
});
|
||||
conn.db.on('reconnect', function() {
|
||||
conn.readyState = STATES.connected;
|
||||
conn.emit('reconnect');
|
||||
conn.emit('reconnected');
|
||||
conn.onOpen();
|
||||
});
|
||||
conn.db.on('timeout', function(err) {
|
||||
conn.emit('timeout', err);
|
||||
});
|
||||
conn.db.on('open', function(err, db) {
|
||||
if (STATES.disconnected === conn.readyState && db && db.databaseName) {
|
||||
|
||||
if (!conn.client.s.options.useUnifiedTopology) {
|
||||
conn.db.on('reconnect', function() {
|
||||
conn.readyState = STATES.connected;
|
||||
conn.emit('reconnect');
|
||||
conn.emit('reconnected');
|
||||
}
|
||||
conn.onOpen();
|
||||
});
|
||||
conn.db.on('open', function(err, db) {
|
||||
if (STATES.disconnected === conn.readyState && db && db.databaseName) {
|
||||
conn.readyState = STATES.connected;
|
||||
conn.emit('reconnect');
|
||||
conn.emit('reconnected');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
conn.client.on('timeout', function(err) {
|
||||
conn.emit('timeout', err);
|
||||
});
|
||||
conn.db.on('parseError', function(err) {
|
||||
conn.client.on('parseError', function(err) {
|
||||
conn.emit('parseError', err);
|
||||
});
|
||||
}
|
||||
@@ -168,6 +189,11 @@ function listen(conn) {
|
||||
*/
|
||||
|
||||
NativeConnection.prototype.doClose = function(force, fn) {
|
||||
if (this.client == null) {
|
||||
immediate(() => fn());
|
||||
return this;
|
||||
}
|
||||
|
||||
this.client.close(force, (err, res) => {
|
||||
// Defer because the driver will wait at least 1ms before finishing closing
|
||||
// the pool, see https://github.com/mongodb-js/mongodb-core/blob/a8f8e4ce41936babc3b9112bf42d609779f03b39/lib/connection/pool.js#L1026-L1030.
|
||||
|
||||
3
node_modules/mongoose/lib/drivers/node-mongodb-native/index.js
generated
vendored
3
node_modules/mongoose/lib/drivers/node-mongodb-native/index.js
generated
vendored
@@ -8,4 +8,5 @@ exports.Binary = require('./binary');
|
||||
exports.Collection = require('./collection');
|
||||
exports.Decimal128 = require('./decimal128');
|
||||
exports.ObjectId = require('./objectid');
|
||||
exports.ReadPreference = require('./ReadPreference');
|
||||
exports.ReadPreference = require('./ReadPreference');
|
||||
exports.getConnection = () => require('./connection');
|
||||
40
node_modules/mongoose/lib/error/cast.js
generated
vendored
40
node_modules/mongoose/lib/error/cast.js
generated
vendored
@@ -22,8 +22,9 @@ class CastError extends MongooseError {
|
||||
// If no args, assume we'll `init()` later.
|
||||
if (arguments.length > 0) {
|
||||
const stringValue = getStringValue(value);
|
||||
const valueType = getValueType(value);
|
||||
const messageFormat = getMessageFormat(schemaType);
|
||||
const msg = formatMessage(null, type, stringValue, path, messageFormat);
|
||||
const msg = formatMessage(null, type, stringValue, path, messageFormat, valueType);
|
||||
super(msg);
|
||||
this.init(type, value, path, reason, schemaType);
|
||||
} else {
|
||||
@@ -31,6 +32,18 @@ class CastError extends MongooseError {
|
||||
}
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
stringValue: this.stringValue,
|
||||
valueType: this.valueType,
|
||||
kind: this.kind,
|
||||
value: this.value,
|
||||
path: this.path,
|
||||
reason: this.reason,
|
||||
name: this.name,
|
||||
message: this.message
|
||||
};
|
||||
}
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -41,6 +54,7 @@ class CastError extends MongooseError {
|
||||
this.value = value;
|
||||
this.path = path;
|
||||
this.reason = reason;
|
||||
this.valueType = getValueType(value);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -55,6 +69,7 @@ class CastError extends MongooseError {
|
||||
this.path = other.path;
|
||||
this.reason = other.reason;
|
||||
this.message = other.message;
|
||||
this.valueType = other.valueType;
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -63,7 +78,7 @@ class CastError extends MongooseError {
|
||||
setModel(model) {
|
||||
this.model = model;
|
||||
this.message = formatMessage(model, this.kind, this.stringValue, this.path,
|
||||
this.messageFormat);
|
||||
this.messageFormat, this.valueType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +95,21 @@ function getStringValue(value) {
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
function getValueType(value) {
|
||||
if (value == null) {
|
||||
return '' + value;
|
||||
}
|
||||
|
||||
const t = typeof value;
|
||||
if (t !== 'object') {
|
||||
return t;
|
||||
}
|
||||
if (typeof value.constructor !== 'function') {
|
||||
return t;
|
||||
}
|
||||
return value.constructor.name;
|
||||
}
|
||||
|
||||
function getMessageFormat(schemaType) {
|
||||
const messageFormat = get(schemaType, 'options.cast', null);
|
||||
if (typeof messageFormat === 'string') {
|
||||
@@ -91,7 +121,7 @@ function getMessageFormat(schemaType) {
|
||||
* ignore
|
||||
*/
|
||||
|
||||
function formatMessage(model, kind, stringValue, path, messageFormat) {
|
||||
function formatMessage(model, kind, stringValue, path, messageFormat, valueType) {
|
||||
if (messageFormat != null) {
|
||||
let ret = messageFormat.
|
||||
replace('{KIND}', kind).
|
||||
@@ -103,12 +133,12 @@ function formatMessage(model, kind, stringValue, path, messageFormat) {
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
const valueTypeMsg = valueType ? ' (type ' + valueType + ')' : '';
|
||||
let ret = 'Cast to ' + kind + ' failed for value ' +
|
||||
stringValue + ' at path "' + path + '"';
|
||||
stringValue + valueTypeMsg + ' at path "' + path + '"';
|
||||
if (model != null) {
|
||||
ret += ' for model "' + model.modelName + '"';
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
2
node_modules/mongoose/lib/error/messages.js
generated
vendored
2
node_modules/mongoose/lib/error/messages.js
generated
vendored
@@ -3,7 +3,7 @@
|
||||
* The default built-in validator error messages. These may be customized.
|
||||
*
|
||||
* // customize within each schema or globally like so
|
||||
* var mongoose = require('mongoose');
|
||||
* const mongoose = require('mongoose');
|
||||
* mongoose.Error.messages.String.enum = "Your custom message for {PATH}.";
|
||||
*
|
||||
* As you might have noticed, error messages support basic templating
|
||||
|
||||
20
node_modules/mongoose/lib/error/serverSelection.js
generated
vendored
20
node_modules/mongoose/lib/error/serverSelection.js
generated
vendored
@@ -7,6 +7,7 @@
|
||||
const MongooseError = require('./mongooseError');
|
||||
const allServersUnknown = require('../helpers/topology/allServersUnknown');
|
||||
const isAtlas = require('../helpers/topology/isAtlas');
|
||||
const isSSLError = require('../helpers/topology/isSSLError');
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
@@ -17,6 +18,11 @@ const atlasMessage = 'Could not connect to any servers in your MongoDB Atlas clu
|
||||
'an IP that isn\'t whitelisted. Make sure your current IP address is on your Atlas ' +
|
||||
'cluster\'s IP whitelist: https://docs.atlas.mongodb.com/security-whitelist/';
|
||||
|
||||
const sslMessage = 'Mongoose is connecting with SSL enabled, but the server is ' +
|
||||
'not accepting SSL connections. Please ensure that the MongoDB server you are ' +
|
||||
'connecting to is configured to accept SSL connections. Learn more: ' +
|
||||
'https://mongoosejs.com/docs/tutorials/ssl.html';
|
||||
|
||||
class MongooseServerSelectionError extends MongooseError {
|
||||
/**
|
||||
* MongooseServerSelectionError constructor
|
||||
@@ -28,10 +34,16 @@ class MongooseServerSelectionError extends MongooseError {
|
||||
// Special message for a case that is likely due to IP whitelisting issues.
|
||||
const isAtlasWhitelistError = isAtlas(reason) &&
|
||||
allServersUnknown(reason) &&
|
||||
err.message.indexOf('bad auth') === -1;
|
||||
this.message = isAtlasWhitelistError ?
|
||||
atlasMessage :
|
||||
err.message;
|
||||
err.message.indexOf('bad auth') === -1 &&
|
||||
err.message.indexOf('Authentication failed') === -1;
|
||||
|
||||
if (isAtlasWhitelistError) {
|
||||
this.message = atlasMessage;
|
||||
} else if (isSSLError(reason)) {
|
||||
this.message = sslMessage;
|
||||
} else {
|
||||
this.message = err.message;
|
||||
}
|
||||
for (const key in err) {
|
||||
if (key !== 'name') {
|
||||
this[key] = err[key];
|
||||
|
||||
11
node_modules/mongoose/lib/error/validation.js
generated
vendored
11
node_modules/mongoose/lib/error/validation.js
generated
vendored
@@ -4,10 +4,10 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const MongooseError = require('./');
|
||||
const MongooseError = require('./mongooseError');
|
||||
const getConstructorName = require('../helpers/getConstructorName');
|
||||
const util = require('util');
|
||||
|
||||
|
||||
class ValidationError extends MongooseError {
|
||||
/**
|
||||
* Document Validation Error
|
||||
@@ -18,7 +18,7 @@ class ValidationError extends MongooseError {
|
||||
*/
|
||||
constructor(instance) {
|
||||
let _message;
|
||||
if (instance && instance.constructor.name === 'model') {
|
||||
if (getConstructorName(instance) === 'model') {
|
||||
_message = instance.constructor.modelName + ' validation failed';
|
||||
} else {
|
||||
_message = 'Validation failed';
|
||||
@@ -68,13 +68,14 @@ if (util.inspect.custom) {
|
||||
|
||||
/*!
|
||||
* Helper for JSON.stringify
|
||||
* Ensure `name` and `message` show up in toJSON output re: gh-9847
|
||||
*/
|
||||
Object.defineProperty(ValidationError.prototype, 'toJSON', {
|
||||
enumerable: false,
|
||||
writable: false,
|
||||
configurable: true,
|
||||
value: function() {
|
||||
return Object.assign({}, this, { message: this.message });
|
||||
return Object.assign({}, this, { name: this.name, message: this.message });
|
||||
}
|
||||
});
|
||||
|
||||
@@ -108,4 +109,4 @@ function _generateMessage(err) {
|
||||
* Module exports
|
||||
*/
|
||||
|
||||
module.exports = exports = ValidationError;
|
||||
module.exports = ValidationError;
|
||||
|
||||
8
node_modules/mongoose/lib/error/validator.js
generated
vendored
8
node_modules/mongoose/lib/error/validator.js
generated
vendored
@@ -38,6 +38,14 @@ class ValidatorError extends MongooseError {
|
||||
toString() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Ensure `name` and `message` show up in toJSON output re: gh-9296
|
||||
*/
|
||||
|
||||
toJSON() {
|
||||
return Object.assign({ name: this.name, message: this.message }, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
9
node_modules/mongoose/lib/helpers/arrayDepth.js
generated
vendored
9
node_modules/mongoose/lib/helpers/arrayDepth.js
generated
vendored
@@ -4,13 +4,17 @@ module.exports = arrayDepth;
|
||||
|
||||
function arrayDepth(arr) {
|
||||
if (!Array.isArray(arr)) {
|
||||
return { min: 0, max: 0 };
|
||||
return { min: 0, max: 0, containsNonArrayItem: true };
|
||||
}
|
||||
if (arr.length === 0) {
|
||||
return { min: 1, max: 1 };
|
||||
return { min: 1, max: 1, containsNonArrayItem: false };
|
||||
}
|
||||
if (arr.length === 1 && !Array.isArray(arr[0])) {
|
||||
return { min: 1, max: 1, containsNonArrayItem: false };
|
||||
}
|
||||
|
||||
const res = arrayDepth(arr[0]);
|
||||
|
||||
for (let i = 1; i < arr.length; ++i) {
|
||||
const _res = arrayDepth(arr[i]);
|
||||
if (_res.min < res.min) {
|
||||
@@ -19,6 +23,7 @@ function arrayDepth(arr) {
|
||||
if (_res.max > res.max) {
|
||||
res.max = _res.max;
|
||||
}
|
||||
res.containsNonArrayItem = res.containsNonArrayItem || _res.containsNonArrayItem;
|
||||
}
|
||||
|
||||
res.min = res.min + 1;
|
||||
|
||||
8
node_modules/mongoose/lib/helpers/clone.js
generated
vendored
8
node_modules/mongoose/lib/helpers/clone.js
generated
vendored
@@ -10,6 +10,7 @@ const getFunctionName = require('./getFunctionName');
|
||||
const isBsonType = require('./isBsonType');
|
||||
const isObject = require('./isObject');
|
||||
const symbols = require('./symbols');
|
||||
const utils = require('../utils');
|
||||
|
||||
|
||||
/*!
|
||||
@@ -41,6 +42,11 @@ function clone(obj, options, isArrayChild) {
|
||||
if (options && options._skipSingleNestedGetters && obj.$isSingleNested) {
|
||||
options = Object.assign({}, options, { getters: false });
|
||||
}
|
||||
|
||||
if (utils.isPOJO(obj) && obj.$__ != null && obj._doc != null) {
|
||||
return obj._doc;
|
||||
}
|
||||
|
||||
if (options && options.json && typeof obj.toJSON === 'function') {
|
||||
return obj.toJSON(options);
|
||||
}
|
||||
@@ -105,7 +111,7 @@ function cloneObject(obj, options, isArrayChild) {
|
||||
const ret = {};
|
||||
let hasKeys;
|
||||
|
||||
for (const k in obj) {
|
||||
for (const k of Object.keys(obj)) {
|
||||
if (specialProperties.has(k)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
44
node_modules/mongoose/lib/helpers/cursor/eachAsync.js
generated
vendored
44
node_modules/mongoose/lib/helpers/cursor/eachAsync.js
generated
vendored
@@ -4,6 +4,7 @@
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
const immediate = require('../immediate');
|
||||
const promiseOrCallback = require('../promiseOrCallback');
|
||||
|
||||
/**
|
||||
@@ -22,9 +23,22 @@ const promiseOrCallback = require('../promiseOrCallback');
|
||||
|
||||
module.exports = function eachAsync(next, fn, options, callback) {
|
||||
const parallel = options.parallel || 1;
|
||||
const batchSize = options.batchSize;
|
||||
const enqueue = asyncQueue();
|
||||
|
||||
return promiseOrCallback(callback, cb => {
|
||||
if (batchSize != null) {
|
||||
if (typeof batchSize !== 'number') {
|
||||
throw new TypeError('batchSize must be a number');
|
||||
}
|
||||
if (batchSize < 1) {
|
||||
throw new TypeError('batchSize must be at least 1');
|
||||
}
|
||||
if (batchSize !== Math.floor(batchSize)) {
|
||||
throw new TypeError('batchSize must be a positive integer');
|
||||
}
|
||||
}
|
||||
|
||||
iterate(cb);
|
||||
});
|
||||
|
||||
@@ -32,6 +46,7 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
||||
let drained = false;
|
||||
let handleResultsInProgress = 0;
|
||||
let currentDocumentIndex = 0;
|
||||
let documentsBatch = [];
|
||||
|
||||
let error = null;
|
||||
for (let i = 0; i < parallel; ++i) {
|
||||
@@ -56,6 +71,8 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
||||
drained = true;
|
||||
if (handleResultsInProgress <= 0) {
|
||||
finalCallback(null);
|
||||
} else if (batchSize != null && documentsBatch.length) {
|
||||
handleNextResult(documentsBatch, currentDocumentIndex++, handleNextResultCallBack);
|
||||
}
|
||||
return done();
|
||||
}
|
||||
@@ -64,10 +81,27 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
||||
|
||||
// Kick off the subsequent `next()` before handling the result, but
|
||||
// make sure we know that we still have a result to handle re: #8422
|
||||
process.nextTick(() => done());
|
||||
immediate(() => done());
|
||||
|
||||
handleNextResult(doc, currentDocumentIndex++, function(err) {
|
||||
--handleResultsInProgress;
|
||||
if (batchSize != null) {
|
||||
documentsBatch.push(doc);
|
||||
}
|
||||
|
||||
// If the current documents size is less than the provided patch size don't process the documents yet
|
||||
if (batchSize != null && documentsBatch.length !== batchSize) {
|
||||
setTimeout(() => enqueue(fetch), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const docsToProcess = batchSize != null ? documentsBatch : doc;
|
||||
|
||||
function handleNextResultCallBack(err) {
|
||||
if (batchSize != null) {
|
||||
handleResultsInProgress -= documentsBatch.length;
|
||||
documentsBatch = [];
|
||||
} else {
|
||||
--handleResultsInProgress;
|
||||
}
|
||||
if (err != null) {
|
||||
error = err;
|
||||
return finalCallback(err);
|
||||
@@ -77,7 +111,9 @@ module.exports = function eachAsync(next, fn, options, callback) {
|
||||
}
|
||||
|
||||
setTimeout(() => enqueue(fetch), 0);
|
||||
});
|
||||
}
|
||||
|
||||
handleNextResult(docsToProcess, currentDocumentIndex++, handleNextResultCallBack);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
2
node_modules/mongoose/lib/helpers/discriminator/getConstructor.js
generated
vendored
2
node_modules/mongoose/lib/helpers/discriminator/getConstructor.js
generated
vendored
@@ -14,7 +14,7 @@ module.exports = function getConstructor(Constructor, value) {
|
||||
if (Constructor.discriminators[value[discriminatorKey]]) {
|
||||
Constructor = Constructor.discriminators[value[discriminatorKey]];
|
||||
} else {
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor, value[discriminatorKey]);
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, value[discriminatorKey]);
|
||||
if (constructorByValue) {
|
||||
Constructor = constructorByValue;
|
||||
}
|
||||
|
||||
20
node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js
generated
vendored
20
node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js
generated
vendored
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const areDiscriminatorValuesEqual = require('./areDiscriminatorValuesEqual');
|
||||
|
||||
/*!
|
||||
* returns discriminator by discriminatorMapping.value
|
||||
*
|
||||
@@ -7,21 +9,19 @@
|
||||
* @param {string} value
|
||||
*/
|
||||
|
||||
module.exports = function getDiscriminatorByValue(model, value) {
|
||||
let discriminator = null;
|
||||
if (!model.discriminators) {
|
||||
return discriminator;
|
||||
module.exports = function getDiscriminatorByValue(discriminators, value) {
|
||||
if (discriminators == null) {
|
||||
return null;
|
||||
}
|
||||
for (const name in model.discriminators) {
|
||||
const it = model.discriminators[name];
|
||||
for (const name of Object.keys(discriminators)) {
|
||||
const it = discriminators[name];
|
||||
if (
|
||||
it.schema &&
|
||||
it.schema.discriminatorMapping &&
|
||||
it.schema.discriminatorMapping.value == value
|
||||
areDiscriminatorValuesEqual(it.schema.discriminatorMapping.value, value)
|
||||
) {
|
||||
discriminator = it;
|
||||
break;
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return discriminator;
|
||||
return null;
|
||||
};
|
||||
2
node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js
generated
vendored
2
node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js
generated
vendored
@@ -14,7 +14,7 @@ module.exports = function cleanModifiedSubpaths(doc, path, options) {
|
||||
}
|
||||
for (const modifiedPath of Object.keys(doc.$__.activePaths.states.modify)) {
|
||||
if (skipDocArrays) {
|
||||
const schemaType = doc.schema.path(modifiedPath);
|
||||
const schemaType = doc.$__schema.path(modifiedPath);
|
||||
if (schemaType && schemaType.$isMongooseDocumentArray) {
|
||||
continue;
|
||||
}
|
||||
|
||||
48
node_modules/mongoose/lib/helpers/document/compile.js
generated
vendored
48
node_modules/mongoose/lib/helpers/document/compile.js
generated
vendored
@@ -2,6 +2,7 @@
|
||||
|
||||
const documentSchemaSymbol = require('../../helpers/symbols').documentSchemaSymbol;
|
||||
const get = require('../../helpers/get');
|
||||
const internalToObjectOptions = require('../../options').internalToObjectOptions;
|
||||
const utils = require('../../utils');
|
||||
|
||||
let Document;
|
||||
@@ -73,6 +74,13 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
|
||||
value: prototype.schema
|
||||
});
|
||||
|
||||
Object.defineProperty(nested, '$__schema', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: false,
|
||||
value: prototype.schema
|
||||
});
|
||||
|
||||
Object.defineProperty(nested, documentSchemaSymbol, {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
@@ -91,6 +99,17 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(nested, '$__get', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: false,
|
||||
value: function() {
|
||||
return _this.get(path, null, {
|
||||
virtuals: get(this, 'schema.options.toObject.virtuals', null)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(nested, 'toJSON', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
@@ -124,6 +143,13 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
|
||||
}
|
||||
});
|
||||
|
||||
Object.defineProperty(nested, '$__parent', {
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: false,
|
||||
value: this
|
||||
});
|
||||
|
||||
compile(subprops, nested, path, options);
|
||||
this.$__.getters[path] = nested;
|
||||
}
|
||||
@@ -131,8 +157,12 @@ function defineKey(prop, subprops, prototype, prefix, keys, options) {
|
||||
return this.$__.getters[path];
|
||||
},
|
||||
set: function(v) {
|
||||
if (v instanceof Document) {
|
||||
v = v.toObject({ transform: false });
|
||||
if (v != null && v.$__isNested) {
|
||||
// Convert top-level to POJO, but leave subdocs hydrated so `$set`
|
||||
// can handle them. See gh-9293.
|
||||
v = v.$__get();
|
||||
} else if (v instanceof Document && !v.$__isNested) {
|
||||
v = v.toObject(internalToObjectOptions);
|
||||
}
|
||||
const doc = this.$__[scopeSymbol] || this;
|
||||
doc.$set(path, v);
|
||||
@@ -158,13 +188,7 @@ function getOwnPropertyDescriptors(object) {
|
||||
const result = {};
|
||||
|
||||
Object.getOwnPropertyNames(object).forEach(function(key) {
|
||||
result[key] = Object.getOwnPropertyDescriptor(object, key);
|
||||
// Assume these are schema paths, ignore them re: #5470
|
||||
if (result[key].get) {
|
||||
delete result[key];
|
||||
return;
|
||||
}
|
||||
result[key].enumerable = [
|
||||
const skip = [
|
||||
'isNew',
|
||||
'$__',
|
||||
'errors',
|
||||
@@ -175,6 +199,12 @@ function getOwnPropertyDescriptors(object) {
|
||||
'__index',
|
||||
'$isDocumentArrayElement'
|
||||
].indexOf(key) === -1;
|
||||
if (skip) {
|
||||
return;
|
||||
}
|
||||
|
||||
result[key] = Object.getOwnPropertyDescriptor(object, key);
|
||||
result[key].enumerable = false;
|
||||
});
|
||||
|
||||
return result;
|
||||
|
||||
31
node_modules/mongoose/lib/helpers/get.js
generated
vendored
31
node_modules/mongoose/lib/helpers/get.js
generated
vendored
@@ -6,7 +6,30 @@
|
||||
*/
|
||||
|
||||
module.exports = function get(obj, path, def) {
|
||||
const parts = path.split('.');
|
||||
let parts;
|
||||
let isPathArray = false;
|
||||
if (typeof path === 'string') {
|
||||
if (path.indexOf('.') === -1) {
|
||||
const _v = getProperty(obj, path);
|
||||
if (_v == null) {
|
||||
return def;
|
||||
}
|
||||
return _v;
|
||||
}
|
||||
|
||||
parts = path.split('.');
|
||||
} else {
|
||||
isPathArray = true;
|
||||
parts = path;
|
||||
|
||||
if (parts.length === 1) {
|
||||
const _v = getProperty(obj, parts[0]);
|
||||
if (_v == null) {
|
||||
return def;
|
||||
}
|
||||
return _v;
|
||||
}
|
||||
}
|
||||
let rest = path;
|
||||
let cur = obj;
|
||||
for (const part of parts) {
|
||||
@@ -16,13 +39,15 @@ module.exports = function get(obj, path, def) {
|
||||
|
||||
// `lib/cast.js` depends on being able to get dotted paths in updates,
|
||||
// like `{ $set: { 'a.b': 42 } }`
|
||||
if (cur[rest] != null) {
|
||||
if (!isPathArray && cur[rest] != null) {
|
||||
return cur[rest];
|
||||
}
|
||||
|
||||
cur = getProperty(cur, part);
|
||||
|
||||
rest = rest.substr(part.length + 1);
|
||||
if (!isPathArray) {
|
||||
rest = rest.substr(part.length + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return cur == null ? def : cur;
|
||||
|
||||
4
node_modules/mongoose/lib/helpers/immediate.js
generated
vendored
4
node_modules/mongoose/lib/helpers/immediate.js
generated
vendored
@@ -7,6 +7,8 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const nextTick = process.nextTick.bind(process);
|
||||
|
||||
module.exports = function immediate(cb) {
|
||||
return process.nextTick(cb);
|
||||
return nextTick(cb);
|
||||
};
|
||||
|
||||
51
node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js
generated
vendored
51
node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js
generated
vendored
@@ -3,8 +3,52 @@
|
||||
const get = require('../get');
|
||||
const utils = require('../../utils');
|
||||
|
||||
/**
|
||||
* Given a Mongoose index definition (key + options objects) and a MongoDB server
|
||||
* index definition, determine if the two indexes are equal.
|
||||
*
|
||||
* @param {Object} key the Mongoose index spec
|
||||
* @param {Object} options the Mongoose index definition's options
|
||||
* @param {Object} dbIndex the index in MongoDB as returned by `listIndexes()`
|
||||
* @api private
|
||||
*/
|
||||
|
||||
module.exports = function isIndexEqual(key, options, dbIndex) {
|
||||
// If these options are different, need to rebuild the index
|
||||
// Special case: text indexes have a special format in the db. For example,
|
||||
// `{ name: 'text' }` becomes:
|
||||
// {
|
||||
// v: 2,
|
||||
// key: { _fts: 'text', _ftsx: 1 },
|
||||
// name: 'name_text',
|
||||
// ns: 'test.tests',
|
||||
// background: true,
|
||||
// weights: { name: 1 },
|
||||
// default_language: 'english',
|
||||
// language_override: 'language',
|
||||
// textIndexVersion: 3
|
||||
// }
|
||||
if (dbIndex.textIndexVersion != null) {
|
||||
const weights = dbIndex.weights;
|
||||
if (Object.keys(weights).length !== Object.keys(key).length) {
|
||||
return false;
|
||||
}
|
||||
for (const prop of Object.keys(weights)) {
|
||||
if (!(prop in key)) {
|
||||
return false;
|
||||
}
|
||||
const weight = weights[prop];
|
||||
if (weight !== get(options, 'weights.' + prop) && !(weight === 1 && get(options, 'weights.' + prop) == null)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (options['default_language'] !== dbIndex['default_language']) {
|
||||
return dbIndex['default_language'] === 'english' && options['default_language'] == null;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
const optionKeys = [
|
||||
'unique',
|
||||
'partialFilterExpression',
|
||||
@@ -17,6 +61,9 @@ module.exports = function isIndexEqual(key, options, dbIndex) {
|
||||
continue;
|
||||
}
|
||||
if (key === 'collation') {
|
||||
if (options[key] == null || dbIndex[key] == null) {
|
||||
return options[key] == null && dbIndex[key] == null;
|
||||
}
|
||||
const definedKeys = Object.keys(options.collation);
|
||||
const schemaCollation = options.collation;
|
||||
const dbCollation = dbIndex.collation;
|
||||
@@ -45,4 +92,4 @@ module.exports = function isIndexEqual(key, options, dbIndex) {
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
};
|
||||
|
||||
5
node_modules/mongoose/lib/helpers/model/applyHooks.js
generated
vendored
5
node_modules/mongoose/lib/helpers/model/applyHooks.js
generated
vendored
@@ -75,9 +75,12 @@ function applyHooks(model, schema, options) {
|
||||
if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
|
||||
return !!hook['document'];
|
||||
}
|
||||
if (hook.name === 'remove') {
|
||||
if (hook.name === 'remove' || hook.name === 'init') {
|
||||
return hook['document'] == null || !!hook['document'];
|
||||
}
|
||||
if (hook.query != null || hook.document != null) {
|
||||
return hook.document !== false;
|
||||
}
|
||||
return true;
|
||||
}).
|
||||
filter(hook => {
|
||||
|
||||
31
node_modules/mongoose/lib/helpers/model/castBulkWrite.js
generated
vendored
31
node_modules/mongoose/lib/helpers/model/castBulkWrite.js
generated
vendored
@@ -20,7 +20,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
const model = decideModelByObject(originalModel, op['insertOne']['document']);
|
||||
|
||||
const doc = new model(op['insertOne']['document']);
|
||||
if (model.schema.options.timestamps != null) {
|
||||
if (model.schema.options.timestamps) {
|
||||
doc.initializeTimestamps();
|
||||
}
|
||||
if (options.session != null) {
|
||||
@@ -37,8 +37,12 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
} else if (op['updateOne']) {
|
||||
return (callback) => {
|
||||
try {
|
||||
if (!op['updateOne']['filter']) throw new Error('Must provide a filter object.');
|
||||
if (!op['updateOne']['update']) throw new Error('Must provide an update object.');
|
||||
if (!op['updateOne']['filter']) {
|
||||
throw new Error('Must provide a filter object.');
|
||||
}
|
||||
if (!op['updateOne']['update']) {
|
||||
throw new Error('Must provide an update object.');
|
||||
}
|
||||
|
||||
const model = decideModelByObject(originalModel, op['updateOne']['filter']);
|
||||
const schema = model.schema;
|
||||
@@ -54,7 +58,6 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
|
||||
applyTimestampsToChildren(now, op['updateOne']['update'], model.schema);
|
||||
|
||||
|
||||
if (op['updateOne'].setDefaultsOnInsert) {
|
||||
setDefaultsOnInsert(op['updateOne']['filter'], model.schema, op['updateOne']['update'], {
|
||||
setDefaultsOnInsert: true,
|
||||
@@ -71,8 +74,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
strict: strict,
|
||||
overwrite: false,
|
||||
upsert: op['updateOne'].upsert
|
||||
});
|
||||
|
||||
}, model, op['updateOne']['filter']);
|
||||
} catch (error) {
|
||||
return callback(error, null);
|
||||
}
|
||||
@@ -82,8 +84,12 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
} else if (op['updateMany']) {
|
||||
return (callback) => {
|
||||
try {
|
||||
if (!op['updateMany']['filter']) throw new Error('Must provide a filter object.');
|
||||
if (!op['updateMany']['update']) throw new Error('Must provide an update object.');
|
||||
if (!op['updateMany']['filter']) {
|
||||
throw new Error('Must provide a filter object.');
|
||||
}
|
||||
if (!op['updateMany']['update']) {
|
||||
throw new Error('Must provide an update object.');
|
||||
}
|
||||
|
||||
const model = decideModelByObject(originalModel, op['updateMany']['filter']);
|
||||
const schema = model.schema;
|
||||
@@ -115,7 +121,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
strict: strict,
|
||||
overwrite: false,
|
||||
upsert: op['updateMany'].upsert
|
||||
});
|
||||
}, model, op['updateMany']['filter']);
|
||||
|
||||
} catch (error) {
|
||||
return callback(error, null);
|
||||
@@ -141,7 +147,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
|
||||
// set `skipId`, otherwise we get "_id field cannot be changed"
|
||||
const doc = new model(op['replaceOne']['replacement'], strict, true);
|
||||
if (model.schema.options.timestamps != null) {
|
||||
if (model.schema.options.timestamps) {
|
||||
doc.initializeTimestamps();
|
||||
}
|
||||
if (options.session != null) {
|
||||
@@ -153,6 +159,7 @@ module.exports = function castBulkWrite(originalModel, op, options) {
|
||||
if (error) {
|
||||
return callback(error, null);
|
||||
}
|
||||
op['replaceOne']['replacement'] = op['replaceOne']['replacement'].toBSON();
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
@@ -211,7 +218,7 @@ function _addDiscriminatorToObject(schema, obj) {
|
||||
function decideModelByObject(model, object) {
|
||||
const discriminatorKey = model.schema.options.discriminatorKey;
|
||||
if (object != null && object.hasOwnProperty(discriminatorKey)) {
|
||||
model = getDiscriminatorByValue(model, object[discriminatorKey]) || model;
|
||||
model = getDiscriminatorByValue(model.discriminators, object[discriminatorKey]) || model;
|
||||
}
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
||||
30
node_modules/mongoose/lib/helpers/model/discriminator.js
generated
vendored
30
node_modules/mongoose/lib/helpers/model/discriminator.js
generated
vendored
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const Mixed = require('../../schema/mixed');
|
||||
const defineKey = require('../document/compile').defineKey;
|
||||
const get = require('../get');
|
||||
const utils = require('../../utils');
|
||||
@@ -62,7 +63,7 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
||||
}
|
||||
|
||||
let value = name;
|
||||
if (typeof tiedValue == 'string' && tiedValue.length) {
|
||||
if ((typeof tiedValue === 'string' && tiedValue.length) || tiedValue != null) {
|
||||
value = tiedValue;
|
||||
}
|
||||
|
||||
@@ -84,22 +85,25 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
||||
for (const path of baseSchemaPaths) {
|
||||
if (schema.nested[path]) {
|
||||
conflictingPaths.push(path);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (path.indexOf('.') === -1) {
|
||||
continue;
|
||||
}
|
||||
const sp = path.split('.');
|
||||
const sp = path.split('.').slice(0, -1);
|
||||
let cur = '';
|
||||
for (const piece of sp) {
|
||||
cur += (cur.length ? '.' : '') + piece;
|
||||
if (schema.paths[cur] || schema.singleNestedPaths[cur]) {
|
||||
if (schema.paths[cur] instanceof Mixed ||
|
||||
schema.singleNestedPaths[cur] instanceof Mixed) {
|
||||
conflictingPaths.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
utils.merge(schema, baseSchema, {
|
||||
isDiscriminatorSchemaMerge: true,
|
||||
omit: { discriminators: true, base: true },
|
||||
omitNested: conflictingPaths.reduce((cur, path) => {
|
||||
cur['tree.' + path] = true;
|
||||
@@ -122,17 +126,17 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
||||
default: value,
|
||||
select: true,
|
||||
set: function(newName) {
|
||||
if (newName === value) {
|
||||
if (newName === value || (Array.isArray(value) && utils.deepEqual(newName, value))) {
|
||||
return value;
|
||||
}
|
||||
throw new Error('Can\'t set discriminator key "' + key + '"');
|
||||
},
|
||||
$skipDiscriminatorCheck: true
|
||||
};
|
||||
obj[key][schema.options.typeKey] = existingPath ?
|
||||
existingPath.instance :
|
||||
String;
|
||||
obj[key][schema.options.typeKey] = existingPath ? existingPath.options[schema.options.typeKey] : String;
|
||||
schema.add(obj);
|
||||
|
||||
|
||||
schema.discriminatorMapping = { key: key, value: value, isRoot: false };
|
||||
|
||||
if (baseSchema.options.collection) {
|
||||
@@ -149,11 +153,17 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
|
||||
|
||||
for (const _key of keys) {
|
||||
if (!CUSTOMIZABLE_DISCRIMINATOR_OPTIONS[_key]) {
|
||||
// Special case: compiling a model sets `pluralization = true` by default. Avoid throwing an error
|
||||
// for that case. See gh-9238
|
||||
if (_key === 'pluralization' && schema.options[_key] == true && baseSchema.options[_key] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!utils.deepEqual(schema.options[_key], baseSchema.options[_key])) {
|
||||
throw new Error('Can\'t customize discriminator option ' + _key +
|
||||
' (can only modify ' +
|
||||
Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') +
|
||||
')');
|
||||
' (can only modify ' +
|
||||
Object.keys(CUSTOMIZABLE_DISCRIMINATOR_OPTIONS).join(', ') +
|
||||
')');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
7
node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
generated
vendored
7
node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
generated
vendored
@@ -69,7 +69,12 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
|
||||
if (recursed) {
|
||||
if (doc) {
|
||||
if (sorting) {
|
||||
newOrder[resultOrder[sid]] = doc;
|
||||
const _resultOrder = resultOrder[sid];
|
||||
if (Array.isArray(_resultOrder) && Array.isArray(doc) && _resultOrder.length === doc.length) {
|
||||
newOrder.push(doc);
|
||||
} else {
|
||||
newOrder[_resultOrder] = doc;
|
||||
}
|
||||
} else {
|
||||
newOrder.push(doc);
|
||||
}
|
||||
|
||||
109
node_modules/mongoose/lib/helpers/populate/assignVals.js
generated
vendored
109
node_modules/mongoose/lib/helpers/populate/assignVals.js
generated
vendored
@@ -5,24 +5,27 @@ const assignRawDocsToIdStructure = require('./assignRawDocsToIdStructure');
|
||||
const get = require('../get');
|
||||
const getVirtual = require('./getVirtual');
|
||||
const leanPopulateMap = require('./leanPopulateMap');
|
||||
const lookupLocalFields = require('./lookupLocalFields');
|
||||
const mpath = require('mpath');
|
||||
const sift = require('sift').default;
|
||||
const utils = require('../../utils');
|
||||
|
||||
module.exports = function assignVals(o) {
|
||||
// Options that aren't explicitly listed in `populateOptions`
|
||||
const userOptions = get(o, 'allOptions.options.options');
|
||||
const userOptions = Object.assign({}, get(o, 'allOptions.options.options'), get(o, 'allOptions.options'));
|
||||
// `o.options` contains options explicitly listed in `populateOptions`, like
|
||||
// `match` and `limit`.
|
||||
const populateOptions = Object.assign({}, o.options, userOptions, {
|
||||
justOne: o.justOne
|
||||
});
|
||||
populateOptions.$nullIfNotFound = o.isVirtual;
|
||||
const populatedModel = o.populatedModel;
|
||||
|
||||
const originalIds = [].concat(o.rawIds);
|
||||
|
||||
// replace the original ids in our intermediate _ids structure
|
||||
// with the documents found by query
|
||||
o.allIds = [].concat(o.allIds);
|
||||
assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);
|
||||
|
||||
// now update the original documents being populated using the
|
||||
@@ -31,6 +34,7 @@ module.exports = function assignVals(o) {
|
||||
const rawIds = o.rawIds;
|
||||
const options = o.options;
|
||||
const count = o.count && o.isVirtual;
|
||||
let i;
|
||||
|
||||
function setValue(val) {
|
||||
if (count) {
|
||||
@@ -39,17 +43,42 @@ module.exports = function assignVals(o) {
|
||||
if (val instanceof SkipPopulateValue) {
|
||||
return val.val;
|
||||
}
|
||||
if (o.justOne === true && Array.isArray(val)) {
|
||||
return valueFilter(val[0], options, populateOptions);
|
||||
} else if (o.justOne === false && !Array.isArray(val)) {
|
||||
return valueFilter([val], options, populateOptions);
|
||||
if (val === void 0) {
|
||||
return val;
|
||||
}
|
||||
return valueFilter(val, options, populateOptions);
|
||||
|
||||
const _allIds = o.allIds[i];
|
||||
|
||||
if (o.justOne === true && Array.isArray(val)) {
|
||||
// Might be an embedded discriminator (re: gh-9244) with multiple models, so make sure to pick the right
|
||||
// model before assigning.
|
||||
const ret = [];
|
||||
for (const doc of val) {
|
||||
const _docPopulatedModel = leanPopulateMap.get(doc);
|
||||
if (_docPopulatedModel == null || _docPopulatedModel === populatedModel) {
|
||||
ret.push(doc);
|
||||
}
|
||||
}
|
||||
// Since we don't want to have to create a new mongoosearray, make sure to
|
||||
// modify the array in place
|
||||
while (val.length > ret.length) {
|
||||
Array.prototype.pop.apply(val, []);
|
||||
}
|
||||
for (let i = 0; i < ret.length; ++i) {
|
||||
val[i] = ret[i];
|
||||
}
|
||||
|
||||
return valueFilter(val[0], options, populateOptions, _allIds);
|
||||
} else if (o.justOne === false && !Array.isArray(val)) {
|
||||
return valueFilter([val], options, populateOptions, _allIds);
|
||||
}
|
||||
return valueFilter(val, options, populateOptions, _allIds);
|
||||
}
|
||||
|
||||
for (let i = 0; i < docs.length; ++i) {
|
||||
const existingVal = utils.getValue(o.path, docs[i]);
|
||||
if (existingVal == null && !getVirtual(o.originalModel.schema, o.path)) {
|
||||
for (i = 0; i < docs.length; ++i) {
|
||||
const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
|
||||
const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
|
||||
if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -58,8 +87,8 @@ module.exports = function assignVals(o) {
|
||||
valueToSet = numDocs(rawIds[i]);
|
||||
} else if (Array.isArray(o.match)) {
|
||||
valueToSet = Array.isArray(rawIds[i]) ?
|
||||
sift(o.match[i], rawIds[i]) :
|
||||
sift(o.match[i], [rawIds[i]])[0];
|
||||
rawIds[i].filter(sift(o.match[i])) :
|
||||
[rawIds[i]].filter(sift(o.match[i]))[0];
|
||||
} else {
|
||||
valueToSet = rawIds[i];
|
||||
}
|
||||
@@ -73,7 +102,7 @@ module.exports = function assignVals(o) {
|
||||
utils.isPOJO(existingVal);
|
||||
// If we pass the first check, also make sure the local field's schematype
|
||||
// is map (re: gh-6460)
|
||||
isMap = isMap && get(originalSchema._getSchema(o.path), '$isSchemaMap');
|
||||
isMap = isMap && get(originalSchema._getSchema(_path), '$isSchemaMap');
|
||||
if (!o.isVirtual && isMap) {
|
||||
const _keys = existingVal instanceof Map ?
|
||||
Array.from(existingVal.keys()) :
|
||||
@@ -84,15 +113,25 @@ module.exports = function assignVals(o) {
|
||||
}, new Map());
|
||||
}
|
||||
|
||||
if (isDoc && Array.isArray(valueToSet)) {
|
||||
for (const val of valueToSet) {
|
||||
if (val != null && val.$__ != null) {
|
||||
val.$__.parent = docs[i];
|
||||
}
|
||||
}
|
||||
} else if (isDoc && valueToSet != null && valueToSet.$__ != null) {
|
||||
valueToSet.$__.parent = docs[i];
|
||||
}
|
||||
|
||||
if (o.isVirtual && isDoc) {
|
||||
docs[i].populated(o.path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
|
||||
docs[i].populated(_path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
|
||||
// If virtual populate and doc is already init-ed, need to walk through
|
||||
// the actual doc to set rather than setting `_doc` directly
|
||||
mpath.set(o.path, valueToSet, docs[i], setValue);
|
||||
mpath.set(_path, valueToSet, docs[i], setValue);
|
||||
continue;
|
||||
}
|
||||
|
||||
const parts = o.path.split('.');
|
||||
const parts = _path.split('.');
|
||||
let cur = docs[i];
|
||||
const curPath = parts[0];
|
||||
for (let j = 0; j < parts.length - 1; ++j) {
|
||||
@@ -102,13 +141,17 @@ module.exports = function assignVals(o) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (parts[j] === '$*') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (cur[parts[j]] == null) {
|
||||
// If nothing to set, avoid creating an unnecessary array. Otherwise
|
||||
// we'll end up with a single doc in the array with only defaults.
|
||||
// See gh-8342, gh-8455
|
||||
const schematype = originalSchema._getSchema(curPath);
|
||||
if (valueToSet == null && schematype != null && schematype.$isMongooseArray) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
cur[parts[j]] = {};
|
||||
}
|
||||
@@ -116,17 +159,17 @@ module.exports = function assignVals(o) {
|
||||
// If the property in MongoDB is a primitive, we won't be able to populate
|
||||
// the nested path, so skip it. See gh-7545
|
||||
if (typeof cur !== 'object') {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (docs[i].$__) {
|
||||
docs[i].populated(o.path, o.allIds[i], o.allOptions);
|
||||
docs[i].populated(_path, o.allIds[i], o.allOptions);
|
||||
}
|
||||
|
||||
// If lean, need to check that each individual virtual respects
|
||||
// `justOne`, because you may have a populated virtual with `justOne`
|
||||
// underneath an array. See gh-6867
|
||||
utils.setValue(o.path, valueToSet, docs[i], setValue, false);
|
||||
mpath.set(_path, valueToSet, docs[i], lookupLocalFields, setValue, false);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -160,15 +203,20 @@ function numDocs(v) {
|
||||
* that population mapping can occur.
|
||||
*/
|
||||
|
||||
function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
function valueFilter(val, assignmentOpts, populateOptions, allIds) {
|
||||
const userSpecifiedTransform = typeof populateOptions.transform === 'function';
|
||||
const transform = userSpecifiedTransform ? populateOptions.transform : noop;
|
||||
if (Array.isArray(val)) {
|
||||
// find logic
|
||||
const ret = [];
|
||||
const numValues = val.length;
|
||||
for (let i = 0; i < numValues; ++i) {
|
||||
const subdoc = val[i];
|
||||
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null)) {
|
||||
let subdoc = val[i];
|
||||
const _allIds = Array.isArray(allIds) ? allIds[i] : allIds;
|
||||
if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
|
||||
continue;
|
||||
} else if (userSpecifiedTransform) {
|
||||
subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, _allIds);
|
||||
}
|
||||
maybeRemoveId(subdoc, assignmentOpts);
|
||||
ret.push(subdoc);
|
||||
@@ -190,22 +238,19 @@ function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
}
|
||||
|
||||
// findOne
|
||||
if (isPopulatedObject(val)) {
|
||||
if (isPopulatedObject(val) || utils.isPOJO(val)) {
|
||||
maybeRemoveId(val, assignmentOpts);
|
||||
return val;
|
||||
return transform(val, allIds);
|
||||
}
|
||||
|
||||
if (val instanceof Map) {
|
||||
return val;
|
||||
}
|
||||
|
||||
if (populateOptions.justOne === true) {
|
||||
return (val == null ? val : null);
|
||||
}
|
||||
if (populateOptions.justOne === false) {
|
||||
return [];
|
||||
}
|
||||
return val;
|
||||
|
||||
return val == null ? transform(val, allIds) : transform(null, allIds);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -213,7 +258,7 @@ function valueFilter(val, assignmentOpts, populateOptions) {
|
||||
*/
|
||||
|
||||
function maybeRemoveId(subdoc, assignmentOpts) {
|
||||
if (assignmentOpts.excludeId) {
|
||||
if (subdoc != null && assignmentOpts.excludeId) {
|
||||
if (typeof subdoc.$__setValue === 'function') {
|
||||
delete subdoc._doc._id;
|
||||
} else {
|
||||
@@ -236,4 +281,8 @@ function isPopulatedObject(obj) {
|
||||
obj.$isMongooseMap ||
|
||||
obj.$__ != null ||
|
||||
leanPopulateMap.has(obj);
|
||||
}
|
||||
|
||||
function noop(v) {
|
||||
return v;
|
||||
}
|
||||
127
node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
generated
vendored
127
node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
generated
vendored
@@ -5,8 +5,11 @@ const SkipPopulateValue = require('./SkipPopulateValue');
|
||||
const get = require('../get');
|
||||
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
|
||||
const isPathExcluded = require('../projection/isPathExcluded');
|
||||
const getConstructorName = require('../getConstructorName');
|
||||
const getSchemaTypes = require('./getSchemaTypes');
|
||||
const getVirtual = require('./getVirtual');
|
||||
const lookupLocalFields = require('./lookupLocalFields');
|
||||
const mpath = require('mpath');
|
||||
const normalizeRefPath = require('./normalizeRefPath');
|
||||
const util = require('util');
|
||||
const utils = require('../../utils');
|
||||
@@ -28,7 +31,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
let currentOptions;
|
||||
let modelNames;
|
||||
let modelName;
|
||||
let modelForFindSchema;
|
||||
|
||||
const originalModel = options.model;
|
||||
let isVirtual = false;
|
||||
@@ -40,7 +42,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
doc = docs[i];
|
||||
|
||||
let justOne = null;
|
||||
schema = getSchemaTypes(modelSchema, doc, options.path);
|
||||
// Special case: populating a path that's a DocumentArray unless
|
||||
// there's an explicit `ref` or `refPath` re: gh-8946
|
||||
@@ -52,7 +54,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
// Populating a nested path should always be a no-op re: #9073.
|
||||
// People shouldn't do this, but apparently they do.
|
||||
if (modelSchema.nested[options.path]) {
|
||||
if (options._localModel != null && options._localModel.schema.nested[options.path]) {
|
||||
continue;
|
||||
}
|
||||
const isUnderneathDocArray = schema && schema.$isUnderneathDocArray;
|
||||
@@ -64,6 +66,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
modelNames = null;
|
||||
let isRefPath = !!_firstWithRefPath;
|
||||
let normalizedRefPath = _firstWithRefPath ? get(_firstWithRefPath, 'options.refPath', null) : null;
|
||||
let schemaOptions = null;
|
||||
|
||||
if (Array.isArray(schema)) {
|
||||
const schemasArray = schema;
|
||||
@@ -76,6 +79,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
isRefPath = isRefPath || res.isRefPath;
|
||||
normalizedRefPath = normalizeRefPath(normalizedRefPath, doc, options.path) ||
|
||||
res.refPath;
|
||||
justOne = res.justOne;
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -99,6 +103,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
modelNames = res.modelNames;
|
||||
isRefPath = res.isRefPath;
|
||||
normalizedRefPath = res.refPath;
|
||||
justOne = res.justOne;
|
||||
schemaOptions = get(schema, 'options.populate', null);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
@@ -118,6 +124,8 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
_virtualRes.nestedSchemaPath + '.' : '';
|
||||
if (typeof virtual.options.localField === 'function') {
|
||||
localField = virtualPrefix + virtual.options.localField.call(doc, doc);
|
||||
} else if (Array.isArray(virtual.options.localField)) {
|
||||
localField = virtual.options.localField.map(field => virtualPrefix + field);
|
||||
} else {
|
||||
localField = virtualPrefix + virtual.options.localField;
|
||||
}
|
||||
@@ -142,7 +150,6 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
// `justOne = null` means we don't know from the schema whether the end
|
||||
// result should be an array or a single doc. This can result from
|
||||
// populating a POJO using `Model.populate()`
|
||||
let justOne = null;
|
||||
if ('justOne' in options && options.justOne !== void 0) {
|
||||
justOne = options.justOne;
|
||||
} else if (virtual && virtual.options && virtual.options.refPath) {
|
||||
@@ -166,9 +173,11 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
} else if (schema && !schema[schemaMixedSymbol]) {
|
||||
// Skip Mixed types because we explicitly don't do casting on those.
|
||||
justOne = Array.isArray(schema) ?
|
||||
schema.every(schema => !schema.$isMongooseArray) :
|
||||
!schema.$isMongooseArray;
|
||||
if (options.path.endsWith('.' + schema.path)) {
|
||||
justOne = Array.isArray(schema) ?
|
||||
schema.every(schema => !schema.$isMongooseArray) :
|
||||
!schema.$isMongooseArray;
|
||||
}
|
||||
}
|
||||
|
||||
if (!modelNames) {
|
||||
@@ -189,6 +198,27 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
foreignField = foreignField.call(doc);
|
||||
}
|
||||
|
||||
let match = get(options, 'match', null) ||
|
||||
get(currentOptions, 'match', null) ||
|
||||
get(options, 'virtual.options.match', null) ||
|
||||
get(options, 'virtual.options.options.match', null);
|
||||
|
||||
let hasMatchFunction = typeof match === 'function';
|
||||
if (hasMatchFunction) {
|
||||
match = match.call(doc, doc);
|
||||
}
|
||||
|
||||
if (Array.isArray(localField) && Array.isArray(foreignField) && localField.length === foreignField.length) {
|
||||
match = Object.assign({}, match);
|
||||
for (let i = 1; i < localField.length; ++i) {
|
||||
match[foreignField[i]] = convertTo_id(mpath.get(localField[i], doc, lookupLocalFields), schema);
|
||||
hasMatchFunction = true;
|
||||
}
|
||||
|
||||
localField = localField[0];
|
||||
foreignField = foreignField[0];
|
||||
}
|
||||
|
||||
const localFieldPathType = modelSchema._getPathType(localField);
|
||||
const localFieldPath = localFieldPathType === 'real' ? modelSchema.path(localField) : localFieldPathType.schema;
|
||||
const localFieldGetters = localFieldPath && localFieldPath.getters ? localFieldPath.getters : [];
|
||||
@@ -201,31 +231,21 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
options.isVirtual && get(virtual, 'options.getters', false);
|
||||
if (localFieldGetters.length > 0 && getters) {
|
||||
const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
|
||||
const localFieldValue = utils.getValue(localField, doc);
|
||||
const localFieldValue = mpath.get(localField, doc, lookupLocalFields);
|
||||
if (Array.isArray(localFieldValue)) {
|
||||
const localFieldHydratedValue = utils.getValue(localField.split('.').slice(0, -1), hydratedDoc);
|
||||
const localFieldHydratedValue = mpath.get(localField.split('.').slice(0, -1), hydratedDoc, lookupLocalFields);
|
||||
ret = localFieldValue.map((localFieldArrVal, localFieldArrIndex) =>
|
||||
localFieldPath.applyGetters(localFieldArrVal, localFieldHydratedValue[localFieldArrIndex]));
|
||||
} else {
|
||||
ret = localFieldPath.applyGetters(localFieldValue, hydratedDoc);
|
||||
}
|
||||
} else {
|
||||
ret = convertTo_id(utils.getValue(localField, doc), schema);
|
||||
ret = convertTo_id(mpath.get(localField, doc, lookupLocalFields), schema);
|
||||
}
|
||||
|
||||
const id = String(utils.getValue(foreignField, doc));
|
||||
options._docs[id] = Array.isArray(ret) ? ret.slice() : ret;
|
||||
|
||||
let match = get(options, 'match', null) ||
|
||||
get(currentOptions, 'match', null) ||
|
||||
get(options, 'virtual.options.match', null) ||
|
||||
get(options, 'virtual.options.options.match', null);
|
||||
|
||||
const hasMatchFunction = typeof match === 'function';
|
||||
if (hasMatchFunction) {
|
||||
match = match.call(doc, doc);
|
||||
}
|
||||
|
||||
// Re: gh-8452. Embedded discriminators may not have `refPath`, so clear
|
||||
// out embedded discriminator docs that don't have a `refPath` on the
|
||||
// populated path.
|
||||
@@ -280,7 +300,12 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
originalModel :
|
||||
modelName[modelSymbol] ? modelName : connection.model(modelName);
|
||||
} catch (error) {
|
||||
return error;
|
||||
// If `ret` is undefined, we'll add an empty entry to modelsMap. We shouldn't
|
||||
// execute a query, but it is necessary to make sure `justOne` gets handled
|
||||
// correctly for setting an empty array (see gh-8455)
|
||||
if (ret !== undefined) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
let ids = ret;
|
||||
@@ -290,13 +315,15 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
ids = flat.filter((val, i) => modelNames[i] === modelName);
|
||||
}
|
||||
|
||||
if (!available[modelName] || currentOptions.perDocumentLimit != null) {
|
||||
if (!available[modelName] || currentOptions.perDocumentLimit != null || get(currentOptions, 'options.perDocumentLimit') != null) {
|
||||
currentOptions = {
|
||||
model: Model
|
||||
};
|
||||
|
||||
if (isVirtual && get(virtual, 'options.options')) {
|
||||
currentOptions.options = utils.clone(virtual.options.options);
|
||||
} else if (schemaOptions != null) {
|
||||
currentOptions.options = Object.assign({}, schemaOptions);
|
||||
}
|
||||
utils.merge(currentOptions, options);
|
||||
|
||||
@@ -332,13 +359,13 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
|
||||
function _getModelNames(doc, schema) {
|
||||
let modelNames;
|
||||
let discriminatorKey;
|
||||
let isRefPath = false;
|
||||
let justOne = null;
|
||||
|
||||
if (schema && schema.caster) {
|
||||
schema = schema.caster;
|
||||
@@ -378,28 +405,26 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
} else {
|
||||
let modelForCurrentDoc = model;
|
||||
let schemaForCurrentDoc;
|
||||
let discriminatorValue;
|
||||
|
||||
if (!schema && discriminatorKey) {
|
||||
modelForFindSchema = utils.getValue(discriminatorKey, doc);
|
||||
if (modelForFindSchema) {
|
||||
// `modelForFindSchema` is the discriminator value, so we might need
|
||||
// find the discriminated model name
|
||||
const discriminatorModel = getDiscriminatorByValue(model, modelForFindSchema);
|
||||
if (discriminatorModel != null) {
|
||||
modelForCurrentDoc = discriminatorModel;
|
||||
} else {
|
||||
try {
|
||||
modelForCurrentDoc = model.db.model(modelForFindSchema);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
if (!schema && discriminatorKey && (discriminatorValue = utils.getValue(discriminatorKey, doc))) {
|
||||
// `modelNameForFind` is the discriminator value, so we might need
|
||||
// find the discriminated model name
|
||||
const discriminatorModel = getDiscriminatorByValue(model.discriminators, discriminatorValue) || model;
|
||||
if (discriminatorModel != null) {
|
||||
modelForCurrentDoc = discriminatorModel;
|
||||
} else {
|
||||
try {
|
||||
modelForCurrentDoc = model.db.model(discriminatorValue);
|
||||
} catch (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
|
||||
schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
|
||||
|
||||
if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
|
||||
schemaForCurrentDoc = schemaForCurrentDoc.caster;
|
||||
}
|
||||
if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
|
||||
schemaForCurrentDoc = schemaForCurrentDoc.caster;
|
||||
}
|
||||
} else {
|
||||
schemaForCurrentDoc = schema;
|
||||
@@ -407,6 +432,10 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
const _virtualRes = getVirtual(modelForCurrentDoc.schema, options.path);
|
||||
const virtual = _virtualRes == null ? null : _virtualRes.virtual;
|
||||
|
||||
if (schemaForCurrentDoc != null) {
|
||||
justOne = !schemaForCurrentDoc.$isMongooseArray && !schemaForCurrentDoc._arrayPath;
|
||||
}
|
||||
|
||||
let ref;
|
||||
let refPath;
|
||||
|
||||
@@ -440,14 +469,14 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
|
||||
}
|
||||
|
||||
if (!modelNames) {
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath };
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
|
||||
}
|
||||
|
||||
if (!Array.isArray(modelNames)) {
|
||||
modelNames = [modelNames];
|
||||
}
|
||||
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath };
|
||||
return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
|
||||
}
|
||||
};
|
||||
|
||||
@@ -470,7 +499,12 @@ function handleRefFunction(ref, doc) {
|
||||
*/
|
||||
|
||||
function convertTo_id(val, schema) {
|
||||
if (val != null && val.$__ != null) return val._id;
|
||||
if (val != null && val.$__ != null) {
|
||||
return val._id;
|
||||
}
|
||||
if (val != null && val._id != null && (schema == null || !schema.$isSchemaMap)) {
|
||||
return val._id;
|
||||
}
|
||||
|
||||
if (Array.isArray(val)) {
|
||||
for (let i = 0; i < val.length; ++i) {
|
||||
@@ -479,7 +513,7 @@ function convertTo_id(val, schema) {
|
||||
}
|
||||
}
|
||||
if (val.isMongooseArray && val.$schema()) {
|
||||
return val.$schema().cast(val, val.$parent());
|
||||
return val.$schema()._castForPopulate(val, val.$parent());
|
||||
}
|
||||
|
||||
return [].concat(val);
|
||||
@@ -487,8 +521,7 @@ function convertTo_id(val, schema) {
|
||||
|
||||
// `populate('map')` may be an object if populating on a doc that hasn't
|
||||
// been hydrated yet
|
||||
if (val != null &&
|
||||
val.constructor.name === 'Object' &&
|
||||
if (getConstructorName(val) === 'Object' &&
|
||||
// The intent here is we should only flatten the object if we expect
|
||||
// to get a Map in the end. Avoid doing this for mixed types.
|
||||
(schema == null || schema[schemaMixedSymbol] == null)) {
|
||||
|
||||
35
node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
generated
vendored
35
node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
generated
vendored
@@ -20,7 +20,6 @@ const populateModelSymbol = require('../symbols').populateModelSymbol;
|
||||
module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
const pathschema = schema.path(path);
|
||||
const topLevelDoc = doc;
|
||||
|
||||
if (pathschema) {
|
||||
return pathschema;
|
||||
}
|
||||
@@ -33,7 +32,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
while (p--) {
|
||||
trypath = parts.slice(0, p).join('.');
|
||||
foundschema = schema.path(trypath);
|
||||
|
||||
if (foundschema == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -52,7 +50,8 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
const keys = subdoc ? mpath.get(discriminatorKeyPath, subdoc) || [] : [];
|
||||
schemas = Object.keys(discriminators).
|
||||
reduce(function(cur, discriminator) {
|
||||
if (doc == null || keys.indexOf(discriminator) !== -1) {
|
||||
const tiedValue = discriminators[discriminator].discriminatorMapping.value;
|
||||
if (doc == null || keys.indexOf(discriminator) !== -1 || keys.indexOf(tiedValue) !== -1) {
|
||||
cur.push(discriminators[discriminator]);
|
||||
}
|
||||
return cur;
|
||||
@@ -117,24 +116,40 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!foundschema.schema.$isSingleNested;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
} else if (p !== parts.length &&
|
||||
foundschema.$isMongooseArray &&
|
||||
foundschema.casterConstructor.$isMongooseArray) {
|
||||
// Nested arrays. Drill down to the bottom of the nested array.
|
||||
// Ignore discriminators.
|
||||
let type = foundschema;
|
||||
while (type.$isMongooseArray && !type.$isMongooseDocumentArray) {
|
||||
type = type.casterConstructor;
|
||||
}
|
||||
return search(
|
||||
|
||||
const ret = search(
|
||||
parts.slice(p),
|
||||
type.schema,
|
||||
null,
|
||||
nestedPath.concat(parts.slice(0, p))
|
||||
);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type.schema.discriminators) {
|
||||
const discriminatorPaths = [];
|
||||
for (const discriminatorName of Object.keys(type.schema.discriminators)) {
|
||||
const _schema = type.schema.discriminators[discriminatorName] || type.schema;
|
||||
const ret = search(parts.slice(p), _schema, null, nestedPath.concat(parts.slice(0, p)));
|
||||
if (ret != null) {
|
||||
discriminatorPaths.push(ret);
|
||||
}
|
||||
}
|
||||
if (discriminatorPaths.length > 0) {
|
||||
return discriminatorPaths;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +168,6 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!model.schema.$isSingleNested;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -173,19 +187,16 @@ module.exports = function getSchemaTypes(schema, doc, path) {
|
||||
nestedPath.concat(parts.slice(0, p))
|
||||
);
|
||||
|
||||
if (ret) {
|
||||
if (ret != null) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!schema.$isSingleNested;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return foundschema;
|
||||
}
|
||||
}
|
||||
|
||||
// look for arrays
|
||||
const parts = path.split('.');
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
|
||||
7
node_modules/mongoose/lib/helpers/printJestWarning.js
generated
vendored
7
node_modules/mongoose/lib/helpers/printJestWarning.js
generated
vendored
@@ -5,4 +5,11 @@ if (typeof jest !== 'undefined' && typeof window !== 'undefined') {
|
||||
'with Jest\'s default jsdom test environment. Please make sure you read ' +
|
||||
'Mongoose\'s docs on configuring Jest to test Node.js apps: ' +
|
||||
'http://mongoosejs.com/docs/jest.html');
|
||||
}
|
||||
|
||||
if (typeof jest !== 'undefined' && process.nextTick.toString().indexOf('nextTick') === -1) {
|
||||
console.warn('Mongoose: looks like you\'re trying to test a Mongoose app ' +
|
||||
'with Jest\'s mock timers enabled. Please make sure you read ' +
|
||||
'Mongoose\'s docs on configuring Jest to test Node.js apps: ' +
|
||||
'http://mongoosejs.com/docs/jest.html');
|
||||
}
|
||||
4
node_modules/mongoose/lib/helpers/projection/isExclusive.js
generated
vendored
4
node_modules/mongoose/lib/helpers/projection/isExclusive.js
generated
vendored
@@ -7,6 +7,10 @@ const isDefiningProjection = require('./isDefiningProjection');
|
||||
*/
|
||||
|
||||
module.exports = function isExclusive(projection) {
|
||||
if (projection == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const keys = Object.keys(projection);
|
||||
let ki = keys.length;
|
||||
let exclude = null;
|
||||
|
||||
15
node_modules/mongoose/lib/helpers/promiseOrCallback.js
generated
vendored
15
node_modules/mongoose/lib/helpers/promiseOrCallback.js
generated
vendored
@@ -1,21 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const PromiseProvider = require('../promise_provider');
|
||||
const immediate = require('./immediate');
|
||||
|
||||
const emittedSymbol = Symbol.for('mongoose:emitted');
|
||||
const emittedSymbol = Symbol('mongoose:emitted');
|
||||
|
||||
module.exports = function promiseOrCallback(callback, fn, ee) {
|
||||
module.exports = function promiseOrCallback(callback, fn, ee, Promise) {
|
||||
if (typeof callback === 'function') {
|
||||
return fn(function(error) {
|
||||
if (error != null) {
|
||||
if (ee != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
|
||||
if (ee != null && ee.listeners != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
|
||||
error[emittedSymbol] = true;
|
||||
ee.emit('error', error);
|
||||
}
|
||||
try {
|
||||
callback(error);
|
||||
} catch (error) {
|
||||
return process.nextTick(() => {
|
||||
return immediate(() => {
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
@@ -25,12 +26,12 @@ module.exports = function promiseOrCallback(callback, fn, ee) {
|
||||
});
|
||||
}
|
||||
|
||||
const Promise = PromiseProvider.get();
|
||||
Promise = Promise || PromiseProvider.get();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
fn(function(error, res) {
|
||||
if (error != null) {
|
||||
if (ee != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
|
||||
if (ee != null && ee.listeners != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
|
||||
error[emittedSymbol] = true;
|
||||
ee.emit('error', error);
|
||||
}
|
||||
@@ -42,4 +43,4 @@ module.exports = function promiseOrCallback(callback, fn, ee) {
|
||||
resolve(res);
|
||||
});
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
3
node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js
generated
vendored
3
node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js
generated
vendored
@@ -56,6 +56,9 @@ function applyQueryMiddleware(Query, model) {
|
||||
if (hook.name === 'validate' || hook.name === 'remove') {
|
||||
return !!contexts.query;
|
||||
}
|
||||
if (hook.query != null || hook.document != null) {
|
||||
return !!hook.query;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
2
node_modules/mongoose/lib/helpers/query/castFilterPath.js
generated
vendored
2
node_modules/mongoose/lib/helpers/query/castFilterPath.js
generated
vendored
@@ -25,7 +25,7 @@ module.exports = function castFilterPath(query, schematype, val) {
|
||||
if (nested && schematype && !schematype.caster) {
|
||||
const _keys = Object.keys(nested);
|
||||
if (_keys.length && isOperator(_keys[0])) {
|
||||
for (const key in nested) {
|
||||
for (const key of Object.keys(nested)) {
|
||||
nested[key] = schematype.castForQueryWrapper({
|
||||
$conditional: key,
|
||||
val: nested[key],
|
||||
|
||||
34
node_modules/mongoose/lib/helpers/query/castUpdate.js
generated
vendored
34
node_modules/mongoose/lib/helpers/query/castUpdate.js
generated
vendored
@@ -6,10 +6,12 @@ const StrictModeError = require('../../error/strict');
|
||||
const ValidationError = require('../../error/validation');
|
||||
const castNumber = require('../../cast/number');
|
||||
const cast = require('../../cast');
|
||||
const getConstructorName = require('../getConstructorName');
|
||||
const getEmbeddedDiscriminatorPath = require('./getEmbeddedDiscriminatorPath');
|
||||
const handleImmutable = require('./handleImmutable');
|
||||
const moveImmutableProperties = require('../update/moveImmutableProperties');
|
||||
const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
|
||||
const setDottedPath = require('../path/setDottedPath');
|
||||
const utils = require('../../utils');
|
||||
|
||||
/*!
|
||||
@@ -105,6 +107,14 @@ module.exports = function castUpdate(schema, obj, options, context, filter) {
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(ret).length === 0 &&
|
||||
options.upsert &&
|
||||
Object.keys(filter).length > 0) {
|
||||
// Trick the driver into allowing empty upserts to work around
|
||||
// https://github.com/mongodb/node-mongodb-native/pull/2490
|
||||
return { $setOnInsert: filter };
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
@@ -191,11 +201,19 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
|
||||
}
|
||||
}
|
||||
|
||||
if (val && val.constructor.name === 'Object') {
|
||||
if (getConstructorName(val) === 'Object') {
|
||||
// watch for embedded doc schemas
|
||||
schematype = schema._getSchema(prefix + key);
|
||||
|
||||
if (handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
|
||||
if (schematype == null) {
|
||||
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, prefix + key, options);
|
||||
if (_res.schematype != null) {
|
||||
schematype = _res.schematype;
|
||||
}
|
||||
}
|
||||
|
||||
if (op !== '$setOnInsert' &&
|
||||
handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -308,7 +326,7 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
|
||||
// If no schema type, check for embedded discriminators because the
|
||||
// filter or update may imply an embedded discriminator type. See #8378
|
||||
if (schematype == null) {
|
||||
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath);
|
||||
const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath, options);
|
||||
if (_res.schematype != null) {
|
||||
schematype = _res.schematype;
|
||||
pathDetails = _res.type;
|
||||
@@ -344,7 +362,15 @@ function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
|
||||
}
|
||||
|
||||
try {
|
||||
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
|
||||
if (prefix.length === 0 || key.indexOf('.') === -1) {
|
||||
obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
|
||||
} else {
|
||||
// Setting a nested dotted path that's in the schema. We don't allow paths with '.' in
|
||||
// a schema, so replace the dotted path with a nested object to avoid ending up with
|
||||
// dotted properties in the updated object. See (gh-10200)
|
||||
setDottedPath(obj, key, castUpdateVal(schematype, val, op, key, context, prefix + key));
|
||||
delete obj[key];
|
||||
}
|
||||
} catch (error) {
|
||||
aggregatedError = _handleCastError(error, context, key, aggregatedError);
|
||||
}
|
||||
|
||||
10
node_modules/mongoose/lib/helpers/query/completeMany.js
generated
vendored
10
node_modules/mongoose/lib/helpers/query/completeMany.js
generated
vendored
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const helpers = require('../../queryhelpers');
|
||||
const immediate = require('../immediate');
|
||||
|
||||
module.exports = completeMany;
|
||||
|
||||
@@ -29,10 +30,10 @@ function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
|
||||
error = error || _error;
|
||||
}
|
||||
if (error != null) {
|
||||
--count || process.nextTick(() => callback(error));
|
||||
--count || immediate(() => callback(error));
|
||||
return;
|
||||
}
|
||||
--count || process.nextTick(() => callback(error, arr));
|
||||
--count || immediate(() => callback(error, arr));
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; ++i) {
|
||||
@@ -42,6 +43,9 @@ function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
|
||||
} catch (error) {
|
||||
init(error);
|
||||
}
|
||||
arr[i].$session(opts.session);
|
||||
|
||||
if (opts.session != null) {
|
||||
arr[i].$session(opts.session);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
20
node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js
generated
vendored
20
node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js
generated
vendored
@@ -3,19 +3,23 @@
|
||||
const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
|
||||
const get = require('../get');
|
||||
const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
|
||||
const updatedPathsByArrayFilter = require('../update/updatedPathsByArrayFilter');
|
||||
|
||||
/*!
|
||||
* Like `schema.path()`, except with a document, because impossible to
|
||||
* determine path type without knowing the embedded discriminator key.
|
||||
*/
|
||||
|
||||
module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path) {
|
||||
module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, path, options) {
|
||||
const parts = path.split('.');
|
||||
let schematype = null;
|
||||
let type = 'adhocOrUndefined';
|
||||
|
||||
filter = filter || {};
|
||||
update = update || {};
|
||||
const arrayFilters = options != null && Array.isArray(options.arrayFilters) ?
|
||||
options.arrayFilters : [];
|
||||
const updatedPathsByFilter = updatedPathsByArrayFilter(update);
|
||||
|
||||
for (let i = 0; i < parts.length; ++i) {
|
||||
const subpath = cleanPositionalOperators(parts.slice(0, i + 1).join('.'));
|
||||
@@ -39,6 +43,7 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
|
||||
if (discriminatorFilterPath in filter) {
|
||||
discriminatorKey = filter[discriminatorFilterPath];
|
||||
}
|
||||
|
||||
const wrapperPath = subpath.replace(/\.\d+$/, '');
|
||||
if (schematype.$isMongooseDocumentArrayElement &&
|
||||
get(filter[wrapperPath], '$elemMatch.' + key) != null) {
|
||||
@@ -49,11 +54,22 @@ module.exports = function getEmbeddedDiscriminatorPath(schema, update, filter, p
|
||||
discriminatorKey = update[discriminatorValuePath];
|
||||
}
|
||||
|
||||
for (const filterKey of Object.keys(updatedPathsByFilter)) {
|
||||
const schemaKey = updatedPathsByFilter[filterKey] + '.' + key;
|
||||
const arrayFilterKey = filterKey + '.' + key;
|
||||
if (schemaKey === discriminatorFilterPath) {
|
||||
const filter = arrayFilters.find(filter => filter.hasOwnProperty(arrayFilterKey));
|
||||
if (filter != null) {
|
||||
discriminatorKey = filter[arrayFilterKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (discriminatorKey == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const discriminatorSchema = getDiscriminatorByValue(schematype.caster, discriminatorKey).schema;
|
||||
const discriminatorSchema = getDiscriminatorByValue(schematype.caster.discriminators, discriminatorKey).schema;
|
||||
|
||||
const rest = parts.slice(i + 1).join('.');
|
||||
schematype = discriminatorSchema.path(rest);
|
||||
|
||||
41
node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js
generated
vendored
41
node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js
generated
vendored
@@ -1,28 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const isExclusive = require('../projection/isExclusive');
|
||||
const isInclusive = require('../projection/isInclusive');
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
module.exports = function selectPopulatedFields(query) {
|
||||
const opts = query._mongooseOptions;
|
||||
module.exports = function selectPopulatedFields(fields, userProvidedFields, populateOptions) {
|
||||
if (populateOptions == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (opts.populate != null) {
|
||||
const paths = Object.keys(opts.populate);
|
||||
const userProvidedFields = query._userProvidedFields || {};
|
||||
if (query.selectedInclusively()) {
|
||||
for (const path of paths) {
|
||||
if (!isPathInFields(userProvidedFields, path)) {
|
||||
query.select(path);
|
||||
} else if (userProvidedFields[path] === 0) {
|
||||
delete query._fields[path];
|
||||
}
|
||||
const paths = Object.keys(populateOptions);
|
||||
userProvidedFields = userProvidedFields || {};
|
||||
if (isInclusive(fields)) {
|
||||
for (const path of paths) {
|
||||
if (!isPathInFields(userProvidedFields, path)) {
|
||||
fields[path] = 1;
|
||||
} else if (userProvidedFields[path] === 0) {
|
||||
delete fields[path];
|
||||
}
|
||||
} else if (query.selectedExclusively()) {
|
||||
for (const path of paths) {
|
||||
if (userProvidedFields[path] == null) {
|
||||
delete query._fields[path];
|
||||
}
|
||||
}
|
||||
} else if (isExclusive(fields)) {
|
||||
for (const path of paths) {
|
||||
if (userProvidedFields[path] == null) {
|
||||
delete fields[path];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,10 +40,10 @@ function isPathInFields(userProvidedFields, path) {
|
||||
const len = pieces.length;
|
||||
let cur = pieces[0];
|
||||
for (let i = 1; i < len; ++i) {
|
||||
if (userProvidedFields[cur] != null) {
|
||||
if (userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null) {
|
||||
return true;
|
||||
}
|
||||
cur += '.' + pieces[i];
|
||||
}
|
||||
return userProvidedFields[cur] != null;
|
||||
return userProvidedFields[cur] != null || userProvidedFields[cur + '.$'] != null;
|
||||
}
|
||||
|
||||
28
node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js
generated
vendored
28
node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js
generated
vendored
@@ -4,13 +4,27 @@ const get = require('../get');
|
||||
|
||||
module.exports = function applyWriteConcern(schema, options) {
|
||||
const writeConcern = get(schema, 'options.writeConcern', {});
|
||||
if (!('w' in options) && writeConcern.w != null) {
|
||||
options.w = writeConcern.w;
|
||||
if (Object.keys(writeConcern).length != 0) {
|
||||
options.writeConcern = {};
|
||||
if (!('w' in options) && writeConcern.w != null) {
|
||||
options.writeConcern.w = writeConcern.w;
|
||||
}
|
||||
if (!('j' in options) && writeConcern.j != null) {
|
||||
options.writeConcern.j = writeConcern.j;
|
||||
}
|
||||
if (!('wtimeout' in options) && writeConcern.wtimeout != null) {
|
||||
options.writeConcern.wtimeout = writeConcern.wtimeout;
|
||||
}
|
||||
}
|
||||
if (!('j' in options) && writeConcern.j != null) {
|
||||
options.j = writeConcern.j;
|
||||
}
|
||||
if (!('wtimeout' in options) && writeConcern.wtimeout != null) {
|
||||
options.wtimeout = writeConcern.wtimeout;
|
||||
else {
|
||||
if (!('w' in options) && writeConcern.w != null) {
|
||||
options.w = writeConcern.w;
|
||||
}
|
||||
if (!('j' in options) && writeConcern.j != null) {
|
||||
options.j = writeConcern.j;
|
||||
}
|
||||
if (!('wtimeout' in options) && writeConcern.wtimeout != null) {
|
||||
options.wtimeout = writeConcern.wtimeout;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
4
node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js
generated
vendored
4
node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js
generated
vendored
@@ -7,6 +7,6 @@
|
||||
|
||||
module.exports = function cleanPositionalOperators(path) {
|
||||
return path.
|
||||
replace(/\.\$(\[[^\]]*\])?\./g, '.0.').
|
||||
replace(/\.(\[[^\]]*\])?\$$/g, '.0');
|
||||
replace(/\.\$(\[[^\]]*\])?(?=\.)/g, '.0').
|
||||
replace(/\.\$(\[[^\]]*\])?$/g, '.0');
|
||||
};
|
||||
12
node_modules/mongoose/lib/helpers/schema/merge.js
generated
vendored
12
node_modules/mongoose/lib/helpers/schema/merge.js
generated
vendored
@@ -1,7 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function merge(s1, s2) {
|
||||
s1.add(s2.tree || {});
|
||||
module.exports = function merge(s1, s2, skipConflictingPaths) {
|
||||
const paths = Object.keys(s2.tree);
|
||||
const pathsToAdd = {};
|
||||
for (const key of paths) {
|
||||
if (skipConflictingPaths && (s1.paths[key] || s1.nested[key] || s1.singleNestedPaths[key])) {
|
||||
continue;
|
||||
}
|
||||
pathsToAdd[key] = s2.tree[key];
|
||||
}
|
||||
s1.add(pathsToAdd);
|
||||
|
||||
s1.callQueue = s1.callQueue.concat(s2.callQueue);
|
||||
s1.method(s2.methods);
|
||||
|
||||
6
node_modules/mongoose/lib/helpers/schematype/handleImmutable.js
generated
vendored
6
node_modules/mongoose/lib/helpers/schematype/handleImmutable.js
generated
vendored
@@ -33,11 +33,13 @@ function createImmutableSetter(path, immutable) {
|
||||
if (!_immutable) {
|
||||
return v;
|
||||
}
|
||||
if (this.$__.strictMode === 'throw' && v !== this[path]) {
|
||||
|
||||
const _value = this.$__getValue(path);
|
||||
if (this.$__.strictMode === 'throw' && v !== _value) {
|
||||
throw new StrictModeError(path, 'Path `' + path + '` is immutable ' +
|
||||
'and strict mode is set to throw.', true);
|
||||
}
|
||||
|
||||
return this[path];
|
||||
return _value;
|
||||
};
|
||||
}
|
||||
|
||||
17
node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js
generated
vendored
17
node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js
generated
vendored
@@ -14,6 +14,17 @@ const get = require('./get');
|
||||
*/
|
||||
|
||||
module.exports = function(filter, schema, castedDoc, options) {
|
||||
options = options || {};
|
||||
|
||||
const shouldSetDefaultsOnInsert =
|
||||
options.setDefaultsOnInsert != null ?
|
||||
options.setDefaultsOnInsert :
|
||||
schema.base.options.setDefaultsOnInsert;
|
||||
|
||||
if (!options.upsert || !shouldSetDefaultsOnInsert) {
|
||||
return castedDoc;
|
||||
}
|
||||
|
||||
const keys = Object.keys(castedDoc || {});
|
||||
const updatedKeys = {};
|
||||
const updatedValues = {};
|
||||
@@ -22,12 +33,6 @@ module.exports = function(filter, schema, castedDoc, options) {
|
||||
|
||||
let hasDollarUpdate = false;
|
||||
|
||||
options = options || {};
|
||||
|
||||
if (!options.upsert || !options.setDefaultsOnInsert) {
|
||||
return castedDoc;
|
||||
}
|
||||
|
||||
for (let i = 0; i < numKeys; ++i) {
|
||||
if (keys[i].startsWith('$')) {
|
||||
modifiedPaths(castedDoc[keys[i]], '', modified);
|
||||
|
||||
4
node_modules/mongoose/lib/helpers/symbols.js
generated
vendored
4
node_modules/mongoose/lib/helpers/symbols.js
generated
vendored
@@ -5,11 +5,15 @@ exports.arrayParentSymbol = Symbol('mongoose#Array#_parent');
|
||||
exports.arrayPathSymbol = Symbol('mongoose#Array#_path');
|
||||
exports.arraySchemaSymbol = Symbol('mongoose#Array#_schema');
|
||||
exports.documentArrayParent = Symbol('mongoose:documentArrayParent');
|
||||
exports.documentIsSelected = Symbol('mongoose#Document#isSelected');
|
||||
exports.documentIsModified = Symbol('mongoose#Document#isModified');
|
||||
exports.documentModifiedPaths = Symbol('mongoose#Document#modifiedPaths');
|
||||
exports.documentSchemaSymbol = Symbol('mongoose#Document#schema');
|
||||
exports.getSymbol = Symbol('mongoose#Document#get');
|
||||
exports.modelSymbol = Symbol('mongoose#Model');
|
||||
exports.objectIdSymbol = Symbol('mongoose#ObjectId');
|
||||
exports.populateModelSymbol = Symbol('mongoose.PopulateOptions#Model');
|
||||
exports.schemaTypeSymbol = Symbol('mongoose#schemaType');
|
||||
exports.sessionNewDocuments = Symbol('mongoose:ClientSession#newDocuments');
|
||||
exports.scopeSymbol = Symbol('mongoose#Document#scope');
|
||||
exports.validatorErrorSymbol = Symbol('mongoose:validatorError');
|
||||
9
node_modules/mongoose/lib/helpers/topology/allServersUnknown.js
generated
vendored
9
node_modules/mongoose/lib/helpers/topology/allServersUnknown.js
generated
vendored
@@ -1,11 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const getConstructorName = require('../getConstructorName');
|
||||
|
||||
module.exports = function allServersUnknown(topologyDescription) {
|
||||
if (topologyDescription == null ||
|
||||
topologyDescription.constructor.name !== 'TopologyDescription') {
|
||||
if (getConstructorName(topologyDescription) !== 'TopologyDescription') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Array.from(topologyDescription.servers.values()).
|
||||
every(server => server.type === 'Unknown');
|
||||
const servers = Array.from(topologyDescription.servers.values());
|
||||
return servers.length > 0 && servers.every(server => server.type === 'Unknown');
|
||||
};
|
||||
10
node_modules/mongoose/lib/helpers/topology/isAtlas.js
generated
vendored
10
node_modules/mongoose/lib/helpers/topology/isAtlas.js
generated
vendored
@@ -1,11 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const getConstructorName = require('../getConstructorName');
|
||||
|
||||
module.exports = function isAtlas(topologyDescription) {
|
||||
if (topologyDescription == null ||
|
||||
topologyDescription.constructor.name !== 'TopologyDescription') {
|
||||
if (getConstructorName(topologyDescription) !== 'TopologyDescription') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Array.from(topologyDescription.servers.keys()).
|
||||
every(host => host.endsWith('.mongodb.net:27017'));
|
||||
const hostnames = Array.from(topologyDescription.servers.keys());
|
||||
return hostnames.length > 0 &&
|
||||
hostnames.every(host => host.endsWith('.mongodb.net:27017'));
|
||||
};
|
||||
230
node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js
generated
vendored
230
node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js
generated
vendored
@@ -15,133 +15,61 @@ function applyTimestampsToChildren(now, update, schema) {
|
||||
}
|
||||
|
||||
const keys = Object.keys(update);
|
||||
let key;
|
||||
let createdAt;
|
||||
let updatedAt;
|
||||
let timestamps;
|
||||
let path;
|
||||
|
||||
const hasDollarKey = keys.length && keys[0].startsWith('$');
|
||||
const hasDollarKey = keys.some(key => key.startsWith('$'));
|
||||
|
||||
if (hasDollarKey) {
|
||||
if (update.$push) {
|
||||
for (key in update.$push) {
|
||||
const $path = schema.path(key);
|
||||
if (update.$push[key] &&
|
||||
$path &&
|
||||
$path.$isMongooseDocumentArray &&
|
||||
$path.schema.options.timestamps) {
|
||||
timestamps = $path.schema.options.timestamps;
|
||||
createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
if (update.$push[key].$each) {
|
||||
update.$push[key].$each.forEach(function(subdoc) {
|
||||
if (updatedAt != null) {
|
||||
subdoc[updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
subdoc[createdAt] = now;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (updatedAt != null) {
|
||||
update.$push[key][updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
update.$push[key][createdAt] = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_applyTimestampToUpdateOperator(update.$push);
|
||||
}
|
||||
if (update.$addToSet) {
|
||||
_applyTimestampToUpdateOperator(update.$addToSet);
|
||||
}
|
||||
if (update.$set != null) {
|
||||
const keys = Object.keys(update.$set);
|
||||
for (key of keys) {
|
||||
// Replace positional operator `$` and array filters `$[]` and `$[.*]`
|
||||
const keyToSearch = cleanPositionalOperators(key);
|
||||
path = schema.path(keyToSearch);
|
||||
if (!path) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const parentSchemaTypes = [];
|
||||
const pieces = keyToSearch.split('.');
|
||||
for (let i = pieces.length - 1; i > 0; --i) {
|
||||
const s = schema.path(pieces.slice(0, i).join('.'));
|
||||
if (s != null &&
|
||||
(s.$isMongooseDocumentArray || s.$isSingleNested)) {
|
||||
parentSchemaTypes.push({ parentPath: key.split('.').slice(0, i).join('.'), parentSchemaType: s });
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(update.$set[key]) && path.$isMongooseDocumentArray) {
|
||||
applyTimestampsToDocumentArray(update.$set[key], path, now);
|
||||
} else if (update.$set[key] && path.$isSingleNested) {
|
||||
applyTimestampsToSingleNested(update.$set[key], path, now);
|
||||
} else if (parentSchemaTypes.length > 0) {
|
||||
for (const item of parentSchemaTypes) {
|
||||
const parentPath = item.parentPath;
|
||||
const parentSchemaType = item.parentSchemaType;
|
||||
timestamps = parentSchemaType.schema.options.timestamps;
|
||||
createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
|
||||
if (!timestamps || updatedAt == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parentSchemaType.$isSingleNested) {
|
||||
// Single nested is easy
|
||||
update.$set[parentPath + '.' + updatedAt] = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parentSchemaType.$isMongooseDocumentArray) {
|
||||
let childPath = key.substr(parentPath.length + 1);
|
||||
|
||||
if (/^\d+$/.test(childPath)) {
|
||||
update.$set[parentPath + '.' + childPath][updatedAt] = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
const firstDot = childPath.indexOf('.');
|
||||
childPath = firstDot !== -1 ? childPath.substr(0, firstDot) : childPath;
|
||||
|
||||
update.$set[parentPath + '.' + childPath + '.' + updatedAt] = now;
|
||||
}
|
||||
}
|
||||
} else if (path.schema != null && path.schema != schema && update.$set[key]) {
|
||||
timestamps = path.schema.options.timestamps;
|
||||
createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
|
||||
if (!timestamps) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (updatedAt != null) {
|
||||
update.$set[key][updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
update.$set[key][createdAt] = now;
|
||||
}
|
||||
}
|
||||
for (const key of keys) {
|
||||
applyTimestampsToUpdateKey(schema, key, update.$set, now);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const keys = Object.keys(update).filter(key => !key.startsWith('$'));
|
||||
for (key of keys) {
|
||||
// Replace positional operator `$` and array filters `$[]` and `$[.*]`
|
||||
const keyToSearch = cleanPositionalOperators(key);
|
||||
path = schema.path(keyToSearch);
|
||||
if (!path) {
|
||||
continue;
|
||||
if (update.$setOnInsert != null) {
|
||||
const keys = Object.keys(update.$setOnInsert);
|
||||
for (const key of keys) {
|
||||
applyTimestampsToUpdateKey(schema, key, update.$setOnInsert, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(update[key]) && path.$isMongooseDocumentArray) {
|
||||
applyTimestampsToDocumentArray(update[key], path, now);
|
||||
} else if (update[key] != null && path.$isSingleNested) {
|
||||
applyTimestampsToSingleNested(update[key], path, now);
|
||||
const updateKeys = Object.keys(update).filter(key => !key.startsWith('$'));
|
||||
for (const key of updateKeys) {
|
||||
applyTimestampsToUpdateKey(schema, key, update, now);
|
||||
}
|
||||
|
||||
function _applyTimestampToUpdateOperator(op) {
|
||||
for (const key of Object.keys(op)) {
|
||||
const $path = schema.path(key.replace(/\.\$\./i, '.').replace(/.\$$/, ''));
|
||||
if (op[key] &&
|
||||
$path &&
|
||||
$path.$isMongooseDocumentArray &&
|
||||
$path.schema.options.timestamps) {
|
||||
const timestamps = $path.schema.options.timestamps;
|
||||
const createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
if (op[key].$each) {
|
||||
op[key].$each.forEach(function(subdoc) {
|
||||
if (updatedAt != null) {
|
||||
subdoc[updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
subdoc[createdAt] = now;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (updatedAt != null) {
|
||||
op[key][updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
op[key][createdAt] = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,3 +115,71 @@ function applyTimestampsToSingleNested(subdoc, schematype, now) {
|
||||
|
||||
applyTimestampsToChildren(now, subdoc, schematype.schema);
|
||||
}
|
||||
|
||||
function applyTimestampsToUpdateKey(schema, key, update, now) {
|
||||
// Replace positional operator `$` and array filters `$[]` and `$[.*]`
|
||||
const keyToSearch = cleanPositionalOperators(key);
|
||||
const path = schema.path(keyToSearch);
|
||||
if (!path) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parentSchemaTypes = [];
|
||||
const pieces = keyToSearch.split('.');
|
||||
for (let i = pieces.length - 1; i > 0; --i) {
|
||||
const s = schema.path(pieces.slice(0, i).join('.'));
|
||||
if (s != null &&
|
||||
(s.$isMongooseDocumentArray || s.$isSingleNested)) {
|
||||
parentSchemaTypes.push({ parentPath: key.split('.').slice(0, i).join('.'), parentSchemaType: s });
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(update[key]) && path.$isMongooseDocumentArray) {
|
||||
applyTimestampsToDocumentArray(update[key], path, now);
|
||||
} else if (update[key] && path.$isSingleNested) {
|
||||
applyTimestampsToSingleNested(update[key], path, now);
|
||||
} else if (parentSchemaTypes.length > 0) {
|
||||
for (const item of parentSchemaTypes) {
|
||||
const parentPath = item.parentPath;
|
||||
const parentSchemaType = item.parentSchemaType;
|
||||
const timestamps = parentSchemaType.schema.options.timestamps;
|
||||
const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
|
||||
if (!timestamps || updatedAt == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parentSchemaType.$isSingleNested) {
|
||||
// Single nested is easy
|
||||
update[parentPath + '.' + updatedAt] = now;
|
||||
} else if (parentSchemaType.$isMongooseDocumentArray) {
|
||||
let childPath = key.substr(parentPath.length + 1);
|
||||
|
||||
if (/^\d+$/.test(childPath)) {
|
||||
update[parentPath + '.' + childPath][updatedAt] = now;
|
||||
continue;
|
||||
}
|
||||
|
||||
const firstDot = childPath.indexOf('.');
|
||||
childPath = firstDot !== -1 ? childPath.substr(0, firstDot) : childPath;
|
||||
|
||||
update[parentPath + '.' + childPath + '.' + updatedAt] = now;
|
||||
}
|
||||
}
|
||||
} else if (path.schema != null && path.schema != schema && update[key]) {
|
||||
const timestamps = path.schema.options.timestamps;
|
||||
const createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
|
||||
if (!timestamps) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updatedAt != null) {
|
||||
update[key][updatedAt] = now;
|
||||
}
|
||||
if (createdAt != null) {
|
||||
update[key][createdAt] = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
node_modules/mongoose/lib/helpers/update/castArrayFilters.js
generated
vendored
24
node_modules/mongoose/lib/helpers/update/castArrayFilters.js
generated
vendored
@@ -3,7 +3,7 @@
|
||||
const castFilterPath = require('../query/castFilterPath');
|
||||
const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
|
||||
const getPath = require('../schema/getPath');
|
||||
const modifiedPaths = require('./modifiedPaths');
|
||||
const updatedPathsByArrayFilter = require('./updatedPathsByArrayFilter');
|
||||
|
||||
module.exports = function castArrayFilters(query) {
|
||||
const arrayFilters = query.options.arrayFilters;
|
||||
@@ -15,31 +15,13 @@ module.exports = function castArrayFilters(query) {
|
||||
const schema = query.schema;
|
||||
const strictQuery = schema.options.strictQuery;
|
||||
|
||||
const updatedPaths = modifiedPaths(update);
|
||||
|
||||
const updatedPathsByFilter = Object.keys(updatedPaths).reduce((cur, path) => {
|
||||
const matches = path.match(/\$\[[^\]]+\]/g);
|
||||
if (matches == null) {
|
||||
return cur;
|
||||
}
|
||||
for (const match of matches) {
|
||||
const firstMatch = path.indexOf(match);
|
||||
if (firstMatch !== path.lastIndexOf(match)) {
|
||||
throw new Error(`Path '${path}' contains the same array filter multiple times`);
|
||||
}
|
||||
cur[match.substring(2, match.length - 1)] = path.
|
||||
substr(0, firstMatch - 1).
|
||||
replace(/\$\[[^\]]+\]/g, '0');
|
||||
}
|
||||
return cur;
|
||||
}, {});
|
||||
const updatedPathsByFilter = updatedPathsByArrayFilter(update);
|
||||
|
||||
for (const filter of arrayFilters) {
|
||||
if (filter == null) {
|
||||
throw new Error(`Got null array filter in ${arrayFilters}`);
|
||||
}
|
||||
for (const key in filter) {
|
||||
|
||||
for (const key of Object.keys(filter)) {
|
||||
if (filter[key] == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
143
node_modules/mongoose/lib/index.js
generated
vendored
143
node_modules/mongoose/lib/index.js
generated
vendored
@@ -16,6 +16,7 @@ if (global.MONGOOSE_DRIVER_PATH) {
|
||||
}
|
||||
|
||||
const Document = require('./document');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const Schema = require('./schema');
|
||||
const SchemaType = require('./schematype');
|
||||
const SchemaTypes = require('./schema/index');
|
||||
@@ -26,6 +27,7 @@ const Types = require('./types');
|
||||
const Query = require('./query');
|
||||
const Model = require('./model');
|
||||
const applyPlugins = require('./helpers/schema/applyPlugins');
|
||||
const driver = require('./driver');
|
||||
const get = require('./helpers/get');
|
||||
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
||||
const legacyPluralize = require('mongoose-legacy-pluralize');
|
||||
@@ -34,6 +36,7 @@ const pkg = require('../package.json');
|
||||
const cast = require('./cast');
|
||||
const removeSubdocs = require('./plugins/removeSubdocs');
|
||||
const saveSubdocs = require('./plugins/saveSubdocs');
|
||||
const trackTransaction = require('./plugins/trackTransaction');
|
||||
const validateBeforeSave = require('./plugins/validateBeforeSave');
|
||||
|
||||
const Aggregate = require('./aggregate');
|
||||
@@ -64,9 +67,12 @@ function Mongoose(options) {
|
||||
this.connections = [];
|
||||
this.models = {};
|
||||
this.modelSchemas = {};
|
||||
this.events = new EventEmitter();
|
||||
// default global options
|
||||
this.options = Object.assign({
|
||||
pluralization: true
|
||||
pluralization: true,
|
||||
autoIndex: true,
|
||||
useCreateIndex: false
|
||||
}, options);
|
||||
const conn = this.createConnection(); // default connection
|
||||
conn.models = this.models;
|
||||
@@ -106,7 +112,8 @@ function Mongoose(options) {
|
||||
[saveSubdocs, { deduplicate: true }],
|
||||
[validateBeforeSave, { deduplicate: true }],
|
||||
[shardingPlugin, { deduplicate: true }],
|
||||
[removeSubdocs, { deduplicate: true }]
|
||||
[removeSubdocs, { deduplicate: true }],
|
||||
[trackTransaction, { deduplicate: true }]
|
||||
]
|
||||
});
|
||||
}
|
||||
@@ -121,8 +128,8 @@ Mongoose.prototype.cast = cast;
|
||||
Mongoose.prototype.STATES = STATES;
|
||||
|
||||
/**
|
||||
* The underlying driver this Mongoose instance uses to communicate with
|
||||
* the database. A driver is a Mongoose-specific interface that defines functions
|
||||
* Object with `get()` and `set()` containing the underlying driver this Mongoose instance
|
||||
* uses to communicate with the database. A driver is a Mongoose-specific interface that defines functions
|
||||
* like `find()`.
|
||||
*
|
||||
* @memberOf Mongoose
|
||||
@@ -130,7 +137,7 @@ Mongoose.prototype.STATES = STATES;
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Mongoose.prototype.driver = require('./driver');
|
||||
Mongoose.prototype.driver = driver;
|
||||
|
||||
/**
|
||||
* Sets mongoose options
|
||||
@@ -145,6 +152,7 @@ Mongoose.prototype.driver = require('./driver');
|
||||
*
|
||||
* Currently supported options are:
|
||||
* - 'debug': If `true`, prints the operations mongoose sends to MongoDB to the console. If a writable stream is passed, it will log to that stream, without colorization. If a callback function is passed, it will receive the collection name, the method name, then all arugments passed to the method. For example, if you wanted to replicate the default logging, you could output from the callback `Mongoose: ${collectionName}.${methodName}(${methodArgs.join(', ')})`.
|
||||
* - 'returnOriginal': If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`, `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to setting the `new` option to `true` for `findOneAndX()` calls by default. Read our [`findOneAndUpdate()` tutorial](/docs/tutorials/findoneandupdate.html) for more information.
|
||||
* - 'bufferCommands': enable/disable mongoose's buffering mechanism for all connections and models
|
||||
* - 'useCreateIndex': false by default. Set to `true` to make Mongoose's default index build use `createIndex()` instead of `ensureIndex()` to avoid deprecation warnings from the MongoDB driver.
|
||||
* - 'useFindAndModify': true by default. Set to `false` to make `findOneAndUpdate()` and `findOneAndRemove()` use native `findOneAndUpdate()` rather than `findAndModify()`.
|
||||
@@ -158,10 +166,13 @@ Mongoose.prototype.driver = require('./driver');
|
||||
* - 'toObject': `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toObject()`](/docs/api.html#document_Document-toObject)
|
||||
* - 'toJSON': `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toJSON()`](/docs/api.html#document_Document-toJSON), for determining how Mongoose documents get serialized by `JSON.stringify()`
|
||||
* - 'strict': true by default, may be `false`, `true`, or `'throw'`. Sets the default strict mode for schemas.
|
||||
* - 'strictQuery': false by default, may be `false`, `true`, or `'throw'`. Sets the default [strictQuery](/docs/guide.html#strictQuery) mode for schemas.
|
||||
* - 'selectPopulatedPaths': true by default. Set to false to opt out of Mongoose adding all fields that you `populate()` to your `select()`. The schema-level option `selectPopulatedPaths` overwrites this one.
|
||||
* - 'typePojoToMixed': true by default, may be `false` or `true`. Sets the default typePojoToMixed for schemas.
|
||||
* - 'maxTimeMS': If set, attaches [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) to every query
|
||||
* - 'autoIndex': true by default. Set to false to disable automatic index creation for all models associated with this Mongoose instance.
|
||||
* - 'autoCreate': Set to `true` to make Mongoose call [`Model.createCollection()`](/docs/api/model.html#model_Model.createCollection) automatically when you create a model with `mongoose.model()` or `conn.model()`. This is useful for testing transactions, change streams, and other features that require the collection to exist.
|
||||
* - 'overwriteModels': Set to `true` to default to overwriting models with the same name when calling `mongoose.model()`, as opposed to throwing an `OverwriteModelError`.
|
||||
*
|
||||
* @param {String} key
|
||||
* @param {String|Function|Boolean} value
|
||||
@@ -213,7 +224,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
||||
/**
|
||||
* Creates a Connection instance.
|
||||
*
|
||||
* Each `connection` instance maps to a single database. This method is helpful when mangaging multiple db connections.
|
||||
* Each `connection` instance maps to a single database. This method is helpful when managing multiple db connections.
|
||||
*
|
||||
*
|
||||
* _Options passed take precedence over options included in connection strings._
|
||||
@@ -224,18 +235,18 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
||||
* db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
|
||||
*
|
||||
* // and options
|
||||
* var opts = { db: { native_parser: true }}
|
||||
* const 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,anotherhost:port,yetanother:port/database');
|
||||
*
|
||||
* // and options
|
||||
* var opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
|
||||
* const opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
|
||||
* db = mongoose.createConnection('mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/database', opts);
|
||||
*
|
||||
* // and options
|
||||
* var opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
|
||||
* const opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
|
||||
* db = mongoose.createConnection('localhost', 'database', port, opts)
|
||||
*
|
||||
* // initialize now, connect later
|
||||
@@ -245,7 +256,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
||||
* @param {String} [uri] a mongodb:// URI
|
||||
* @param {Object} [options] passed down to the [MongoDB driver's `connect()` function](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html), except for 4 mongoose-specific options explained below.
|
||||
* @param {Boolean} [options.bufferCommands=true] Mongoose specific option. Set to false to [disable buffering](http://mongoosejs.com/docs/faq.html#callback_never_executes) on all models associated with this connection.
|
||||
* @param {String} [options.dbName] The name of the database we want to use. If not provided, use database name from connection string.
|
||||
* @param {String} [options.dbName] The name of the database you want to use. If not provided, Mongoose uses the database name from connection string.
|
||||
* @param {String} [options.user] username for authentication, equivalent to `options.auth.user`. Maintained for backwards compatibility.
|
||||
* @param {String} [options.pass] password for authentication, equivalent to `options.auth.password`. Maintained for backwards compatibility.
|
||||
* @param {Boolean} [options.autoIndex=true] Mongoose-specific option. Set to false to disable automatic index creation for all models associated with this connection.
|
||||
@@ -260,7 +271,7 @@ Mongoose.prototype.get = Mongoose.prototype.set;
|
||||
* @param {Number} [options.bufferMaxEntries] This option does nothing if `useUnifiedTopology` is set. The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set `bufferCommands` to `false` on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.
|
||||
* @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
|
||||
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
||||
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
||||
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
||||
* @return {Connection} the created Connection object. Connections are thenable, so you can do `await mongoose.createConnection()`
|
||||
* @api public
|
||||
*/
|
||||
@@ -274,6 +285,7 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
||||
options = null;
|
||||
}
|
||||
_mongoose.connections.push(conn);
|
||||
_mongoose.events.emit('createConnection', conn);
|
||||
|
||||
if (arguments.length > 0) {
|
||||
return conn.openUri(uri, options, callback);
|
||||
@@ -290,14 +302,14 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
||||
* mongoose.connect('mongodb://user:pass@localhost:port/database');
|
||||
*
|
||||
* // replica sets
|
||||
* var uri = 'mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/mydatabase';
|
||||
* const uri = 'mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/mydatabase';
|
||||
* mongoose.connect(uri);
|
||||
*
|
||||
* // with options
|
||||
* mongoose.connect(uri, options);
|
||||
*
|
||||
* // optional callback that gets fired when initial connection completed
|
||||
* var uri = 'mongodb://nonexistent.domain:27000';
|
||||
* const uri = 'mongodb://nonexistent.domain:27000';
|
||||
* mongoose.connect(uri, function(error) {
|
||||
* // if error is truthy, the initial connection failed.
|
||||
* })
|
||||
@@ -305,6 +317,7 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
||||
* @param {String} uri(s)
|
||||
* @param {Object} [options] passed down to the [MongoDB driver's `connect()` function](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html), except for 4 mongoose-specific options explained below.
|
||||
* @param {Boolean} [options.bufferCommands=true] Mongoose specific option. Set to false to [disable buffering](http://mongoosejs.com/docs/faq.html#callback_never_executes) on all models associated with this connection.
|
||||
* @param {Number} [options.bufferTimeoutMS=10000] Mongoose specific option. If `bufferCommands` is true, Mongoose will throw an error after `bufferTimeoutMS` if the operation is still buffered.
|
||||
* @param {String} [options.dbName] The name of the database we want to use. If not provided, use database name from connection string.
|
||||
* @param {String} [options.user] username for authentication, equivalent to `options.auth.user`. Maintained for backwards compatibility.
|
||||
* @param {String} [options.pass] password for authentication, equivalent to `options.auth.password`. Maintained for backwards compatibility.
|
||||
@@ -322,7 +335,8 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
||||
* @param {Number} [options.bufferMaxEntries] This option does nothing if `useUnifiedTopology` is set. The MongoDB driver also has its own buffering mechanism that kicks in when the driver is disconnected. Set this option to 0 and set `bufferCommands` to `false` on your schemas if you want your database operations to fail immediately when the driver is not connected, as opposed to waiting for reconnection.
|
||||
* @param {Number} [options.connectTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _during initial connection_. Defaults to 30000. This option is passed transparently to [Node.js' `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback).
|
||||
* @param {Number} [options.socketTimeoutMS=30000] How long the MongoDB driver will wait before killing a socket due to inactivity _after initial connection_. A socket may be inactive because of either no activity or a long-running operation. This is set to `30000` by default, you should set this to 2-3x your longest running operation if you expect some of your database operations to run longer than 20 seconds. This option is passed to [Node.js `socket#setTimeout()` function](https://nodejs.org/api/net.html#net_socket_settimeout_timeout_callback) after the MongoDB driver successfully completes.
|
||||
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
||||
* @param {Number} [options.family=0] Passed transparently to [Node.js' `dns.lookup()`](https://nodejs.org/api/dns.html#dns_dns_lookup_hostname_options_callback) function. May be either `0`, `4`, or `6`. `4` means use IPv4 only, `6` means use IPv6 only, `0` means try both.
|
||||
* @param {Boolean} [options.autoCreate=false] Set to `true` to make Mongoose automatically call `createCollection()` on every model created on this connection.
|
||||
* @param {Function} [callback]
|
||||
* @see Mongoose#createConnection #index_Mongoose-createConnection
|
||||
* @api public
|
||||
@@ -332,7 +346,15 @@ Mongoose.prototype.createConnection = function(uri, options, callback) {
|
||||
Mongoose.prototype.connect = function(uri, options, callback) {
|
||||
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
||||
const conn = _mongoose.connection;
|
||||
return conn.openUri(uri, options, callback).then(() => _mongoose);
|
||||
|
||||
return _mongoose._promiseOrCallback(callback, cb => {
|
||||
conn.openUri(uri, options, err => {
|
||||
if (err != null) {
|
||||
return cb(err);
|
||||
}
|
||||
return cb(null, _mongoose);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -346,7 +368,7 @@ Mongoose.prototype.connect = function(uri, options, callback) {
|
||||
Mongoose.prototype.disconnect = function(callback) {
|
||||
const _mongoose = this instanceof Mongoose ? this : mongoose;
|
||||
|
||||
return promiseOrCallback(callback, cb => {
|
||||
return _mongoose._promiseOrCallback(callback, cb => {
|
||||
let remaining = _mongoose.connections.length;
|
||||
if (remaining <= 0) {
|
||||
return cb(null);
|
||||
@@ -415,17 +437,17 @@ Mongoose.prototype.pluralize = function(fn) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* const mongoose = require('mongoose');
|
||||
*
|
||||
* // define an Actor model with this mongoose instance
|
||||
* const schema = new Schema({ name: String });
|
||||
* mongoose.model('Actor', schema);
|
||||
*
|
||||
* // create a new connection
|
||||
* var conn = mongoose.createConnection(..);
|
||||
* const conn = mongoose.createConnection(..);
|
||||
*
|
||||
* // create Actor model
|
||||
* var Actor = conn.model('Actor', schema);
|
||||
* const Actor = conn.model('Actor', schema);
|
||||
* conn.model('Actor') === Actor; // true
|
||||
* conn.model('Actor', schema) === Actor; // true, same schema
|
||||
* conn.model('Actor', schema, 'actors') === Actor; // true, same schema and collection name
|
||||
@@ -437,7 +459,7 @@ Mongoose.prototype.pluralize = function(fn) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var schema = new Schema({ name: String }, { collection: 'actor' });
|
||||
* const schema = new Schema({ name: String }, { collection: 'actor' });
|
||||
*
|
||||
* // or
|
||||
*
|
||||
@@ -445,13 +467,13 @@ Mongoose.prototype.pluralize = function(fn) {
|
||||
*
|
||||
* // or
|
||||
*
|
||||
* var collectionName = 'actor'
|
||||
* var M = mongoose.model('Actor', schema, collectionName)
|
||||
* const collectionName = 'actor'
|
||||
* const M = mongoose.model('Actor', schema, collectionName)
|
||||
*
|
||||
* @param {String|Function} name model name or class extending Model
|
||||
* @param {Schema} [schema] the schema to use.
|
||||
* @param {String} [collection] name (optional, inferred from model name)
|
||||
* @param {Boolean} [skipInit] whether to skip initialization (defaults to false)
|
||||
* @param {Boolean|Object} [skipInit] whether to skip initialization (defaults to false). If an object, treated as options.
|
||||
* @return {Model} The model associated with `name`. Mongoose will create the model if it doesn't already exist.
|
||||
* @api public
|
||||
*/
|
||||
@@ -473,10 +495,10 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
||||
schema = false;
|
||||
}
|
||||
|
||||
if (utils.isObject(schema) && !(schema.instanceOfSchema)) {
|
||||
if (utils.isObject(schema) && !(schema instanceof Schema)) {
|
||||
schema = new Schema(schema);
|
||||
}
|
||||
if (schema && !schema.instanceOfSchema) {
|
||||
if (schema && !(schema instanceof Schema)) {
|
||||
throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
|
||||
'schema or a POJO');
|
||||
}
|
||||
@@ -517,7 +539,10 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
||||
|
||||
// connection.model() may be passing a different schema for
|
||||
// an existing model name. in this case don't read from cache.
|
||||
if (_mongoose.models[name] && options.cache !== false) {
|
||||
const overwriteModels = _mongoose.options.hasOwnProperty('overwriteModels') ?
|
||||
_mongoose.options.overwriteModels :
|
||||
options.overwriteModels;
|
||||
if (_mongoose.models[name] && options.cache !== false && overwriteModels !== true) {
|
||||
if (originalSchema &&
|
||||
originalSchema.instanceOfSchema &&
|
||||
originalSchema !== _mongoose.models[name].schema) {
|
||||
@@ -562,6 +587,8 @@ Mongoose.prototype.model = function(name, schema, collection, skipInit) {
|
||||
model.init(function $modelInitNoop() {});
|
||||
}
|
||||
|
||||
connection.emit('model', model);
|
||||
|
||||
if (options.cache === false) {
|
||||
return model;
|
||||
}
|
||||
@@ -661,7 +688,7 @@ Mongoose.prototype.plugin = function(fn, opts) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* const mongoose = require('mongoose');
|
||||
* mongoose.connect(...);
|
||||
* mongoose.connection.on('error', cb);
|
||||
*
|
||||
@@ -709,23 +736,17 @@ Mongoose.prototype.__defineSetter__('connection', function(v) {
|
||||
|
||||
Mongoose.prototype.connections;
|
||||
|
||||
/*!
|
||||
* Driver dependent APIs
|
||||
*/
|
||||
|
||||
const driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
|
||||
|
||||
/*!
|
||||
* Connection
|
||||
*/
|
||||
|
||||
const Connection = require(driver + '/connection');
|
||||
const Connection = driver.get().getConnection();
|
||||
|
||||
/*!
|
||||
* Collection
|
||||
*/
|
||||
|
||||
const Collection = require(driver + '/collection');
|
||||
const Collection = driver.get().Collection;
|
||||
|
||||
/**
|
||||
* The Mongoose Aggregate constructor
|
||||
@@ -776,8 +797,8 @@ Mongoose.prototype.version = pkg.version;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var mongoose2 = new mongoose.Mongoose();
|
||||
* const mongoose = require('mongoose');
|
||||
* const mongoose2 = new mongoose.Mongoose();
|
||||
*
|
||||
* @method Mongoose
|
||||
* @api public
|
||||
@@ -790,9 +811,9 @@ Mongoose.prototype.Mongoose = Mongoose;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var Schema = mongoose.Schema;
|
||||
* var CatSchema = new Schema(..);
|
||||
* const mongoose = require('mongoose');
|
||||
* const Schema = mongoose.Schema;
|
||||
* const CatSchema = new Schema(..);
|
||||
*
|
||||
* @method Schema
|
||||
* @api public
|
||||
@@ -837,21 +858,24 @@ Mongoose.prototype.VirtualType = VirtualType;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var array = mongoose.Types.Array;
|
||||
* const mongoose = require('mongoose');
|
||||
* const 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)
|
||||
* - [Array](/docs/schematypes.html#arrays)
|
||||
* - [Buffer](/docs/schematypes.html#buffers)
|
||||
* - [Embedded](/docs/schematypes.html#schemas)
|
||||
* - [DocumentArray](/docs/api/documentarraypath.html)
|
||||
* - [Decimal128](/docs/api.html#mongoose_Mongoose-Decimal128)
|
||||
* - [ObjectId](/docs/schematypes.html#objectids)
|
||||
* - [Map](/docs/schematypes.html#maps)
|
||||
* - [Subdocument](/docs/schematypes.html#schemas)
|
||||
*
|
||||
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
|
||||
*
|
||||
* var ObjectId = mongoose.Types.ObjectId;
|
||||
* var id1 = new ObjectId;
|
||||
* const ObjectId = mongoose.Types.ObjectId;
|
||||
* const id1 = new ObjectId;
|
||||
*
|
||||
* @property Types
|
||||
* @api public
|
||||
@@ -970,7 +994,13 @@ Mongoose.prototype.isValidObjectId = function(v) {
|
||||
}
|
||||
if (v._id.toString instanceof Function) {
|
||||
v = v._id.toString();
|
||||
return typeof v === 'string' && (v.length === 12 || v.length === 24);
|
||||
if (typeof v === 'string' && v.length === 12) {
|
||||
return true;
|
||||
}
|
||||
if (typeof v === 'string' && v.length === 24 && /^[a-f0-9]*$/.test(v)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -978,7 +1008,10 @@ Mongoose.prototype.isValidObjectId = function(v) {
|
||||
v = v.toString();
|
||||
}
|
||||
|
||||
if (typeof v === 'string' && (v.length === 12 || v.length === 24)) {
|
||||
if (typeof v === 'string' && v.length === 12) {
|
||||
return true;
|
||||
}
|
||||
if (typeof v === 'string' && v.length === 24 && /^[a-f0-9]*$/.test(v)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1108,6 +1141,14 @@ Mongoose.prototype.mongo = require('mongodb');
|
||||
|
||||
Mongoose.prototype.mquery = require('mquery');
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
Mongoose.prototype._promiseOrCallback = function(callback, fn, ee) {
|
||||
return promiseOrCallback(callback, fn, ee, this.Promise);
|
||||
};
|
||||
|
||||
/*!
|
||||
* The exports object is an instance of Mongoose.
|
||||
*
|
||||
|
||||
931
node_modules/mongoose/lib/model.js
generated
vendored
931
node_modules/mongoose/lib/model.js
generated
vendored
File diff suppressed because it is too large
Load Diff
3
node_modules/mongoose/lib/options.js
generated
vendored
3
node_modules/mongoose/lib/options.js
generated
vendored
@@ -10,5 +10,6 @@ exports.internalToObjectOptions = {
|
||||
getters: false,
|
||||
_skipDepopulateTopLevel: true,
|
||||
depopulate: true,
|
||||
flattenDecimals: false
|
||||
flattenDecimals: false,
|
||||
useProjection: false
|
||||
};
|
||||
|
||||
1
node_modules/mongoose/lib/options/PopulateOptions.js
generated
vendored
1
node_modules/mongoose/lib/options/PopulateOptions.js
generated
vendored
@@ -5,6 +5,7 @@ const clone = require('../helpers/clone');
|
||||
class PopulateOptions {
|
||||
constructor(obj) {
|
||||
this._docs = {};
|
||||
this._childDocs = [];
|
||||
|
||||
if (obj == null) {
|
||||
return;
|
||||
|
||||
20
node_modules/mongoose/lib/options/SchemaArrayOptions.js
generated
vendored
20
node_modules/mongoose/lib/options/SchemaArrayOptions.js
generated
vendored
@@ -32,6 +32,26 @@ const opts = require('./propertyOptions');
|
||||
|
||||
Object.defineProperty(SchemaArrayOptions.prototype, 'enum', opts);
|
||||
|
||||
/**
|
||||
* If set, specifies the type of this array's values. Equivalent to setting
|
||||
* `type` to an array whose first element is `of`.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* // `arr` is an array of numbers.
|
||||
* new Schema({ arr: [Number] });
|
||||
* // Equivalent way to define `arr` as an array of numbers
|
||||
* new Schema({ arr: { type: Array, of: Number } });
|
||||
*
|
||||
* @api public
|
||||
* @property of
|
||||
* @memberOf SchemaArrayOptions
|
||||
* @type Function|String
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaArrayOptions.prototype, 'of', opts);
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
25
node_modules/mongoose/lib/options/SchemaNumberOptions.js
generated
vendored
25
node_modules/mongoose/lib/options/SchemaNumberOptions.js
generated
vendored
@@ -67,6 +67,31 @@ Object.defineProperty(SchemaNumberOptions.prototype, 'max', opts);
|
||||
|
||||
Object.defineProperty(SchemaNumberOptions.prototype, 'enum', opts);
|
||||
|
||||
/**
|
||||
* Sets default [populate options](/docs/populate.html#query-conditions).
|
||||
*
|
||||
* ####Example:
|
||||
* const schema = new Schema({
|
||||
* child: {
|
||||
* type: Number,
|
||||
* ref: 'Child',
|
||||
* populate: { select: 'name' }
|
||||
* }
|
||||
* });
|
||||
* const Parent = mongoose.model('Parent', schema);
|
||||
*
|
||||
* // Automatically adds `.select('name')`
|
||||
* Parent.findOne().populate('child');
|
||||
*
|
||||
* @api public
|
||||
* @property populate
|
||||
* @memberOf SchemaNumberOptions
|
||||
* @type Object
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaNumberOptions.prototype, 'populate', opts);
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
25
node_modules/mongoose/lib/options/SchemaObjectIdOptions.js
generated
vendored
25
node_modules/mongoose/lib/options/SchemaObjectIdOptions.js
generated
vendored
@@ -31,6 +31,31 @@ const opts = require('./propertyOptions');
|
||||
|
||||
Object.defineProperty(SchemaObjectIdOptions.prototype, 'auto', opts);
|
||||
|
||||
/**
|
||||
* Sets default [populate options](/docs/populate.html#query-conditions).
|
||||
*
|
||||
* ####Example:
|
||||
* const schema = new Schema({
|
||||
* child: {
|
||||
* type: 'ObjectId',
|
||||
* ref: 'Child',
|
||||
* populate: { select: 'name' }
|
||||
* }
|
||||
* });
|
||||
* const Parent = mongoose.model('Parent', schema);
|
||||
*
|
||||
* // Automatically adds `.select('name')`
|
||||
* Parent.findOne().populate('child');
|
||||
*
|
||||
* @api public
|
||||
* @property populate
|
||||
* @memberOf SchemaObjectIdOptions
|
||||
* @type Object
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaObjectIdOptions.prototype, 'populate', opts);
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
28
node_modules/mongoose/lib/options/SchemaStringOptions.js
generated
vendored
28
node_modules/mongoose/lib/options/SchemaStringOptions.js
generated
vendored
@@ -87,30 +87,52 @@ Object.defineProperty(SchemaStringOptions.prototype, 'uppercase', opts);
|
||||
* If set, Mongoose will add a custom validator that ensures the given
|
||||
* string's `length` is at least the given number.
|
||||
*
|
||||
* Mongoose supports two different spellings for this option: `minLength` and `minlength`.
|
||||
* `minLength` is the recommended way to specify this option, but Mongoose also supports
|
||||
* `minlength` (lowercase "l").
|
||||
*
|
||||
* @api public
|
||||
* @property minlength
|
||||
* @property minLength
|
||||
* @memberOf SchemaStringOptions
|
||||
* @type Number
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaStringOptions.prototype, 'minLength', opts);
|
||||
Object.defineProperty(SchemaStringOptions.prototype, 'minlength', opts);
|
||||
|
||||
/**
|
||||
* If set, Mongoose will add a custom validator that ensures the given
|
||||
* string's `length` is at most the given number.
|
||||
*
|
||||
* Mongoose supports two different spellings for this option: `maxLength` and `maxlength`.
|
||||
* `maxLength` is the recommended way to specify this option, but Mongoose also supports
|
||||
* `maxlength` (lowercase "l").
|
||||
*
|
||||
* @api public
|
||||
* @property maxlength
|
||||
* @property maxLength
|
||||
* @memberOf SchemaStringOptions
|
||||
* @type Number
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaStringOptions.prototype, 'maxLength', opts);
|
||||
Object.defineProperty(SchemaStringOptions.prototype, 'maxlength', opts);
|
||||
|
||||
/**
|
||||
* Sets default [populate options](/docs/populate.html#query-conditions).
|
||||
*
|
||||
* @api public
|
||||
* @property populate
|
||||
* @memberOf SchemaStringOptions
|
||||
* @type Object
|
||||
* @instance
|
||||
*/
|
||||
|
||||
Object.defineProperty(SchemaStringOptions.prototype, 'populate', opts);
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
module.exports = SchemaStringOptions;
|
||||
module.exports = SchemaStringOptions;
|
||||
|
||||
3
node_modules/mongoose/lib/options/SchemaTypeOptions.js
generated
vendored
3
node_modules/mongoose/lib/options/SchemaTypeOptions.js
generated
vendored
@@ -134,8 +134,7 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'select', opts);
|
||||
|
||||
/**
|
||||
* If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
|
||||
* build an index on this path when the model is
|
||||
* compiled.
|
||||
* build an index on this path when the model is compiled.
|
||||
*
|
||||
* @api public
|
||||
* @property index
|
||||
|
||||
4
node_modules/mongoose/lib/plugins/removeSubdocs.js
generated
vendored
4
node_modules/mongoose/lib/plugins/removeSubdocs.js
generated
vendored
@@ -15,13 +15,13 @@ module.exports = function(schema) {
|
||||
}
|
||||
|
||||
const _this = this;
|
||||
const subdocs = this.$__getAllSubdocs();
|
||||
const subdocs = this.$getAllSubdocs();
|
||||
|
||||
each(subdocs, function(subdoc, cb) {
|
||||
subdoc.$__remove(cb);
|
||||
}, function(error) {
|
||||
if (error) {
|
||||
return _this.schema.s.hooks.execPost('remove:error', _this, [_this], { error: error }, function(error) {
|
||||
return _this.$__schema.s.hooks.execPost('remove:error', _this, [_this], { error: error }, function(error) {
|
||||
next(error);
|
||||
});
|
||||
}
|
||||
|
||||
12
node_modules/mongoose/lib/plugins/saveSubdocs.js
generated
vendored
12
node_modules/mongoose/lib/plugins/saveSubdocs.js
generated
vendored
@@ -15,7 +15,7 @@ module.exports = function(schema) {
|
||||
}
|
||||
|
||||
const _this = this;
|
||||
const subdocs = this.$__getAllSubdocs();
|
||||
const subdocs = this.$getAllSubdocs();
|
||||
|
||||
if (!subdocs.length) {
|
||||
next();
|
||||
@@ -23,12 +23,12 @@ module.exports = function(schema) {
|
||||
}
|
||||
|
||||
each(subdocs, function(subdoc, cb) {
|
||||
subdoc.schema.s.hooks.execPre('save', subdoc, function(err) {
|
||||
subdoc.$__schema.s.hooks.execPre('save', subdoc, function(err) {
|
||||
cb(err);
|
||||
});
|
||||
}, function(error) {
|
||||
if (error) {
|
||||
return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
return _this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
next(error);
|
||||
});
|
||||
}
|
||||
@@ -43,7 +43,7 @@ module.exports = function(schema) {
|
||||
}
|
||||
|
||||
const _this = this;
|
||||
const subdocs = this.$__getAllSubdocs();
|
||||
const subdocs = this.$getAllSubdocs();
|
||||
|
||||
if (!subdocs.length) {
|
||||
next();
|
||||
@@ -51,12 +51,12 @@ module.exports = function(schema) {
|
||||
}
|
||||
|
||||
each(subdocs, function(subdoc, cb) {
|
||||
subdoc.schema.s.hooks.execPost('save', subdoc, [subdoc], function(err) {
|
||||
subdoc.$__schema.s.hooks.execPost('save', subdoc, [subdoc], function(err) {
|
||||
cb(err);
|
||||
});
|
||||
}, function(error) {
|
||||
if (error) {
|
||||
return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
return _this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
next(error);
|
||||
});
|
||||
}
|
||||
|
||||
2
node_modules/mongoose/lib/plugins/sharding.js
generated
vendored
2
node_modules/mongoose/lib/plugins/sharding.js
generated
vendored
@@ -56,7 +56,7 @@ module.exports.storeShard = storeShard;
|
||||
|
||||
function storeShard() {
|
||||
// backwards compat
|
||||
const key = this.schema.options.shardKey || this.schema.options.shardkey;
|
||||
const key = this.$__schema.options.shardKey || this.$__schema.options.shardkey;
|
||||
if (!utils.isPOJO(key)) {
|
||||
return;
|
||||
}
|
||||
|
||||
4
node_modules/mongoose/lib/plugins/validateBeforeSave.js
generated
vendored
4
node_modules/mongoose/lib/plugins/validateBeforeSave.js
generated
vendored
@@ -21,7 +21,7 @@ module.exports = function(schema) {
|
||||
if (hasValidateBeforeSaveOption) {
|
||||
shouldValidate = !!options.validateBeforeSave;
|
||||
} else {
|
||||
shouldValidate = this.schema.options.validateBeforeSave;
|
||||
shouldValidate = this.$__schema.options.validateBeforeSave;
|
||||
}
|
||||
|
||||
// Validate
|
||||
@@ -33,7 +33,7 @@ module.exports = function(schema) {
|
||||
{ validateModifiedOnly: options.validateModifiedOnly } :
|
||||
null;
|
||||
this.validate(validateOptions, function(error) {
|
||||
return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
return _this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
||||
_this.$op = 'save';
|
||||
next(error);
|
||||
});
|
||||
|
||||
549
node_modules/mongoose/lib/query.js
generated
vendored
549
node_modules/mongoose/lib/query.js
generated
vendored
File diff suppressed because it is too large
Load Diff
35
node_modules/mongoose/lib/queryhelpers.js
generated
vendored
35
node_modules/mongoose/lib/queryhelpers.js
generated
vendored
@@ -31,6 +31,10 @@ exports.preparePopulationOptions = function preparePopulationOptions(query, opti
|
||||
forEach(makeLean(options.lean));
|
||||
}
|
||||
|
||||
pop.forEach(opts => {
|
||||
opts._localModel = query.model;
|
||||
});
|
||||
|
||||
return pop;
|
||||
};
|
||||
|
||||
@@ -71,6 +75,9 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
||||
pop.forEach(p => {
|
||||
p._queryProjection = projection;
|
||||
});
|
||||
pop.forEach(opts => {
|
||||
opts._localModel = query.model;
|
||||
});
|
||||
|
||||
return pop;
|
||||
};
|
||||
@@ -85,7 +92,7 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
||||
*
|
||||
* @return {Document}
|
||||
*/
|
||||
exports.createModel = function createModel(model, doc, fields, userProvidedFields) {
|
||||
exports.createModel = function createModel(model, doc, fields, userProvidedFields, options) {
|
||||
model.hooks.execPreSync('createModel', doc);
|
||||
const discriminatorMapping = model.schema ?
|
||||
model.schema.discriminatorMapping :
|
||||
@@ -97,18 +104,22 @@ exports.createModel = function createModel(model, doc, fields, userProvidedField
|
||||
|
||||
const value = doc[key];
|
||||
if (key && value && model.discriminators) {
|
||||
const discriminator = model.discriminators[value] || getDiscriminatorByValue(model, value);
|
||||
const discriminator = model.discriminators[value] || getDiscriminatorByValue(model.discriminators, value);
|
||||
if (discriminator) {
|
||||
const _fields = clone(userProvidedFields);
|
||||
exports.applyPaths(_fields, discriminator.schema);
|
||||
return new discriminator(undefined, _fields, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof options === 'undefined') {
|
||||
options = {};
|
||||
options.defaults = true;
|
||||
}
|
||||
return new model(undefined, fields, {
|
||||
skipId: true,
|
||||
isNew: false,
|
||||
willInit: true
|
||||
willInit: true,
|
||||
defaults: options.defaults
|
||||
});
|
||||
};
|
||||
|
||||
@@ -199,7 +210,11 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
||||
schema.eachPath(function(path, type) {
|
||||
if (prefix) path = prefix + '.' + path;
|
||||
|
||||
const addedPath = analyzePath(path, type);
|
||||
let addedPath = analyzePath(path, type);
|
||||
// arrays
|
||||
if (addedPath == null && type.$isMongooseArray && !type.$isMongooseDocumentArray) {
|
||||
addedPath = analyzePath(path, type.caster);
|
||||
}
|
||||
if (addedPath != null) {
|
||||
addedPaths.push(addedPath);
|
||||
}
|
||||
@@ -261,7 +276,7 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
||||
let cur = '';
|
||||
for (let i = 0; i < pieces.length; ++i) {
|
||||
cur += (cur.length === 0 ? '' : '.') + pieces[i];
|
||||
const projection = get(fields, cur, false);
|
||||
const projection = get(fields, cur, false) || get(fields, cur + '.$', false);
|
||||
if (projection && typeof projection !== 'object') {
|
||||
return;
|
||||
}
|
||||
@@ -282,6 +297,14 @@ exports.applyPaths = function applyPaths(fields, schema) {
|
||||
function makeLean(val) {
|
||||
return function(option) {
|
||||
option.options || (option.options = {});
|
||||
|
||||
if (val != null && Array.isArray(val.virtuals)) {
|
||||
val = Object.assign({}, val);
|
||||
val.virtuals = val.virtuals.
|
||||
filter(path => typeof path === 'string' && path.startsWith(option.path + '.')).
|
||||
map(path => path.slice(option.path.length + 1));
|
||||
}
|
||||
|
||||
option.options.lean = val;
|
||||
};
|
||||
}
|
||||
|
||||
401
node_modules/mongoose/lib/schema.js
generated
vendored
401
node_modules/mongoose/lib/schema.js
generated
vendored
@@ -12,16 +12,14 @@ const SchemaTypeOptions = require('./options/SchemaTypeOptions');
|
||||
const VirtualOptions = require('./options/VirtualOptions');
|
||||
const VirtualType = require('./virtualtype');
|
||||
const addAutoId = require('./helpers/schema/addAutoId');
|
||||
const applyTimestampsToChildren = require('./helpers/update/applyTimestampsToChildren');
|
||||
const applyTimestampsToUpdate = require('./helpers/update/applyTimestampsToUpdate');
|
||||
const arrayParentSymbol = require('./helpers/symbols').arrayParentSymbol;
|
||||
const get = require('./helpers/get');
|
||||
const getConstructorName = require('./helpers/getConstructorName');
|
||||
const getIndexes = require('./helpers/schema/getIndexes');
|
||||
const handleTimestampOption = require('./helpers/schema/handleTimestampOption');
|
||||
const merge = require('./helpers/schema/merge');
|
||||
const mpath = require('mpath');
|
||||
const readPref = require('./driver').get().ReadPreference;
|
||||
const symbols = require('./schema/symbols');
|
||||
const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
|
||||
const util = require('util');
|
||||
const utils = require('./utils');
|
||||
const validateRef = require('./helpers/populate/validateRef');
|
||||
@@ -41,9 +39,9 @@ let id = 0;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var child = new Schema({ name: String });
|
||||
* var schema = new Schema({ name: String, age: Number, children: [child] });
|
||||
* var Tree = mongoose.model('Tree', schema);
|
||||
* const child = new Schema({ name: String });
|
||||
* const schema = new Schema({ name: String, age: Number, children: [child] });
|
||||
* const Tree = mongoose.model('Tree', schema);
|
||||
*
|
||||
* // setting schema options
|
||||
* new Schema({ name: String }, { _id: false, autoIndex: false })
|
||||
@@ -53,8 +51,10 @@ let id = 0;
|
||||
* - [autoIndex](/docs/guide.html#autoIndex): bool - defaults to null (which means use the connection's autoIndex option)
|
||||
* - [autoCreate](/docs/guide.html#autoCreate): bool - defaults to null (which means use the connection's autoCreate option)
|
||||
* - [bufferCommands](/docs/guide.html#bufferCommands): bool - defaults to true
|
||||
* - [bufferTimeoutMS](/docs/guide.html#bufferTimeoutMS): number - defaults to 10000 (10 seconds). If `bufferCommands` is enabled, the amount of time Mongoose will wait for connectivity to be restablished before erroring out.
|
||||
* - [capped](/docs/guide.html#capped): bool - defaults to false
|
||||
* - [collection](/docs/guide.html#collection): string - no default
|
||||
* - [discriminatorKey](/docs/guide.html#discriminatorKey): string - defaults to `__t`
|
||||
* - [id](/docs/guide.html#id): bool - defaults to true
|
||||
* - [_id](/docs/guide.html#_id): bool - defaults to true
|
||||
* - [minimize](/docs/guide.html#minimize): bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true
|
||||
@@ -69,7 +69,8 @@ let id = 0;
|
||||
* - [typePojoToMixed](/docs/guide.html#typePojoToMixed) - boolean - defaults to true. Determines whether a type set to a POJO becomes a Mixed path or a Subdocument
|
||||
* - [useNestedStrict](/docs/guide.html#useNestedStrict) - boolean - defaults to false
|
||||
* - [validateBeforeSave](/docs/guide.html#validateBeforeSave) - bool - defaults to `true`
|
||||
* - [versionKey](/docs/guide.html#versionKey): string - defaults to "__v"
|
||||
* - [versionKey](/docs/guide.html#versionKey): string or object - defaults to "__v"
|
||||
* - [optimisticConcurrency](/docs/guide.html#optimisticConcurrency): bool - defaults to false. Set to true to enable [optimistic concurrency](https://thecodebarbarian.com/whats-new-in-mongoose-5-10-optimistic-concurrency.html).
|
||||
* - [collation](/docs/guide.html#collation): object - defaults to null (which means use no collation)
|
||||
* - [selectPopulatedPaths](/docs/guide.html#selectPopulatedPaths): boolean - defaults to `true`
|
||||
* - [skipVersioning](/docs/guide.html#skipVersioning): object - paths to exclude from versioning
|
||||
@@ -114,6 +115,7 @@ function Schema(obj, options) {
|
||||
this.plugins = [];
|
||||
// For internal debugging. Do not use this to try to save a schema in MDB.
|
||||
this.$id = ++id;
|
||||
this.mapPaths = [];
|
||||
|
||||
this.s = {
|
||||
hooks: new Kareem()
|
||||
@@ -180,7 +182,7 @@ function aliasFields(schema, paths) {
|
||||
})(prop)).
|
||||
set((function(p) {
|
||||
return function(v) {
|
||||
return this.set(p, v);
|
||||
return this.$set(p, v);
|
||||
};
|
||||
})(prop));
|
||||
}
|
||||
@@ -228,7 +230,7 @@ Object.defineProperty(Schema.prototype, 'childSchemas', {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var schema = new Schema({ a: String }).add({ b: String });
|
||||
* const schema = new Schema({ a: String }).add({ b: String });
|
||||
* schema.obj; // { a: String }
|
||||
*
|
||||
* @api public
|
||||
@@ -294,7 +296,9 @@ Schema.prototype.tree;
|
||||
*/
|
||||
|
||||
Schema.prototype.clone = function() {
|
||||
const s = new Schema({}, this._userProvidedOptions);
|
||||
const Constructor = this.base == null ? Schema : this.base.Schema;
|
||||
|
||||
const s = new Constructor({}, this._userProvidedOptions);
|
||||
s.base = this.base;
|
||||
s.obj = this.obj;
|
||||
s.options = utils.clone(this.options);
|
||||
@@ -318,6 +322,7 @@ Schema.prototype.clone = function() {
|
||||
s.$globalPluginsApplied = this.$globalPluginsApplied;
|
||||
s.$isRootDiscriminator = this.$isRootDiscriminator;
|
||||
s.$implicitlyCreated = this.$implicitlyCreated;
|
||||
s.mapPaths = [].concat(this.mapPaths);
|
||||
|
||||
if (this.discriminatorMapping != null) {
|
||||
s.discriminatorMapping = Object.assign({}, this.discriminatorMapping);
|
||||
@@ -400,9 +405,11 @@ Schema.prototype.defaultOptions = function(options) {
|
||||
const baseOptions = get(this, 'base.options', {});
|
||||
options = utils.options({
|
||||
strict: 'strict' in baseOptions ? baseOptions.strict : true,
|
||||
strictQuery: 'strictQuery' in baseOptions ? baseOptions.strictQuery : false,
|
||||
bufferCommands: true,
|
||||
capped: false, // { size, max, autoIndexId }
|
||||
versionKey: '__v',
|
||||
optimisticConcurrency: false,
|
||||
discriminatorKey: '__t',
|
||||
minimize: true,
|
||||
autoIndex: null,
|
||||
@@ -422,6 +429,10 @@ Schema.prototype.defaultOptions = function(options) {
|
||||
options.read = readPref(options.read);
|
||||
}
|
||||
|
||||
if (options.optimisticConcurrency && !options.versionKey) {
|
||||
throw new MongooseError('Must set `versionKey` if using `optimisticConcurrency`');
|
||||
}
|
||||
|
||||
return options;
|
||||
};
|
||||
|
||||
@@ -445,8 +456,9 @@ Schema.prototype.defaultOptions = function(options) {
|
||||
*/
|
||||
|
||||
Schema.prototype.add = function add(obj, prefix) {
|
||||
if (obj instanceof Schema) {
|
||||
if (obj instanceof Schema || (obj != null && obj.instanceOfSchema)) {
|
||||
merge(this, obj);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -458,9 +470,18 @@ Schema.prototype.add = function add(obj, prefix) {
|
||||
}
|
||||
|
||||
prefix = prefix || '';
|
||||
// avoid prototype pollution
|
||||
if (prefix === '__proto__.' || prefix === 'constructor.' || prefix === 'prototype.') {
|
||||
return this;
|
||||
}
|
||||
|
||||
const keys = Object.keys(obj);
|
||||
|
||||
for (const key of keys) {
|
||||
if (utils.specialProperties.has(key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const fullPath = prefix + key;
|
||||
|
||||
if (obj[key] == null) {
|
||||
@@ -471,7 +492,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
||||
if (key === '_id' && obj[key] === false) {
|
||||
continue;
|
||||
}
|
||||
if (obj[key] instanceof VirtualType) {
|
||||
if (obj[key] instanceof VirtualType || get(obj[key], 'constructor.name', null) === 'VirtualType') {
|
||||
this.virtual(obj[key]);
|
||||
continue;
|
||||
}
|
||||
@@ -559,7 +580,7 @@ Schema.prototype.add = function add(obj, prefix) {
|
||||
*
|
||||
* _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(..);
|
||||
* const schema = new Schema(..);
|
||||
* schema.methods.init = function () {} // potentially breaking
|
||||
*/
|
||||
|
||||
@@ -583,18 +604,9 @@ reserved.isNew =
|
||||
reserved.populated =
|
||||
reserved.remove =
|
||||
reserved.save =
|
||||
reserved.schema =
|
||||
reserved.toObject =
|
||||
reserved.validate = 1;
|
||||
|
||||
/*!
|
||||
* Document keys to print warnings for
|
||||
*/
|
||||
|
||||
const warnings = {};
|
||||
warnings.increment = '`increment` should not be used as a schema path name ' +
|
||||
'unless you have disabled versioning.';
|
||||
|
||||
/**
|
||||
* Gets/sets schema paths.
|
||||
*
|
||||
@@ -644,10 +656,6 @@ Schema.prototype.path = function(path, obj) {
|
||||
throw new Error('`' + firstPieceOfPath + '` may not be used as a schema pathname');
|
||||
}
|
||||
|
||||
if (warnings[path]) {
|
||||
console.log('WARN: ' + warnings[path]);
|
||||
}
|
||||
|
||||
if (typeof obj === 'object' && utils.hasUserDefinedProperty(obj, 'ref')) {
|
||||
validateRef(obj.ref, path);
|
||||
}
|
||||
@@ -659,6 +667,9 @@ Schema.prototype.path = function(path, obj) {
|
||||
let fullPath = '';
|
||||
|
||||
for (const sub of subpaths) {
|
||||
if (utils.specialProperties.has(sub)) {
|
||||
throw new Error('Cannot set special property `' + sub + '` on a schema');
|
||||
}
|
||||
fullPath = fullPath += (fullPath.length > 0 ? '.' : '') + sub;
|
||||
if (!branch[sub]) {
|
||||
this.nested[fullPath] = true;
|
||||
@@ -692,23 +703,31 @@ Schema.prototype.path = function(path, obj) {
|
||||
!utils.hasUserDefinedProperty(obj.of, this.options.typeKey);
|
||||
_mapType = isInlineSchema ? new Schema(obj.of) : obj.of;
|
||||
}
|
||||
if (utils.hasUserDefinedProperty(obj, 'ref')) {
|
||||
_mapType = { type: _mapType, ref: obj.ref };
|
||||
}
|
||||
|
||||
this.paths[mapPath] = this.interpretAsType(mapPath,
|
||||
_mapType, this.options);
|
||||
this.mapPaths.push(this.paths[mapPath]);
|
||||
schemaType.$__schemaType = this.paths[mapPath];
|
||||
}
|
||||
|
||||
if (schemaType.$isSingleNested) {
|
||||
for (const key in schemaType.schema.paths) {
|
||||
for (const key of Object.keys(schemaType.schema.paths)) {
|
||||
this.singleNestedPaths[path + '.' + key] = schemaType.schema.paths[key];
|
||||
}
|
||||
for (const key in schemaType.schema.singleNestedPaths) {
|
||||
for (const key of Object.keys(schemaType.schema.singleNestedPaths)) {
|
||||
this.singleNestedPaths[path + '.' + key] =
|
||||
schemaType.schema.singleNestedPaths[key];
|
||||
}
|
||||
for (const key in schemaType.schema.subpaths) {
|
||||
for (const key of Object.keys(schemaType.schema.subpaths)) {
|
||||
this.singleNestedPaths[path + '.' + key] =
|
||||
schemaType.schema.subpaths[key];
|
||||
}
|
||||
for (const key of Object.keys(schemaType.schema.nested)) {
|
||||
this.singleNestedPaths[path + '.' + key] = 'nested';
|
||||
}
|
||||
|
||||
Object.defineProperty(schemaType.schema, 'base', {
|
||||
configurable: true,
|
||||
@@ -748,9 +767,11 @@ Schema.prototype.path = function(path, obj) {
|
||||
// Skip arrays of document arrays
|
||||
if (_schemaType.$isMongooseDocumentArray) {
|
||||
_schemaType.$embeddedSchemaType._arrayPath = arrayPath;
|
||||
_schemaType.$embeddedSchemaType._arrayParentPath = path;
|
||||
_schemaType = _schemaType.$embeddedSchemaType.clone();
|
||||
} else {
|
||||
_schemaType.caster._arrayPath = arrayPath;
|
||||
_schemaType.caster._arrayParentPath = path;
|
||||
_schemaType = _schemaType.caster.clone();
|
||||
}
|
||||
|
||||
@@ -765,16 +786,25 @@ Schema.prototype.path = function(path, obj) {
|
||||
|
||||
if (schemaType.$isMongooseDocumentArray) {
|
||||
for (const key of Object.keys(schemaType.schema.paths)) {
|
||||
this.subpaths[path + '.' + key] = schemaType.schema.paths[key];
|
||||
schemaType.schema.paths[key].$isUnderneathDocArray = true;
|
||||
const _schemaType = schemaType.schema.paths[key];
|
||||
this.subpaths[path + '.' + key] = _schemaType;
|
||||
if (typeof _schemaType === 'object' && _schemaType != null) {
|
||||
_schemaType.$isUnderneathDocArray = true;
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(schemaType.schema.subpaths)) {
|
||||
this.subpaths[path + '.' + key] = schemaType.schema.subpaths[key];
|
||||
schemaType.schema.subpaths[key].$isUnderneathDocArray = true;
|
||||
const _schemaType = schemaType.schema.subpaths[key];
|
||||
this.subpaths[path + '.' + key] = _schemaType;
|
||||
if (typeof _schemaType === 'object' && _schemaType != null) {
|
||||
_schemaType.$isUnderneathDocArray = true;
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(schemaType.schema.singleNestedPaths)) {
|
||||
this.subpaths[path + '.' + key] = schemaType.schema.singleNestedPaths[key];
|
||||
schemaType.schema.singleNestedPaths[key].$isUnderneathDocArray = true;
|
||||
const _schemaType = schemaType.schema.singleNestedPaths[key];
|
||||
this.subpaths[path + '.' + key] = _schemaType;
|
||||
if (typeof _schemaType === 'object' && _schemaType != null) {
|
||||
_schemaType.$isUnderneathDocArray = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,7 +839,7 @@ function _getPath(schema, path, cleanPath) {
|
||||
if (schema.subpaths.hasOwnProperty(cleanPath)) {
|
||||
return schema.subpaths[cleanPath];
|
||||
}
|
||||
if (schema.singleNestedPaths.hasOwnProperty(cleanPath)) {
|
||||
if (schema.singleNestedPaths.hasOwnProperty(cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') {
|
||||
return schema.singleNestedPaths[cleanPath];
|
||||
}
|
||||
|
||||
@@ -832,10 +862,11 @@ function _pathToPositionalSyntax(path) {
|
||||
*/
|
||||
|
||||
function getMapPath(schema, path) {
|
||||
for (const _path of Object.keys(schema.paths)) {
|
||||
if (!_path.includes('.$*')) {
|
||||
continue;
|
||||
}
|
||||
if (schema.mapPaths.length === 0) {
|
||||
return null;
|
||||
}
|
||||
for (const val of schema.mapPaths) {
|
||||
const _path = val.path;
|
||||
const re = new RegExp('^' + _path.replace(/\.\$\*/g, '\\.[^.]+') + '$');
|
||||
if (re.test(path)) {
|
||||
return schema.paths[_path];
|
||||
@@ -869,7 +900,12 @@ Object.defineProperty(Schema.prototype, 'base', {
|
||||
|
||||
Schema.prototype.interpretAsType = function(path, obj, options) {
|
||||
if (obj instanceof SchemaType) {
|
||||
return obj;
|
||||
if (obj.path === path) {
|
||||
return obj;
|
||||
}
|
||||
const clone = obj.clone();
|
||||
clone.path = path;
|
||||
return clone;
|
||||
}
|
||||
|
||||
// If this schema has an associated Mongoose object, use the Mongoose object's
|
||||
@@ -900,15 +936,25 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
||||
if (Array.isArray(type) || type === Array || type === 'array' || type === MongooseTypes.Array) {
|
||||
// if it was specified through { type } look for `cast`
|
||||
let cast = (type === Array || type === 'array')
|
||||
? obj.cast
|
||||
? obj.cast || obj.of
|
||||
: type[0];
|
||||
|
||||
if (cast && cast.instanceOfSchema) {
|
||||
if (!(cast instanceof Schema)) {
|
||||
throw new TypeError('Schema for array path `' + path +
|
||||
'` is from a different copy of the Mongoose module. Please make sure you\'re using the same version ' +
|
||||
'of Mongoose everywhere with `npm list mongoose`.');
|
||||
}
|
||||
return new MongooseTypes.DocumentArray(path, cast, obj);
|
||||
}
|
||||
if (cast &&
|
||||
cast[options.typeKey] &&
|
||||
cast[options.typeKey].instanceOfSchema) {
|
||||
if (!(cast[options.typeKey] instanceof Schema)) {
|
||||
throw new TypeError('Schema for array path `' + path +
|
||||
'` is from a different copy of the Mongoose module. Please make sure you\'re using the same version ' +
|
||||
'of Mongoose everywhere with `npm list mongoose`.');
|
||||
}
|
||||
return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
|
||||
}
|
||||
|
||||
@@ -935,6 +981,14 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
||||
if (options.hasOwnProperty('typePojoToMixed')) {
|
||||
childSchemaOptions.typePojoToMixed = options.typePojoToMixed;
|
||||
}
|
||||
|
||||
if (this._userProvidedOptions.hasOwnProperty('_id')) {
|
||||
childSchemaOptions._id = this._userProvidedOptions._id;
|
||||
} else if (Schema.Types.DocumentArray.defaultOptions &&
|
||||
Schema.Types.DocumentArray.defaultOptions._id != null) {
|
||||
childSchemaOptions._id = Schema.Types.DocumentArray.defaultOptions._id;
|
||||
}
|
||||
|
||||
const childSchema = new Schema(cast, childSchemaOptions);
|
||||
childSchema.$implicitlyCreated = true;
|
||||
return new MongooseTypes.DocumentArray(path, childSchema, obj);
|
||||
@@ -953,6 +1007,11 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
||||
? type
|
||||
: type.schemaName || utils.getFunctionName(type);
|
||||
|
||||
// For Jest 26+, see #10296
|
||||
if (name === 'ClockDate') {
|
||||
name = 'Date';
|
||||
}
|
||||
|
||||
if (!MongooseTypes.hasOwnProperty(name)) {
|
||||
throw new TypeError('Invalid schema configuration: ' +
|
||||
`\`${name}\` is not a valid type within the array \`${path}\`.` +
|
||||
@@ -983,6 +1042,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
|
||||
if (name === 'ObjectID') {
|
||||
name = 'ObjectId';
|
||||
}
|
||||
// For Jest 26+, see #10296
|
||||
if (name === 'ClockDate') {
|
||||
name = 'Date';
|
||||
}
|
||||
|
||||
if (MongooseTypes[name] == null) {
|
||||
throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
|
||||
@@ -1108,8 +1171,10 @@ Schema.prototype.pathType = function(path) {
|
||||
if (this.subpaths.hasOwnProperty(cleanPath) || this.subpaths.hasOwnProperty(path)) {
|
||||
return 'real';
|
||||
}
|
||||
if (this.singleNestedPaths.hasOwnProperty(cleanPath) || this.singleNestedPaths.hasOwnProperty(path)) {
|
||||
return 'real';
|
||||
|
||||
const singleNestedPath = this.singleNestedPaths.hasOwnProperty(cleanPath) || this.singleNestedPaths.hasOwnProperty(path);
|
||||
if (singleNestedPath) {
|
||||
return singleNestedPath === 'nested' ? 'nested' : 'real';
|
||||
}
|
||||
|
||||
// Look for maps
|
||||
@@ -1137,7 +1202,7 @@ Schema.prototype.hasMixedParent = function(path) {
|
||||
path = '';
|
||||
for (let i = 0; i < subpaths.length; ++i) {
|
||||
path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
|
||||
if (path in this.paths &&
|
||||
if (this.paths.hasOwnProperty(path) &&
|
||||
this.paths[path] instanceof MongooseTypes.Mixed) {
|
||||
return this.paths[path];
|
||||
}
|
||||
@@ -1153,100 +1218,7 @@ Schema.prototype.hasMixedParent = function(path) {
|
||||
* @api private
|
||||
*/
|
||||
Schema.prototype.setupTimestamp = function(timestamps) {
|
||||
const childHasTimestamp = this.childSchemas.find(withTimestamp);
|
||||
|
||||
function withTimestamp(s) {
|
||||
const ts = s.schema.options.timestamps;
|
||||
return !!ts;
|
||||
}
|
||||
|
||||
if (!timestamps && !childHasTimestamp) {
|
||||
return;
|
||||
}
|
||||
|
||||
const createdAt = handleTimestampOption(timestamps, 'createdAt');
|
||||
const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
|
||||
const currentTime = timestamps != null && timestamps.hasOwnProperty('currentTime') ?
|
||||
timestamps.currentTime :
|
||||
null;
|
||||
const schemaAdditions = {};
|
||||
|
||||
this.$timestamps = { createdAt: createdAt, updatedAt: updatedAt };
|
||||
|
||||
if (updatedAt && !this.paths[updatedAt]) {
|
||||
schemaAdditions[updatedAt] = Date;
|
||||
}
|
||||
|
||||
if (createdAt && !this.paths[createdAt]) {
|
||||
schemaAdditions[createdAt] = Date;
|
||||
}
|
||||
|
||||
this.add(schemaAdditions);
|
||||
|
||||
this.pre('save', function(next) {
|
||||
const timestampOption = get(this, '$__.saveOptions.timestamps');
|
||||
if (timestampOption === false) {
|
||||
return next();
|
||||
}
|
||||
|
||||
const skipUpdatedAt = timestampOption != null && timestampOption.updatedAt === false;
|
||||
const skipCreatedAt = timestampOption != null && timestampOption.createdAt === false;
|
||||
|
||||
const defaultTimestamp = currentTime != null ?
|
||||
currentTime() :
|
||||
(this.ownerDocument ? this.ownerDocument() : this).constructor.base.now();
|
||||
const auto_id = this._id && this._id.auto;
|
||||
|
||||
if (!skipCreatedAt && createdAt && !this.get(createdAt) && this.isSelected(createdAt)) {
|
||||
this.set(createdAt, auto_id ? this._id.getTimestamp() : defaultTimestamp);
|
||||
}
|
||||
|
||||
if (!skipUpdatedAt && updatedAt && (this.isNew || this.isModified())) {
|
||||
let ts = defaultTimestamp;
|
||||
if (this.isNew) {
|
||||
if (createdAt != null) {
|
||||
ts = this.$__getValue(createdAt);
|
||||
} else if (auto_id) {
|
||||
ts = this._id.getTimestamp();
|
||||
}
|
||||
}
|
||||
this.set(updatedAt, ts);
|
||||
}
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
this.methods.initializeTimestamps = function() {
|
||||
const ts = currentTime != null ?
|
||||
currentTime() :
|
||||
this.constructor.base.now();
|
||||
if (createdAt && !this.get(createdAt)) {
|
||||
this.set(createdAt, ts);
|
||||
}
|
||||
if (updatedAt && !this.get(updatedAt)) {
|
||||
this.set(updatedAt, ts);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
_setTimestampsOnUpdate[symbols.builtInMiddleware] = true;
|
||||
|
||||
const opts = { query: true, model: false };
|
||||
this.pre('findOneAndUpdate', opts, _setTimestampsOnUpdate);
|
||||
this.pre('replaceOne', opts, _setTimestampsOnUpdate);
|
||||
this.pre('update', opts, _setTimestampsOnUpdate);
|
||||
this.pre('updateOne', opts, _setTimestampsOnUpdate);
|
||||
this.pre('updateMany', opts, _setTimestampsOnUpdate);
|
||||
|
||||
function _setTimestampsOnUpdate(next) {
|
||||
const now = currentTime != null ?
|
||||
currentTime() :
|
||||
this.model.base.now();
|
||||
applyTimestampsToUpdate(now, createdAt, updatedAt, this.getUpdate(),
|
||||
this.options, this.schema);
|
||||
applyTimestampsToChildren(now, this.getUpdate(), this.model.schema);
|
||||
next();
|
||||
}
|
||||
return setupTimestamps(this, timestamps);
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -1346,11 +1318,11 @@ Schema.prototype.queue = function(name, args) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a pre hook for the document.
|
||||
* Defines a pre hook for the model.
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* var toySchema = new Schema({ name: String, created: Date });
|
||||
* const toySchema = new Schema({ name: String, created: Date });
|
||||
*
|
||||
* toySchema.pre('save', function(next) {
|
||||
* if (!this.created) this.created = new Date;
|
||||
@@ -1412,7 +1384,7 @@ Schema.prototype.pre = function(name) {
|
||||
/**
|
||||
* Defines a post hook for the document
|
||||
*
|
||||
* var schema = new Schema(..);
|
||||
* const schema = new Schema(..);
|
||||
* schema.post('save', function (doc) {
|
||||
* console.log('this fired after a document was saved');
|
||||
* });
|
||||
@@ -1425,9 +1397,9 @@ Schema.prototype.pre = function(name) {
|
||||
* console.log('this fired after you ran `updateMany()` or `deleteMany()`);
|
||||
* });
|
||||
*
|
||||
* var Model = mongoose.model('Model', schema);
|
||||
* const Model = mongoose.model('Model', schema);
|
||||
*
|
||||
* var m = new Model(..);
|
||||
* const m = new Model(..);
|
||||
* m.save(function(err) {
|
||||
* console.log('this fires after the `post` hook');
|
||||
* });
|
||||
@@ -1506,15 +1478,15 @@ Schema.prototype.plugin = function(fn, opts) {
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* var schema = kittySchema = new Schema(..);
|
||||
* const schema = kittySchema = new Schema(..);
|
||||
*
|
||||
* schema.method('meow', function () {
|
||||
* console.log('meeeeeoooooooooooow');
|
||||
* })
|
||||
*
|
||||
* var Kitty = mongoose.model('Kitty', schema);
|
||||
* const Kitty = mongoose.model('Kitty', schema);
|
||||
*
|
||||
* var fizz = new Kitty;
|
||||
* const 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.
|
||||
@@ -1528,7 +1500,7 @@ Schema.prototype.plugin = function(fn, opts) {
|
||||
* fizz.purr();
|
||||
* fizz.scratch();
|
||||
*
|
||||
* NOTE: `Schema.method()` adds instance methods to the `Schema.methods` object. You can also add instance methods directly to the `Schema.methods` object as seen in the [guide](./guide.html#methods)
|
||||
* NOTE: `Schema.method()` adds instance methods to the `Schema.methods` object. You can also add instance methods directly to the `Schema.methods` object as seen in the [guide](/docs/guide.html#methods)
|
||||
*
|
||||
* @param {String|Object} method name
|
||||
* @param {Function} [fn]
|
||||
@@ -1590,7 +1562,7 @@ Schema.prototype.static = function(name, fn) {
|
||||
*
|
||||
* @param {Object} fields
|
||||
* @param {Object} [options] Options to pass to [MongoDB driver's `createIndex()` function](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#createIndex)
|
||||
* @param {String} [options.expires=null] Mongoose-specific syntactic sugar, uses [ms](https://www.npmjs.com/package/ms) to convert `expires` option into seconds for the `expireAfterSeconds` in the above link.
|
||||
* @param {String | number} [options.expires=null] Mongoose-specific syntactic sugar, uses [ms](https://www.npmjs.com/package/ms) to convert `expires` option into seconds for the `expireAfterSeconds` in the above link.
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -1607,7 +1579,7 @@ Schema.prototype.index = function(fields, options) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets/gets a schema option.
|
||||
* Sets a schema option.
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
@@ -1640,6 +1612,16 @@ Schema.prototype.set = function(key, value, _tags) {
|
||||
this.options[key] = value;
|
||||
this._userProvidedOptions[key] = this.options[key];
|
||||
break;
|
||||
case '_id':
|
||||
this.options[key] = value;
|
||||
this._userProvidedOptions[key] = this.options[key];
|
||||
|
||||
if (value && !this.paths['_id']) {
|
||||
addAutoId(this);
|
||||
} else if (!value && this.paths['_id'] != null && this.paths['_id'].auto) {
|
||||
this.remove('_id');
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this.options[key] = value;
|
||||
this._userProvidedOptions[key] = this.options[key];
|
||||
@@ -1701,8 +1683,8 @@ Object.defineProperty(Schema, 'indexTypes', {
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns a list of indexes that this schema declares, via `schema.index()`
|
||||
* or by `index: true` in a path's options.
|
||||
* Returns a list of indexes that this schema declares, via `schema.index()` or by `index: true` in a path's options.
|
||||
* Indexes are expressed as an array `[spec, options]`.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
@@ -1715,6 +1697,17 @@ Object.defineProperty(Schema, 'indexTypes', {
|
||||
* // [ { registeredAt: 1 }, { background: true } ] ]
|
||||
* userSchema.indexes();
|
||||
*
|
||||
* [Plugins](/docs/plugins.html) can use the return value of this function to modify a schema's indexes.
|
||||
* For example, the below plugin makes every index unique by default.
|
||||
*
|
||||
* function myPlugin(schema) {
|
||||
* for (const index of schema.indexes()) {
|
||||
* if (index[1].unique === undefined) {
|
||||
* index[1].unique = true;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* @api public
|
||||
* @return {Array} list of indexes defined in the schema
|
||||
*/
|
||||
@@ -1733,11 +1726,12 @@ Schema.prototype.indexes = function() {
|
||||
* @param {String|Function} [options.foreignField] Required for populate virtuals. See [populate virtual docs](populate.html#populate-virtuals) for more information.
|
||||
* @param {Boolean|Function} [options.justOne=false] Only works with populate virtuals. If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), will be a single doc or `null`. Otherwise, the populate virtual will be an array.
|
||||
* @param {Boolean} [options.count=false] Only works with populate virtuals. If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), this populate virtual will contain the number of documents rather than the documents themselves when you `populate()`.
|
||||
* @param {Function|null} [options.get=null] Adds a [getter](/docs/tutorials/getters-setters.html) to this virtual to transform the populated doc.
|
||||
* @return {VirtualType}
|
||||
*/
|
||||
|
||||
Schema.prototype.virtual = function(name, options) {
|
||||
if (name instanceof VirtualType) {
|
||||
if (name instanceof VirtualType || getConstructorName(name) === 'VirtualType') {
|
||||
return this.virtual(name.path, name.options);
|
||||
}
|
||||
|
||||
@@ -1775,15 +1769,8 @@ Schema.prototype.virtual = function(name, options) {
|
||||
|
||||
const virtual = this.virtual(name);
|
||||
virtual.options = options;
|
||||
return virtual.
|
||||
get(function(_v) {
|
||||
if (this.$$populatedVirtuals &&
|
||||
this.$$populatedVirtuals.hasOwnProperty(name)) {
|
||||
return this.$$populatedVirtuals[name];
|
||||
}
|
||||
if (_v == null) return undefined;
|
||||
return _v;
|
||||
}).
|
||||
|
||||
virtual.
|
||||
set(function(_v) {
|
||||
if (!this.$$populatedVirtuals) {
|
||||
this.$$populatedVirtuals = {};
|
||||
@@ -1807,6 +1794,12 @@ Schema.prototype.virtual = function(name, options) {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof options.get === 'function') {
|
||||
virtual.get(options.get);
|
||||
}
|
||||
|
||||
return virtual;
|
||||
}
|
||||
|
||||
const virtuals = this.virtuals;
|
||||
@@ -1922,9 +1915,9 @@ function _deletePath(schema, name) {
|
||||
/**
|
||||
* Loads an ES6 class into a schema. Maps [setters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/set) + [getters](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get), [static methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/static),
|
||||
* and [instance methods](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#Class_body_and_method_definitions)
|
||||
* to schema [virtuals](http://mongoosejs.com/docs/guide.html#virtuals),
|
||||
* [statics](http://mongoosejs.com/docs/guide.html#statics), and
|
||||
* [methods](http://mongoosejs.com/docs/guide.html#methods).
|
||||
* to schema [virtuals](/docs/guide.html#virtuals),
|
||||
* [statics](/docs/guide.html#statics), and
|
||||
* [methods](/docs/guide.html#methods).
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
@@ -1964,17 +1957,17 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.loadClass(Object.getPrototypeOf(model));
|
||||
this.loadClass(Object.getPrototypeOf(model), virtualsOnly);
|
||||
|
||||
// Add static methods
|
||||
if (!virtualsOnly) {
|
||||
Object.getOwnPropertyNames(model).forEach(function(name) {
|
||||
if (name.match(/^(length|name|prototype)$/)) {
|
||||
if (name.match(/^(length|name|prototype|constructor|__proto__)$/)) {
|
||||
return;
|
||||
}
|
||||
const method = Object.getOwnPropertyDescriptor(model, name);
|
||||
if (typeof method.value === 'function') {
|
||||
this.static(name, method.value);
|
||||
const prop = Object.getOwnPropertyDescriptor(model, name);
|
||||
if (prop.hasOwnProperty('value')) {
|
||||
this.static(name, prop.value);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
@@ -1991,9 +1984,15 @@ Schema.prototype.loadClass = function(model, virtualsOnly) {
|
||||
}
|
||||
}
|
||||
if (typeof method.get === 'function') {
|
||||
if (this.virtuals[name]) {
|
||||
this.virtuals[name].getters = [];
|
||||
}
|
||||
this.virtual(name).get(method.get);
|
||||
}
|
||||
if (typeof method.set === 'function') {
|
||||
if (this.virtuals[name]) {
|
||||
this.virtuals[name].setters = [];
|
||||
}
|
||||
this.virtual(name).set(method.set);
|
||||
}
|
||||
}, this);
|
||||
@@ -2039,29 +2038,37 @@ Schema.prototype._getSchema = function(path) {
|
||||
// doesn't work for that.
|
||||
// If there is no foundschema.schema we are dealing with
|
||||
// a path like array.$
|
||||
if (p !== parts.length && foundschema.schema) {
|
||||
let ret;
|
||||
if (parts[p] === '$' || isArrayFilter(parts[p])) {
|
||||
if (p + 1 === parts.length) {
|
||||
// comments.$
|
||||
return foundschema;
|
||||
if (p !== parts.length) {
|
||||
if (foundschema.schema) {
|
||||
let ret;
|
||||
if (parts[p] === '$' || isArrayFilter(parts[p])) {
|
||||
if (p + 1 === parts.length) {
|
||||
// comments.$
|
||||
return foundschema;
|
||||
}
|
||||
// comments.$.comments.$.title
|
||||
ret = search(parts.slice(p + 1), foundschema.schema);
|
||||
if (ret) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!foundschema.schema.$isSingleNested;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// comments.$.comments.$.title
|
||||
ret = search(parts.slice(p + 1), foundschema.schema);
|
||||
// this is the last path of the selector
|
||||
ret = search(parts.slice(p), foundschema.schema);
|
||||
if (ret) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!foundschema.schema.$isSingleNested;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
// this is the last path of the selector
|
||||
ret = search(parts.slice(p), foundschema.schema);
|
||||
if (ret) {
|
||||
ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
|
||||
!foundschema.schema.$isSingleNested;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
} else if (foundschema.$isSchemaMap) {
|
||||
if (p + 1 >= parts.length) {
|
||||
return foundschema;
|
||||
}
|
||||
const ret = search(parts.slice(p + 1), foundschema.$__schemaType.schema);
|
||||
return ret;
|
||||
}
|
||||
|
||||
foundschema.$fullPath = resultPath.join('.');
|
||||
@@ -2164,23 +2171,23 @@ module.exports = exports = Schema;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var mongoose = require('mongoose');
|
||||
* var ObjectId = mongoose.Schema.Types.ObjectId;
|
||||
* const mongoose = require('mongoose');
|
||||
* const 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)
|
||||
* - [String](/docs/schematypes.html#strings)
|
||||
* - [Number](/docs/schematypes.html#numbers)
|
||||
* - [Boolean](/docs/schematypes.html#booleans) | Bool
|
||||
* - [Array](/docs/schematypes.html#arrays)
|
||||
* - [Buffer](/docs/schematypes.html#buffers)
|
||||
* - [Date](/docs/schematypes.html#dates)
|
||||
* - [ObjectId](/docs/schematypes.html#objectids) | Oid
|
||||
* - [Mixed](/docs/schematypes.html#mixed)
|
||||
*
|
||||
* Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
|
||||
*
|
||||
* var Mixed = mongoose.Schema.Types.Mixed;
|
||||
* const Mixed = mongoose.Schema.Types.Mixed;
|
||||
* new mongoose.Schema({ _user: Mixed })
|
||||
*
|
||||
* @api public
|
||||
|
||||
30
node_modules/mongoose/lib/schema/SingleNestedPath.js
generated
vendored
30
node_modules/mongoose/lib/schema/SingleNestedPath.js
generated
vendored
@@ -62,7 +62,7 @@ function _createConstructor(schema, baseClass) {
|
||||
const _embedded = function SingleNested(value, path, parent) {
|
||||
const _this = this;
|
||||
|
||||
this.$parent = parent;
|
||||
this.$__parent = parent;
|
||||
Subdocument.apply(this, arguments);
|
||||
|
||||
this.$session(this.ownerDocument().$session());
|
||||
@@ -147,7 +147,7 @@ SingleNestedPath.prototype.$conditionalHandlers.$exists = $exists;
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SingleNestedPath.prototype.cast = function(val, doc, init, priorVal) {
|
||||
SingleNestedPath.prototype.cast = function(val, doc, init, priorVal, options) {
|
||||
if (val && val.$isSingleNested && val.parent === doc) {
|
||||
return val;
|
||||
}
|
||||
@@ -169,16 +169,16 @@ SingleNestedPath.prototype.cast = function(val, doc, init, priorVal) {
|
||||
}
|
||||
return obj;
|
||||
}, {});
|
||||
|
||||
options = Object.assign({}, options, { priorDoc: priorVal });
|
||||
if (init) {
|
||||
subdoc = new Constructor(void 0, selected, doc);
|
||||
subdoc.init(val);
|
||||
} else {
|
||||
if (Object.keys(val).length === 0) {
|
||||
return new Constructor({}, selected, doc);
|
||||
return new Constructor({}, selected, doc, undefined, options);
|
||||
}
|
||||
|
||||
return new Constructor(val, selected, doc, undefined, { priorDoc: priorVal });
|
||||
return new Constructor(val, selected, doc, undefined, options);
|
||||
}
|
||||
|
||||
return subdoc;
|
||||
@@ -300,6 +300,26 @@ SingleNestedPath.prototype.discriminator = function(name, schema, value) {
|
||||
return this.caster.discriminators[name];
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a default option for all SingleNestedPath instances.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* // Make all numbers have option `min` equal to 0.
|
||||
* mongoose.Schema.Embedded.set('required', true);
|
||||
*
|
||||
* @param {String} option - The option you'd like to set the value for
|
||||
* @param {*} value - value for option
|
||||
* @return {undefined}
|
||||
* @function set
|
||||
* @static
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SingleNestedPath.defaultOptions = {};
|
||||
|
||||
SingleNestedPath.set = SchemaType.set;
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
158
node_modules/mongoose/lib/schema/array.js
generated
vendored
158
node_modules/mongoose/lib/schema/array.js
generated
vendored
@@ -25,6 +25,7 @@ let MongooseArray;
|
||||
let EmbeddedDoc;
|
||||
|
||||
const isNestedArraySymbol = Symbol('mongoose#isNestedArray');
|
||||
const emptyOpts = Object.freeze({});
|
||||
|
||||
/**
|
||||
* Array SchemaType constructor
|
||||
@@ -60,6 +61,10 @@ function SchemaArray(key, cast, options, schemaOptions) {
|
||||
}
|
||||
}
|
||||
|
||||
if (options != null && options.ref != null && castOptions.ref == null) {
|
||||
castOptions.ref = options.ref;
|
||||
}
|
||||
|
||||
if (cast === Object) {
|
||||
cast = Mixed;
|
||||
}
|
||||
@@ -81,16 +86,16 @@ function SchemaArray(key, cast, options, schemaOptions) {
|
||||
if (typeof caster === 'function' &&
|
||||
!caster.$isArraySubdocument &&
|
||||
!caster.$isSchemaMap) {
|
||||
this.caster = new caster(null, castOptions);
|
||||
const path = this.caster instanceof EmbeddedDoc ? null : key;
|
||||
this.caster = new caster(path, castOptions);
|
||||
} else {
|
||||
this.caster = caster;
|
||||
if (!(this.caster instanceof EmbeddedDoc)) {
|
||||
this.caster.path = key;
|
||||
}
|
||||
}
|
||||
|
||||
this.$embeddedSchemaType = this.caster;
|
||||
|
||||
if (!(this.caster instanceof EmbeddedDoc)) {
|
||||
this.caster.path = key;
|
||||
}
|
||||
}
|
||||
|
||||
this.$isMongooseArray = true;
|
||||
@@ -116,7 +121,7 @@ function SchemaArray(key, cast, options, schemaOptions) {
|
||||
// Leave it up to `cast()` to convert the array
|
||||
return arr;
|
||||
};
|
||||
defaultFn.$runBeforeSetters = true;
|
||||
defaultFn.$runBeforeSetters = !fn;
|
||||
this.default(defaultFn);
|
||||
}
|
||||
}
|
||||
@@ -141,6 +146,10 @@ SchemaArray.schemaName = 'Array';
|
||||
|
||||
SchemaArray.options = { castNonArrays: true };
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaArray.defaultOptions = {};
|
||||
|
||||
/**
|
||||
@@ -158,7 +167,6 @@ SchemaArray.defaultOptions = {};
|
||||
* @param {*} value - value for option
|
||||
* @return {undefined}
|
||||
* @function set
|
||||
* @static
|
||||
* @api public
|
||||
*/
|
||||
SchemaArray.set = SchemaType.set;
|
||||
@@ -191,7 +199,6 @@ SchemaArray._checkRequired = SchemaType.prototype.checkRequired;
|
||||
* @param {Function} fn
|
||||
* @return {Function}
|
||||
* @function checkRequired
|
||||
* @static
|
||||
* @api public
|
||||
*/
|
||||
|
||||
@@ -242,7 +249,13 @@ SchemaArray.prototype.enum = function() {
|
||||
}
|
||||
break;
|
||||
}
|
||||
arr.caster.enum.apply(arr.caster, arguments);
|
||||
|
||||
let enumArray = arguments;
|
||||
if (!Array.isArray(arguments) && utils.isObject(arguments)) {
|
||||
enumArray = utils.object.vals(enumArray);
|
||||
}
|
||||
|
||||
arr.caster.enum.apply(arr.caster, enumArray);
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -255,23 +268,30 @@ SchemaArray.prototype.enum = function() {
|
||||
*/
|
||||
|
||||
SchemaArray.prototype.applyGetters = function(value, scope) {
|
||||
if (this.caster.options && this.caster.options.ref) {
|
||||
if (scope != null && scope.$__ != null && scope.populated(this.path)) {
|
||||
// means the object id was populated
|
||||
return value;
|
||||
}
|
||||
|
||||
return SchemaType.prototype.applyGetters.call(this, value, scope);
|
||||
const ret = SchemaType.prototype.applyGetters.call(this, value, scope);
|
||||
if (Array.isArray(ret)) {
|
||||
const len = ret.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
ret[i] = this.caster.applyGetters(ret[i], scope);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
|
||||
if (this.casterConstructor instanceof SchemaArray &&
|
||||
if (this.casterConstructor.$isMongooseArray &&
|
||||
SchemaArray.options.castNonArrays &&
|
||||
!this[isNestedArraySymbol]) {
|
||||
// Check nesting levels and wrap in array if necessary
|
||||
let depth = 0;
|
||||
let arr = this;
|
||||
while (arr != null &&
|
||||
arr instanceof SchemaArray &&
|
||||
arr.$isMongooseArray &&
|
||||
!arr.$isMongooseDocumentArray) {
|
||||
++depth;
|
||||
arr = arr.casterConstructor;
|
||||
@@ -280,7 +300,7 @@ SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
|
||||
// No need to wrap empty arrays
|
||||
if (value != null && value.length > 0) {
|
||||
const valueDepth = arrayDepth(value);
|
||||
if (valueDepth.min === valueDepth.max && valueDepth.max < depth) {
|
||||
if (valueDepth.min === valueDepth.max && valueDepth.max < depth && valueDepth.containsNonArrayItem) {
|
||||
for (let i = valueDepth.max; i < depth; ++i) {
|
||||
value = [value];
|
||||
}
|
||||
@@ -308,7 +328,8 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
||||
let l;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (!value.length && doc) {
|
||||
const len = value.length;
|
||||
if (!len && doc) {
|
||||
const indexes = doc.schema.indexedPaths();
|
||||
|
||||
const arrayPath = this.path;
|
||||
@@ -333,39 +354,42 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!(value && value.isMongooseArray)) {
|
||||
value = new MongooseArray(value, this.path, doc);
|
||||
} else if (value && value.isMongooseArray) {
|
||||
// We need to create a new array, otherwise change tracking will
|
||||
// update the old doc (gh-4449)
|
||||
value = new MongooseArray(value, this.path, doc);
|
||||
}
|
||||
options = options || emptyOpts;
|
||||
|
||||
const isPopulated = doc != null && doc.$__ != null && doc.populated(this.path);
|
||||
if (isPopulated) {
|
||||
value = MongooseArray(value, options.path || this._arrayPath || this.path, doc, this);
|
||||
|
||||
if (init && doc != null && doc.$__ != null && doc.populated(this.path)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (this.caster && this.casterConstructor !== Mixed) {
|
||||
const caster = this.caster;
|
||||
const isMongooseArray = caster.$isMongooseArray;
|
||||
const isArrayOfNumbers = caster.instance === 'Number';
|
||||
if (caster && this.casterConstructor !== Mixed) {
|
||||
try {
|
||||
for (i = 0, l = value.length; i < l; i++) {
|
||||
for (i = 0; i < len; i++) {
|
||||
// Special case: number arrays disallow undefined.
|
||||
// Re: gh-840
|
||||
// See commit 1298fe92d2c790a90594bd08199e45a4a09162a6
|
||||
if (this.caster.instance === 'Number' && value[i] === void 0) {
|
||||
if (isArrayOfNumbers && value[i] === void 0) {
|
||||
throw new MongooseError('Mongoose number arrays disallow storing undefined');
|
||||
}
|
||||
const opts = {};
|
||||
if (options != null && options.arrayPath != null) {
|
||||
opts.arrayPath = options.arrayPath + '.' + i;
|
||||
} else if (this.caster._arrayPath != null) {
|
||||
opts.arrayPath = this.caster._arrayPath.slice(0, -2) + '.' + i;
|
||||
// Perf: creating `arrayPath` is expensive for large arrays.
|
||||
// We only need `arrayPath` if this is a nested array, so
|
||||
// skip if possible.
|
||||
if (isMongooseArray) {
|
||||
if (options.arrayPath != null) {
|
||||
opts.arrayPathIndex = i;
|
||||
} else if (caster._arrayParentPath != null) {
|
||||
opts.arrayPathIndex = i;
|
||||
}
|
||||
}
|
||||
value[i] = this.caster.cast(value[i], doc, init, void 0, opts);
|
||||
value[i] = caster.applySetters(value[i], doc, init, void 0, opts);
|
||||
}
|
||||
} catch (e) {
|
||||
// rethrow
|
||||
throw new CastError('[' + e.kind + ']', util.inspect(value), this.path, e, this);
|
||||
throw new CastError('[' + e.kind + ']', util.inspect(value), this.path + '.' + i, e, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,12 +408,50 @@ SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
|
||||
throw new CastError('Array', util.inspect(value), this.path, null, this);
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaArray.prototype._castForPopulate = function _castForPopulate(value, doc) {
|
||||
// lazy load
|
||||
MongooseArray || (MongooseArray = require('../types').Array);
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
let i;
|
||||
const len = value.length;
|
||||
|
||||
const caster = this.caster;
|
||||
if (caster && this.casterConstructor !== Mixed) {
|
||||
try {
|
||||
for (i = 0; i < len; i++) {
|
||||
const opts = {};
|
||||
// Perf: creating `arrayPath` is expensive for large arrays.
|
||||
// We only need `arrayPath` if this is a nested array, so
|
||||
// skip if possible.
|
||||
if (caster.$isMongooseArray && caster._arrayParentPath != null) {
|
||||
opts.arrayPathIndex = i;
|
||||
}
|
||||
|
||||
value[i] = caster.cast(value[i], doc, false, void 0, opts);
|
||||
}
|
||||
} catch (e) {
|
||||
// rethrow
|
||||
throw new CastError('[' + e.kind + ']', util.inspect(value), this.path + '.' + i, e, this);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new CastError('Array', util.inspect(value), this.path, null, this);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Ignore
|
||||
*/
|
||||
|
||||
SchemaArray.prototype.discriminator = function(name, schema) {
|
||||
let arr = this; // eslint-disable-line consistent-this
|
||||
let arr = this;
|
||||
while (arr.$isMongooseArray && !arr.$isMongooseDocumentArray) {
|
||||
arr = arr.casterConstructor;
|
||||
if (arr == null || typeof arr === 'function') {
|
||||
@@ -447,7 +509,7 @@ SchemaArray.prototype.castForQuery = function($conditional, value) {
|
||||
Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]]) {
|
||||
Constructor = Constructor.discriminators[val[Constructor.schema.options.discriminatorKey]];
|
||||
} else {
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor, val[Constructor.schema.options.discriminatorKey]);
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, val[Constructor.schema.options.discriminatorKey]);
|
||||
if (constructorByValue) {
|
||||
Constructor = constructorByValue;
|
||||
}
|
||||
@@ -537,18 +599,24 @@ handle.$all = cast$all;
|
||||
handle.$options = String;
|
||||
handle.$elemMatch = cast$elemMatch;
|
||||
handle.$geoIntersects = geospatial.cast$geoIntersects;
|
||||
handle.$or = handle.$and = function(val) {
|
||||
if (!Array.isArray(val)) {
|
||||
throw new TypeError('conditional $or/$and require array');
|
||||
}
|
||||
handle.$or = createLogicalQueryOperatorHandler('$or');
|
||||
handle.$and = createLogicalQueryOperatorHandler('$and');
|
||||
handle.$nor = createLogicalQueryOperatorHandler('$nor');
|
||||
|
||||
const ret = [];
|
||||
for (const obj of val) {
|
||||
ret.push(cast(this.casterConstructor.schema, obj));
|
||||
}
|
||||
function createLogicalQueryOperatorHandler(op) {
|
||||
return function logicalQueryOperatorHandler(val) {
|
||||
if (!Array.isArray(val)) {
|
||||
throw new TypeError('conditional ' + op + ' requires an array');
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
const ret = [];
|
||||
for (const obj of val) {
|
||||
ret.push(cast(this.casterConstructor.schema, obj));
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
handle.$near =
|
||||
handle.$nearSphere = geospatial.cast$near;
|
||||
|
||||
57
node_modules/mongoose/lib/schema/boolean.js
generated
vendored
57
node_modules/mongoose/lib/schema/boolean.js
generated
vendored
@@ -94,18 +94,24 @@ SchemaBoolean.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (v != null && typeof v !== 'boolean') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaBoolean._defaultCaster = v => {
|
||||
if (v != null && typeof v !== 'boolean') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -188,9 +194,15 @@ Object.defineProperty(SchemaBoolean, 'convertToFalse', {
|
||||
*/
|
||||
|
||||
SchemaBoolean.prototype.cast = function(value) {
|
||||
const castBoolean = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
SchemaBoolean.cast();
|
||||
let castBoolean;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castBoolean = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castBoolean = this.constructor.cast();
|
||||
} else {
|
||||
castBoolean = SchemaBoolean.cast();
|
||||
}
|
||||
|
||||
try {
|
||||
return castBoolean(value);
|
||||
} catch (error) {
|
||||
@@ -224,6 +236,33 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val) {
|
||||
return this._castForQuery($conditional);
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SchemaBoolean.prototype._castNullish = function _castNullish(v) {
|
||||
if (typeof v === 'undefined' &&
|
||||
this.$$context != null &&
|
||||
this.$$context._mongooseOptions != null &&
|
||||
this.$$context._mongooseOptions.omitUndefined) {
|
||||
return v;
|
||||
}
|
||||
const castBoolean = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
SchemaBoolean.cast();
|
||||
if (castBoolean == null) {
|
||||
return v;
|
||||
}
|
||||
if (castBoolean.convertToFalse instanceof Set && castBoolean.convertToFalse.has(v)) {
|
||||
return false;
|
||||
}
|
||||
if (castBoolean.convertToTrue instanceof Set && castBoolean.convertToTrue.has(v)) {
|
||||
return true;
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
49
node_modules/mongoose/lib/schema/buffer.js
generated
vendored
49
node_modules/mongoose/lib/schema/buffer.js
generated
vendored
@@ -10,11 +10,8 @@ const SchemaType = require('../schematype');
|
||||
const handleBitwiseOperator = require('./operators/bitwise');
|
||||
const utils = require('../utils');
|
||||
|
||||
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
const Binary = MongooseBuffer.Binary;
|
||||
const CastError = SchemaType.CastError;
|
||||
let Document;
|
||||
|
||||
/**
|
||||
* Buffer SchemaType constructor
|
||||
@@ -124,36 +121,30 @@ SchemaBuffer.prototype.checkRequired = function(value, doc) {
|
||||
SchemaBuffer.prototype.cast = function(value, doc, init) {
|
||||
let ret;
|
||||
if (SchemaType._isRef(this, value, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
if (value && value.isMongooseBuffer) {
|
||||
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)) {
|
||||
if (!value || !value.isMongooseBuffer) {
|
||||
value = new MongooseBuffer(value, [this.path, doc]);
|
||||
if (this.options.subtype != null) {
|
||||
value._subtype = this.options.subtype;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
} else if (!utils.isObject(value)) {
|
||||
throw new CastError('Buffer', value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
if (value instanceof Binary) {
|
||||
ret = new MongooseBuffer(value.value(true), [this.path, doc]);
|
||||
if (typeof value.sub_type !== 'number') {
|
||||
throw new CastError('Buffer', value, this.path, null, this);
|
||||
}
|
||||
ret._subtype = value.sub_type;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return this._castRef(value, doc, init);
|
||||
}
|
||||
|
||||
// documents
|
||||
@@ -213,9 +204,9 @@ SchemaBuffer.prototype.cast = function(value, doc, init) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ uuid: { type: Buffer, subtype: 4 });
|
||||
* var M = db.model('M', s);
|
||||
* var m = new M({ uuid: 'test string' });
|
||||
* const s = new Schema({ uuid: { type: Buffer, subtype: 4 });
|
||||
* const M = db.model('M', s);
|
||||
* const m = new M({ uuid: 'test string' });
|
||||
* m.uuid._subtype; // 4
|
||||
*
|
||||
* @param {Number} subtype the default subtype
|
||||
|
||||
63
node_modules/mongoose/lib/schema/date.js
generated
vendored
63
node_modules/mongoose/lib/schema/date.js
generated
vendored
@@ -8,6 +8,7 @@ const MongooseError = require('../error/index');
|
||||
const SchemaDateOptions = require('../options/SchemaDateOptions');
|
||||
const SchemaType = require('../schematype');
|
||||
const castDate = require('../cast/date');
|
||||
const getConstructorName = require('../helpers/getConstructorName');
|
||||
const utils = require('../utils');
|
||||
|
||||
const CastError = SchemaType.CastError;
|
||||
@@ -97,18 +98,24 @@ SchemaDate.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (v != null && !(v instanceof Date)) {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaDate._defaultCaster = v => {
|
||||
if (v != null && !(v instanceof Date)) {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Declares a TTL index (rounded to the nearest second) for _Date_ types only.
|
||||
*
|
||||
@@ -131,7 +138,7 @@ SchemaDate.cast = function cast(caster) {
|
||||
* new Schema({ createdAt: { type: Date, expires: '1.5h' }});
|
||||
*
|
||||
* // expire in 7 days
|
||||
* var schema = new Schema({ createdAt: Date });
|
||||
* const schema = new Schema({ createdAt: Date });
|
||||
* schema.path('createdAt').expires('7d');
|
||||
*
|
||||
* @param {Number|String} when
|
||||
@@ -141,7 +148,7 @@ SchemaDate.cast = function cast(caster) {
|
||||
*/
|
||||
|
||||
SchemaDate.prototype.expires = function(when) {
|
||||
if (!this._index || this._index.constructor.name !== 'Object') {
|
||||
if (getConstructorName(this._index) !== 'Object') {
|
||||
this._index = {};
|
||||
}
|
||||
|
||||
@@ -205,9 +212,9 @@ SchemaDate.prototype.checkRequired = function(value, doc) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ d: { type: Date, min: Date('1970-01-01') })
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ d: Date('1969-12-31') })
|
||||
* const s = new Schema({ d: { type: Date, min: Date('1970-01-01') })
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ d: Date('1969-12-31') })
|
||||
* m.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* m.d = Date('2014-12-08');
|
||||
@@ -216,10 +223,10 @@ SchemaDate.prototype.checkRequired = function(value, doc) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MIN} token which will be replaced with the invalid value
|
||||
* var min = [Date('1970-01-01'), 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
|
||||
* var schema = new Schema({ d: { type: Date, min: min })
|
||||
* var M = mongoose.model('M', schema);
|
||||
* var s= new M({ d: Date('1969-12-31') });
|
||||
* const min = [Date('1970-01-01'), 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
|
||||
* const schema = new Schema({ d: { type: Date, min: min })
|
||||
* const M = mongoose.model('M', schema);
|
||||
* const s= new M({ d: Date('1969-12-31') });
|
||||
* s.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `d` (1969-12-31) is before the limit (1970-01-01).
|
||||
* })
|
||||
@@ -267,9 +274,9 @@ SchemaDate.prototype.min = function(value, message) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ d: { type: Date, max: Date('2014-01-01') })
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ d: Date('2014-12-08') })
|
||||
* const s = new Schema({ d: { type: Date, max: Date('2014-01-01') })
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ d: Date('2014-12-08') })
|
||||
* m.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* m.d = Date('2013-12-31');
|
||||
@@ -278,10 +285,10 @@ SchemaDate.prototype.min = function(value, message) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MAX} token which will be replaced with the invalid value
|
||||
* var max = [Date('2014-01-01'), 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
|
||||
* var schema = new Schema({ d: { type: Date, max: max })
|
||||
* var M = mongoose.model('M', schema);
|
||||
* var s= new M({ d: Date('2014-12-08') });
|
||||
* const max = [Date('2014-01-01'), 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
|
||||
* const schema = new Schema({ d: { type: Date, max: max })
|
||||
* const M = mongoose.model('M', schema);
|
||||
* const s= new M({ d: Date('2014-12-08') });
|
||||
* s.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `d` (2014-12-08) exceeds the limit (2014-01-01).
|
||||
* })
|
||||
@@ -332,9 +339,15 @@ SchemaDate.prototype.max = function(value, message) {
|
||||
*/
|
||||
|
||||
SchemaDate.prototype.cast = function(value) {
|
||||
const castDate = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
SchemaDate.cast();
|
||||
let castDate;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castDate = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castDate = this.constructor.cast();
|
||||
} else {
|
||||
castDate = SchemaDate.cast();
|
||||
}
|
||||
|
||||
try {
|
||||
return castDate(value);
|
||||
} catch (error) {
|
||||
|
||||
69
node_modules/mongoose/lib/schema/decimal128.js
generated
vendored
69
node_modules/mongoose/lib/schema/decimal128.js
generated
vendored
@@ -10,10 +10,6 @@ const Decimal128Type = require('../types/decimal128');
|
||||
const castDecimal128 = require('../cast/decimal128');
|
||||
const utils = require('../utils');
|
||||
|
||||
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
let Document;
|
||||
|
||||
/**
|
||||
* Decimal128 SchemaType constructor.
|
||||
*
|
||||
@@ -97,18 +93,24 @@ Decimal128.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (v != null && !(v instanceof Decimal128Type)) {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
Decimal128._defaultCaster = v => {
|
||||
if (v != null && !(v instanceof Decimal128Type)) {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -162,49 +164,22 @@ Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
|
||||
|
||||
Decimal128.prototype.cast = function(value, doc, init) {
|
||||
if (SchemaType._isRef(this, value, doc, init)) {
|
||||
// wait! we may need to cast this to a document
|
||||
|
||||
if (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (value instanceof Decimal128Type) {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('Decimal128', value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
let ret = value;
|
||||
if (!doc.$__.populated ||
|
||||
!doc.$__.populated[path] ||
|
||||
!doc.$__.populated[path].options ||
|
||||
!doc.$__.populated[path].options.options ||
|
||||
!doc.$__.populated[path].options.options.lean) {
|
||||
ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this._castRef(value, doc, init);
|
||||
}
|
||||
|
||||
let castDecimal128;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castDecimal128 = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castDecimal128 = this.constructor.cast();
|
||||
} else {
|
||||
castDecimal128 = Decimal128.cast();
|
||||
}
|
||||
|
||||
const castDecimal128 = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
Decimal128.cast();
|
||||
try {
|
||||
return castDecimal128(value);
|
||||
} catch (error) {
|
||||
|
||||
56
node_modules/mongoose/lib/schema/documentarray.js
generated
vendored
56
node_modules/mongoose/lib/schema/documentarray.js
generated
vendored
@@ -18,6 +18,7 @@ const util = require('util');
|
||||
const utils = require('../utils');
|
||||
const getConstructor = require('../helpers/discriminator/getConstructor');
|
||||
|
||||
const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
|
||||
const arrayPathSymbol = require('../helpers/symbols').arrayPathSymbol;
|
||||
const documentArrayParent = require('../helpers/symbols').documentArrayParent;
|
||||
|
||||
@@ -251,6 +252,11 @@ DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
|
||||
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
||||
}
|
||||
|
||||
if (options != null && options.validateModifiedOnly && !doc.isModified()) {
|
||||
--count || fn(error);
|
||||
continue;
|
||||
}
|
||||
|
||||
doc.$__validate(callback);
|
||||
}
|
||||
}
|
||||
@@ -267,7 +273,7 @@ DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
DocumentArrayPath.prototype.doValidateSync = function(array, scope) {
|
||||
DocumentArrayPath.prototype.doValidateSync = function(array, scope, options) {
|
||||
const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
|
||||
if (schemaTypeError != null) {
|
||||
schemaTypeError.$isArrayValidatorError = true;
|
||||
@@ -299,6 +305,10 @@ DocumentArrayPath.prototype.doValidateSync = function(array, scope) {
|
||||
doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
|
||||
}
|
||||
|
||||
if (options != null && options.validateModifiedOnly && !doc.isModified()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const subdocValidateError = doc.validateSync();
|
||||
|
||||
if (subdocValidateError && resultError == null) {
|
||||
@@ -361,6 +371,11 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
||||
// lazy load
|
||||
MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray'));
|
||||
|
||||
// Skip casting if `value` is the same as the previous value, no need to cast. See gh-9266
|
||||
if (value != null && value[arrayPathSymbol] != null && value === prev) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let selected;
|
||||
let subdoc;
|
||||
const _opts = { transform: false, virtuals: false };
|
||||
@@ -387,11 +402,16 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
||||
value = new MongooseDocumentArray(value, this.path, doc);
|
||||
}
|
||||
|
||||
if (options.arrayPath != null) {
|
||||
value[arrayPathSymbol] = options.arrayPath;
|
||||
if (prev != null) {
|
||||
value[arrayAtomicsSymbol] = prev[arrayAtomicsSymbol] || {};
|
||||
}
|
||||
|
||||
if (options.arrayPathIndex != null) {
|
||||
value[arrayPathSymbol] = this.path + '.' + options.arrayPathIndex;
|
||||
}
|
||||
|
||||
const len = value.length;
|
||||
const initDocumentOptions = { skipId: true, willInit: true };
|
||||
|
||||
for (let i = 0; i < len; ++i) {
|
||||
if (!value[i]) {
|
||||
@@ -424,7 +444,7 @@ DocumentArrayPath.prototype.cast = function(value, doc, init, prev, options) {
|
||||
selected = true;
|
||||
}
|
||||
|
||||
subdoc = new Constructor(null, value, true, selected, i);
|
||||
subdoc = new Constructor(null, value, initDocumentOptions, selected, i);
|
||||
value[i] = subdoc.init(value[i]);
|
||||
} else {
|
||||
if (prev && typeof prev.id === 'function') {
|
||||
@@ -473,6 +493,14 @@ DocumentArrayPath.prototype.clone = function() {
|
||||
return schematype;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
DocumentArrayPath.prototype.applyGetters = function(value, scope) {
|
||||
return SchemaType.prototype.applyGetters.call(this, value, scope);
|
||||
};
|
||||
|
||||
/*!
|
||||
* Scopes paths selected in a query to this array.
|
||||
* Necessary for proper default application of subdocument values.
|
||||
@@ -513,6 +541,26 @@ function scopePaths(array, fields, init) {
|
||||
return hasKeys && selected || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a default option for all DocumentArray instances.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* // Make all numbers have option `min` equal to 0.
|
||||
* mongoose.Schema.DocumentArray.set('_id', false);
|
||||
*
|
||||
* @param {String} option - The option you'd like to set the value for
|
||||
* @param {*} value - value for option
|
||||
* @return {undefined}
|
||||
* @function set
|
||||
* @static
|
||||
* @api public
|
||||
*/
|
||||
|
||||
DocumentArrayPath.defaultOptions = {};
|
||||
|
||||
DocumentArrayPath.set = SchemaType.set;
|
||||
|
||||
/*!
|
||||
* Module exports.
|
||||
*/
|
||||
|
||||
22
node_modules/mongoose/lib/schema/map.js
generated
vendored
22
node_modules/mongoose/lib/schema/map.js
generated
vendored
@@ -26,23 +26,37 @@ class Map extends SchemaType {
|
||||
return val;
|
||||
}
|
||||
|
||||
const path = this.path;
|
||||
|
||||
if (init) {
|
||||
const map = new MongooseMap({}, this.path, doc, this.$__schemaType);
|
||||
const map = new MongooseMap({}, path, doc, this.$__schemaType);
|
||||
|
||||
if (val instanceof global.Map) {
|
||||
for (const key of val.keys()) {
|
||||
map.$init(key, map.$__schemaType.cast(val.get(key), doc, true));
|
||||
let _val = val.get(key);
|
||||
if (_val == null) {
|
||||
_val = map.$__schemaType._castNullish(_val);
|
||||
} else {
|
||||
_val = map.$__schemaType.cast(_val, doc, true, null, { path: path + '.' + key });
|
||||
}
|
||||
map.$init(key, _val);
|
||||
}
|
||||
} else {
|
||||
for (const key of Object.keys(val)) {
|
||||
map.$init(key, map.$__schemaType.cast(val[key], doc, true));
|
||||
let _val = val[key];
|
||||
if (_val == null) {
|
||||
_val = map.$__schemaType._castNullish(_val);
|
||||
} else {
|
||||
_val = map.$__schemaType.cast(_val, doc, true, null, { path: path + '.' + key });
|
||||
}
|
||||
map.$init(key, _val);
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
return new MongooseMap(val, this.path, doc, this.$__schemaType);
|
||||
return new MongooseMap(val, path, doc, this.$__schemaType);
|
||||
}
|
||||
|
||||
clone() {
|
||||
|
||||
4
node_modules/mongoose/lib/schema/mixed.js
generated
vendored
4
node_modules/mongoose/lib/schema/mixed.js
generated
vendored
@@ -7,6 +7,7 @@
|
||||
const SchemaType = require('../schematype');
|
||||
const symbols = require('./symbols');
|
||||
const isObject = require('../helpers/isObject');
|
||||
const utils = require('../utils');
|
||||
|
||||
/**
|
||||
* Mixed SchemaType constructor.
|
||||
@@ -103,6 +104,9 @@ Mixed.set = SchemaType.set;
|
||||
*/
|
||||
|
||||
Mixed.prototype.cast = function(val) {
|
||||
if (val instanceof Error) {
|
||||
return utils.errorToPOJO(val);
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
|
||||
101
node_modules/mongoose/lib/schema/number.js
generated
vendored
101
node_modules/mongoose/lib/schema/number.js
generated
vendored
@@ -11,10 +11,7 @@ const castNumber = require('../cast/number');
|
||||
const handleBitwiseOperator = require('./operators/bitwise');
|
||||
const utils = require('../utils');
|
||||
|
||||
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
const CastError = SchemaType.CastError;
|
||||
let Document;
|
||||
|
||||
/**
|
||||
* Number SchemaType constructor.
|
||||
@@ -103,18 +100,24 @@ SchemaNumber.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (typeof v !== 'number') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaNumber._defaultCaster = v => {
|
||||
if (typeof v !== 'number') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* This schema type's name, to defend against minifiers that mangle
|
||||
* function names.
|
||||
@@ -179,9 +182,9 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ n: { type: Number, min: 10 })
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ n: 9 })
|
||||
* const s = new Schema({ n: { type: Number, min: 10 })
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ n: 9 })
|
||||
* m.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* m.n = 10;
|
||||
@@ -190,10 +193,10 @@ SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MIN} token which will be replaced with the invalid value
|
||||
* var min = [10, 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
|
||||
* var schema = new Schema({ n: { type: Number, min: min })
|
||||
* var M = mongoose.model('Measurement', schema);
|
||||
* var s= new M({ n: 4 });
|
||||
* const min = [10, 'The value of path `{PATH}` ({VALUE}) is beneath the limit ({MIN}).'];
|
||||
* const schema = new Schema({ n: { type: Number, min: min })
|
||||
* const M = mongoose.model('Measurement', schema);
|
||||
* const s= new M({ n: 4 });
|
||||
* s.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `n` (4) is beneath the limit (10).
|
||||
* })
|
||||
@@ -233,9 +236,9 @@ SchemaNumber.prototype.min = function(value, message) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ n: { type: Number, max: 10 })
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ n: 11 })
|
||||
* const s = new Schema({ n: { type: Number, max: 10 })
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ n: 11 })
|
||||
* m.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* m.n = 10;
|
||||
@@ -244,10 +247,10 @@ SchemaNumber.prototype.min = function(value, message) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MAX} token which will be replaced with the invalid value
|
||||
* var max = [10, 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
|
||||
* var schema = new Schema({ n: { type: Number, max: max })
|
||||
* var M = mongoose.model('Measurement', schema);
|
||||
* var s= new M({ n: 4 });
|
||||
* const max = [10, 'The value of path `{PATH}` ({VALUE}) exceeds the limit ({MAX}).'];
|
||||
* const schema = new Schema({ n: { type: Number, max: max })
|
||||
* const M = mongoose.model('Measurement', schema);
|
||||
* const s= new M({ n: 4 });
|
||||
* s.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `n` (4) exceeds the limit (10).
|
||||
* })
|
||||
@@ -287,10 +290,10 @@ SchemaNumber.prototype.max = function(value, message) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ n: { type: Number, enum: [1, 2, 3] });
|
||||
* var M = db.model('M', s);
|
||||
* const s = new Schema({ n: { type: Number, enum: [1, 2, 3] });
|
||||
* const M = db.model('M', s);
|
||||
*
|
||||
* var m = new M({ n: 4 });
|
||||
* const m = new M({ n: 4 });
|
||||
* await m.save(); // throws validation error
|
||||
*
|
||||
* m.n = 3;
|
||||
@@ -310,8 +313,13 @@ SchemaNumber.prototype.enum = function(values, message) {
|
||||
}, this);
|
||||
}
|
||||
|
||||
|
||||
if (!Array.isArray(values)) {
|
||||
values = Array.prototype.slice.call(arguments);
|
||||
if (utils.isObject(values)) {
|
||||
values = utils.object.vals(values);
|
||||
} else {
|
||||
values = Array.prototype.slice.call(arguments);
|
||||
}
|
||||
message = MongooseError.messages.Number.enum;
|
||||
}
|
||||
|
||||
@@ -339,45 +347,26 @@ SchemaNumber.prototype.enum = function(values, message) {
|
||||
|
||||
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 (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (typeof value === 'number') {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('Number', value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
const ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
return this._castRef(value, doc, init);
|
||||
}
|
||||
|
||||
const val = value && typeof value._id !== 'undefined' ?
|
||||
value._id : // documents
|
||||
value;
|
||||
|
||||
const castNumber = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
SchemaNumber.cast();
|
||||
let castNumber;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castNumber = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castNumber = this.constructor.cast();
|
||||
} else {
|
||||
castNumber = SchemaNumber.cast();
|
||||
}
|
||||
|
||||
try {
|
||||
return castNumber(val);
|
||||
} catch (err) {
|
||||
|
||||
69
node_modules/mongoose/lib/schema/objectid.js
generated
vendored
69
node_modules/mongoose/lib/schema/objectid.js
generated
vendored
@@ -7,11 +7,10 @@
|
||||
const SchemaObjectIdOptions = require('../options/SchemaObjectIdOptions');
|
||||
const SchemaType = require('../schematype');
|
||||
const castObjectId = require('../cast/objectid');
|
||||
const getConstructorName = require('../helpers/getConstructorName');
|
||||
const oid = require('../types/objectid');
|
||||
const utils = require('../utils');
|
||||
|
||||
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
const CastError = SchemaType.CastError;
|
||||
let Document;
|
||||
|
||||
@@ -151,18 +150,24 @@ ObjectId.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (!(v instanceof oid)) {
|
||||
throw new Error(v + ' is not an instance of ObjectId');
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
ObjectId._defaultCaster = v => {
|
||||
if (!(v instanceof oid)) {
|
||||
throw new Error(v + ' is not an instance of ObjectId');
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Override the function the required validator uses to check whether a string
|
||||
* passes the `required` check.
|
||||
@@ -219,50 +224,24 @@ ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
|
||||
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 (value === null || value === undefined) {
|
||||
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 ((value.constructor.name || '').toLowerCase() === 'objectid') {
|
||||
} else if ((getConstructorName(value) || '').toLowerCase() === 'objectid') {
|
||||
return new oid(value.toHexString());
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('ObjectId', value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
let ret = value;
|
||||
if (!doc.$__.populated ||
|
||||
!doc.$__.populated[path] ||
|
||||
!doc.$__.populated[path].options ||
|
||||
!doc.$__.populated[path].options.options ||
|
||||
!doc.$__.populated[path].options.options.lean) {
|
||||
ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this._castRef(value, doc, init);
|
||||
}
|
||||
|
||||
let castObjectId;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castObjectId = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castObjectId = this.constructor.cast();
|
||||
} else {
|
||||
castObjectId = ObjectId.cast();
|
||||
}
|
||||
|
||||
const castObjectId = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
ObjectId.cast();
|
||||
try {
|
||||
return castObjectId(value);
|
||||
} catch (error) {
|
||||
|
||||
9
node_modules/mongoose/lib/schema/operators/type.js
generated
vendored
9
node_modules/mongoose/lib/schema/operators/type.js
generated
vendored
@@ -5,8 +5,15 @@
|
||||
*/
|
||||
|
||||
module.exports = function(val) {
|
||||
if (Array.isArray(val)) {
|
||||
if (!val.every(v => typeof v === 'number' || typeof v === 'string')) {
|
||||
throw new Error('$type array values must be strings or numbers');
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
if (typeof val !== 'number' && typeof val !== 'string') {
|
||||
throw new Error('$type parameter must be number or string');
|
||||
throw new Error('$type parameter must be number, string, or array of numbers and strings');
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
157
node_modules/mongoose/lib/schema/string.js
generated
vendored
157
node_modules/mongoose/lib/schema/string.js
generated
vendored
@@ -10,10 +10,7 @@ const SchemaStringOptions = require('../options/SchemaStringOptions');
|
||||
const castString = require('../cast/string');
|
||||
const utils = require('../utils');
|
||||
|
||||
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
const CastError = SchemaType.CastError;
|
||||
let Document;
|
||||
|
||||
/**
|
||||
* String SchemaType constructor.
|
||||
@@ -86,18 +83,24 @@ SchemaString.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = v => {
|
||||
if (v != null && typeof v !== 'string') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
caster = this._defaultCaster;
|
||||
}
|
||||
this._cast = caster;
|
||||
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaString._defaultCaster = v => {
|
||||
if (v != null && typeof v !== 'string') {
|
||||
throw new Error();
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/**
|
||||
* Attaches a getter for all String instances.
|
||||
*
|
||||
@@ -171,10 +174,10 @@ SchemaString.checkRequired = SchemaType.checkRequired;
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var states = ['opening', 'open', 'closing', 'closed']
|
||||
* var s = new Schema({ state: { type: String, enum: states }})
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ state: 'invalid' })
|
||||
* const states = ['opening', 'open', 'closing', 'closed']
|
||||
* const s = new Schema({ state: { type: String, enum: states }})
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ state: 'invalid' })
|
||||
* m.save(function (err) {
|
||||
* console.error(String(err)) // ValidationError: `invalid` is not a valid enum value for path `state`.
|
||||
* m.state = 'open'
|
||||
@@ -182,13 +185,13 @@ SchemaString.checkRequired = SchemaType.checkRequired;
|
||||
* })
|
||||
*
|
||||
* // or with custom error messages
|
||||
* var enum = {
|
||||
* const enum = {
|
||||
* values: ['opening', 'open', 'closing', 'closed'],
|
||||
* message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
|
||||
* }
|
||||
* var s = new Schema({ state: { type: String, enum: enum })
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ state: 'invalid' })
|
||||
* const s = new Schema({ state: { type: String, enum: enum })
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ state: 'invalid' })
|
||||
* m.save(function (err) {
|
||||
* console.error(String(err)) // ValidationError: enum validator failed for path `state` with value `invalid`
|
||||
* m.state = 'open'
|
||||
@@ -217,8 +220,13 @@ SchemaString.prototype.enum = function() {
|
||||
let errorMessage;
|
||||
|
||||
if (utils.isObject(arguments[0])) {
|
||||
values = arguments[0].values;
|
||||
errorMessage = arguments[0].message;
|
||||
if (Array.isArray(arguments[0].values)) {
|
||||
values = arguments[0].values;
|
||||
errorMessage = arguments[0].message;
|
||||
} else {
|
||||
values = utils.object.vals(arguments[0]);
|
||||
errorMessage = MongooseError.messages.String.enum;
|
||||
}
|
||||
} else {
|
||||
values = arguments;
|
||||
errorMessage = MongooseError.messages.String.enum;
|
||||
@@ -249,9 +257,9 @@ SchemaString.prototype.enum = function() {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ email: { type: String, lowercase: true }})
|
||||
* var M = db.model('M', s);
|
||||
* var m = new M({ email: 'SomeEmail@example.COM' });
|
||||
* const s = new Schema({ email: { type: String, lowercase: true }})
|
||||
* const M = db.model('M', s);
|
||||
* const m = new M({ email: 'SomeEmail@example.COM' });
|
||||
* console.log(m.email) // someemail@example.com
|
||||
* M.find({ email: 'SomeEmail@example.com' }); // Queries by 'someemail@example.com'
|
||||
*
|
||||
@@ -287,9 +295,9 @@ SchemaString.prototype.lowercase = function(shouldApply) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ caps: { type: String, uppercase: true }})
|
||||
* var M = db.model('M', s);
|
||||
* var m = new M({ caps: 'an example' });
|
||||
* const s = new Schema({ caps: { type: String, uppercase: true }})
|
||||
* const M = db.model('M', s);
|
||||
* const m = new M({ caps: 'an example' });
|
||||
* console.log(m.caps) // AN EXAMPLE
|
||||
* M.find({ caps: 'an example' }) // Matches documents where caps = 'AN EXAMPLE'
|
||||
*
|
||||
@@ -325,11 +333,11 @@ SchemaString.prototype.uppercase = function(shouldApply) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ name: { type: String, trim: true }});
|
||||
* var M = db.model('M', s);
|
||||
* var string = ' some name ';
|
||||
* const s = new Schema({ name: { type: String, trim: true }});
|
||||
* const M = db.model('M', s);
|
||||
* const string = ' some name ';
|
||||
* console.log(string.length); // 11
|
||||
* var m = new M({ name: string });
|
||||
* const m = new M({ name: string });
|
||||
* console.log(m.name.length); // 9
|
||||
*
|
||||
* // Equivalent to `findOne({ name: string.trim() })`
|
||||
@@ -365,9 +373,9 @@ SchemaString.prototype.trim = function(shouldTrim) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var schema = new Schema({ postalCode: { type: String, minlength: 5 })
|
||||
* var Address = db.model('Address', schema)
|
||||
* var address = new Address({ postalCode: '9512' })
|
||||
* const schema = new Schema({ postalCode: { type: String, minlength: 5 })
|
||||
* const Address = db.model('Address', schema)
|
||||
* const address = new Address({ postalCode: '9512' })
|
||||
* address.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* address.postalCode = '95125';
|
||||
@@ -376,10 +384,10 @@ SchemaString.prototype.trim = function(shouldTrim) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MINLENGTH} token which will be replaced with the minimum allowed length
|
||||
* var minlength = [5, 'The value of path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).'];
|
||||
* var schema = new Schema({ postalCode: { type: String, minlength: minlength })
|
||||
* var Address = mongoose.model('Address', schema);
|
||||
* var address = new Address({ postalCode: '9512' });
|
||||
* const minlength = [5, 'The value of path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).'];
|
||||
* const schema = new Schema({ postalCode: { type: String, minlength: minlength })
|
||||
* const Address = mongoose.model('Address', schema);
|
||||
* const address = new Address({ postalCode: '9512' });
|
||||
* address.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `postalCode` (`9512`) is shorter than the minimum length (5).
|
||||
* })
|
||||
@@ -414,14 +422,16 @@ SchemaString.prototype.minlength = function(value, message) {
|
||||
return this;
|
||||
};
|
||||
|
||||
SchemaString.prototype.minLength = SchemaString.prototype.minlength;
|
||||
|
||||
/**
|
||||
* Sets a maximum length validator.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var schema = new Schema({ postalCode: { type: String, maxlength: 9 })
|
||||
* var Address = db.model('Address', schema)
|
||||
* var address = new Address({ postalCode: '9512512345' })
|
||||
* const schema = new Schema({ postalCode: { type: String, maxlength: 9 })
|
||||
* const Address = db.model('Address', schema)
|
||||
* const address = new Address({ postalCode: '9512512345' })
|
||||
* address.save(function (err) {
|
||||
* console.error(err) // validator error
|
||||
* address.postalCode = '95125';
|
||||
@@ -430,10 +440,10 @@ SchemaString.prototype.minlength = function(value, message) {
|
||||
*
|
||||
* // custom error messages
|
||||
* // We can also use the special {MAXLENGTH} token which will be replaced with the maximum allowed length
|
||||
* var maxlength = [9, 'The value of path `{PATH}` (`{VALUE}`) exceeds the maximum allowed length ({MAXLENGTH}).'];
|
||||
* var schema = new Schema({ postalCode: { type: String, maxlength: maxlength })
|
||||
* var Address = mongoose.model('Address', schema);
|
||||
* var address = new Address({ postalCode: '9512512345' });
|
||||
* const maxlength = [9, 'The value of path `{PATH}` (`{VALUE}`) exceeds the maximum allowed length ({MAXLENGTH}).'];
|
||||
* const schema = new Schema({ postalCode: { type: String, maxlength: maxlength })
|
||||
* const Address = mongoose.model('Address', schema);
|
||||
* const address = new Address({ postalCode: '9512512345' });
|
||||
* address.validate(function (err) {
|
||||
* console.log(String(err)) // ValidationError: The value of path `postalCode` (`9512512345`) exceeds the maximum allowed length (9).
|
||||
* })
|
||||
@@ -468,6 +478,8 @@ SchemaString.prototype.maxlength = function(value, message) {
|
||||
return this;
|
||||
};
|
||||
|
||||
SchemaString.prototype.maxLength = SchemaString.prototype.maxlength;
|
||||
|
||||
/**
|
||||
* Sets a regexp validator.
|
||||
*
|
||||
@@ -475,9 +487,9 @@ SchemaString.prototype.maxlength = function(value, message) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ name: { type: String, match: /^a/ }})
|
||||
* var M = db.model('M', s)
|
||||
* var m = new M({ name: 'I am invalid' })
|
||||
* const s = new Schema({ name: { type: String, match: /^a/ }})
|
||||
* const M = db.model('M', s)
|
||||
* const m = new M({ name: 'I am invalid' })
|
||||
* m.validate(function (err) {
|
||||
* console.error(String(err)) // "ValidationError: Path `name` is invalid (I am invalid)."
|
||||
* m.name = 'apples'
|
||||
@@ -487,17 +499,17 @@ SchemaString.prototype.maxlength = function(value, message) {
|
||||
* })
|
||||
*
|
||||
* // using a custom error message
|
||||
* var match = [ /\.html$/, "That file doesn't end in .html ({VALUE})" ];
|
||||
* var s = new Schema({ file: { type: String, match: match }})
|
||||
* var M = db.model('M', s);
|
||||
* var m = new M({ file: 'invalid' });
|
||||
* const match = [ /\.html$/, "That file doesn't end in .html ({VALUE})" ];
|
||||
* const s = new Schema({ file: { type: String, match: match }})
|
||||
* const M = db.model('M', s);
|
||||
* const m = new M({ file: 'invalid' });
|
||||
* m.validate(function (err) {
|
||||
* console.log(String(err)) // "ValidationError: That file doesn't end in .html (invalid)"
|
||||
* })
|
||||
*
|
||||
* Empty strings, `undefined`, and `null` values always pass the match validator. If you require these values, enable the `required` validator also.
|
||||
*
|
||||
* var s = new Schema({ name: { type: String, match: /^a/, required: true }})
|
||||
* const s = new Schema({ name: { type: String, match: /^a/, required: true }})
|
||||
*
|
||||
* @param {RegExp} regExp regular expression to test against
|
||||
* @param {String} [message] optional custom error message
|
||||
@@ -516,6 +528,10 @@ SchemaString.prototype.match = function match(regExp, message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// In case RegExp happens to have `/g` flag set, we need to reset the
|
||||
// `lastIndex`, otherwise `match` will intermittently fail.
|
||||
regExp.lastIndex = 0;
|
||||
|
||||
const ret = ((v != null && v !== '')
|
||||
? regExp.test(v)
|
||||
: true);
|
||||
@@ -565,41 +581,22 @@ SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
|
||||
|
||||
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 (value === null || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
|
||||
// lazy load
|
||||
Document || (Document = require('./../document'));
|
||||
|
||||
if (value instanceof Document) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (typeof value === 'string') {
|
||||
return value;
|
||||
} else if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
throw new CastError('string', value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
const ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
return ret;
|
||||
return this._castRef(value, doc, init);
|
||||
}
|
||||
|
||||
let castString;
|
||||
if (typeof this._castFunction === 'function') {
|
||||
castString = this._castFunction;
|
||||
} else if (typeof this.constructor.cast === 'function') {
|
||||
castString = this.constructor.cast();
|
||||
} else {
|
||||
castString = SchemaString.cast();
|
||||
}
|
||||
|
||||
const castString = typeof this.constructor.cast === 'function' ?
|
||||
this.constructor.cast() :
|
||||
SchemaString.cast();
|
||||
try {
|
||||
return castString(value);
|
||||
} catch (error) {
|
||||
|
||||
296
node_modules/mongoose/lib/schematype.js
generated
vendored
296
node_modules/mongoose/lib/schematype.js
generated
vendored
@@ -15,6 +15,9 @@ const schemaTypeSymbol = require('./helpers/symbols').schemaTypeSymbol;
|
||||
const util = require('util');
|
||||
const utils = require('./utils');
|
||||
const validatorErrorSymbol = require('./helpers/symbols').validatorErrorSymbol;
|
||||
const documentIsModified = require('./helpers/symbols').documentIsModified;
|
||||
|
||||
const populateModelSymbol = require('./helpers/symbols').populateModelSymbol;
|
||||
|
||||
const CastError = MongooseError.CastError;
|
||||
const ValidatorError = MongooseError.ValidatorError;
|
||||
@@ -44,6 +47,8 @@ function SchemaType(path, options, instance) {
|
||||
[];
|
||||
this.setters = [];
|
||||
|
||||
this.splitPath();
|
||||
|
||||
options = options || {};
|
||||
const defaultOptions = this.constructor.defaultOptions || {};
|
||||
const defaultOptionsKeys = Object.keys(defaultOptions);
|
||||
@@ -54,7 +59,6 @@ function SchemaType(path, options, instance) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (options.select == null) {
|
||||
delete options.select;
|
||||
}
|
||||
@@ -73,6 +77,7 @@ function SchemaType(path, options, instance) {
|
||||
const keys = Object.keys(this.options);
|
||||
for (const prop of keys) {
|
||||
if (prop === 'cast') {
|
||||
this.castFunction(this.options[prop]);
|
||||
continue;
|
||||
}
|
||||
if (utils.hasUserDefinedProperty(this.options, prop) && typeof this[prop] === 'function') {
|
||||
@@ -118,11 +123,27 @@ function SchemaType(path, options, instance) {
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
* The class that Mongoose uses internally to instantiate this SchemaType's `options` property.
|
||||
*/
|
||||
|
||||
SchemaType.prototype.OptionsConstructor = SchemaTypeOptions;
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaType.prototype.splitPath = function() {
|
||||
if (this._presplitPath != null) {
|
||||
return this._presplitPath;
|
||||
}
|
||||
if (this.path == null) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
this._presplitPath = this.path.indexOf('.') === -1 ? [this.path] : this.path.split('.');
|
||||
return this._presplitPath;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get/set the function used to cast arbitrary values to this type.
|
||||
*
|
||||
@@ -155,6 +176,53 @@ SchemaType.cast = function cast(caster) {
|
||||
return this._cast;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get/set the function used to cast arbitrary values to this particular schematype instance.
|
||||
* Overrides `SchemaType.cast()`.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* // Disallow `null` for numbers, and don't try to cast any values to
|
||||
* // numbers, so even strings like '123' will cause a CastError.
|
||||
* const number = new mongoose.Number('mypath', {});
|
||||
* number.cast(function(v) {
|
||||
* assert.ok(v === undefined || typeof v === 'number');
|
||||
* return v;
|
||||
* });
|
||||
*
|
||||
* @param {Function|false} caster Function that casts arbitrary values to this type, or throws an error if casting failed
|
||||
* @return {Function}
|
||||
* @static
|
||||
* @receiver SchemaType
|
||||
* @function cast
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaType.prototype.castFunction = function castFunction(caster) {
|
||||
if (arguments.length === 0) {
|
||||
return this._castFunction;
|
||||
}
|
||||
if (caster === false) {
|
||||
caster = this.constructor._defaultCaster || (v => v);
|
||||
}
|
||||
this._castFunction = caster;
|
||||
|
||||
return this._castFunction;
|
||||
};
|
||||
|
||||
/**
|
||||
* The function that Mongoose calls to cast arbitrary values to this SchemaType.
|
||||
*
|
||||
* @param {Object} value value to cast
|
||||
* @param {Document} doc document that triggers the casting
|
||||
* @param {Boolean} init
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaType.prototype.cast = function cast() {
|
||||
throw new Error('Base SchemaType class does not implement a `cast()` function');
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a default option for this schema type.
|
||||
*
|
||||
@@ -205,9 +273,9 @@ SchemaType.get = function(getter) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var schema = new Schema({ n: { type: Number, default: 10 })
|
||||
* var M = db.model('M', schema)
|
||||
* var m = new M;
|
||||
* const schema = new Schema({ n: { type: Number, default: 10 })
|
||||
* const M = db.model('M', schema)
|
||||
* const 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.
|
||||
@@ -215,13 +283,13 @@ SchemaType.get = function(getter) {
|
||||
* ####Example:
|
||||
*
|
||||
* // values are cast:
|
||||
* var schema = new Schema({ aNumber: { type: Number, default: 4.815162342 }})
|
||||
* var M = db.model('M', schema)
|
||||
* var m = new M;
|
||||
* const schema = new Schema({ aNumber: { type: Number, default: 4.815162342 }})
|
||||
* const M = db.model('M', schema)
|
||||
* const m = new M;
|
||||
* console.log(m.aNumber) // 4.815162342
|
||||
*
|
||||
* // default unique objects for Mixed types:
|
||||
* var schema = new Schema({ mixed: Schema.Types.Mixed });
|
||||
* const schema = new Schema({ mixed: Schema.Types.Mixed });
|
||||
* schema.path('mixed').default(function () {
|
||||
* return {};
|
||||
* });
|
||||
@@ -229,13 +297,13 @@ SchemaType.get = function(getter) {
|
||||
* // if we don't use a function to return object literals for Mixed defaults,
|
||||
* // each document will receive a reference to the same object literal creating
|
||||
* // a "shared" object instance:
|
||||
* var schema = new Schema({ mixed: Schema.Types.Mixed });
|
||||
* const schema = new Schema({ mixed: Schema.Types.Mixed });
|
||||
* schema.path('mixed').default({});
|
||||
* var M = db.model('M', schema);
|
||||
* var m1 = new M;
|
||||
* const M = db.model('M', schema);
|
||||
* const m1 = new M;
|
||||
* m1.mixed.added = 1;
|
||||
* console.log(m1.mixed); // { added: 1 }
|
||||
* var m2 = new M;
|
||||
* const m2 = new M;
|
||||
* console.log(m2.mixed); // { added: 1 }
|
||||
*
|
||||
* @param {Function|any} val the default value
|
||||
@@ -268,11 +336,11 @@ SchemaType.prototype.default = function(val) {
|
||||
*
|
||||
* ####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' }})
|
||||
* const s = new Schema({ name: { type: String, index: true })
|
||||
* const s = new Schema({ loc: { type: [Number], index: 'hashed' })
|
||||
* const s = new Schema({ loc: { type: [Number], index: '2d', sparse: true })
|
||||
* const s = new Schema({ loc: { type: [Number], index: { type: '2dsphere', sparse: true }})
|
||||
* const s = new Schema({ date: { type: Date, index: { unique: true, expires: '1d' }})
|
||||
* s.path('my.path').index(true);
|
||||
* s.path('my.date').index({ expires: 60 });
|
||||
* s.path('my.path').index({ unique: true, sparse: true });
|
||||
@@ -300,7 +368,7 @@ SchemaType.prototype.index = function(options) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ name: { type: String, unique: true }});
|
||||
* const s = new Schema({ name: { type: String, unique: true }});
|
||||
* s.path('name').index({ unique: true });
|
||||
*
|
||||
* _NOTE: violating the constraint returns an `E11000` error from MongoDB when saving, not a Mongoose validation error._
|
||||
@@ -333,7 +401,7 @@ SchemaType.prototype.unique = function(bool) {
|
||||
*
|
||||
* ###Example:
|
||||
*
|
||||
* var s = new Schema({name : {type: String, text : true })
|
||||
* const s = new Schema({name : {type: String, text : true })
|
||||
* s.path('name').index({text : true});
|
||||
* @param {Boolean} bool
|
||||
* @return {SchemaType} this
|
||||
@@ -365,7 +433,7 @@ SchemaType.prototype.text = function(bool) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ name: { type: String, sparse: true } });
|
||||
* const s = new Schema({ name: { type: String, sparse: true } });
|
||||
* s.path('name').index({ sparse: true });
|
||||
*
|
||||
* @param {Boolean} bool
|
||||
@@ -442,6 +510,38 @@ SchemaType.prototype.immutable = function(bool) {
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Defines a custom function for transforming this path when converting a document to JSON.
|
||||
*
|
||||
* Mongoose calls this function with one parameter: the current `value` of the path. Mongoose
|
||||
* then uses the return value in the JSON output.
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* const schema = new Schema({
|
||||
* date: { type: Date, transform: v => v.getFullYear() }
|
||||
* });
|
||||
* const Model = mongoose.model('Test', schema);
|
||||
*
|
||||
* await Model.create({ date: new Date('2016-06-01') });
|
||||
* const doc = await Model.findOne();
|
||||
*
|
||||
* doc.date instanceof Date; // true
|
||||
*
|
||||
* doc.toJSON().date; // 2016 as a number
|
||||
* JSON.stringify(doc); // '{"_id":...,"date":2016}'
|
||||
*
|
||||
* @param {Function} fn
|
||||
* @return {SchemaType} this
|
||||
* @api public
|
||||
*/
|
||||
|
||||
SchemaType.prototype.transform = function(fn) {
|
||||
this.options.transform = fn;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds a setter to this schematype.
|
||||
*
|
||||
@@ -453,10 +553,10 @@ SchemaType.prototype.immutable = function(bool) {
|
||||
* }
|
||||
*
|
||||
* // defining within the schema
|
||||
* var s = new Schema({ name: { type: String, set: capitalize }});
|
||||
* const s = new Schema({ name: { type: String, set: capitalize }});
|
||||
*
|
||||
* // or with the SchemaType
|
||||
* var s = new Schema({ name: String })
|
||||
* const s = new Schema({ name: String })
|
||||
* s.path('name').set(capitalize);
|
||||
*
|
||||
* Setters allow you to transform the data before it gets to the raw mongodb
|
||||
@@ -473,17 +573,17 @@ SchemaType.prototype.immutable = function(bool) {
|
||||
* return v.toLowerCase();
|
||||
* }
|
||||
*
|
||||
* var UserSchema = new Schema({
|
||||
* const UserSchema = new Schema({
|
||||
* email: { type: String, set: toLower }
|
||||
* });
|
||||
*
|
||||
* var User = db.model('User', UserSchema);
|
||||
* const User = db.model('User', UserSchema);
|
||||
*
|
||||
* var user = new User({email: 'AVENUE@Q.COM'});
|
||||
* const user = new User({email: 'AVENUE@Q.COM'});
|
||||
* console.log(user.email); // 'avenue@q.com'
|
||||
*
|
||||
* // or
|
||||
* var user = new User();
|
||||
* const user = new User();
|
||||
* user.email = 'Avenue@Q.com';
|
||||
* console.log(user.email); // 'avenue@q.com'
|
||||
* User.updateOne({ _id: _id }, { $set: { email: 'AVENUE@Q.COM' } }); // update to 'avenue@q.com'
|
||||
@@ -505,13 +605,13 @@ SchemaType.prototype.immutable = function(bool) {
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var VirusSchema = new Schema({
|
||||
* const 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' });
|
||||
* const Virus = db.model('Virus', VirusSchema);
|
||||
* const v = new Virus({ name: 'Parvoviridae', taxonomy: 'Parvovirinae' });
|
||||
*
|
||||
* console.log(v.name); // name is required
|
||||
* console.log(v.taxonomy); // Parvovirinae
|
||||
@@ -558,10 +658,10 @@ SchemaType.prototype.set = function(fn) {
|
||||
* }
|
||||
*
|
||||
* // defining within the schema
|
||||
* var s = new Schema({ born: { type: Date, get: dob })
|
||||
* const s = new Schema({ born: { type: Date, get: dob })
|
||||
*
|
||||
* // or by retreiving its SchemaType
|
||||
* var s = new Schema({ born: Date })
|
||||
* const 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.
|
||||
@@ -572,11 +672,11 @@ SchemaType.prototype.set = function(fn) {
|
||||
* return '****-****-****-' + cc.slice(cc.length-4, cc.length);
|
||||
* }
|
||||
*
|
||||
* var AccountSchema = new Schema({
|
||||
* const AccountSchema = new Schema({
|
||||
* creditCardNumber: { type: String, get: obfuscate }
|
||||
* });
|
||||
*
|
||||
* var Account = db.model('Account', AccountSchema);
|
||||
* const Account = db.model('Account', AccountSchema);
|
||||
*
|
||||
* Account.findById(id, function (err, found) {
|
||||
* console.log(found.creditCardNumber); // '****-****-****-1234'
|
||||
@@ -592,12 +692,12 @@ SchemaType.prototype.set = function(fn) {
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* var VirusSchema = new Schema({
|
||||
* const VirusSchema = new Schema({
|
||||
* name: { type: String, required: true, get: inspector },
|
||||
* taxonomy: { type: String, get: inspector }
|
||||
* })
|
||||
*
|
||||
* var Virus = db.model('Virus', VirusSchema);
|
||||
* const Virus = db.model('Virus', VirusSchema);
|
||||
*
|
||||
* Virus.findById(id, function (err, virus) {
|
||||
* console.log(virus.name); // name is required
|
||||
@@ -636,12 +736,12 @@ SchemaType.prototype.get = function(fn) {
|
||||
*
|
||||
* // with a custom error message
|
||||
*
|
||||
* var custom = [validator, 'Uh oh, {PATH} does not equal "something".']
|
||||
* const custom = [validator, 'Uh oh, {PATH} does not equal "something".']
|
||||
* new Schema({ name: { type: String, validate: custom }});
|
||||
*
|
||||
* // adding many validators at a time
|
||||
*
|
||||
* var many = [
|
||||
* const many = [
|
||||
* { validator: validator, msg: 'uh oh' }
|
||||
* , { validator: anotherValidator, msg: 'failed' }
|
||||
* ]
|
||||
@@ -649,7 +749,7 @@ SchemaType.prototype.get = function(fn) {
|
||||
*
|
||||
* // or utilizing SchemaType methods directly:
|
||||
*
|
||||
* var schema = new Schema({ name: 'string' });
|
||||
* const schema = new Schema({ name: 'string' });
|
||||
* schema.path('name').validate(validator, 'validation of `{PATH}` failed with value `{VALUE}`');
|
||||
*
|
||||
* ####Error message templates:
|
||||
@@ -699,11 +799,11 @@ SchemaType.prototype.get = function(fn) {
|
||||
*
|
||||
* 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(..);
|
||||
* const conn = mongoose.createConnection(..);
|
||||
* conn.on('error', handleError);
|
||||
*
|
||||
* var Product = conn.model('Product', yourSchema);
|
||||
* var dvd = new Product(..);
|
||||
* const Product = conn.model('Product', yourSchema);
|
||||
* const dvd = new Product(..);
|
||||
* dvd.save(); // emits error on the `conn` above
|
||||
*
|
||||
* If you want to handle these errors at the Model level, add an `error`
|
||||
@@ -787,15 +887,15 @@ const handleIsAsync = util.deprecate(function handleIsAsync() {},
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var s = new Schema({ born: { type: Date, required: true })
|
||||
* const s = new Schema({ born: { type: Date, required: true })
|
||||
*
|
||||
* // or with custom error message
|
||||
*
|
||||
* var s = new Schema({ born: { type: Date, required: '{PATH} is required!' })
|
||||
* const s = new Schema({ born: { type: Date, required: '{PATH} is required!' })
|
||||
*
|
||||
* // or with a function
|
||||
*
|
||||
* var s = new Schema({
|
||||
* const s = new Schema({
|
||||
* userId: ObjectId,
|
||||
* username: {
|
||||
* type: String,
|
||||
@@ -804,7 +904,7 @@ const handleIsAsync = util.deprecate(function handleIsAsync() {},
|
||||
* })
|
||||
*
|
||||
* // or with a function and a custom message
|
||||
* var s = new Schema({
|
||||
* const s = new Schema({
|
||||
* userId: ObjectId,
|
||||
* username: {
|
||||
* type: String,
|
||||
@@ -824,7 +924,7 @@ const handleIsAsync = util.deprecate(function handleIsAsync() {},
|
||||
* s.path('name').required(true, 'grrr :( ');
|
||||
*
|
||||
* // or make a path conditionally required based on a function
|
||||
* var isOver18 = function() { return this.age >= 18; };
|
||||
* const isOver18 = function() { return this.age >= 18; };
|
||||
* s.path('voterRegistrationId').required(isOver18);
|
||||
*
|
||||
* The required validator uses the SchemaType's `checkRequired` function to
|
||||
@@ -884,7 +984,7 @@ SchemaType.prototype.required = function(required, message) {
|
||||
const cachedRequired = get(this, '$__.cachedRequired');
|
||||
|
||||
// no validation when this path wasn't selected in the query.
|
||||
if (cachedRequired != null && !this.isSelected(_this.path) && !this.isModified(_this.path)) {
|
||||
if (cachedRequired != null && !this.$__isSelected(_this.path) && !this[documentIsModified](_this.path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -929,8 +1029,10 @@ SchemaType.prototype.required = function(required, message) {
|
||||
* const User = mongoose.model('User', userSchema);
|
||||
*
|
||||
* const postSchema = new Schema({ user: mongoose.ObjectId });
|
||||
* postSchema.path('user').ref('User'); // By model name
|
||||
* postSchema.path('user').ref(User); // Can pass the model as well
|
||||
* postSchema.path('user').ref('User'); // Can set ref to a model name
|
||||
* postSchema.path('user').ref(User); // Or a model class
|
||||
* postSchema.path('user').ref(() => 'User'); // Or a function that returns the model name
|
||||
* postSchema.path('user').ref(() => User); // Or a function that returns the model class
|
||||
*
|
||||
* // Or you can just declare the `ref` inline in your schema
|
||||
* const postSchema2 = new Schema({
|
||||
@@ -967,7 +1069,7 @@ SchemaType.prototype.getDefault = function(scope, init) {
|
||||
|
||||
const casted = this.applySetters(ret, scope, init);
|
||||
if (casted && casted.$isSingleNested) {
|
||||
casted.$parent = scope;
|
||||
casted.$__parent = scope;
|
||||
}
|
||||
return casted;
|
||||
}
|
||||
@@ -980,34 +1082,25 @@ SchemaType.prototype.getDefault = function(scope, init) {
|
||||
* @api private
|
||||
*/
|
||||
|
||||
SchemaType.prototype._applySetters = function(value, scope, init, priorVal) {
|
||||
SchemaType.prototype._applySetters = function(value, scope, init) {
|
||||
let v = value;
|
||||
if (init) {
|
||||
return v;
|
||||
}
|
||||
const setters = this.setters;
|
||||
const caster = this.caster;
|
||||
|
||||
for (const setter of utils.clone(setters).reverse()) {
|
||||
v = setter.call(scope, v, this);
|
||||
for (let i = setters.length - 1; i >= 0; i--) {
|
||||
v = setters[i].call(scope, v, this);
|
||||
}
|
||||
|
||||
if (Array.isArray(v) && caster && caster.setters) {
|
||||
const newVal = [];
|
||||
|
||||
for (let i = 0; i < v.length; ++i) {
|
||||
const value = v[i];
|
||||
try {
|
||||
newVal.push(caster.applySetters(value, scope, init, priorVal));
|
||||
} catch (err) {
|
||||
if (err instanceof MongooseError.CastError) {
|
||||
err.$originalErrorPath = err.path;
|
||||
err.path = err.path + '.' + i;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
v = newVal;
|
||||
}
|
||||
return v;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaType.prototype._castNullish = function _castNullish(v) {
|
||||
return v;
|
||||
};
|
||||
|
||||
@@ -1022,9 +1115,8 @@ SchemaType.prototype._applySetters = function(value, scope, init, priorVal) {
|
||||
|
||||
SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) {
|
||||
let v = this._applySetters(value, scope, init, priorVal, options);
|
||||
|
||||
if (v == null) {
|
||||
return v;
|
||||
return this._castNullish(v);
|
||||
}
|
||||
|
||||
// do not cast until all setters are applied #665
|
||||
@@ -1354,11 +1446,54 @@ SchemaType._isRef = function(self, value, doc, init) {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return init;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
SchemaType.prototype._castRef = function _castRef(value, doc, init) {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (value.$__ != null) {
|
||||
value.$__.wasPopulated = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
// setting a populated path
|
||||
if (Buffer.isBuffer(value) || !utils.isObject(value)) {
|
||||
if (init) {
|
||||
return value;
|
||||
}
|
||||
throw new CastError(this.instance, value, this.path, null, this);
|
||||
}
|
||||
|
||||
// Handle the case where user directly sets a populated
|
||||
// path to a plain object; cast to the Model used in
|
||||
// the population query.
|
||||
const path = doc.$__fullPath(this.path);
|
||||
const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
|
||||
const pop = owner.populated(path, true);
|
||||
let ret = value;
|
||||
if (!doc.$__.populated ||
|
||||
!doc.$__.populated[path] ||
|
||||
!doc.$__.populated[path].options ||
|
||||
!doc.$__.populated[path].options.options ||
|
||||
!doc.$__.populated[path].options.options.lean) {
|
||||
ret = new pop.options[populateModelSymbol](value);
|
||||
ret.$__.wasPopulated = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -1420,12 +1555,19 @@ SchemaType.prototype.$conditionalHandlers = {
|
||||
SchemaType.prototype.castForQueryWrapper = function(params) {
|
||||
this.$$context = params.context;
|
||||
if ('$conditional' in params) {
|
||||
return this.castForQuery(params.$conditional, params.val);
|
||||
const ret = this.castForQuery(params.$conditional, params.val);
|
||||
this.$$context = null;
|
||||
return ret;
|
||||
}
|
||||
if (params.$skipQueryCastForUpdate || params.$applySetters) {
|
||||
return this._castForQuery(params.val);
|
||||
const ret = this._castForQuery(params.val);
|
||||
this.$$context = null;
|
||||
return ret;
|
||||
}
|
||||
return this.castForQuery(params.val);
|
||||
|
||||
const ret = this.castForQuery(params.val);
|
||||
this.$$context = null;
|
||||
return ret;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
39
node_modules/mongoose/lib/types/array.js
generated
vendored
39
node_modules/mongoose/lib/types/array.js
generated
vendored
@@ -5,7 +5,6 @@
|
||||
'use strict';
|
||||
|
||||
const CoreMongooseArray = require('./core_array');
|
||||
const Document = require('../document');
|
||||
|
||||
const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
|
||||
const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
|
||||
@@ -29,31 +28,47 @@ const _basePush = Array.prototype.push;
|
||||
* @see http://bit.ly/f6CnZU
|
||||
*/
|
||||
|
||||
function MongooseArray(values, path, doc) {
|
||||
// TODO: replace this with `new CoreMongooseArray().concat()` when we remove
|
||||
// support for node 4.x and 5.x, see https://i.imgur.com/UAAHk4S.png
|
||||
const arr = new CoreMongooseArray();
|
||||
arr[arrayAtomicsSymbol] = {};
|
||||
function MongooseArray(values, path, doc, schematype) {
|
||||
let arr;
|
||||
|
||||
if (Array.isArray(values)) {
|
||||
const len = values.length;
|
||||
for (let i = 0; i < len; ++i) {
|
||||
_basePush.call(arr, values[i]);
|
||||
|
||||
// Perf optimizations for small arrays: much faster to use `...` than `for` + `push`,
|
||||
// but large arrays may cause stack overflows. And for arrays of length 0/1, just
|
||||
// modifying the array is faster. Seems small, but adds up when you have a document
|
||||
// with thousands of nested arrays.
|
||||
if (len === 0) {
|
||||
arr = new CoreMongooseArray();
|
||||
} else if (len === 1) {
|
||||
arr = new CoreMongooseArray(1);
|
||||
arr[0] = values[0];
|
||||
} else if (len < 10000) {
|
||||
arr = new CoreMongooseArray();
|
||||
_basePush.apply(arr, values);
|
||||
} else {
|
||||
arr = new CoreMongooseArray();
|
||||
for (let i = 0; i < len; ++i) {
|
||||
_basePush.call(arr, values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
arr[arrayAtomicsSymbol] = values[arrayAtomicsSymbol] || {};
|
||||
if (values[arrayAtomicsSymbol] != null) {
|
||||
arr[arrayAtomicsSymbol] = values[arrayAtomicsSymbol];
|
||||
}
|
||||
} else {
|
||||
arr = new CoreMongooseArray();
|
||||
}
|
||||
|
||||
arr[arrayPathSymbol] = path;
|
||||
arr[arraySchemaSymbol] = void 0;
|
||||
|
||||
// Because doc comes from the context of another function, doc === global
|
||||
// can happen if there was a null somewhere up the chain (see #3020)
|
||||
// RB Jun 17, 2015 updated to check for presence of expected paths instead
|
||||
// to make more proof against unusual node environments
|
||||
if (doc && doc instanceof Document) {
|
||||
if (doc != null && doc.$__ != null) {
|
||||
arr[arrayParentSymbol] = doc;
|
||||
arr[arraySchemaSymbol] = doc.schema.path(path);
|
||||
arr[arraySchemaSymbol] = schematype || doc.schema.path(path);
|
||||
}
|
||||
|
||||
return arr;
|
||||
|
||||
4
node_modules/mongoose/lib/types/buffer.js
generated
vendored
4
node_modules/mongoose/lib/types/buffer.js
generated
vendored
@@ -168,7 +168,7 @@ MongooseBuffer.mixin = {
|
||||
*
|
||||
* ####SubTypes:
|
||||
*
|
||||
* var bson = require('bson')
|
||||
* const bson = require('bson')
|
||||
* bson.BSON_BINARY_SUBTYPE_DEFAULT
|
||||
* bson.BSON_BINARY_SUBTYPE_FUNCTION
|
||||
* bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
|
||||
@@ -238,7 +238,7 @@ MongooseBuffer.mixin.equals = function(other) {
|
||||
*
|
||||
* ####SubTypes:
|
||||
*
|
||||
* var bson = require('bson')
|
||||
* const bson = require('bson')
|
||||
* bson.BSON_BINARY_SUBTYPE_DEFAULT
|
||||
* bson.BSON_BINARY_SUBTYPE_FUNCTION
|
||||
* bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
|
||||
|
||||
58
node_modules/mongoose/lib/types/core_array.js
generated
vendored
58
node_modules/mongoose/lib/types/core_array.js
generated
vendored
@@ -52,7 +52,7 @@ class CoreMongooseArray extends Array {
|
||||
|
||||
$__getAtomics() {
|
||||
const ret = [];
|
||||
const keys = Object.keys(this[arrayAtomicsSymbol]);
|
||||
const keys = Object.keys(this[arrayAtomicsSymbol] || {});
|
||||
let i = keys.length;
|
||||
|
||||
const opts = Object.assign({}, internalToObjectOptions, { _isNested: true });
|
||||
@@ -94,7 +94,7 @@ class CoreMongooseArray extends Array {
|
||||
*/
|
||||
|
||||
$atomics() {
|
||||
return this[arrayAtomicsSymbol];
|
||||
return this[arrayAtomicsSymbol] || {};
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -123,7 +123,7 @@ class CoreMongooseArray extends Array {
|
||||
*
|
||||
* doc.array = [1,2,3];
|
||||
*
|
||||
* var shifted = doc.array.$shift();
|
||||
* const shifted = doc.array.$shift();
|
||||
* console.log(shifted); // 1
|
||||
* console.log(doc.array); // [2,3]
|
||||
*
|
||||
@@ -170,7 +170,7 @@ class CoreMongooseArray extends Array {
|
||||
*
|
||||
* doc.array = [1,2,3];
|
||||
*
|
||||
* var popped = doc.array.$pop();
|
||||
* const popped = doc.array.$pop();
|
||||
* console.log(popped); // 3
|
||||
* console.log(doc.array); // [1,2]
|
||||
*
|
||||
@@ -248,8 +248,8 @@ class CoreMongooseArray extends Array {
|
||||
|
||||
// gh-2399
|
||||
// we should cast model only when it's not a discriminator
|
||||
const isDisc = value.schema && value.schema.discriminatorMapping &&
|
||||
value.schema.discriminatorMapping.key !== undefined;
|
||||
const isDisc = value.$__schema && value.$__schema.discriminatorMapping &&
|
||||
value.$__schema.discriminatorMapping.key !== undefined;
|
||||
if (!isDisc) {
|
||||
value = new Model(value);
|
||||
}
|
||||
@@ -284,7 +284,7 @@ class CoreMongooseArray extends Array {
|
||||
* @memberOf MongooseArray
|
||||
*/
|
||||
|
||||
_markModified(elem, embeddedPath) {
|
||||
_markModified(elem) {
|
||||
const parent = this[arrayParentSymbol];
|
||||
let dirtyPath;
|
||||
|
||||
@@ -292,13 +292,7 @@ class CoreMongooseArray extends Array {
|
||||
dirtyPath = this[arrayPathSymbol];
|
||||
|
||||
if (arguments.length) {
|
||||
if (embeddedPath != null) {
|
||||
// an embedded doc bubbled up the change
|
||||
dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + embeddedPath;
|
||||
} else {
|
||||
// directly set an index
|
||||
dirtyPath = dirtyPath + '.' + elem;
|
||||
}
|
||||
dirtyPath = dirtyPath + '.' + elem;
|
||||
}
|
||||
|
||||
if (dirtyPath != null && dirtyPath.endsWith('.$')) {
|
||||
@@ -334,6 +328,8 @@ class CoreMongooseArray extends Array {
|
||||
return this;
|
||||
}
|
||||
|
||||
this[arrayAtomicsSymbol] || (this[arrayAtomicsSymbol] = {});
|
||||
|
||||
const atomics = this[arrayAtomicsSymbol];
|
||||
|
||||
// reset pop/shift after save
|
||||
@@ -389,7 +385,7 @@ class CoreMongooseArray extends Array {
|
||||
* ####Example:
|
||||
*
|
||||
* console.log(doc.array) // [2,3,4]
|
||||
* var added = doc.array.addToSet(4,5);
|
||||
* const added = doc.array.addToSet(4,5);
|
||||
* console.log(doc.array) // [2,3,4,5]
|
||||
* console.log(added) // [5]
|
||||
*
|
||||
@@ -605,7 +601,7 @@ class CoreMongooseArray extends Array {
|
||||
|
||||
if (values[0] instanceof EmbeddedDocument) {
|
||||
this._registerAtomic('$pullDocs', values.map(function(v) {
|
||||
return v._id || v;
|
||||
return v.$__getValue('_id') || v;
|
||||
}));
|
||||
} else {
|
||||
this._registerAtomic('$pullAll', values);
|
||||
@@ -703,7 +699,7 @@ class CoreMongooseArray extends Array {
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of [pull](#types_array_MongooseArray-pull)
|
||||
* Alias of [pull](#mongoosearray_MongooseArray-pull)
|
||||
*
|
||||
* @see MongooseArray#pull #types_array_MongooseArray-pull
|
||||
* @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
|
||||
@@ -723,9 +719,9 @@ class CoreMongooseArray extends Array {
|
||||
* ####Example:
|
||||
*
|
||||
* // given documents based on the following
|
||||
* var Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
|
||||
* const Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
|
||||
*
|
||||
* var doc = new Doc({ array: [2,3,4] })
|
||||
* const doc = new Doc({ array: [2,3,4] })
|
||||
*
|
||||
* console.log(doc.array) // [2,3,4]
|
||||
*
|
||||
@@ -757,7 +753,7 @@ class CoreMongooseArray extends Array {
|
||||
* ####Example:
|
||||
*
|
||||
* doc.array = [2,3];
|
||||
* var res = doc.array.shift();
|
||||
* const res = doc.array.shift();
|
||||
* console.log(res) // 2
|
||||
* console.log(doc.array) // [3]
|
||||
*
|
||||
@@ -843,10 +839,24 @@ class CoreMongooseArray extends Array {
|
||||
ret[arrayParentSymbol] = this[arrayParentSymbol];
|
||||
ret[arraySchemaSymbol] = this[arraySchemaSymbol];
|
||||
ret[arrayAtomicsSymbol] = this[arrayAtomicsSymbol];
|
||||
ret[arrayPathSymbol] = this[arrayPathSymbol];
|
||||
ret[slicedSymbol] = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
|
||||
filter() {
|
||||
const ret = super.filter.apply(this, arguments);
|
||||
ret[arrayParentSymbol] = this[arrayParentSymbol];
|
||||
ret[arraySchemaSymbol] = this[arraySchemaSymbol];
|
||||
ret[arrayAtomicsSymbol] = this[arrayAtomicsSymbol];
|
||||
ret[arrayPathSymbol] = this[arrayPathSymbol];
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* ignore
|
||||
*/
|
||||
@@ -869,14 +879,16 @@ class CoreMongooseArray extends Array {
|
||||
if (options && options.depopulate) {
|
||||
options = utils.clone(options);
|
||||
options._isNested = true;
|
||||
return this.map(function(doc) {
|
||||
// Ensure return value is a vanilla array, because in Node.js 6+ `map()`
|
||||
// is smart enough to use the inherited array's constructor.
|
||||
return [].concat(this).map(function(doc) {
|
||||
return doc instanceof Document
|
||||
? doc.toObject(options)
|
||||
: doc;
|
||||
});
|
||||
}
|
||||
|
||||
return this.slice();
|
||||
return [].concat(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -955,4 +967,4 @@ function _checkManualPopulation(arr, docs) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CoreMongooseArray;
|
||||
module.exports = CoreMongooseArray;
|
||||
|
||||
2
node_modules/mongoose/lib/types/decimal128.js
generated
vendored
2
node_modules/mongoose/lib/types/decimal128.js
generated
vendored
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* var id = new mongoose.Types.ObjectId;
|
||||
* const id = new mongoose.Types.ObjectId;
|
||||
*
|
||||
* @constructor ObjectId
|
||||
*/
|
||||
|
||||
37
node_modules/mongoose/lib/types/documentarray.js
generated
vendored
37
node_modules/mongoose/lib/types/documentarray.js
generated
vendored
@@ -96,7 +96,7 @@ class CoreDocumentArray extends CoreMongooseArray {
|
||||
Constructor.discriminators[value[Constructor.schema.options.discriminatorKey]]) {
|
||||
Constructor = Constructor.discriminators[value[Constructor.schema.options.discriminatorKey]];
|
||||
} else {
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor, value[Constructor.schema.options.discriminatorKey]);
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, value[Constructor.schema.options.discriminatorKey]);
|
||||
if (constructorByValue) {
|
||||
Constructor = constructorByValue;
|
||||
}
|
||||
@@ -114,7 +114,7 @@ class CoreDocumentArray extends CoreMongooseArray {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var embeddedDoc = m.array.id(some_id);
|
||||
* const embeddedDoc = m.array.id(some_id);
|
||||
*
|
||||
* @return {EmbeddedDocument|null} the subdocument or null if not found.
|
||||
* @param {ObjectId|String|Number|Buffer} id
|
||||
@@ -289,7 +289,7 @@ class CoreDocumentArray extends CoreMongooseArray {
|
||||
Constructor.discriminators[obj[Constructor.schema.options.discriminatorKey]]) {
|
||||
Constructor = Constructor.discriminators[obj[Constructor.schema.options.discriminatorKey]];
|
||||
} else {
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor, obj[Constructor.schema.options.discriminatorKey]);
|
||||
const constructorByValue = getDiscriminatorByValue(Constructor.discriminators, obj[Constructor.schema.options.discriminatorKey]);
|
||||
if (constructorByValue) {
|
||||
Constructor = constructorByValue;
|
||||
}
|
||||
@@ -330,6 +330,34 @@ class CoreDocumentArray extends CoreMongooseArray {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
_markModified(elem, embeddedPath) {
|
||||
const parent = this[arrayParentSymbol];
|
||||
let dirtyPath;
|
||||
|
||||
if (parent) {
|
||||
dirtyPath = this[arrayPathSymbol];
|
||||
|
||||
if (arguments.length) {
|
||||
if (embeddedPath != null) {
|
||||
// an embedded doc bubbled up the change
|
||||
const index = elem.__index;
|
||||
dirtyPath = dirtyPath + '.' + index + '.' + embeddedPath;
|
||||
} else {
|
||||
// directly set an index
|
||||
dirtyPath = dirtyPath + '.' + elem;
|
||||
}
|
||||
}
|
||||
|
||||
if (dirtyPath != null && dirtyPath.endsWith('.$')) {
|
||||
return this;
|
||||
}
|
||||
|
||||
parent.markModified(dirtyPath, arguments.length > 0 ? elem : parent);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
if (util.inspect.custom) {
|
||||
@@ -380,8 +408,7 @@ function MongooseDocumentArray(values, path, doc) {
|
||||
arr[arrayAtomicsSymbol] = {};
|
||||
arr[arraySchemaSymbol] = void 0;
|
||||
if (Array.isArray(values)) {
|
||||
if (values instanceof CoreDocumentArray &&
|
||||
values[arrayPathSymbol] === path &&
|
||||
if (values[arrayPathSymbol] === path &&
|
||||
values[arrayParentSymbol] === doc) {
|
||||
arr[arrayAtomicsSymbol] = Object.assign({}, values[arrayAtomicsSymbol]);
|
||||
}
|
||||
|
||||
43
node_modules/mongoose/lib/types/embedded.js
generated
vendored
43
node_modules/mongoose/lib/types/embedded.js
generated
vendored
@@ -29,6 +29,7 @@ const validatorErrorSymbol = require('../helpers/symbols').validatorErrorSymbol;
|
||||
*/
|
||||
|
||||
function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
|
||||
const options = {};
|
||||
if (parentArr != null && parentArr.isMongooseDocumentArray) {
|
||||
this.__parentArray = parentArr;
|
||||
this[documentArrayParent] = parentArr.$parent();
|
||||
@@ -39,7 +40,11 @@ function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
|
||||
this.$setIndex(index);
|
||||
this.$isDocumentArrayElement = true;
|
||||
|
||||
Document.call(this, obj, fields, skipId);
|
||||
if (this[documentArrayParent] != null) {
|
||||
options.defaults = this[documentArrayParent].$__.$options.defaults;
|
||||
}
|
||||
|
||||
Document.call(this, obj, fields, skipId, options);
|
||||
|
||||
const _this = this;
|
||||
this.on('isNew', function(val) {
|
||||
@@ -85,7 +90,7 @@ EmbeddedDocument.prototype.$setIndex = function(index) {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var doc = blogpost.comments.id(hexstring);
|
||||
* const doc = blogpost.comments.id(hexstring);
|
||||
* doc.mixed.type = 'changed';
|
||||
* doc.markModified('mixed.type');
|
||||
*
|
||||
@@ -100,7 +105,8 @@ EmbeddedDocument.prototype.markModified = function(path) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isNew) {
|
||||
const pathToCheck = this.__parentArray.$path() + '.0.' + path;
|
||||
if (this.isNew && this.ownerDocument().$__isSelected(pathToCheck)) {
|
||||
// Mark the WHOLE parent array as modified
|
||||
// if this is a new document (i.e., we are initializing
|
||||
// a document),
|
||||
@@ -195,6 +201,9 @@ function registerRemoveListener(sub) {
|
||||
*/
|
||||
|
||||
EmbeddedDocument.prototype.$__remove = function(cb) {
|
||||
if (cb == null) {
|
||||
return;
|
||||
}
|
||||
return cb(null, this);
|
||||
};
|
||||
|
||||
@@ -212,7 +221,7 @@ EmbeddedDocument.prototype.remove = function(options, fn) {
|
||||
options = undefined;
|
||||
}
|
||||
if (!this.__parentArray || (options && options.noop)) {
|
||||
fn && fn(null);
|
||||
this.$__remove(fn);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -228,9 +237,7 @@ EmbeddedDocument.prototype.remove = function(options, fn) {
|
||||
registerRemoveListener(this);
|
||||
}
|
||||
|
||||
if (fn) {
|
||||
fn(null);
|
||||
}
|
||||
this.$__remove(fn);
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -280,7 +287,7 @@ EmbeddedDocument.prototype.invalidate = function(path, err, val) {
|
||||
|
||||
if (!this[documentArrayParent] || this.__index == null) {
|
||||
if (err[validatorErrorSymbol] || err instanceof ValidationError) {
|
||||
return true;
|
||||
return this.ownerDocument().$__.validationError;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
@@ -290,7 +297,7 @@ EmbeddedDocument.prototype.invalidate = function(path, err, val) {
|
||||
const fullPath = [parentPath, index, path].join('.');
|
||||
this[documentArrayParent].invalidate(fullPath, err, val);
|
||||
|
||||
return true;
|
||||
return this.ownerDocument().$__.validationError;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -369,8 +376,8 @@ EmbeddedDocument.prototype.ownerDocument = function() {
|
||||
return this;
|
||||
}
|
||||
|
||||
while (parent[documentArrayParent] || parent.$parent) {
|
||||
parent = parent[documentArrayParent] || parent.$parent;
|
||||
while (parent[documentArrayParent] || parent.$__parent) {
|
||||
parent = parent[documentArrayParent] || parent.$__parent;
|
||||
}
|
||||
|
||||
this.$__.ownerDocument = parent;
|
||||
@@ -390,19 +397,19 @@ EmbeddedDocument.prototype.ownerDocument = function() {
|
||||
|
||||
EmbeddedDocument.prototype.$__fullPath = function(path) {
|
||||
if (!this.$__.fullPath) {
|
||||
let parent = this; // eslint-disable-line consistent-this
|
||||
let parent = this;
|
||||
if (!parent[documentArrayParent]) {
|
||||
return path;
|
||||
}
|
||||
|
||||
const paths = [];
|
||||
while (parent[documentArrayParent] || parent.$parent) {
|
||||
while (parent[documentArrayParent] || parent.$__parent) {
|
||||
if (parent[documentArrayParent]) {
|
||||
paths.unshift(parent.__parentArray.$path());
|
||||
} else {
|
||||
paths.unshift(parent.$basePath);
|
||||
}
|
||||
parent = parent[documentArrayParent] || parent.$parent;
|
||||
parent = parent[documentArrayParent] || parent.$__parent;
|
||||
}
|
||||
|
||||
this.$__.fullPath = paths.join('.');
|
||||
@@ -428,6 +435,14 @@ EmbeddedDocument.prototype.parent = function() {
|
||||
return this[documentArrayParent];
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this sub-documents parent document.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
EmbeddedDocument.prototype.$parent = EmbeddedDocument.prototype.parent;
|
||||
|
||||
/**
|
||||
* Returns this sub-documents parent array.
|
||||
*
|
||||
|
||||
30
node_modules/mongoose/lib/types/map.js
generated
vendored
30
node_modules/mongoose/lib/types/map.js
generated
vendored
@@ -1,8 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const Mixed = require('../schema/mixed');
|
||||
const ObjectId = require('./objectid');
|
||||
const clone = require('../helpers/clone');
|
||||
const deepEqual = require('../utils').deepEqual;
|
||||
const get = require('../helpers/get');
|
||||
const getConstructorName = require('../helpers/getConstructorName');
|
||||
const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
|
||||
const util = require('util');
|
||||
const specialProperties = require('../helpers/specialProperties');
|
||||
@@ -15,11 +18,10 @@ const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
||||
|
||||
class MongooseMap extends Map {
|
||||
constructor(v, path, doc, schemaType) {
|
||||
if (v != null && v.constructor.name === 'Object') {
|
||||
if (getConstructorName(v) === 'Object') {
|
||||
v = Object.keys(v).reduce((arr, key) => arr.concat([[key, v[key]]]), []);
|
||||
}
|
||||
super(v);
|
||||
|
||||
this.$__parent = doc != null && doc.$__ != null ? doc : null;
|
||||
this.$__path = path;
|
||||
this.$__schemaType = schemaType == null ? new Mixed(path) : schemaType;
|
||||
@@ -42,6 +44,10 @@ class MongooseMap extends Map {
|
||||
}
|
||||
|
||||
get(key, options) {
|
||||
if (key instanceof ObjectId) {
|
||||
key = key.toString();
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
if (options.getters === false) {
|
||||
return super.get(key);
|
||||
@@ -50,6 +56,10 @@ class MongooseMap extends Map {
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
if (key instanceof ObjectId) {
|
||||
key = key.toString();
|
||||
}
|
||||
|
||||
checkValidKey(key);
|
||||
value = handleSpreadDoc(value);
|
||||
|
||||
@@ -77,7 +87,7 @@ class MongooseMap extends Map {
|
||||
} else {
|
||||
try {
|
||||
value = this.$__schemaType.
|
||||
applySetters(value, this.$__parent, false, this.get(key));
|
||||
applySetters(value, this.$__parent, false, this.get(key), { path: fullPath });
|
||||
} catch (error) {
|
||||
if (this.$__parent != null && this.$__parent.$__ != null) {
|
||||
this.$__parent.invalidate(fullPath, error);
|
||||
@@ -99,7 +109,19 @@ class MongooseMap extends Map {
|
||||
}
|
||||
}
|
||||
|
||||
clear() {
|
||||
super.clear();
|
||||
const parent = this.$__parent;
|
||||
if (parent != null) {
|
||||
parent.markModified(this.$__path);
|
||||
}
|
||||
}
|
||||
|
||||
delete(key) {
|
||||
if (key instanceof ObjectId) {
|
||||
key = key.toString();
|
||||
}
|
||||
|
||||
this.set(key, undefined);
|
||||
super.delete(key);
|
||||
}
|
||||
@@ -113,7 +135,7 @@ class MongooseMap extends Map {
|
||||
const ret = {};
|
||||
const keys = this.keys();
|
||||
for (const key of keys) {
|
||||
ret[key] = this.get(key);
|
||||
ret[key] = clone(this.get(key));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
2
node_modules/mongoose/lib/types/objectid.js
generated
vendored
2
node_modules/mongoose/lib/types/objectid.js
generated
vendored
@@ -3,7 +3,7 @@
|
||||
*
|
||||
* ####Example
|
||||
*
|
||||
* var id = new mongoose.Types.ObjectId;
|
||||
* const id = new mongoose.Types.ObjectId;
|
||||
*
|
||||
* @constructor ObjectId
|
||||
*/
|
||||
|
||||
67
node_modules/mongoose/lib/types/subdocument.js
generated
vendored
67
node_modules/mongoose/lib/types/subdocument.js
generated
vendored
@@ -18,18 +18,23 @@ module.exports = Subdocument;
|
||||
|
||||
function Subdocument(value, fields, parent, skipId, options) {
|
||||
this.$isSingleNested = true;
|
||||
|
||||
if (options != null && options.path != null) {
|
||||
this.$basePath = options.path;
|
||||
}
|
||||
const hasPriorDoc = options != null && options.priorDoc;
|
||||
let initedPaths = null;
|
||||
if (hasPriorDoc) {
|
||||
this._doc = Object.assign({}, options.priorDoc._doc);
|
||||
delete this._doc[this.schema.options.discriminatorKey];
|
||||
delete this._doc[this.$__schema.options.discriminatorKey];
|
||||
initedPaths = Object.keys(options.priorDoc._doc || {}).
|
||||
filter(key => key !== this.schema.options.discriminatorKey);
|
||||
filter(key => key !== this.$__schema.options.discriminatorKey);
|
||||
}
|
||||
if (parent != null) {
|
||||
// If setting a nested path, should copy isNew from parent re: gh-7048
|
||||
options = Object.assign({}, options, { isNew: parent.isNew });
|
||||
options = Object.assign({}, options, {
|
||||
isNew: parent.isNew,
|
||||
defaults: parent.$__.$options.defaults
|
||||
});
|
||||
}
|
||||
Document.call(this, value, fields, skipId, options);
|
||||
|
||||
@@ -38,7 +43,7 @@ function Subdocument(value, fields, parent, skipId, options) {
|
||||
if (!this.$__.activePaths.states.modify[key] &&
|
||||
!this.$__.activePaths.states.default[key] &&
|
||||
!this.$__.$setCalled.has(key)) {
|
||||
const schematype = this.schema.path(key);
|
||||
const schematype = this.$__schema.path(key);
|
||||
const def = schematype == null ? void 0 : schematype.getDefault(this);
|
||||
if (def === void 0) {
|
||||
delete this._doc[key];
|
||||
@@ -48,6 +53,9 @@ function Subdocument(value, fields, parent, skipId, options) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete options.priorDoc;
|
||||
delete this.$__.$options.priorDoc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,8 +113,8 @@ Subdocument.prototype.$__save = function(fn) {
|
||||
};
|
||||
|
||||
Subdocument.prototype.$isValid = function(path) {
|
||||
if (this.$parent && this.$basePath) {
|
||||
return this.$parent.$isValid([this.$basePath, path].join('.'));
|
||||
if (this.$__parent && this.$basePath) {
|
||||
return this.$__parent.$isValid([this.$basePath, path].join('.'));
|
||||
}
|
||||
return Document.prototype.$isValid.call(this, path);
|
||||
};
|
||||
@@ -114,22 +122,24 @@ Subdocument.prototype.$isValid = function(path) {
|
||||
Subdocument.prototype.markModified = function(path) {
|
||||
Document.prototype.markModified.call(this, path);
|
||||
|
||||
if (this.$parent && this.$basePath) {
|
||||
if (this.$parent.isDirectModified(this.$basePath)) {
|
||||
if (this.$__parent && this.$basePath) {
|
||||
if (this.$__parent.isDirectModified(this.$basePath)) {
|
||||
return;
|
||||
}
|
||||
this.$parent.markModified([this.$basePath, path].join('.'), this);
|
||||
this.$__parent.markModified([this.$basePath, path].join('.'), this);
|
||||
}
|
||||
};
|
||||
|
||||
Subdocument.prototype.isModified = function(paths, modifiedPaths) {
|
||||
if (this.$parent && this.$basePath) {
|
||||
if (this.$__parent && this.$basePath) {
|
||||
if (Array.isArray(paths) || typeof paths === 'string') {
|
||||
paths = (Array.isArray(paths) ? paths : paths.split(' '));
|
||||
paths = paths.map(p => [this.$basePath, p].join('.'));
|
||||
|
||||
return this.$__parent.isModified(paths, modifiedPaths);
|
||||
}
|
||||
|
||||
return this.$parent.isModified(paths, modifiedPaths);
|
||||
return this.$__parent.isModified(this.$basePath);
|
||||
}
|
||||
|
||||
return Document.prototype.isModified.call(this, paths, modifiedPaths);
|
||||
@@ -146,8 +156,8 @@ Subdocument.prototype.isModified = function(paths, modifiedPaths) {
|
||||
|
||||
Subdocument.prototype.$markValid = function(path) {
|
||||
Document.prototype.$markValid.call(this, path);
|
||||
if (this.$parent && this.$basePath) {
|
||||
this.$parent.$markValid([this.$basePath, path].join('.'));
|
||||
if (this.$__parent && this.$basePath) {
|
||||
this.$__parent.$markValid([this.$basePath, path].join('.'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -163,11 +173,13 @@ Subdocument.prototype.invalidate = function(path, err, val) {
|
||||
Document.prototype.invalidate.call(this, path, err, val);
|
||||
}
|
||||
|
||||
if (this.$parent && this.$basePath) {
|
||||
this.$parent.invalidate([this.$basePath, path].join('.'), err, val);
|
||||
if (this.$__parent && this.$basePath) {
|
||||
this.$__parent.invalidate([this.$basePath, path].join('.'), err, val);
|
||||
} else if (err.kind === 'cast' || err.name === 'CastError') {
|
||||
throw err;
|
||||
}
|
||||
|
||||
return this.ownerDocument().$__.validationError;
|
||||
};
|
||||
|
||||
/*!
|
||||
@@ -176,8 +188,8 @@ Subdocument.prototype.invalidate = function(path, err, val) {
|
||||
|
||||
Subdocument.prototype.$ignore = function(path) {
|
||||
Document.prototype.$ignore.call(this, path);
|
||||
if (this.$parent && this.$basePath) {
|
||||
this.$parent.$ignore([this.$basePath, path].join('.'));
|
||||
if (this.$__parent && this.$basePath) {
|
||||
this.$__parent.$ignore([this.$basePath, path].join('.'));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,13 +204,13 @@ Subdocument.prototype.ownerDocument = function() {
|
||||
return this.$__.ownerDocument;
|
||||
}
|
||||
|
||||
let parent = this.$parent;
|
||||
let parent = this.$__parent;
|
||||
if (!parent) {
|
||||
return this;
|
||||
}
|
||||
|
||||
while (parent.$parent || parent[documentArrayParent]) {
|
||||
parent = parent.$parent || parent[documentArrayParent];
|
||||
while (parent.$__parent || parent[documentArrayParent]) {
|
||||
parent = parent.$__parent || parent[documentArrayParent];
|
||||
}
|
||||
|
||||
this.$__.ownerDocument = parent;
|
||||
@@ -212,9 +224,17 @@ Subdocument.prototype.ownerDocument = function() {
|
||||
*/
|
||||
|
||||
Subdocument.prototype.parent = function() {
|
||||
return this.$parent;
|
||||
return this.$__parent;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns this sub-documents parent document.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Subdocument.prototype.$parent = Subdocument.prototype.parent;
|
||||
|
||||
/*!
|
||||
* no-op for hooks
|
||||
*/
|
||||
@@ -235,12 +255,11 @@ Subdocument.prototype.remove = function(options, callback) {
|
||||
callback = options;
|
||||
options = null;
|
||||
}
|
||||
|
||||
registerRemoveListener(this);
|
||||
|
||||
// If removing entire doc, no need to remove subdoc
|
||||
if (!options || !options.noop) {
|
||||
this.$parent.set(this.$basePath, null);
|
||||
this.$__parent.set(this.$basePath, null);
|
||||
}
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
|
||||
104
node_modules/mongoose/lib/utils.js
generated
vendored
104
node_modules/mongoose/lib/utils.js
generated
vendored
@@ -12,11 +12,13 @@ const Decimal = require('./types/decimal128');
|
||||
const ObjectId = require('./types/objectid');
|
||||
const PopulateOptions = require('./options/PopulateOptions');
|
||||
const clone = require('./helpers/clone');
|
||||
const immediate = require('./helpers/immediate');
|
||||
const isObject = require('./helpers/isObject');
|
||||
const isBsonType = require('./helpers/isBsonType');
|
||||
const getFunctionName = require('./helpers/getFunctionName');
|
||||
const isMongooseObject = require('./helpers/isMongooseObject');
|
||||
const promiseOrCallback = require('./helpers/promiseOrCallback');
|
||||
const schemaMerge = require('./helpers/schema/merge');
|
||||
const specialProperties = require('./helpers/specialProperties');
|
||||
|
||||
let Document;
|
||||
@@ -62,6 +64,10 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof a !== 'object' && typeof b !== 'object') {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
if (a instanceof Date && b instanceof Date) {
|
||||
return a.getTime() === b.getTime();
|
||||
}
|
||||
@@ -78,11 +84,7 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
a.global === b.global;
|
||||
}
|
||||
|
||||
if (typeof a !== 'object' && typeof b !== 'object') {
|
||||
return a === b;
|
||||
}
|
||||
|
||||
if (a === null || b === null || a === undefined || b === undefined) {
|
||||
if (a == null || b == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -90,6 +92,11 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a instanceof Map && b instanceof Map) {
|
||||
return deepEqual(Array.from(a.keys()), Array.from(b.keys())) &&
|
||||
deepEqual(Array.from(a.values()), Array.from(b.values()));
|
||||
}
|
||||
|
||||
// Handle MongooseNumbers
|
||||
if (a instanceof Number && b instanceof Number) {
|
||||
return a.valueOf() === b.valueOf();
|
||||
@@ -99,28 +106,38 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
return exports.buffer.areEqual(a, b);
|
||||
}
|
||||
|
||||
if (isMongooseObject(a)) {
|
||||
if (Array.isArray(a) && Array.isArray(b)) {
|
||||
const len = a.length;
|
||||
if (len !== b.length) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < len; ++i) {
|
||||
if (!deepEqual(a[i], b[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (a.$__ != null) {
|
||||
a = a._doc;
|
||||
} else if (isMongooseObject(a)) {
|
||||
a = a.toObject();
|
||||
}
|
||||
if (isMongooseObject(b)) {
|
||||
|
||||
if (b.$__ != null) {
|
||||
b = b._doc;
|
||||
} else if (isMongooseObject(b)) {
|
||||
b = b.toObject();
|
||||
}
|
||||
|
||||
let ka;
|
||||
let kb;
|
||||
let key;
|
||||
let i;
|
||||
try {
|
||||
ka = Object.keys(a);
|
||||
kb = Object.keys(b);
|
||||
} catch (e) {
|
||||
// happens when one is a string literal and the other isn't
|
||||
return false;
|
||||
}
|
||||
const ka = Object.keys(a);
|
||||
const kb = Object.keys(b);
|
||||
const kaLength = ka.length;
|
||||
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length !== kb.length) {
|
||||
if (kaLength !== kb.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -129,7 +146,7 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
kb.sort();
|
||||
|
||||
// ~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
for (let i = kaLength - 1; i >= 0; i--) {
|
||||
if (ka[i] !== kb[i]) {
|
||||
return false;
|
||||
}
|
||||
@@ -137,8 +154,7 @@ exports.deepEqual = function deepEqual(a, b) {
|
||||
|
||||
// equivalent values for every corresponding key, and
|
||||
// ~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i];
|
||||
for (const key of ka) {
|
||||
if (!deepEqual(a[key], b[key])) {
|
||||
return false;
|
||||
}
|
||||
@@ -259,9 +275,16 @@ exports.merge = function merge(to, from, options, path) {
|
||||
to[key] = {};
|
||||
}
|
||||
if (from[key] != null) {
|
||||
if (from[key].instanceOfSchema) {
|
||||
// Skip merging schemas if we're creating a discriminator schema and
|
||||
// base schema has a given path as a single nested but discriminator schema
|
||||
// has the path as a document array, or vice versa (gh-9534)
|
||||
if (options.isDiscriminatorSchemaMerge &&
|
||||
(from[key].$isSingleNested && to[key].$isMongooseDocumentArray) ||
|
||||
(from[key].$isMongooseDocumentArray && to[key].$isSingleNested)) {
|
||||
continue;
|
||||
} else if (from[key].instanceOfSchema) {
|
||||
if (to[key].instanceOfSchema) {
|
||||
to[key].add(from[key].clone());
|
||||
schemaMerge(to[key], from[key].clone(), options.isDiscriminatorSchemaMerge);
|
||||
} else {
|
||||
to[key] = from[key].clone();
|
||||
}
|
||||
@@ -311,7 +334,7 @@ exports.toObject = function toObject(obj) {
|
||||
if (exports.isPOJO(obj)) {
|
||||
ret = {};
|
||||
|
||||
for (const k in obj) {
|
||||
for (const k of Object.keys(obj)) {
|
||||
if (specialProperties.has(k)) {
|
||||
continue;
|
||||
}
|
||||
@@ -418,7 +441,7 @@ exports.tick = function tick(callback) {
|
||||
} catch (err) {
|
||||
// only nextTick on err to get out of
|
||||
// the event loop and avoid state corruption.
|
||||
process.nextTick(function() {
|
||||
immediate(function() {
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
@@ -734,23 +757,23 @@ exports.isArrayIndex = function(val) {
|
||||
*/
|
||||
|
||||
exports.array.unique = function(arr) {
|
||||
const primitives = {};
|
||||
const ids = {};
|
||||
const primitives = new Set();
|
||||
const ids = new Set();
|
||||
const ret = [];
|
||||
|
||||
for (const item of arr) {
|
||||
if (typeof item === 'number' || typeof item === 'string' || item == null) {
|
||||
if (primitives[item]) {
|
||||
if (primitives.has(item)) {
|
||||
continue;
|
||||
}
|
||||
ret.push(item);
|
||||
primitives[item] = true;
|
||||
primitives.add(item);
|
||||
} else if (item instanceof ObjectId) {
|
||||
if (ids[item.toString()]) {
|
||||
if (ids.has(item.toString())) {
|
||||
continue;
|
||||
}
|
||||
ret.push(item);
|
||||
ids[item.toString()] = true;
|
||||
ids.add(item.toString());
|
||||
} else {
|
||||
ret.push(item);
|
||||
}
|
||||
@@ -899,3 +922,20 @@ exports.getOption = function(name) {
|
||||
*/
|
||||
|
||||
exports.noop = function() {};
|
||||
|
||||
exports.errorToPOJO = function errorToPOJO(error) {
|
||||
const isError = error instanceof Error;
|
||||
if (!isError) {
|
||||
throw new Error('`error` must be `instanceof Error`.');
|
||||
}
|
||||
|
||||
const ret = {};
|
||||
for (const properyName of Object.getOwnPropertyNames(error)) {
|
||||
ret[properyName] = error[properyName];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
|
||||
exports.nodeMajorVersion = function nodeMajorVersion() {
|
||||
return parseInt(process.versions.node.split('.')[0], 10);
|
||||
};
|
||||
|
||||
11
node_modules/mongoose/lib/validoptions.js
generated
vendored
11
node_modules/mongoose/lib/validoptions.js
generated
vendored
@@ -8,23 +8,30 @@
|
||||
const VALID_OPTIONS = Object.freeze([
|
||||
'applyPluginsToChildSchemas',
|
||||
'applyPluginsToDiscriminators',
|
||||
'autoCreate',
|
||||
'autoIndex',
|
||||
'bufferCommands',
|
||||
'bufferTimeoutMS',
|
||||
'cloneSchemas',
|
||||
'debug',
|
||||
'maxTimeMS',
|
||||
'objectIdGetter',
|
||||
'overwriteModels',
|
||||
'returnOriginal',
|
||||
'runValidators',
|
||||
'sanitizeProjection',
|
||||
'selectPopulatedPaths',
|
||||
'setDefaultsOnInsert',
|
||||
'strict',
|
||||
'strictQuery',
|
||||
'toJSON',
|
||||
'toObject',
|
||||
'typePojoToMixed',
|
||||
'useCreateIndex',
|
||||
'useFindAndModify',
|
||||
'useNewUrlParser',
|
||||
'usePushEach',
|
||||
'useUnifiedTopology',
|
||||
'typePojoToMixed'
|
||||
'useUnifiedTopology'
|
||||
]);
|
||||
|
||||
module.exports = VALID_OPTIONS;
|
||||
|
||||
16
node_modules/mongoose/lib/virtualtype.js
generated
vendored
16
node_modules/mongoose/lib/virtualtype.js
generated
vendored
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const utils = require('./utils');
|
||||
|
||||
/**
|
||||
* VirtualType constructor
|
||||
*
|
||||
@@ -69,7 +71,7 @@ VirtualType.prototype.clone = function() {
|
||||
/**
|
||||
* Adds a custom getter to this virtual.
|
||||
*
|
||||
* Mongoose calls the getter function with 3 parameters:
|
||||
* Mongoose calls the getter function with the below 3 parameters.
|
||||
*
|
||||
* - `value`: the value returned by the previous getter. If there is only one getter, `value` will be `undefined`.
|
||||
* - `virtual`: the virtual object you called `.get()` on
|
||||
@@ -77,7 +79,7 @@ VirtualType.prototype.clone = function() {
|
||||
*
|
||||
* ####Example:
|
||||
*
|
||||
* var virtual = schema.virtual('fullname');
|
||||
* const virtual = schema.virtual('fullname');
|
||||
* virtual.get(function(value, virtual, doc) {
|
||||
* return this.name.first + ' ' + this.name.last;
|
||||
* });
|
||||
@@ -95,7 +97,7 @@ VirtualType.prototype.get = function(fn) {
|
||||
/**
|
||||
* Adds a custom setter to this virtual.
|
||||
*
|
||||
* Mongoose calls the setter function with 3 parameters:
|
||||
* Mongoose calls the setter function with the below 3 parameters.
|
||||
*
|
||||
* - `value`: the value being set
|
||||
* - `virtual`: the virtual object you're calling `.set()` on
|
||||
@@ -105,7 +107,7 @@ VirtualType.prototype.get = function(fn) {
|
||||
*
|
||||
* const virtual = schema.virtual('fullname');
|
||||
* virtual.set(function(value, virtual, doc) {
|
||||
* var parts = value.split(' ');
|
||||
* const parts = value.split(' ');
|
||||
* this.name.first = parts[0];
|
||||
* this.name.last = parts[1];
|
||||
* });
|
||||
@@ -137,6 +139,12 @@ VirtualType.prototype.set = function(fn) {
|
||||
*/
|
||||
|
||||
VirtualType.prototype.applyGetters = function(value, doc) {
|
||||
if (utils.hasUserDefinedProperty(this.options, ['ref', 'refPath']) &&
|
||||
doc.$$populatedVirtuals &&
|
||||
doc.$$populatedVirtuals.hasOwnProperty(this.path)) {
|
||||
value = doc.$$populatedVirtuals[this.path];
|
||||
}
|
||||
|
||||
let v = value;
|
||||
for (let l = this.getters.length - 1; l >= 0; l--) {
|
||||
v = this.getters[l].call(doc, v, this, doc);
|
||||
|
||||
Reference in New Issue
Block a user