mongoose 8.8.3 → 8.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.umd.js +1 -1
- package/index.js +1 -0
- package/lib/cast/double.js +50 -0
- package/lib/cast/int32.js +36 -0
- package/lib/connection.js +180 -0
- package/lib/document.js +12 -3
- package/lib/drivers/node-mongodb-native/connection.js +0 -4
- package/lib/helpers/clone.js +5 -0
- package/lib/helpers/model/castBulkWrite.js +218 -205
- package/lib/helpers/populate/getModelsMapForPopulate.js +7 -0
- package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +7 -1
- package/lib/helpers/schema/getIndexes.js +5 -0
- package/lib/model.js +64 -99
- package/lib/mongoose.js +2 -0
- package/lib/plugins/saveSubdocs.js +4 -2
- package/lib/query.js +6 -2
- package/lib/queryHelpers.js +13 -32
- package/lib/schema/bigint.js +2 -2
- package/lib/schema/double.js +212 -0
- package/lib/schema/index.js +2 -0
- package/lib/schema/int32.js +249 -0
- package/lib/schema.js +35 -0
- package/lib/schemaType.js +36 -8
- package/lib/validOptions.js +1 -0
- package/package.json +7 -7
- package/types/expressions.d.ts +102 -0
- package/types/index.d.ts +1 -1
- package/types/indexes.d.ts +4 -2
- package/types/inferschematype.d.ts +29 -27
- package/types/populate.d.ts +2 -0
- package/types/schematypes.d.ts +34 -1
- package/types/types.d.ts +5 -3
package/lib/model.js
CHANGED
|
@@ -436,6 +436,7 @@ Model.prototype.$__handleSave = function(options, callback) {
|
|
|
436
436
|
Model.prototype.$__save = function(options, callback) {
|
|
437
437
|
this.$__handleSave(options, (error, result) => {
|
|
438
438
|
if (error) {
|
|
439
|
+
error = this.$__schema._transformDuplicateKeyError(error);
|
|
439
440
|
const hooks = this.$__schema.s.hooks;
|
|
440
441
|
return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
|
|
441
442
|
callback(error, this);
|
|
@@ -3356,7 +3357,7 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
|
|
|
3356
3357
|
let error;
|
|
3357
3358
|
[res, error] = await this.$__collection.bulkWrite(validOps, options).
|
|
3358
3359
|
then(res => ([res, null])).
|
|
3359
|
-
catch(
|
|
3360
|
+
catch(error => ([null, error]));
|
|
3360
3361
|
|
|
3361
3362
|
if (error) {
|
|
3362
3363
|
if (validationErrors.length > 0) {
|
|
@@ -4199,6 +4200,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4199
4200
|
* - options: optional query options like sort, limit, etc
|
|
4200
4201
|
* - justOne: optional boolean, if true Mongoose will always set `path` to a document, or `null` if no document was found. If false, Mongoose will always set `path` to an array, which will be empty if no documents are found. Inferred from schema by default.
|
|
4201
4202
|
* - strictPopulate: optional boolean, set to `false` to allow populating paths that aren't in the schema.
|
|
4203
|
+
* - forceRepopulate: optional boolean, defaults to `true`. Set to `false` to prevent Mongoose from repopulating paths that are already populated
|
|
4202
4204
|
*
|
|
4203
4205
|
* #### Example:
|
|
4204
4206
|
*
|
|
@@ -4235,6 +4237,7 @@ Model.validate = async function validate(obj, pathsOrOptions, context) {
|
|
|
4235
4237
|
* @param {Boolean} [options.strictPopulate=true] Set to false to allow populating paths that aren't defined in the given model's schema.
|
|
4236
4238
|
* @param {Object} [options.options=null] Additional options like `limit` and `lean`.
|
|
4237
4239
|
* @param {Function} [options.transform=null] Function that Mongoose will call on every populated document that allows you to transform the populated document.
|
|
4240
|
+
* @param {Boolean} [options.forceRepopulate=true] Set to `false` to prevent Mongoose from repopulating paths that are already populated
|
|
4238
4241
|
* @param {Function} [callback(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
|
|
4239
4242
|
* @return {Promise}
|
|
4240
4243
|
* @api public
|
|
@@ -4245,67 +4248,34 @@ Model.populate = async function populate(docs, paths) {
|
|
|
4245
4248
|
if (typeof paths === 'function' || typeof arguments[2] === 'function') {
|
|
4246
4249
|
throw new MongooseError('Model.populate() no longer accepts a callback');
|
|
4247
4250
|
}
|
|
4248
|
-
const _this = this;
|
|
4249
4251
|
// normalized paths
|
|
4250
4252
|
paths = utils.populate(paths);
|
|
4251
|
-
// data that should persist across subPopulate calls
|
|
4252
|
-
const cache = {};
|
|
4253
|
-
|
|
4254
|
-
return new Promise((resolve, reject) => {
|
|
4255
|
-
_populate(_this, docs, paths, cache, (err, res) => {
|
|
4256
|
-
if (err) {
|
|
4257
|
-
return reject(err);
|
|
4258
|
-
}
|
|
4259
|
-
resolve(res);
|
|
4260
|
-
});
|
|
4261
|
-
});
|
|
4262
|
-
};
|
|
4263
|
-
|
|
4264
|
-
/**
|
|
4265
|
-
* Populate helper
|
|
4266
|
-
*
|
|
4267
|
-
* @param {Model} model the model to use
|
|
4268
|
-
* @param {Document|Array} docs Either a single document or array of documents to populate.
|
|
4269
|
-
* @param {Object} paths
|
|
4270
|
-
* @param {never} cache Unused
|
|
4271
|
-
* @param {Function} [callback] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
|
|
4272
|
-
* @return {Function}
|
|
4273
|
-
* @api private
|
|
4274
|
-
*/
|
|
4275
4253
|
|
|
4276
|
-
function _populate(model, docs, paths, cache, callback) {
|
|
4277
|
-
let pending = paths.length;
|
|
4278
4254
|
if (paths.length === 0) {
|
|
4279
|
-
return
|
|
4255
|
+
return docs;
|
|
4280
4256
|
}
|
|
4257
|
+
|
|
4281
4258
|
// each path has its own query options and must be executed separately
|
|
4259
|
+
const promises = [];
|
|
4282
4260
|
for (const path of paths) {
|
|
4283
|
-
|
|
4261
|
+
promises.push(_populatePath(this, docs, path));
|
|
4284
4262
|
}
|
|
4263
|
+
await Promise.all(promises);
|
|
4285
4264
|
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
return callback(err, null);
|
|
4289
|
-
}
|
|
4290
|
-
if (--pending) {
|
|
4291
|
-
return;
|
|
4292
|
-
}
|
|
4293
|
-
callback(null, docs);
|
|
4294
|
-
}
|
|
4295
|
-
}
|
|
4265
|
+
return docs;
|
|
4266
|
+
};
|
|
4296
4267
|
|
|
4297
4268
|
/*!
|
|
4298
|
-
* Populates `docs`
|
|
4269
|
+
* Populates `docs` for a single `populateOptions` instance.
|
|
4299
4270
|
*/
|
|
4300
4271
|
const excludeIdReg = /\s?-_id\s?/;
|
|
4301
4272
|
const excludeIdRegGlobal = /\s?-_id\s?/g;
|
|
4302
4273
|
|
|
4303
|
-
function
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
} else if (options._localModel != null && model.base.options.strictPopulate != null) {
|
|
4274
|
+
async function _populatePath(model, docs, populateOptions) {
|
|
4275
|
+
if (populateOptions.strictPopulate == null) {
|
|
4276
|
+
if (populateOptions._localModel != null && populateOptions._localModel.schema._userProvidedOptions.strictPopulate != null) {
|
|
4277
|
+
populateOptions.strictPopulate = populateOptions._localModel.schema._userProvidedOptions.strictPopulate;
|
|
4278
|
+
} else if (populateOptions._localModel != null && model.base.options.strictPopulate != null) {
|
|
4309
4279
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
4310
4280
|
} else if (model.base.options.strictPopulate != null) {
|
|
4311
4281
|
populateOptions.strictPopulate = model.base.options.strictPopulate;
|
|
@@ -4317,15 +4287,12 @@ function populate(model, docs, options, callback) {
|
|
|
4317
4287
|
docs = [docs];
|
|
4318
4288
|
}
|
|
4319
4289
|
if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) {
|
|
4320
|
-
return
|
|
4290
|
+
return;
|
|
4321
4291
|
}
|
|
4322
4292
|
|
|
4323
4293
|
const modelsMap = getModelsMapForPopulate(model, docs, populateOptions);
|
|
4324
|
-
|
|
4325
4294
|
if (modelsMap instanceof MongooseError) {
|
|
4326
|
-
|
|
4327
|
-
callback(modelsMap);
|
|
4328
|
-
});
|
|
4295
|
+
throw modelsMap;
|
|
4329
4296
|
}
|
|
4330
4297
|
const len = modelsMap.length;
|
|
4331
4298
|
let vals = [];
|
|
@@ -4335,7 +4302,6 @@ function populate(model, docs, options, callback) {
|
|
|
4335
4302
|
return undefined !== item;
|
|
4336
4303
|
}
|
|
4337
4304
|
|
|
4338
|
-
let _remaining = len;
|
|
4339
4305
|
let hasOne = false;
|
|
4340
4306
|
const params = [];
|
|
4341
4307
|
for (let i = 0; i < len; ++i) {
|
|
@@ -4366,7 +4332,6 @@ function populate(model, docs, options, callback) {
|
|
|
4366
4332
|
// Ensure that we set to 0 or empty array even
|
|
4367
4333
|
// if we don't actually execute a query to make sure there's a value
|
|
4368
4334
|
// and we know this path was populated for future sets. See gh-7731, gh-8230
|
|
4369
|
-
--_remaining;
|
|
4370
4335
|
_assign(model, [], mod, assignmentOpts);
|
|
4371
4336
|
continue;
|
|
4372
4337
|
}
|
|
@@ -4397,64 +4362,50 @@ function populate(model, docs, options, callback) {
|
|
|
4397
4362
|
} else if (mod.options.limit != null) {
|
|
4398
4363
|
assignmentOpts.originalLimit = mod.options.limit;
|
|
4399
4364
|
}
|
|
4400
|
-
params.push([mod, match, select, assignmentOpts
|
|
4365
|
+
params.push([mod, match, select, assignmentOpts]);
|
|
4401
4366
|
}
|
|
4402
4367
|
if (!hasOne) {
|
|
4403
4368
|
// If models but no docs, skip further deep populate.
|
|
4404
4369
|
if (modelsMap.length !== 0) {
|
|
4405
|
-
return
|
|
4370
|
+
return;
|
|
4406
4371
|
}
|
|
4407
|
-
// If no models to populate but we have a nested populate,
|
|
4408
|
-
//
|
|
4372
|
+
// If no models and no docs to populate but we have a nested populate,
|
|
4373
|
+
// probably a case of unnecessarily populating a non-ref path re: gh-8946
|
|
4409
4374
|
if (populateOptions.populate != null) {
|
|
4410
4375
|
const opts = utils.populate(populateOptions.populate).map(pop => Object.assign({}, pop, {
|
|
4411
4376
|
path: populateOptions.path + '.' + pop.path
|
|
4412
4377
|
}));
|
|
4413
|
-
model.populate(docs, opts)
|
|
4414
|
-
return;
|
|
4378
|
+
return model.populate(docs, opts);
|
|
4415
4379
|
}
|
|
4416
|
-
return
|
|
4380
|
+
return;
|
|
4417
4381
|
}
|
|
4418
4382
|
|
|
4383
|
+
const promises = [];
|
|
4419
4384
|
for (const arr of params) {
|
|
4420
|
-
_execPopulateQuery.apply(null, arr);
|
|
4421
|
-
}
|
|
4422
|
-
function _next(err, valsFromDb) {
|
|
4423
|
-
if (err != null) {
|
|
4424
|
-
return callback(err, null);
|
|
4425
|
-
}
|
|
4426
|
-
vals = vals.concat(valsFromDb);
|
|
4427
|
-
if (--_remaining === 0) {
|
|
4428
|
-
_done();
|
|
4429
|
-
}
|
|
4385
|
+
promises.push(_execPopulateQuery.apply(null, arr).then(valsFromDb => { vals = vals.concat(valsFromDb); }));
|
|
4430
4386
|
}
|
|
4431
4387
|
|
|
4432
|
-
|
|
4433
|
-
for (const arr of params) {
|
|
4434
|
-
const mod = arr[0];
|
|
4435
|
-
const assignmentOpts = arr[3];
|
|
4436
|
-
for (const val of vals) {
|
|
4437
|
-
mod.options._childDocs.push(val);
|
|
4438
|
-
}
|
|
4439
|
-
try {
|
|
4440
|
-
_assign(model, vals, mod, assignmentOpts);
|
|
4441
|
-
} catch (err) {
|
|
4442
|
-
return callback(err);
|
|
4443
|
-
}
|
|
4444
|
-
}
|
|
4388
|
+
await Promise.all(promises);
|
|
4445
4389
|
|
|
4446
|
-
|
|
4447
|
-
|
|
4390
|
+
for (const arr of params) {
|
|
4391
|
+
const mod = arr[0];
|
|
4392
|
+
const assignmentOpts = arr[3];
|
|
4393
|
+
for (const val of vals) {
|
|
4394
|
+
mod.options._childDocs.push(val);
|
|
4448
4395
|
}
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4396
|
+
_assign(model, vals, mod, assignmentOpts);
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
for (const arr of params) {
|
|
4400
|
+
removeDeselectedForeignField(arr[0].foreignField, arr[0].options, vals);
|
|
4401
|
+
}
|
|
4402
|
+
for (const arr of params) {
|
|
4403
|
+
const mod = arr[0];
|
|
4404
|
+
if (mod.options && mod.options.options && mod.options.options._leanTransform) {
|
|
4405
|
+
for (const doc of vals) {
|
|
4406
|
+
mod.options.options._leanTransform(doc);
|
|
4455
4407
|
}
|
|
4456
4408
|
}
|
|
4457
|
-
callback();
|
|
4458
4409
|
}
|
|
4459
4410
|
}
|
|
4460
4411
|
|
|
@@ -4462,7 +4413,7 @@ function populate(model, docs, options, callback) {
|
|
|
4462
4413
|
* ignore
|
|
4463
4414
|
*/
|
|
4464
4415
|
|
|
4465
|
-
function _execPopulateQuery(mod, match, select
|
|
4416
|
+
function _execPopulateQuery(mod, match, select) {
|
|
4466
4417
|
let subPopulate = clone(mod.options.populate);
|
|
4467
4418
|
const queryOptions = Object.assign({
|
|
4468
4419
|
skip: mod.options.skip,
|
|
@@ -4528,15 +4479,12 @@ function _execPopulateQuery(mod, match, select, assignmentOpts, callback) {
|
|
|
4528
4479
|
query.populate(subPopulate);
|
|
4529
4480
|
}
|
|
4530
4481
|
|
|
4531
|
-
query.exec().then(
|
|
4482
|
+
return query.exec().then(
|
|
4532
4483
|
docs => {
|
|
4533
4484
|
for (const val of docs) {
|
|
4534
4485
|
leanPopulateMap.set(val, mod.model);
|
|
4535
4486
|
}
|
|
4536
|
-
|
|
4537
|
-
},
|
|
4538
|
-
err => {
|
|
4539
|
-
callback(err);
|
|
4487
|
+
return docs;
|
|
4540
4488
|
}
|
|
4541
4489
|
);
|
|
4542
4490
|
}
|
|
@@ -4934,6 +4882,23 @@ Model.inspect = function() {
|
|
|
4934
4882
|
return `Model { ${this.modelName} }`;
|
|
4935
4883
|
};
|
|
4936
4884
|
|
|
4885
|
+
/**
|
|
4886
|
+
* Return the MongoDB namespace for this model as a string. The namespace is the database name, followed by '.', followed by the collection name.
|
|
4887
|
+
*
|
|
4888
|
+
* #### Example:
|
|
4889
|
+
*
|
|
4890
|
+
* const conn = mongoose.createConnection('mongodb://127.0.0.1:27017/mydb');
|
|
4891
|
+
* const TestModel = conn.model('Test', mongoose.Schema({ name: String }));
|
|
4892
|
+
*
|
|
4893
|
+
* TestModel.namespace(); // 'mydb.tests'
|
|
4894
|
+
*
|
|
4895
|
+
* @api public
|
|
4896
|
+
*/
|
|
4897
|
+
|
|
4898
|
+
Model.namespace = function namespace() {
|
|
4899
|
+
return this.db.name + '.' + this.collection.collectionName;
|
|
4900
|
+
};
|
|
4901
|
+
|
|
4937
4902
|
if (util.inspect.custom) {
|
|
4938
4903
|
// Avoid Node deprecation warning DEP0079
|
|
4939
4904
|
Model[util.inspect.custom] = Model.inspect;
|
package/lib/mongoose.js
CHANGED
|
@@ -987,6 +987,7 @@ Mongoose.prototype.VirtualType = VirtualType;
|
|
|
987
987
|
* - [ObjectId](https://mongoosejs.com/docs/schematypes.html#objectids)
|
|
988
988
|
* - [Map](https://mongoosejs.com/docs/schematypes.html#maps)
|
|
989
989
|
* - [Subdocument](https://mongoosejs.com/docs/schematypes.html#schemas)
|
|
990
|
+
* - [Int32](https://mongoosejs.com/docs/schematypes.html#int32)
|
|
990
991
|
*
|
|
991
992
|
* Using this exposed access to the `ObjectId` type, we can construct ids on demand.
|
|
992
993
|
*
|
|
@@ -1138,6 +1139,7 @@ Mongoose.prototype.syncIndexes = function(options) {
|
|
|
1138
1139
|
|
|
1139
1140
|
Mongoose.prototype.Decimal128 = SchemaTypes.Decimal128;
|
|
1140
1141
|
|
|
1142
|
+
|
|
1141
1143
|
/**
|
|
1142
1144
|
* The Mongoose Mixed [SchemaType](https://mongoosejs.com/docs/schematypes.html). Used for
|
|
1143
1145
|
* declaring paths in your schema that Mongoose's change tracking, casting,
|
|
@@ -27,8 +27,10 @@ module.exports = function saveSubdocs(schema) {
|
|
|
27
27
|
cb(err);
|
|
28
28
|
});
|
|
29
29
|
}, function(error) {
|
|
30
|
-
//
|
|
31
|
-
_this.$__.saveOptions
|
|
30
|
+
// Invalidate subdocs cache because subdoc pre hooks can add new subdocuments
|
|
31
|
+
if (_this.$__.saveOptions) {
|
|
32
|
+
_this.$__.saveOptions.__subdocs = null;
|
|
33
|
+
}
|
|
32
34
|
if (error) {
|
|
33
35
|
return _this.$__schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
|
|
34
36
|
next(error);
|
package/lib/query.js
CHANGED
|
@@ -2381,6 +2381,7 @@ Query.prototype._find = async function _find() {
|
|
|
2381
2381
|
_completeManyLean(_this.model.schema, docs, null, completeManyOptions) :
|
|
2382
2382
|
_this._completeMany(docs, fields, userProvidedFields, completeManyOptions);
|
|
2383
2383
|
}
|
|
2384
|
+
|
|
2384
2385
|
const pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions);
|
|
2385
2386
|
|
|
2386
2387
|
if (mongooseOptions.lean) {
|
|
@@ -4466,6 +4467,8 @@ Query.prototype.exec = async function exec(op) {
|
|
|
4466
4467
|
} else {
|
|
4467
4468
|
error = err;
|
|
4468
4469
|
}
|
|
4470
|
+
|
|
4471
|
+
error = this.model.schema._transformDuplicateKeyError(error);
|
|
4469
4472
|
}
|
|
4470
4473
|
|
|
4471
4474
|
res = await _executePostHooks(this, res, error);
|
|
@@ -4762,12 +4765,13 @@ Query.prototype._castUpdate = function _castUpdate(obj) {
|
|
|
4762
4765
|
*/
|
|
4763
4766
|
|
|
4764
4767
|
Query.prototype.populate = function() {
|
|
4768
|
+
const args = Array.from(arguments);
|
|
4765
4769
|
// Bail when given no truthy arguments
|
|
4766
|
-
if (!
|
|
4770
|
+
if (!args.some(Boolean)) {
|
|
4767
4771
|
return this;
|
|
4768
4772
|
}
|
|
4769
4773
|
|
|
4770
|
-
const res = utils.populate.apply(null,
|
|
4774
|
+
const res = utils.populate.apply(null, args);
|
|
4771
4775
|
|
|
4772
4776
|
// Propagate readConcern and readPreference and lean from parent query,
|
|
4773
4777
|
// unless one already specified
|
package/lib/queryHelpers.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* Module dependencies
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
const PopulateOptions = require('./options/populateOptions');
|
|
7
8
|
const checkEmbeddedDiscriminatorKeyProjection =
|
|
8
9
|
require('./helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection');
|
|
9
10
|
const get = require('./helpers/get');
|
|
@@ -13,32 +14,6 @@ const isDefiningProjection = require('./helpers/projection/isDefiningProjection'
|
|
|
13
14
|
const clone = require('./helpers/clone');
|
|
14
15
|
const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
* Prepare a set of path options for query population.
|
|
18
|
-
*
|
|
19
|
-
* @param {Query} query
|
|
20
|
-
* @param {Object} options
|
|
21
|
-
* @return {Array}
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
exports.preparePopulationOptions = function preparePopulationOptions(query, options) {
|
|
25
|
-
const _populate = query.options.populate;
|
|
26
|
-
const pop = Object.keys(_populate).reduce((vals, key) => vals.concat([_populate[key]]), []);
|
|
27
|
-
|
|
28
|
-
// lean options should trickle through all queries
|
|
29
|
-
if (options.lean != null) {
|
|
30
|
-
pop
|
|
31
|
-
.filter(p => (p && p.options && p.options.lean) == null)
|
|
32
|
-
.forEach(makeLean(options.lean));
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
pop.forEach(opts => {
|
|
36
|
-
opts._localModel = query.model;
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
return pop;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
17
|
/**
|
|
43
18
|
* Prepare a set of path options for query population. This is the MongooseQuery
|
|
44
19
|
* version
|
|
@@ -73,12 +48,18 @@ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query,
|
|
|
73
48
|
}
|
|
74
49
|
|
|
75
50
|
const projection = query._fieldsForExec();
|
|
76
|
-
pop.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
51
|
+
for (let i = 0; i < pop.length; ++i) {
|
|
52
|
+
if (pop[i] instanceof PopulateOptions) {
|
|
53
|
+
pop[i] = new PopulateOptions({
|
|
54
|
+
...pop[i],
|
|
55
|
+
_queryProjection: projection,
|
|
56
|
+
_localModel: query.model
|
|
57
|
+
});
|
|
58
|
+
} else {
|
|
59
|
+
pop[i]._queryProjection = projection;
|
|
60
|
+
pop[i]._localModel = query.model;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
82
63
|
|
|
83
64
|
return pop;
|
|
84
65
|
};
|
package/lib/schema/bigint.js
CHANGED
|
@@ -81,12 +81,12 @@ SchemaBigInt.setters = [];
|
|
|
81
81
|
SchemaBigInt.get = SchemaType.get;
|
|
82
82
|
|
|
83
83
|
/**
|
|
84
|
-
* Get/set the function used to cast arbitrary values to
|
|
84
|
+
* Get/set the function used to cast arbitrary values to bigints.
|
|
85
85
|
*
|
|
86
86
|
* #### Example:
|
|
87
87
|
*
|
|
88
88
|
* // Make Mongoose cast empty string '' to false.
|
|
89
|
-
* const original = mongoose.Schema.BigInt.cast();
|
|
89
|
+
* const original = mongoose.Schema.Types.BigInt.cast();
|
|
90
90
|
* mongoose.Schema.BigInt.cast(v => {
|
|
91
91
|
* if (v === '') {
|
|
92
92
|
* return false;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/*!
|
|
4
|
+
* Module dependencies.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const CastError = require('../error/cast');
|
|
8
|
+
const SchemaType = require('../schemaType');
|
|
9
|
+
const castDouble = require('../cast/double');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Double SchemaType constructor.
|
|
13
|
+
*
|
|
14
|
+
* @param {String} path
|
|
15
|
+
* @param {Object} options
|
|
16
|
+
* @inherits SchemaType
|
|
17
|
+
* @api public
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
function SchemaDouble(path, options) {
|
|
21
|
+
SchemaType.call(this, path, options, 'Double');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* This schema type's name, to defend against minifiers that mangle
|
|
26
|
+
* function names.
|
|
27
|
+
*
|
|
28
|
+
* @api public
|
|
29
|
+
*/
|
|
30
|
+
SchemaDouble.schemaName = 'Double';
|
|
31
|
+
|
|
32
|
+
SchemaDouble.defaultOptions = {};
|
|
33
|
+
|
|
34
|
+
/*!
|
|
35
|
+
* Inherits from SchemaType.
|
|
36
|
+
*/
|
|
37
|
+
SchemaDouble.prototype = Object.create(SchemaType.prototype);
|
|
38
|
+
SchemaDouble.prototype.constructor = SchemaDouble;
|
|
39
|
+
|
|
40
|
+
/*!
|
|
41
|
+
* ignore
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
SchemaDouble._cast = castDouble;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Sets a default option for all Double instances.
|
|
48
|
+
*
|
|
49
|
+
* #### Example:
|
|
50
|
+
*
|
|
51
|
+
* // Make all Double fields required by default
|
|
52
|
+
* mongoose.Schema.Double.set('required', true);
|
|
53
|
+
*
|
|
54
|
+
* @param {String} option The option you'd like to set the value for
|
|
55
|
+
* @param {Any} value value for option
|
|
56
|
+
* @return {undefined}
|
|
57
|
+
* @function set
|
|
58
|
+
* @static
|
|
59
|
+
* @api public
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
SchemaDouble.set = SchemaType.set;
|
|
63
|
+
|
|
64
|
+
SchemaDouble.setters = [];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Attaches a getter for all Double instances
|
|
68
|
+
*
|
|
69
|
+
* #### Example:
|
|
70
|
+
*
|
|
71
|
+
* // Converts Double to be a represent milliseconds upon access
|
|
72
|
+
* mongoose.Schema.Double.get(v => v == null ? '0.000 ms' : v.toString() + ' ms');
|
|
73
|
+
*
|
|
74
|
+
* @param {Function} getter
|
|
75
|
+
* @return {this}
|
|
76
|
+
* @function get
|
|
77
|
+
* @static
|
|
78
|
+
* @api public
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
SchemaDouble.get = SchemaType.get;
|
|
82
|
+
|
|
83
|
+
/*!
|
|
84
|
+
* ignore
|
|
85
|
+
*/
|
|
86
|
+
|
|
87
|
+
SchemaDouble._defaultCaster = v => {
|
|
88
|
+
if (v != null) {
|
|
89
|
+
if (v._bsontype !== 'Double') {
|
|
90
|
+
throw new Error();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return v;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Get/set the function used to cast arbitrary values to IEEE 754-2008 floating points
|
|
99
|
+
*
|
|
100
|
+
* #### Example:
|
|
101
|
+
*
|
|
102
|
+
* // Make Mongoose cast any NaNs to 0
|
|
103
|
+
* const defaultCast = mongoose.Schema.Types.Double.cast();
|
|
104
|
+
* mongoose.Schema.Types.Double.cast(v => {
|
|
105
|
+
* if (isNaN(v)) {
|
|
106
|
+
* return 0;
|
|
107
|
+
* }
|
|
108
|
+
* return defaultCast(v);
|
|
109
|
+
* });
|
|
110
|
+
*
|
|
111
|
+
* // Or disable casting for Doubles entirely (only JS numbers are permitted)
|
|
112
|
+
* mongoose.Schema.Double.cast(false);
|
|
113
|
+
*
|
|
114
|
+
*
|
|
115
|
+
* @param {Function} caster
|
|
116
|
+
* @return {Function}
|
|
117
|
+
* @function get
|
|
118
|
+
* @static
|
|
119
|
+
* @api public
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
SchemaDouble.cast = function cast(caster) {
|
|
123
|
+
if (arguments.length === 0) {
|
|
124
|
+
return this._cast;
|
|
125
|
+
}
|
|
126
|
+
if (caster === false) {
|
|
127
|
+
caster = this._defaultCaster;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
this._cast = caster;
|
|
131
|
+
|
|
132
|
+
return this._cast;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
/*!
|
|
137
|
+
* ignore
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
SchemaDouble._checkRequired = v => v != null;
|
|
141
|
+
/**
|
|
142
|
+
* Override the function the required validator uses to check whether a value
|
|
143
|
+
* passes the `required` check.
|
|
144
|
+
*
|
|
145
|
+
* @param {Function} fn
|
|
146
|
+
* @return {Function}
|
|
147
|
+
* @function checkRequired
|
|
148
|
+
* @static
|
|
149
|
+
* @api public
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
SchemaDouble.checkRequired = SchemaType.checkRequired;
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Check if the given value satisfies a required validator.
|
|
156
|
+
*
|
|
157
|
+
* @param {Any} value
|
|
158
|
+
* @return {Boolean}
|
|
159
|
+
* @api public
|
|
160
|
+
*/
|
|
161
|
+
|
|
162
|
+
SchemaDouble.prototype.checkRequired = function(value) {
|
|
163
|
+
return this.constructor._checkRequired(value);
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Casts to Double
|
|
168
|
+
*
|
|
169
|
+
* @param {Object} value
|
|
170
|
+
* @param {Object} model this value is optional
|
|
171
|
+
* @api private
|
|
172
|
+
*/
|
|
173
|
+
|
|
174
|
+
SchemaDouble.prototype.cast = function(value) {
|
|
175
|
+
let castDouble;
|
|
176
|
+
if (typeof this._castFunction === 'function') {
|
|
177
|
+
castDouble = this._castFunction;
|
|
178
|
+
} else if (typeof this.constructor.cast === 'function') {
|
|
179
|
+
castDouble = this.constructor.cast();
|
|
180
|
+
} else {
|
|
181
|
+
castDouble = SchemaDouble.cast();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
try {
|
|
185
|
+
return castDouble(value);
|
|
186
|
+
} catch (error) {
|
|
187
|
+
throw new CastError('Double', value, this.path, error, this);
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/*!
|
|
192
|
+
* ignore
|
|
193
|
+
*/
|
|
194
|
+
|
|
195
|
+
function handleSingle(val) {
|
|
196
|
+
return this.cast(val);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
SchemaDouble.prototype.$conditionalHandlers = {
|
|
200
|
+
...SchemaType.prototype.$conditionalHandlers,
|
|
201
|
+
$gt: handleSingle,
|
|
202
|
+
$gte: handleSingle,
|
|
203
|
+
$lt: handleSingle,
|
|
204
|
+
$lte: handleSingle
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
/*!
|
|
209
|
+
* Module exports.
|
|
210
|
+
*/
|
|
211
|
+
|
|
212
|
+
module.exports = SchemaDouble;
|
package/lib/schema/index.js
CHANGED
|
@@ -19,6 +19,8 @@ exports.ObjectId = require('./objectId');
|
|
|
19
19
|
exports.String = require('./string');
|
|
20
20
|
exports.Subdocument = require('./subdocument');
|
|
21
21
|
exports.UUID = require('./uuid');
|
|
22
|
+
exports.Double = require('./double');
|
|
23
|
+
exports.Int32 = require('./int32');
|
|
22
24
|
|
|
23
25
|
// alias
|
|
24
26
|
|