summaryrefslogtreecommitdiffstats
path: root/node_modules/mongoose
diff options
context:
space:
mode:
authorGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
committerGravatar Piotr Russ <mail@pruss.it> 2020-11-16 00:10:28 +0100
commite06ec920f7a5d784e674c4c4b4e6d1da3dc7391d (patch)
tree55713f725f77b44ebfec86e4eec3ce33e71458ca /node_modules/mongoose
downloadwebsite_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.gz
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.tar.bz2
website_creator-e06ec920f7a5d784e674c4c4b4e6d1da3dc7391d.zip
api, login, auth
Diffstat (limited to 'node_modules/mongoose')
-rw-r--r--node_modules/mongoose/History.md6054
-rw-r--r--node_modules/mongoose/LICENSE.md21
-rw-r--r--node_modules/mongoose/README.md371
-rw-r--r--node_modules/mongoose/SECURITY.md1
-rw-r--r--node_modules/mongoose/browser.js8
-rw-r--r--node_modules/mongoose/build-browser.js18
-rw-r--r--node_modules/mongoose/dist/browser.umd.js1591
-rw-r--r--node_modules/mongoose/dist/createBasicSchemaDefinition.js7
-rw-r--r--node_modules/mongoose/index.js9
-rw-r--r--node_modules/mongoose/lib/aggregate.js1162
-rw-r--r--node_modules/mongoose/lib/browser.js155
-rw-r--r--node_modules/mongoose/lib/browserDocument.js100
-rw-r--r--node_modules/mongoose/lib/cast.js364
-rw-r--r--node_modules/mongoose/lib/cast/boolean.js32
-rw-r--r--node_modules/mongoose/lib/cast/date.js41
-rw-r--r--node_modules/mongoose/lib/cast/decimal128.js36
-rw-r--r--node_modules/mongoose/lib/cast/number.js43
-rw-r--r--node_modules/mongoose/lib/cast/objectid.js29
-rw-r--r--node_modules/mongoose/lib/cast/string.js37
-rw-r--r--node_modules/mongoose/lib/collection.js282
-rw-r--r--node_modules/mongoose/lib/connection.js1459
-rw-r--r--node_modules/mongoose/lib/connectionstate.js26
-rw-r--r--node_modules/mongoose/lib/cursor/AggregationCursor.js368
-rw-r--r--node_modules/mongoose/lib/cursor/ChangeStream.js61
-rw-r--r--node_modules/mongoose/lib/cursor/QueryCursor.js418
-rw-r--r--node_modules/mongoose/lib/document.js4056
-rw-r--r--node_modules/mongoose/lib/document_provider.js30
-rw-r--r--node_modules/mongoose/lib/driver.js15
-rw-r--r--node_modules/mongoose/lib/drivers/SPEC.md4
-rw-r--r--node_modules/mongoose/lib/drivers/browser/ReadPreference.js7
-rw-r--r--node_modules/mongoose/lib/drivers/browser/binary.js14
-rw-r--r--node_modules/mongoose/lib/drivers/browser/decimal128.js7
-rw-r--r--node_modules/mongoose/lib/drivers/browser/index.js13
-rw-r--r--node_modules/mongoose/lib/drivers/browser/objectid.js28
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/ReadPreference.js47
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js10
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js368
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js185
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/decimal128.js7
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/index.js11
-rw-r--r--node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js16
-rw-r--r--node_modules/mongoose/lib/error/browserMissingSchema.js28
-rw-r--r--node_modules/mongoose/lib/error/cast.js120
-rw-r--r--node_modules/mongoose/lib/error/disconnected.js34
-rw-r--r--node_modules/mongoose/lib/error/divergentArray.js37
-rw-r--r--node_modules/mongoose/lib/error/index.js205
-rw-r--r--node_modules/mongoose/lib/error/messages.js47
-rw-r--r--node_modules/mongoose/lib/error/missingSchema.js30
-rw-r--r--node_modules/mongoose/lib/error/mongooseError.js13
-rw-r--r--node_modules/mongoose/lib/error/notFound.js44
-rw-r--r--node_modules/mongoose/lib/error/objectExpected.js30
-rw-r--r--node_modules/mongoose/lib/error/objectParameter.js30
-rw-r--r--node_modules/mongoose/lib/error/overwriteModel.js29
-rw-r--r--node_modules/mongoose/lib/error/parallelSave.js30
-rw-r--r--node_modules/mongoose/lib/error/parallelValidate.js31
-rw-r--r--node_modules/mongoose/lib/error/serverSelection.js61
-rw-r--r--node_modules/mongoose/lib/error/strict.js33
-rw-r--r--node_modules/mongoose/lib/error/validation.js110
-rw-r--r--node_modules/mongoose/lib/error/validator.js94
-rw-r--r--node_modules/mongoose/lib/error/version.js36
-rw-r--r--node_modules/mongoose/lib/helpers/aggregate/stringifyAccumulatorOptions.js38
-rw-r--r--node_modules/mongoose/lib/helpers/arrayDepth.js30
-rw-r--r--node_modules/mongoose/lib/helpers/clone.js143
-rw-r--r--node_modules/mongoose/lib/helpers/common.js106
-rw-r--r--node_modules/mongoose/lib/helpers/cursor/eachAsync.js121
-rw-r--r--node_modules/mongoose/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js12
-rw-r--r--node_modules/mongoose/lib/helpers/discriminator/getConstructor.js25
-rw-r--r--node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js27
-rw-r--r--node_modules/mongoose/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js24
-rw-r--r--node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js28
-rw-r--r--node_modules/mongoose/lib/helpers/document/compile.js204
-rw-r--r--node_modules/mongoose/lib/helpers/document/getEmbeddedDiscriminatorPath.js43
-rw-r--r--node_modules/mongoose/lib/helpers/document/handleSpreadDoc.js17
-rw-r--r--node_modules/mongoose/lib/helpers/each.js25
-rw-r--r--node_modules/mongoose/lib/helpers/get.js39
-rw-r--r--node_modules/mongoose/lib/helpers/getDefaultBulkwriteResult.js27
-rw-r--r--node_modules/mongoose/lib/helpers/getFunctionName.js8
-rw-r--r--node_modules/mongoose/lib/helpers/immediate.js12
-rw-r--r--node_modules/mongoose/lib/helpers/indexes/isDefaultIdIndex.js18
-rw-r--r--node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js95
-rw-r--r--node_modules/mongoose/lib/helpers/isBsonType.js13
-rw-r--r--node_modules/mongoose/lib/helpers/isMongooseObject.js21
-rw-r--r--node_modules/mongoose/lib/helpers/isObject.js16
-rw-r--r--node_modules/mongoose/lib/helpers/isPromise.js6
-rw-r--r--node_modules/mongoose/lib/helpers/model/applyHooks.js135
-rw-r--r--node_modules/mongoose/lib/helpers/model/applyMethods.js56
-rw-r--r--node_modules/mongoose/lib/helpers/model/applyStaticHooks.js71
-rw-r--r--node_modules/mongoose/lib/helpers/model/applyStatics.js12
-rw-r--r--node_modules/mongoose/lib/helpers/model/castBulkWrite.js224
-rw-r--r--node_modules/mongoose/lib/helpers/model/discriminator.js205
-rw-r--r--node_modules/mongoose/lib/helpers/once.js12
-rw-r--r--node_modules/mongoose/lib/helpers/parallelLimit.js55
-rw-r--r--node_modules/mongoose/lib/helpers/populate/SkipPopulateValue.js10
-rw-r--r--node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js98
-rw-r--r--node_modules/mongoose/lib/helpers/populate/assignVals.js274
-rw-r--r--node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js522
-rw-r--r--node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js198
-rw-r--r--node_modules/mongoose/lib/helpers/populate/getVirtual.js72
-rw-r--r--node_modules/mongoose/lib/helpers/populate/leanPopulateMap.js7
-rw-r--r--node_modules/mongoose/lib/helpers/populate/lookupLocalFields.js26
-rw-r--r--node_modules/mongoose/lib/helpers/populate/normalizeRefPath.js45
-rw-r--r--node_modules/mongoose/lib/helpers/populate/removeDeselectedForeignField.js31
-rw-r--r--node_modules/mongoose/lib/helpers/populate/validateRef.js19
-rw-r--r--node_modules/mongoose/lib/helpers/printJestWarning.js8
-rw-r--r--node_modules/mongoose/lib/helpers/projection/isDefiningProjection.js18
-rw-r--r--node_modules/mongoose/lib/helpers/projection/isExclusive.js28
-rw-r--r--node_modules/mongoose/lib/helpers/projection/isInclusive.js34
-rw-r--r--node_modules/mongoose/lib/helpers/projection/isPathExcluded.js35
-rw-r--r--node_modules/mongoose/lib/helpers/projection/isPathSelectedInclusive.js28
-rw-r--r--node_modules/mongoose/lib/helpers/projection/parseProjection.js33
-rw-r--r--node_modules/mongoose/lib/helpers/promiseOrCallback.js45
-rw-r--r--node_modules/mongoose/lib/helpers/query/applyGlobalMaxTimeMS.js15
-rw-r--r--node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js90
-rw-r--r--node_modules/mongoose/lib/helpers/query/castFilterPath.js55
-rw-r--r--node_modules/mongoose/lib/helpers/query/castUpdate.js538
-rw-r--r--node_modules/mongoose/lib/helpers/query/completeMany.js47
-rw-r--r--node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js68
-rw-r--r--node_modules/mongoose/lib/helpers/query/handleImmutable.js28
-rw-r--r--node_modules/mongoose/lib/helpers/query/hasDollarKeys.js19
-rw-r--r--node_modules/mongoose/lib/helpers/query/isOperator.js11
-rw-r--r--node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js46
-rw-r--r--node_modules/mongoose/lib/helpers/query/wrapThunk.js18
-rw-r--r--node_modules/mongoose/lib/helpers/schema/addAutoId.js7
-rw-r--r--node_modules/mongoose/lib/helpers/schema/applyPlugins.js44
-rw-r--r--node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js16
-rw-r--r--node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js12
-rw-r--r--node_modules/mongoose/lib/helpers/schema/getIndexes.js155
-rw-r--r--node_modules/mongoose/lib/helpers/schema/getPath.js35
-rw-r--r--node_modules/mongoose/lib/helpers/schema/handleIdOption.js20
-rw-r--r--node_modules/mongoose/lib/helpers/schema/handleTimestampOption.js24
-rw-r--r--node_modules/mongoose/lib/helpers/schema/merge.js19
-rw-r--r--node_modules/mongoose/lib/helpers/schematype/handleImmutable.js45
-rw-r--r--node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js127
-rw-r--r--node_modules/mongoose/lib/helpers/specialProperties.js3
-rw-r--r--node_modules/mongoose/lib/helpers/symbols.js19
-rw-r--r--node_modules/mongoose/lib/helpers/timestamps/setupTimestamps.js104
-rw-r--r--node_modules/mongoose/lib/helpers/topology/allServersUnknown.js11
-rw-r--r--node_modules/mongoose/lib/helpers/topology/isAtlas.js12
-rw-r--r--node_modules/mongoose/lib/helpers/topology/isSSLError.js15
-rw-r--r--node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js172
-rw-r--r--node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js119
-rw-r--r--node_modules/mongoose/lib/helpers/update/castArrayFilters.js78
-rw-r--r--node_modules/mongoose/lib/helpers/update/modifiedPaths.js33
-rw-r--r--node_modules/mongoose/lib/helpers/update/moveImmutableProperties.js53
-rw-r--r--node_modules/mongoose/lib/helpers/update/removeUnusedArrayFilters.js18
-rw-r--r--node_modules/mongoose/lib/helpers/updateValidators.js257
-rw-r--r--node_modules/mongoose/lib/index.js1132
-rw-r--r--node_modules/mongoose/lib/internal.js38
-rw-r--r--node_modules/mongoose/lib/model.js4902
-rw-r--r--node_modules/mongoose/lib/options.js14
-rw-r--r--node_modules/mongoose/lib/options/PopulateOptions.js36
-rw-r--r--node_modules/mongoose/lib/options/SchemaArrayOptions.js39
-rw-r--r--node_modules/mongoose/lib/options/SchemaBufferOptions.js38
-rw-r--r--node_modules/mongoose/lib/options/SchemaDateOptions.js64
-rw-r--r--node_modules/mongoose/lib/options/SchemaDocumentArrayOptions.js68
-rw-r--r--node_modules/mongoose/lib/options/SchemaMapOptions.js43
-rw-r--r--node_modules/mongoose/lib/options/SchemaNumberOptions.js74
-rw-r--r--node_modules/mongoose/lib/options/SchemaObjectIdOptions.js38
-rw-r--r--node_modules/mongoose/lib/options/SchemaSingleNestedOptions.js42
-rw-r--r--node_modules/mongoose/lib/options/SchemaStringOptions.js116
-rw-r--r--node_modules/mongoose/lib/options/SchemaTypeOptions.js232
-rw-r--r--node_modules/mongoose/lib/options/VirtualOptions.js164
-rw-r--r--node_modules/mongoose/lib/options/propertyOptions.js8
-rw-r--r--node_modules/mongoose/lib/options/removeOptions.js14
-rw-r--r--node_modules/mongoose/lib/options/saveOptions.js14
-rw-r--r--node_modules/mongoose/lib/plugins/idGetter.js28
-rw-r--r--node_modules/mongoose/lib/plugins/removeSubdocs.js31
-rw-r--r--node_modules/mongoose/lib/plugins/saveSubdocs.js66
-rw-r--r--node_modules/mongoose/lib/plugins/sharding.js83
-rw-r--r--node_modules/mongoose/lib/plugins/trackTransaction.js91
-rw-r--r--node_modules/mongoose/lib/plugins/validateBeforeSave.js45
-rw-r--r--node_modules/mongoose/lib/promise_provider.js49
-rw-r--r--node_modules/mongoose/lib/query.js5380
-rw-r--r--node_modules/mongoose/lib/queryhelpers.js307
-rw-r--r--node_modules/mongoose/lib/schema.js2144
-rw-r--r--node_modules/mongoose/lib/schema/SingleNestedPath.js336
-rw-r--r--node_modules/mongoose/lib/schema/array.js589
-rw-r--r--node_modules/mongoose/lib/schema/boolean.js258
-rw-r--r--node_modules/mongoose/lib/schema/buffer.js276
-rw-r--r--node_modules/mongoose/lib/schema/date.js390
-rw-r--r--node_modules/mongoose/lib/schema/decimal128.js235
-rw-r--r--node_modules/mongoose/lib/schema/documentarray.js546
-rw-r--r--node_modules/mongoose/lib/schema/index.js37
-rw-r--r--node_modules/mongoose/lib/schema/map.js62
-rw-r--r--node_modules/mongoose/lib/schema/mixed.js128
-rw-r--r--node_modules/mongoose/lib/schema/number.js444
-rw-r--r--node_modules/mongoose/lib/schema/objectid.js319
-rw-r--r--node_modules/mongoose/lib/schema/operators/bitwise.js38
-rw-r--r--node_modules/mongoose/lib/schema/operators/exists.js12
-rw-r--r--node_modules/mongoose/lib/schema/operators/geospatial.js107
-rw-r--r--node_modules/mongoose/lib/schema/operators/helpers.js32
-rw-r--r--node_modules/mongoose/lib/schema/operators/text.js39
-rw-r--r--node_modules/mongoose/lib/schema/operators/type.js13
-rw-r--r--node_modules/mongoose/lib/schema/string.js679
-rw-r--r--node_modules/mongoose/lib/schema/symbols.js5
-rw-r--r--node_modules/mongoose/lib/schematype.js1581
-rw-r--r--node_modules/mongoose/lib/statemachine.js180
-rw-r--r--node_modules/mongoose/lib/types/array.js66
-rw-r--r--node_modules/mongoose/lib/types/buffer.js276
-rw-r--r--node_modules/mongoose/lib/types/core_array.js958
-rw-r--r--node_modules/mongoose/lib/types/decimal128.js13
-rw-r--r--node_modules/mongoose/lib/types/documentarray.js421
-rw-r--r--node_modules/mongoose/lib/types/embedded.js446
-rw-r--r--node_modules/mongoose/lib/types/index.js20
-rw-r--r--node_modules/mongoose/lib/types/map.js226
-rw-r--r--node_modules/mongoose/lib/types/objectid.js30
-rw-r--r--node_modules/mongoose/lib/types/subdocument.js292
-rw-r--r--node_modules/mongoose/lib/utils.js908
-rw-r--r--node_modules/mongoose/lib/validoptions.js34
-rw-r--r--node_modules/mongoose/lib/virtualtype.js168
-rw-r--r--node_modules/mongoose/node_modules/ms/index.js162
-rw-r--r--node_modules/mongoose/node_modules/ms/license.md21
-rw-r--r--node_modules/mongoose/node_modules/ms/package.json69
-rw-r--r--node_modules/mongoose/node_modules/ms/readme.md60
-rw-r--r--node_modules/mongoose/node_modules/safe-buffer/LICENSE21
-rw-r--r--node_modules/mongoose/node_modules/safe-buffer/README.md584
-rw-r--r--node_modules/mongoose/node_modules/safe-buffer/index.d.ts187
-rw-r--r--node_modules/mongoose/node_modules/safe-buffer/index.js65
-rw-r--r--node_modules/mongoose/node_modules/safe-buffer/package.json76
-rw-r--r--node_modules/mongoose/package.json256
-rw-r--r--node_modules/mongoose/tools/auth.js30
-rw-r--r--node_modules/mongoose/tools/repl.js36
-rw-r--r--node_modules/mongoose/tools/sharded.js45
223 files changed, 51361 insertions, 0 deletions
diff --git a/node_modules/mongoose/History.md b/node_modules/mongoose/History.md
new file mode 100644
index 0000000..8999e98
--- /dev/null
+++ b/node_modules/mongoose/History.md
@@ -0,0 +1,6054 @@
+5.10.14 / 2020-11-12
+====================
+ * fix(update): handle casting immutable object properties with `$setOnInsert` #9537
+ * fix(discriminator): overwrite instead of merge if discriminator schema specifies a path is single nested but base schema has path as doc array #9534
+ * docs(middleware): clarify that you need to set both `document` and `query` on `remove` hooks to get just document middleware #9530 [mustafaKamal-fe](https://github.com/mustafaKamal-fe)
+ * docs(CONTRIBUTING): remove mmapv1 recommendation and clean up a few other details #9529
+ * refactor: remove duplicate function definition #9527 [ksullivan](https://github.com/ksullivan)
+
+5.10.13 / 2020-11-06
+====================
+ * fix: upgrade mongodb driver -> 3.6.3 for Lambda cold start fixes #9521 #9179 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(document): correctly handle setting props to other nested props #9519
+
+5.10.12 / 2020-11-04
+====================
+ * fix(connection): catch and report sync errors in connection wrappers like `startSession()` #9515
+ * fix(document): ignore getters when diffing values for change tracking #9501
+ * fix(connection): avoid executing promise handler unless it's a function #9507 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(error): throw more helpful error when connecting to a non-SSL MongoDB server with SSL enabled #9511
+ * docs(model+query): clarify that `deleteOne` and `deleteMany` trigger middleware #9504
+ * docs(ssl): add note about `ssl` defaulting to `true` for srv connection strings #9511
+
+5.10.11 / 2020-10-26
+====================
+ * fix(connection): when calling `mongoose.connect()` multiple times in parallel, make 2nd call wait for connection before resolving #9476
+ * fix(map): make `save()` persist `Map#clear()` #9493
+ * fix(document): avoid overwriting array subdocument when setting dotted path that isn't selected #9427
+ * fix(connection): don't throw Atlas error if server discovery doesn't find any servers #9470
+ * docs: update options for Model.findOneAndUpdate #9499 [radamson](https://github.com/radamson)
+
+5.10.10 / 2020-10-23
+====================
+ * fix(schema): handle merging schemas from separate Mongoose module instances when schema has a virtual #9471
+ * fix(connection): make connection.then(...) resolve to a connection instance #9497 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(aggregate): when using $search with discriminators, add `$match` as the 2nd stage in pipeline rather than 1st #9487
+ * fix(query): cast $nor within $elemMatch #9479
+ * docs(connection): add note about 'error' event versus 'disconnected' event #9488 [tareqdayya](https://github.com/tareqdayya)
+
+5.10.9 / 2020-10-09
+===================
+ * fix(update): strip out unused array filters to avoid "filter was not used in the update" error #9468
+ * fix(mongoose): allow setting `autoCreate` as a global option to be consistent with `autoIndex` #9466
+
+5.10.8 / 2020-10-05
+===================
+ * fix(schema): handle setting nested paths underneath single nested subdocs #9459
+ * fix(schema+index): allow calling `mongoose.model()` with schema from a different Mongoose module instance #9449
+ * fix(transaction): fix saving new documents w/ arrays in transactions #9457 [PenguinToast](https://github.com/PenguinToast)
+ * fix(document): track `reason` on cast errors that occur while init-ing a document #9448
+ * fix(model): make `createCollection()` not throw error when collection already exists to be consistent with v5.9 #9447
+ * docs(connections): add SSL connections docs #9443
+ * docs(query_casting): fix typo #9458 [craig-davis](https://github.com/craig-davis)
+
+5.10.7 / 2020-09-24
+===================
+ * fix(schema): set correct path and schema on nested primitive arrays #9429
+ * fix(document): pass document to required validator so `required` can use arrow functions #9435 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(document): handle required when schema has property named `isSelected` #9438
+ * fix(timestamps): allow using timestamps when schema has a property named 'set' #9428
+ * fix(schema): make `Schema#clone()` use parent Mongoose instance's Schema constructor #9426
+
+5.10.6 / 2020-09-18
+===================
+ * fix(populate): handle `options.perDocumentLimit` option same as `perDocumentLimit` when calling `populate()` #9418
+ * fix(document): invalidate path if default function throws an error #9408
+ * fix: ensure subdocument defaults run after initial values are set when initing #9408
+ * docs(faq+queries): add more detail about duplicate queries, including an faq entry #9386
+ * docs: replace var with let and const in docs and test files #9414 [jmadankumar](https://github.com/jmadankumar)
+ * docs(model+query): document using array of strings as projection #9413
+ * docs(middleware): add missing backtick #9425 [tphobe9312](https://github.com/tphobe9312)
+
+5.10.5 / 2020-09-11
+===================
+ * fix: bump mongodb -> 3.6.2 #9411 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(query+aggregate+cursor): support async iteration over a cursor instance as opposed to a Query or Aggregate instance #9403
+ * fix(document): respect child schema `minimize` if `toObject()` is called without an explicit `minimize` #9405
+ * docs(guide): use const instead of var #9394 [nainardev](https://github.com/nainardev)
+ * docs(query): link to lean, findOneAndUpdate, query casting tutorials from query docs #9410
+
+5.10.4 / 2020-09-09
+===================
+ * fix(document): allow setting nested path to instance of model #9392
+ * fix: handle `findOneAndRemove()` with `orFail()` #9381
+ * fix(schema): support setting `_id` option to `false` after instantiating schema #9390
+ * docs(document): fix formatting on `getChanges()` #9376
+
+5.10.3 / 2020-09-03
+===================
+ * fix: upgrade mongodb -> 3.6.1 #9380 [lamhieu-vk](https://github.com/lamhieu-vk)
+ * fix(populate): allow populating paths underneath subdocument maps #9359
+ * fix(update): handle casting map paths when map is underneath a single nested subdoc #9298
+ * fix(discriminator): avoid removing nested path if both base and discriminator schema have the same nested path #9362
+ * fix(schema): support `Schema#add()` with schematype instances with different paths #9370
+ * docs(api): fix typo in `Query#get()` example #9372 [elainewlin](https://github.com/elainewlin)
+
+5.10.2 / 2020-08-28
+===================
+ * fix(model): avoid uncaught error if `insertMany()` fails due to server selection error #9355
+ * fix(aggregate): automatically convert accumulator function options to strings #9364
+ * fix(document): handle `pull()` on a document array when `_id` is an alias #9319
+ * fix(queryhelpers): avoid path collision error when projecting in discriminator key with `.$` #9361
+ * fix: fix typo in error message thrown by unimplemented createIndex #9367 [timhaley94](https://github.com/timhaley94)
+ * docs(plugins): note that plugins should be applied before you call `mongoose.model()` #7723
+
+5.10.1 / 2020-08-26
+===================
+ * fix(mongoose): fix `.then()` is not a function error when calling `mongoose.connect()` multiple times #9358 #9335 #9331
+ * fix: allow calling `create()` after `bulkWrite()` by clearing internal casting context #9350
+ * fix(model): dont wipe out changes made while `save()` is in-flight #9327
+ * fix(populate): skip checking `refPath` if the path to populate is undefined #9340
+ * fix(document): allow accessing document values from function `default` on array #9351
+ * fix(model): skip applying init hook if called with `schema.pre(..., { document: false })` #9316
+ * fix(populate): support `retainNullValues` when setting `_id` to `false` for subdocument #9337 #9336 [FelixRe0](https://github.com/FelixRe0)
+ * docs: update connect example to avoid deprecation warnings #9332 [moander](https://github.com/moander)
+
+5.10.0 / 2020-08-14
+===================
+ * feat: upgrade to MongoDB driver 3.6 for full MongoDB 4.4 support
+ * feat(connection): add `Connection#transaction()` helper that handles resetting Mongoose document state if the transaction fails #8380
+ * feat(connection): make transaction() helper reset array atomics after failed transaction
+ * feat(schema+model): add `optimisticConcurrency` option to use OCC for `save()` #9001 #5424
+ * feat(aggregate): add `Aggregate#search()` for Atlas Text Search #9115
+ * feat(mongoose): add support for setting `setDefaultsOnInsert` as a global option #9036 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * feat(mongoose): add support for setting `returnOriginal` as a global option #9189 #9183 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * feat(mongoose): allow global option mongoose.set('strictQuery', true) #9016 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * feat(document): add Document#getChanges #9097 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * feat(document): support `defaults` option to disable adding defaults to a single document #8271
+ * feat(SingleNestedPath+DocumentArray): add static `set()` function for global options, support setting `_id` globally #8883
+ * feat(query): handle casting `$or` when each clause contains a different discriminator key #9018
+ * feat(query): add overwriteDiscriminatorKey option that allows changing the discriminator key in `findOneAndUpdate()`, `updateOne()`, etc. #6087
+ * fix(connection): make calling `mongoose.connect()` while already connected a no-op #9203
+ * feat(connection): add `getClient()` and `setClient()` function for interacting with a connection's underlying MongoClient instance #9164
+ * feat(document+populate): add `parent()` function that allows you to get the parent document for populated docs #8092
+ * feat(document): add `useProjection` option to `toObject()` and `toJSON()` for hiding deselected fields on newly created documents #9118
+
+5.9.29 / 2020-08-13
+===================
+ * fix(document): support setting nested path to itself when it has nested subpaths #9313
+ * fix(model): make `syncIndexes()` report error if it can't create an index #9303
+ * fix: handle auth error when Atlas username is incorrect #9300
+
+5.9.28 / 2020-08-07
+===================
+ * fix(connection): consistently stop buffering when "reconnected" is emitted #9295
+ * fix(error): ensure `name` and `message` show up on individual ValidatorErrors when calling JSON.stringify() on a ValidationError #9296
+ * fix(document): keeps manually populated paths when setting a nested path to itself #9293
+ * fix(document): allow saving after setting document array to itself #9266
+ * fix(schema): handle `match` schema validator with `/g` flag #9287
+ * docs(guide): refactor transactions examples to async/await #9204
+
+5.9.27 / 2020-07-31
+===================
+ * fix: upgrade mongodb driver -> 3.5.10 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(transactions): make transactions docs use async/await for readability #9204
+
+5.9.26 / 2020-07-27
+===================
+ * fix(document): allow unsetting boolean field by setting the field to `undefined` #9275
+ * fix(document): throw error when overwriting a single nested subdoc changes an immutable path within the subdoc #9281
+ * fix(timestamps): apply timestamps to `bulkWrite()` updates when not using `$set` #9268
+ * fix(browser): upgrade babel to v7 to work around an issue with `extends Error` #9273
+ * fix: make subdocument's `invalidate()` methods have the same return value as top-level document #9271
+ * docs(model): make `create()` docs use async/await, and add another warning about how `create()` with options requires array syntax #9280
+ * docs(connections): clarify that Mongoose can emit 'connected' when reconnecting after losing connectivity #9240
+ * docs(populate): clarify that you can't filter based on foreign document properties when populating #9279
+ * docs(document+model): clarify how `validateModifiedOnly` option works #9263
+ * docs: remove extra poolSize option in comment #9270 [shahvicky](https://github.com/shahvicky)
+ * docs: point bulkWrite() link to mongoose docs instead of localhost #9284
+
+5.9.25 / 2020-07-17
+===================
+ * fix(discriminator): allow passing a compiled model's schema as a parameter to `discriminator()` #9238
+ * fix(connection): throw more readable error when querying db before initial connection when `bufferCommands = false` #9239
+ * fix(indexes): don't unnecessarily drop text indexes when running `syncIndexes()` #9225
+ * fix: make Boolean _castNullish respect omitUndefined #9242 [ehpc](https://github.com/ehpc)
+ * fix(populate): populate single nested discriminator underneath doc array when populated docs have different model but same id #9244
+ * docs(mongoose): correct formatting typo #9247 [JNa0](https://github.com/JNa0)
+
+5.9.24 / 2020-07-13
+===================
+ * fix(connection): respect connection-level `bufferCommands` option if `mongoose.connect()` is called after `mongoose.model()` #9179
+ * fix(document): clear out `priorDoc` after overwriting single nested subdoc so changes after overwrite get persisted correctly #9208
+ * fix(connection): dont overwrite user-specified `bufferMaxEntries` when setting `bufferCommands` #9218
+ * fix(model): allow passing projection to `Model.hydrate()` #9209
+ * fix(schema+document): support adding `null` to schema boolean's `convertToFalse` set #9223
+ * docs(model): make `find` and `findOne()` examples use async/await and clarify `find({})` is find all #9210
+
+4.13.21 / 2020-07-12
+====================
+ * fix(query): delete top-level `_bsontype` property in queries to prevent silent empty queries #8222
+
+5.9.23 / 2020-07-10
+===================
+ * fix(model): fix `syncIndexes()` error when db index has a collation but Mongoose index does not #9224 [clhuang](https://github.com/clhuang)
+ * fix(array): only cast array to proper depth if it contains an non-array value #9217 #9215 [cyrilgandon](https://github.com/cyrilgandon)
+ * docs(schematype): document the `transform` option #9211
+ * docs(mongoose): fix typo #9212 [JNa0](https://github.com/JNa0)
+
+5.9.22 / 2020-07-06
+===================
+ * fix(schema): treat `{ type: mongoose.Schema.Types.Array }` as equivalent to `{ type: Array }` #9194
+ * fix: revert fix for #9107 to avoid issues when calling `connect()` multiple times #9167
+ * fix(update): respect storeSubdocValidationError option with update validators #9172
+ * fix: upgrade to safe-buffer 5.2 #9198
+ * docs: add a note about SSL validation to migration guide #9147
+ * docs(schemas): fix inconsistent header #9196 [samtsai15](https://github.com/samtsai15)
+
+5.9.21 / 2020-07-01
+===================
+ * fix: propagate `typeKey` option to implicitly created schemas from `typePojoToMixed` #9185 [joaoritter](https://github.com/joaoritter)
+ * fix(populate): handle embedded discriminator `refPath` with multiple documents #9153
+ * fix(populate): handle deselected foreign field with `perDocumentLimit` and multiple documents #9175
+ * fix(document): disallow `transform` functions that return promises #9176 #9163 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(document): use strict equality when checking mixed paths for modifications #9165
+ * docs: add target="_blank" to all edit links #9058
+
+5.9.20 / 2020-06-22
+===================
+ * fix(populate): handle populating primitive array under document array discriminator #9148
+ * fix(connection): make sure to close previous connection when calling `openUri()` on an already open connection #9107
+ * fix(model): fix conflicting $setOnInsert default values with `update` values in bulkWrite #9160 #9157 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(validation): add note about validateBeforeSave and invalidate #9144 [dandv](https://github.com/dandv)
+ * docs: specify the array field syntax for invalidate #9137 [dandv](https://github.com/dandv)
+ * docs: fix several typos and broken references #9024 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: fix minor typo #9143 [dandv](https://github.com/dandv)
+
+5.9.19 / 2020-06-15
+===================
+ * fix: upgrade mongodb driver -> 3.5.9 #9124 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix: copy `required` validator on single nested subdoc correctly when calling `Schema#clone()` #8819
+ * fix(discriminator): handle `tiedValue` when casting update on nested paths #9108
+ * fix(model): allow empty arrays for bulkWrite #9132 #9131 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(schema): correctly set partialFilterExpression for nested schema indexes #9091
+ * fix(castArrayFilters): handle casting on all fields of array filter #9122 [lafeuil](https://github.com/lafeuil)
+ * fix(update): handle nested path createdAt when overwriting parent path #9105
+ * docs(subdocs): add some notes on the difference between single nested subdocs and nested paths #9085
+ * docs(subdocs): improve docs on `typePojoToMixed` #9085
+ * docs: add note about connections in `globalSetup` with Jest #9063
+ * docs: add schema and how to set default sub-schema to schematype options #9111 [dfle](https://github.com/dfle)
+ * docs(index): use `const` instead of `var` in examples #9125 [dmcgrouther](https://github.com/dmcgrouther)
+ * docs: corrected markdown typo #9117
+
+5.9.18 / 2020-06-05
+===================
+ * fix: improve atlas error in the event of incorrect password #9095
+ * docs: add edit link for all docs pages #9058
+ * fix(document): allow accessing `$locals` when initializing document #9099 #9098 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(query): make `setDefaultsOnInsert` a mongoose option so it doesn't end up in debug output #9086
+ * docs(connection+index): add serverSelectionTimeoutMS and heartbeatFrequencyMS to `connect()` and `openUri()` options #9071
+ * docs(geojson): add notes about geojson 2dsphere indexes #9044
+ * docs: make active page bold in navbar #9062
+ * docs: correct a typo in a code snippet #9089 [Elvis-Sarfo](https://github.com/Elvis-Sarfo)
+
+5.9.17 / 2020-06-02
+===================
+ * fix(document): avoid tracking changes like `splice()` on slice()-ed arrays #9011
+ * fix(populate): make populating a nested path a no-op #9073
+ * fix(document): clear nested cast errors when overwriting an array path #9080
+ * fix: upgrade mongodb to v3.5.8 #9069 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(document): add validateModifiedOnly to Document#save(), Document#validateSync() and Document#validate() #9078 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(faq): fix typo #9075 [tigransimonyan](https://github.com/tigransimonyan)
+ * docs: document all parameters to .debug #9029 [dandv](https://github.com/dandv)
+ * docs: fix property value in Getters example #9061 [ismet](https://github.com/ismet)
+
+5.9.16 / 2020-05-25
+===================
+ * perf(error): convert errors to classes extending Error for lower CPU overhead #9021 [zbjornson](https://github.com/zbjornson)
+ * fix(query): throw CastError if filter `$and`, `$or`, `$nor` contain non-object values #8948
+ * fix(bulkwrite): cast filter & update to schema after applying timestamps #9030 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(document): don't overwrite defaults with undefined keys in nested documents #9039 [vitorhnn](https://github.com/vitorhnn)
+ * fix(discriminator): remove discriminator schema nested paths pulled from base schema underneath a mixed path in discriminator schema #9042
+ * fix(model): make syncIndexes() not drop index if all user-specified collation options are the same #8994
+ * fix(document): make internal `$__.scope` property a symbol instead to work around a bug with fast-safe-stringify #8955
+ * docs: model.findByIdAndUpdate() 'new' param fix #9026 [dandv](https://github.com/dandv)
+
+5.9.15 / 2020-05-18
+===================
+ * fix(schema): treat creating dotted path with no parent as creating a nested path #9020
+ * fix(documentarray): make sure you can call `unshift()` after `map()` #9012 [philippejer](https://github.com/philippejer)
+ * fix(model): cast bulkwrite according to discriminator schema if discriminator key is present #8982 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(schema): remove `db` from reserved keywords #8940
+ * fix(populate): treat populating a doc array that doesn't have a `ref` as a no-op #8946
+ * fix(timestamps): set createdAt and updatedAt on doubly nested subdocs when upserting #8894
+ * fix(model): allow POJOs as schemas for model.discriminator(...) #8991 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(model): report `insertedDocs` on `insertMany()` errors #8938
+ * fix(model): ensure consistent `writeErrors` property on insertMany error with `ordered: false`, even if only one op failed #8938
+ * docs: add anchor tag to strictQuery and strict #9014 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(faq): remove faq ipv6 #9004
+ * docs: add note about throwing error only after validation and fix broken reference to api/CastError #8993 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: fix typos in documents.pug #9005 [dandv](https://github.com/dandv)
+
+5.9.14 / 2020-05-13
+===================
+ * fix(cursor): add index as second parameter to eachAsync callback #8972 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(query): cast filter according to discriminator schema if discriminator key in filter #8881
+ * fix(model): fix throwing error when populating virtual path defined on child discriminator #8924 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(errors): handle case when user has make `Error.prototype.toJSON` read only #8986 [osher](https://github.com/osher)
+ * fix(model): add `kind` to cast errors thrown by query execution #8953 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(update): use child schema strict on single nested updates if useNestedStrict not set #8922
+ * docs(model): improve `save()` docs #8956 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: add immutable type to Schema Types #8987 [Andrew5569](https://github.com/Andrew5569)
+ * docs: sort schema reserved keys in documentation #8966 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+
+5.9.13 / 2020-05-08
+===================
+ * fix(schema): mark correct path as modified when setting a path underneath a nested array of documents #8926
+ * fix(query): Query#select({ field: false }) should not overwrite schema selection options #8929 #8923
+ * fix(update): handle immutable properties are ignored in bulk upserts #8952 [philippejer](https://github.com/philippejer)
+ * docs(browser): add back sample webpack config #8890
+ * docs(faq): fix broken reference in limit vs perDocumentLimit #8937
+
+5.9.12 / 2020-05-04
+===================
+ * fix(document): report cast error on array elements with array index instead of just being a cast error for the whole array #8888
+ * fix(connection): throw more helpful error in case of IP whitelisting issue with Atlas #8846
+ * fix(schema): throw error on schema with reserved key with type of object #8869 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(connection): inherit config for useDB from default connection #8267 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(query): set mongodb options for `distinct()` #8906 [clhuang](https://github.com/clhuang)
+ * fix(schema): allow adding descending indexes on schema #8895 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(document): set defaults if setting nested path to empty object with `minimize: false` #8829
+ * fix(populate): check discriminator existence before accessing schema in getModelsMapForPopulate #8837 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: fix broken references to Mongoose#Document API, and prefer mongoose.model(...) over Document#model(...) #8914 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(model): adds options.limit to Model.insertMany(...) #8864 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: add flattenMaps and aliases to Document#toObject() #8901 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(model): add options.overwrite to findOneAndUpdate #8865 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(populate+faq): separate limit-vs-perDocumentLimit into its own section, add FAQ for populate and limit #8917 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+
+5.9.11 / 2020-04-30
+===================
+ * fix: upgrade mongodb driver -> 3.5.7 #8842 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix: validate nested paths on Model.validate(...) #8848 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(populate): make doc.execPopulate(options) a shorthand for doc.populate(options).execPopulate() #8840 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(model): return validation errors when all docs are invalid & rawResult set #8853 [tusharf5](https://github.com/tusharf5)
+ * fix(schemaType): treat select: null or select: undefined as not specified #8850 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix: fix stream close event listener being called multiple times in Node 14 #8835 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(populate): handle `clone` with `lean` when setting a path to `null` #8807
+ * docs(faq): clarify setting paths under document arrays with `markModified()` #8854
+ * docs: fix race condition in creating connection for lambda #8845 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: add options.path for Model.populate(...) #8833 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: use ES6 classes for custom schema type example #8802
+
+5.9.10 / 2020-04-20
+===================
+ * fix: upgrade mongodb -> 3.5.6, bson -> 1.1.4 #8719
+ * fix(document): avoid calling `$set()` on object keys if object path isn't in schema #8751
+ * fix(timestamps): handle timestamps on doubly nested subdocuments #8799
+ * fix(schematype): throw error if default is set to a schema instance #8751
+ * fix: handle $elemMatch projection with `select: false` in schema #8818 #8806 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs: make FAQ questions more linkable #8825 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(validation): use `init()` as opposed to `once('index')` in `unique` example #8816
+ * docs: clarify `insertMany()` return value #8820 [dandv](https://github.com/dandv)
+ * docs(populate+query): fix typos #8793 #8794 [dandv](https://github.com/dandv)
+ * docs(model): document skipId parameter #8791 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+
+5.9.9 / 2020-04-13
+==================
+ * fix(model): make Model.bulkWrite accept `strict` option #8782 #8788 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(virtual): make populated virtual getter return value when it is passed in #8775 #8774 [makinde](https://github.com/makinde)
+ * fix(document): handle validating document array whose docs contain maps and nested paths #8767
+ * fix(document): skip discriminator key when overwriting a document #8765
+ * fix(populate): support `clone` option with `lean` #8761 #8760
+ * docs(transactions): use `endSession()` in all transactions examples #8741
+ * docs(queries): expand streaming section to include async iterators, cursor timeouts, and sesssion idle timeouts #8720
+ * docs(model+query+findoneandupdate): add docs for `returnOriginal` option #8766
+ * docs(model): fix punctuation #8788 [dandv](https://github.com/dandv)
+ * docs: fix typos #8780 #8799 [dandv](https://github.com/dandv)
+
+5.9.8 / 2020-04-06
+==================
+ * fix(map): run getters when calling `Map#get()` #8730
+ * fix(populate): handle `refPath` function in embedded discriminator #8731
+ * fix(model): allow setting timestamps to false for bulkWrite #8758 #8745 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(model): pass custom options to `exists()` when no changes to save #8764 #8739 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(update): respect `useNestedStrict: false` when updating a single nested path #8735
+ * fix(schema): allow `modelName` as a schema path, since `modelName` is a static property on models #7967
+ * docs(promises): add section about using `exec()` with queries and `await` #8747
+ * docs(connections): clarify that `connectTimeoutMS` doesn't do anything with `useUnifiedTopology`, should use `serverSelectionTimeoutMS` #8721
+ * chore: upgrade mpath -> 0.7.0 #8762 [roja548](https://github.com/roja548)
+
+5.9.7 / 2020-03-30
+==================
+ * fix(map): avoid infinite loop when setting a map of documents to a document copied using spread operator #8722
+ * fix(query): clean stack trace for filter cast errors so they include the calling file #8691
+ * fix(model): make bulkWrite updates error if `strict` and `upsert` are set and `filter` contains a non-schema path #8698
+ * fix(cast): make internal `castToNumber()` allow undefined #8725 [p3x-robot](https://github.com/p3x-robot)
+
+5.9.6 / 2020-03-23
+==================
+ * fix(document): allow saving document with nested document array after setting `nestedArr.0` #8689
+ * docs(connections): expand section about multiple connections to describe patterns for exporting schemas #8679
+ * docs(populate): add note about `execPopulate()` to "populate an existing document" section #8671 #8275
+ * docs: fix broken links #8690 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(guide): fix typos #8704 [MateRyze](https://github.com/MateRyze)
+ * docs(guide): fix minor typo #8683 [pkellz](https://github.com/pkellz)
+
+5.9.5 / 2020-03-16
+==================
+ * fix: upgrade mongodb driver -> 3.5.5 #8667 #8664 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(connection): emit "disconnected" after losing connectivity to every member of a replica set with `useUnifiedTopology: true` #8643
+ * fix(array): allow calling `slice()` after `push()` #8668 #8655 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(map): avoid marking map as modified if setting `key` to the same value #8652
+ * fix(updateValidators): don't run `Mixed` update validator on dotted path underneath mixed type #8659
+ * fix(populate): ensure top-level `limit` applies if one document being populated has more than `limit` results #8657
+ * fix(populate): throw error if both `limit` and `perDocumentLimit` are set #8661 #8658 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(findOneAndUpdate): add a section about the `rawResult` option #8662
+ * docs(guide): add section about `loadClass()` #8623
+ * docs(query): improve `Query#populate()` example to clarify that `sort` doesn't affect the original result's order #8647
+
+5.9.4 / 2020-03-09
+==================
+ * fix(document): allow `new Model(doc)` to set immutable properties when doc is a mongoose document #8642
+ * fix(array): make sure you can call `unshift()` after `slice()` #8482
+ * fix(schema): propagate `typePojoToMixed` to implicitly created arrays #8627
+ * fix(schema): also propagate `typePojoToMixed` option to schemas implicitly created because of `typePojoToMixed` #8627
+ * fix(model): support passing `background` option to `syncIndexes()` #8645
+ * docs(schema): add a section about the `_id` path in schemas #8625
+ * docs(virtualtype+populate): document using `match` with virtual populate #8616
+ * docs(guide): fix typo #8648 [sauzy34](https://github.com/sauzy34)
+
+5.9.3 / 2020-03-02
+==================
+ * fix: upgrade mongodb driver -> 3.5.4 #8620
+ * fix(document): set subpath defaults when overwriting single nested subdoc #8603
+ * fix(document): make calling `validate()` with single nested subpath only validate that single nested subpath #8626
+ * fix(browser): make `mongoose.model()` return a class in the browser to allow hydrating populated data in the browser #8605
+ * fix(model): make `syncIndexes()` and `cleanIndexes()` drop compound indexes with `_id` that aren't in the schema #8559
+ * docs(connection+index): add warnings to explain that bufferMaxEntries does nothing with `useUnifiedTopology` #8604
+ * docs(document+model+query): add `options.timestamps` parameter docs to `findOneAndUpdate()` and `findByIdAndUpdate()` #8619
+ * docs: fix out of date links to tumblr #8599
+
+5.9.2 / 2020-02-21
+==================
+ * fix(model): add discriminator key to bulkWrite filters #8590
+ * fix(document): when setting nested array path to non-nested array, wrap values top-down rather than bottom up when possible #8544
+ * fix(document): dont leave nested key as undefined when setting nested key to empty object with minimize #8565
+ * fix(document): avoid throwing error if setting path to Mongoose document with nullish `_doc` #8565
+ * fix(update): handle Binary type correctly with `runValidators` #8580
+ * fix(query): run `deleteOne` hooks only on `Document#deleteOne()` when setting `options.document = true` for `Schema#pre()` #8555
+ * fix(document): allow calling `validate()` in post validate hook without causing parallel validation error #8597
+ * fix(virtualtype): correctly copy options when cloning #8587
+ * fix(collection): skip creating capped collection if `autoCreate` set to `false` #8566
+ * docs(middleware): clarify that updateOne and deleteOne hooks are query middleware by default, not document middleware #8581
+ * docs(aggregate): clarify that `Aggregate#unwind()` can take object parameters as well as strings #8594
+
+5.9.1 / 2020-02-14
+==================
+ * fix(model): set session when calling `save()` with no changes #8571
+ * fix(schema): return correct pathType when single nested path is embedded under a nested path with a numeric name #8583
+ * fix(queryhelpers): remove `Object.values()` for Node.js 4.x-6.x support #8596
+ * fix(cursor): respect sort order when using `eachAsync()` with `parallel` and a sync callback #8577
+ * docs: update documentation of custom _id overriding in discriminators #8591 [sam-mfb](https://github.com/sam-mfb)
+
+5.9.0 / 2020-02-13
+==================
+ * fix: upgrade to MongoDB driver 3.5 #8520 #8563
+ * feat(schematype): support setting default options for schema type (`trim` on all strings, etc.) #8487
+ * feat(populate): add `perDocumentLimit` option that limits per document in `find()` result, rather than across all documents #7318
+ * feat(schematype): enable setting `transform` option on individual schematypes #8403
+ * feat(timestamps): allow setting `currentTime` option for setting custom function to get the current time #3957
+ * feat(connection): add `Connection#watch()` to watch for changes on an entire database #8425
+ * feat(document): add `Document#$op` property to make it easier to tell what operation is running in middleware #8439
+ * feat(populate): support `limit` as top-level populate option #8445
+
+5.8.13 / 2020-02-13
+===================
+ * fix(populate): use safe get to avoid crash if schematype doesn't have options #8586
+
+5.8.12 / 2020-02-12
+===================
+ * fix(query): correctly cast dbref `$id` with `$elemMatch` #8577
+ * fix(populate): handle populating when some embedded discriminator schemas have `refPath` but none of the subdocs have `refPath` #8553
+ * docs: add useUnifiedTopology to homepage example #8558 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * refactor(utils): moving promiseOrCallback to helpers/promiseOrCallback #8573 [hugosenari](https://github.com/hugosenari)
+
+5.8.11 / 2020-01-31
+===================
+ * fix(document): allow calling `validate()` multiple times in parallel on subdocs to avoid errors if Mongoose double-validates [taxilian](https://github.com/taxilian) #8548 #8539
+ * fix(connection): allow calling initial `mongoose.connect()` after connection helpers on the same tick #8534
+ * fix(connection): throw helpful error when callback param to `mongoose.connect()` or `mongoose.createConnection()` is not a function #8556
+ * fix(drivers): avoid unnecessary caught error when importing #8528
+ * fix(discriminator): remove unnecessary `utils.merge()` [samgladstone](https://github.com/samgladstone) #8542
+ * docs: add "built with mongoose" page #8540
+
+5.8.10 / 2020-01-27
+===================
+ * perf(document): improve performance of document creation by skipping unnecessary split() calls #8533 [igrunert-atlassian](https://github.com/igrunert-atlassian)
+ * fix(document): only call validate once for deeply nested subdocuments #8532 #8531 [taxilian](https://github.com/taxilian)
+ * fix(document): create document array defaults in forward order, not reverse #8514
+ * fix(document): allow function as message for date min/max validator #8512
+ * fix(populate): don't try to populate embedded discriminator that has populated path but no `refPath` #8527
+ * fix(document): plugins from base schema when creating a discriminator #8536 [samgladstone](https://github.com/samgladstone)
+ * fix(document): ensure parent and ownerDocument are set for subdocs in document array defaults #8509
+ * fix(document): dont set undefined keys to null if minimize is false #8504
+ * fix(update): bump timestamps when using update aggregation pipelines #8524
+ * fix(model): ensure `cleanIndexes()` drops indexes with different collations #8521
+ * docs(model): document `insertMany` `lean` option #8522
+ * docs(connections): document `authSource` option #8517
+
+5.8.9 / 2020-01-17
+==================
+ * fix(populate): skip populating embedded discriminator array values that don't have a `refPath` #8499
+ * docs(queries): clarify when to use queries versus aggregations #8494
+
+5.8.8 / 2020-01-14
+==================
+ * fix(model): allow using `lean` with `insertMany()` #8507 #8234 [ntsekouras](https://github.com/ntsekouras)
+ * fix(document): don't throw parallel validate error when validating subdoc underneath modified nested path #8486
+ * fix: allow `typePojoToMixed` as top-level option #8501 #8500 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(populate+schematypes): make note of `_id` getter for ObjectIds in populate docs #8483
+
+5.8.7 / 2020-01-10
+==================
+ * fix(documentarray): modify ownerDocument when setting doc array to a doc array thats part of another document #8479
+ * fix(document): ensure that you can call `splice()` after `slice()` on an array #8482
+ * docs(populate): improve cross-db populate docs to include model refs #8497
+
+5.8.6 / 2020-01-07
+====================
+ * chore: merge changes from 4.13.20 and override mistaken publish to latest tag
+
+4.13.20 / 2020-01-07
+====================
+ * fix(schema): make aliases handle mongoose-lean-virtuals #6069
+
+5.8.5 / 2020-01-06
+==================
+ * fix(document): throw error when running `validate()` multiple times on the same document #8468
+ * fix(model): ensure deleteOne() and deleteMany() set discriminator filter even if no conditions passed #8471
+ * fix(document): allow pre('validate') hooks to throw errors with `name = 'ValidationError'` #8466
+ * fix(update): move top level $set of immutable properties to $setOnInsert so upserting with immutable properties actually sets the property #8467
+ * fix(document): avoid double-running validators on single nested subdocs within single nested subdocs #8468
+ * fix(populate): support top-level match option for virtual populate #8475
+ * fix(model): avoid applying skip when populating virtual with count #8476
+
+5.8.4 / 2020-01-02
+==================
+ * fix(populate): ensure populate virtual gets set to empty array if `localField` is undefined in the database #8455
+ * fix(connection): wrap `mongoose.connect()` server selection timeouts in MongooseTimeoutError for more readable stack traces #8451
+ * fix(populate): allow deselecting `foreignField` from projection by prefixing with `-` #8460
+ * fix(populate): support embedded discriminators with `refPath` when not all discriminator schemas have `refPath` #8452
+ * fix(array): allow defining `enum` on array if an array of numbers #8449
+
+5.8.3 / 2019-12-23
+==================
+ * fix: upgrade mongodb -> 3.4.1 #8430 [jaschaio](https://github.com/jaschaio)
+ * fix(populate): don't add empty subdocument to array when populating path underneath a non-existent document array #8432
+ * fix(schema): handle `_id` option for document array schematypes #8450
+ * fix(update): call setters when updating mixed type #8444
+ * docs(connections): add note about MongoTimeoutError.reason #8402
+
+5.8.2 / 2019-12-20
+==================
+ * fix(schema): copy `.add()`-ed paths when calling `.add()` with schema argument #8429
+ * fix(cursor): pull schema-level readPreference when using `Query#cursor()` #8421
+ * fix(cursor): wait for all promises to resolve if `parallel` is greater than number of documents #8422
+ * fix(document): depopulate entire array when setting array path to a partially populated array #8443
+ * fix: handle setDefaultsOnInsert with deeply nested subdocs #8392
+ * fix(document): report `DocumentNotFoundError` if underlying document deleted but no changes made #8428 #8371 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(populate): clarify limitations of `limit` option for populate and suggest workaround #8409
+ * docs(deprecations): explain which connection options are no longer relevant with useUnifiedTopology #8411
+ * chore: allow browser build to be published #8435 #8427 [captaincaius](https://github.com/captaincaius)
+
+5.8.1 / 2019-12-12
+==================
+ * fix(documentarray): dont attempt to cast when modifying array returned from map() #8399
+ * fix(document): update single nested subdoc parent when setting to existing single nested doc #8400
+ * fix(schema): add `$embeddedSchemaType` property to arrays for consistency with document arrays #8389
+
+5.8.0 / 2019-12-09
+==================
+ * feat: wrap server selection timeout errors in `MongooseTimeoutError` to retain original stack trace #8259
+ * feat(model): add `Model.validate()` function that validates a POJO against the model's schema #7587
+ * feat(schema): add `Schema#pick()` function to create a new schema with a picked subset of the original schema's paths #8207
+ * feat(schema): add ability to change CastError message using `cast` option to SchemaType #8300
+ * feat(schema): group indexes defined in schema path with the same name #6499
+ * fix(model): build all indexes even if one index fails #8185 [unusualbob](https://github.com/unusualbob)
+ * feat(browser): pre-compile mongoose/browser #8350 [captaincaius](https://github.com/captaincaius)
+ * fix(connection): throw error when setting unsupported option #8335 #6899 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * feat(schema): support `enum` validator for number type #8139
+ * feat(update): allow using MongoDB 4.2 update aggregation pipelines, with no Mongoose casting #8225
+ * fix(update): make update validators run on all subpaths when setting a nested path, even omitted subpaths #3587
+ * feat(schema): support setting `_id` as an option to single nested schema paths #8137
+ * feat(query): add Query#mongooseOptions() function #8296
+ * feat(array): make `MongooseArray#push()` support using `$position` #4322
+ * feat(schema): make pojo paths optionally become subdoc instead of Mixed #8228 [captaincaius](https://github.com/captaincaius)
+ * feat(model): add Model.cleanIndexes() to drop non-schema indexes #6676
+ * feat(document): make `updateOne()` document middleware pass `this` to post hooks #8262
+ * feat(aggregate): run pre/post aggregate hooks on `explain()` #5887
+ * docs(model+query): add `session` option to docs for findOneAndX() methods #8396
+
+5.7.14 / 2019-12-06
+===================
+ * fix(cursor): wait until all `eachAsync()` functions finish before resolving the promise #8352
+ * fix(update): handle embedded discriminator paths when discriminator key is defined in the update #8378
+ * fix(schematype): handle passing `message` function to `SchemaType#validate()` as positional arg #8360
+ * fix(map): handle cloning a schema that has a map of subdocuments #8357
+ * docs(schema): clarify that `uppercase`, `lowercase`, and `trim` options for SchemaString don't affect RegExp queries #8333
+
+5.7.13 / 2019-11-29
+===================
+ * fix: upgrade mongodb driver -> 3.3.5 #8383
+ * fix(model): catch the error when insertMany fails to initialize the document #8365 #8363 [Fonger](https://github.com/Fonger)
+ * fix(schema): add array.$, array.$.$ subpaths for nested arrays #6405
+ * docs(error): add more detail about the ValidatorError class, including properties #8346
+ * docs(connection): document `Connection#models` property #8314
+
+5.7.12 / 2019-11-19
+===================
+ * fix: avoid throwing error if calling `push()` on a doc array with no parent #8351 #8317 #8312 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(connection): only buffer for "open" events when calling connection helper while connecting #8319
+ * fix(connection): pull default database from connection string if specified #8355 #8354 [zachazar](https://github.com/zachazar)
+ * fix(populate+discriminator): handle populating document whose discriminator value is different from discriminator model name #8324
+ * fix: add `mongoose.isValidObjectId()` function to test whether Mongoose can cast a value to an objectid #3823
+ * fix(model): support setting `excludeIndexes` as schema option for subdocs #8343
+ * fix: add SchemaMapOptions class for options to map schematype #8318
+ * docs(query): remove duplicate omitUndefined options #8349 [mdumandag](https://github.com/mdumandag)
+ * docs(schema): add Schema#paths docs to public API docs #8340
+
+5.7.11 / 2019-11-14
+===================
+ * fix: update mongodb driver -> 3.3.4 #8276
+ * fix(model): throw readable error when casting bulkWrite update without a 'filter' or 'update' #8332 #8331 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(connection): bubble up connected/disconnected events with unified topology #8338 #8337
+ * fix(model): delete $versionError after saving #8326 #8048 [Fonger](https://github.com/Fonger)
+ * test(model): add test for issue #8040 #8341 [Fonger](https://github.com/Fonger)
+
+5.7.10 / 2019-11-11
+===================
+ * perf(cursor): remove unnecessary `setTimeout()` in `eachAsync()`, 4x speedup in basic benchmarks #8310
+ * docs(README): re-order sections for better readability #8321 [dandv](https://github.com/dandv)
+ * chore: make npm test not hard-code file paths #8322 [stieg](https://github.com/stieg)
+
+5.7.9 / 2019-11-08
+==================
+ * fix(schema): support setting schema path to an instance of SchemaTypeOptions to fix integration with mongoose-i18n-localize #8297 #8292
+ * fix(populate): make `retainNullValues` set array element to `null` if foreign doc with that id was not found #8293
+ * fix(document): support getter setting virtual on manually populated doc when calling toJSON() #8295
+ * fix(model): allow objects with `toBSON()` to make it to `save()` #8299
+
+5.7.8 / 2019-11-04
+==================
+ * fix(document): allow manually populating path within document array #8273
+ * fix(populate): update top-level `populated()` when updating document array with populated subpaths #8265
+ * fix(cursor): throw error when using aggregation cursor as async iterator #8280
+ * fix(schema): retain `_id: false` in schema after nesting in another schema #8274
+ * fix(document): make Document class an event emitter to support defining documents without models in node #8272
+ * docs: document return types for `.discriminator()` #8287
+ * docs(connection): add note about exporting schemas, not models, in multi connection paradigm #8275
+ * docs: clarify that transforms defined in `toObject()` options are applied to subdocs #8260
+
+5.7.7 / 2019-10-24
+==================
+ * fix(populate): make populate virtual consistently an empty array if local field is only empty arrays #8230
+ * fix(query): allow findOne(objectid) and find(objectid) #8268
+
+5.7.6 / 2019-10-21
+==================
+ * fix: upgrade mongodb driver -> 3.3.3 to fix issue with failing to connect to a replica set if one member is down #8209
+ * fix(document): fix TypeError when setting a single nested subdoc with timestamps #8251
+ * fix(cursor): fix issue with long-running `eachAsync()` cursor #8249 #8235
+ * fix(connection): ensure repeated `close` events from useUnifiedTopology don't disconnect Mongoose from replica set #8224
+ * fix(document): support calling `Document` constructor directly in Node.js #8237
+ * fix(populate): add document array subpaths to parent doc `populated()` when calling `DocumentArray#push()` #8247
+ * fix(options): add missing minlength and maxlength to SchemaStringOptions #8256
+ * docs: add documentarraypath to API docs, including DocumentArrayPath#discriminator() #8164
+ * docs(schematypes): add a section about the `type` property #8227
+ * docs(api): fix Connection.close return param #8258 [gosuhiman](https://github.com/gosuhiman)
+ * docs: update link to broken image on home page #8253 [krosenk729](https://github.com/krosenk729)
+
+5.7.5 / 2019-10-14
+==================
+ * fix(query): delete top-level `_bsontype` property in queries to prevent silent empty queries #8222
+ * fix(update): handle subdocument pre('validate') errors in update validation #7187
+ * fix(subdocument): make subdocument#isModified use parent document's isModified #8223
+ * docs(index): add favicon to home page #8226
+ * docs: add schema options to API docs #8012
+ * docs(middleware): add note about accessing the document being updated in pre('findOneAndUpdate') #8218
+ * refactor: remove redundant code in ValidationError #8244 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+
+5.7.4 / 2019-10-09
+==================
+ * fix(schema): handle `required: null` and `required: undefined` as `required: false` #8219
+ * fix(update): support updating array embedded discriminator props if discriminator key in $elemMatch #8063
+ * fix(populate): allow accessing populate virtual prop underneath array when virtual defined on top level #8198
+ * fix(model): support passing `options` to `Model.remove()` #8211
+ * fix(document): handle `Document#set()` merge option when setting underneath single nested schema #8201
+ * fix: use options constructor class for all schematypes #8012
+
+5.7.3 / 2019-09-30
+==================
+ * fix: make CoreMongooseArray#includes() handle `fromIndex` parameter #8203
+ * fix(update): cast right hand side of `$pull` as a query instead of an update for document arrays #8166
+ * fix(populate): handle virtual populate of an embedded discriminator nested path #8173
+ * docs(validation): remove deprecated `isAsync` from validation docs in favor of emphasizing promises #8184
+ * docs(documents): add overwriting section #8178
+ * docs(promises): add note about queries being thenable #8110
+ * perf: avoid update validators going into Mixed types #8192 [birdofpreyru](https://github.com/birdofpreyru)
+ * refactor: remove async as a prod dependency #8073
+
+5.7.2 / 2019-09-23
+==================
+ * fix(mongoose): support `mongoose.set('autoIndex', false)` #8158
+ * fix(discriminator): support `tiedValue` parameter for embedded discriminators analagous to top-level discriminators #8164
+ * fix(query): handle `toConstructor()` with entries-style sort syntax #8159
+ * fix(populate): avoid converting mixed paths into arrays if populating an object path under `Mixed` #8157
+ * fix: use $wrapCallback when using promises for mongoose-async-hooks
+ * fix: handle queries with setter that converts value to Number instance #8150
+ * docs: add mongoosejs-cli to readme #8142
+ * docs: fix example typo for Schema.prototype.plugin() #8175 [anaethoss](https://github.com/anaethoss)
+
+5.7.1 / 2019-09-13
+==================
+ * fix(query): fix TypeError when calling `findOneAndUpdate()` with `runValidators` #8151 [fernandolguevara](https://github.com/fernandolguevara)
+ * fix(document): throw strict mode error if setting an immutable path with strict mode: false #8149
+ * fix(mongoose): support passing options object to Mongoose constructor #8144
+ * fix(model): make syncIndexes() handle changes in index key order #8135
+ * fix(error): export StrictModeError as a static property of MongooseError #8148 [ouyuran](https://github.com/ouyuran)
+ * docs(connection+mongoose): add `useUnifiedTopology` option to `connect()` and `openUri()` docs #8146
+
+5.7.0 / 2019-09-09
+==================
+ * feat(document+query): support conditionally immutable schema paths #8001
+ * perf(documentarray): refactor to use ES6 classes instead of mixins, ~30% speedup #7895
+ * feat: use MongoDB driver 3.3.x for MongoDB 4.2 support #8083 #8078
+ * feat(schema+query): add pre('validate') and post('validate') hooks for update validation #7984
+ * fix(timestamps): ensure updatedAt gets incremented consistently using update with and without $set #4768
+ * feat(query): add `Query#get()` to make writing custom setters that handle both queries and documents easier #7312
+ * feat(document): run setters on defaults #8012
+ * feat(document): add `aliases: false` option to `Document#toObject()` #7548
+ * feat(timestamps): support skipping updatedAt and createdAt for individual save() and update() #3934
+ * docs: fix index creation link in guide #8138 [joebowbeer](https://github.com/joebowbeer)
+
+5.6.13 / 2019-09-04
+===================
+ * fix(parallel): fix parallelLimit when fns is empty #8130 #8128 [sibelius](https://github.com/sibelius)
+ * fix(document): ensure nested mixed validator gets called exactly once #8117
+ * fix(populate): handle `justOne = undefined` #8125 [taxilian](https://github.com/taxilian)
+
+5.6.12 / 2019-09-03
+===================
+ * fix(schema): handle required validator correctly with `clone()` #8111
+ * fix(schema): copy schematype getters and setters when cloning #8124 [StphnDamon](https://github.com/StphnDamon)
+ * fix(discriminator): avoid unnecessarily cloning schema to avoid leaking memory on repeated `discriminator()` calls #2874
+ * docs(schematypes): clarify when Mongoose uses `toString()` to convert an object to a string #8112 [TheTrueRandom](https://github.com/TheTrueRandom)
+ * docs(plugins): fix out of date link to npm docs #8100
+ * docs(deprecations): fix typo #8109 [jgcmarins](https://github.com/jgcmarins)
+ * refactor(model): remove dependency on `async.parallelLimit()` for `insertMany()` #8073
+
+5.6.11 / 2019-08-25
+===================
+ * fix(model): allow passing options to `exists()` #8075
+ * fix(document): make `validateUpdatedOnly` option handle pre-existing errors #8091
+ * fix: throw readable error if middleware callback isnt a function #8087
+ * fix: don't throw error if calling `find()` on a nested array #8089
+ * docs(middleware): clarify that you must add middleware before compiling your model #5087
+ * docs(query): add missing options to `setOptions()` #8099
+
+5.6.10 / 2019-08-20
+===================
+ * fix(schema): fix require() path to work around yet another bug in Jest #8053
+ * fix(document): skip casting when initing a populated path #8062
+ * fix(document): prevent double-calling validators on mixed objects with nested properties #8067
+ * fix(query): handle schematype with `null` options when checking immutability #8070 [rich-earth](https://github.com/rich-earth)
+ * fix(schema): support `Schema#path()` to get schema path underneath doc array #8057
+ * docs(faq): add disable color instruction #8066
+
+5.6.9 / 2019-08-07
+==================
+ * fix(model): delete versionError after saving to prevent memory leak #8048
+ * fix(cursor): correctly handle batchSize option with query cursor #8039
+ * fix(populate): handle virtual populate with count = 0 if virtual embedded in doc array #7573
+ * fix(schema): allow declaring ObjectId array with `{ type: 'ObjectID' }`, last 'D' case insensitive #8034
+
+5.6.8 / 2019-08-02
+==================
+ * fix(aggregate): allow modifying pipeline in pre('aggregate') hooks #8017
+ * fix(query): make `findOneAndReplace()` work with `orFail()` #8030
+ * fix(document): allow saving an unchanged document if required populated path is null #8018
+ * fix(debug): support disabling colors in debug mode #8033 [Mangosteen-Yang](https://github.com/Mangosteen-Yang)
+ * docs: add async-await guide #8028 [Rossh87](https://github.com/Rossh87)
+ * docs(plugins): rewrite plugins docs to be more modern and not use strange `= exports` syntax #8026
+ * docs(transactions): clarify relationship between `session` in docs and MongoDB driver ClientSession class, link to driver docs #8009
+
+5.6.7 / 2019-07-26
+==================
+ * fix(document): support validators on nested arrays #7926
+ * fix(timestamps): handle `timestamps: false` in child schema #8007
+ * fix(query): consistently support `new` option to `findOneAndX()` as an alternative to `returnOriginal` #7846
+ * fix(document): make `inspect()` never return `null`, because a document or nested path is never `== null` #7942
+ * docs(query+lean): add links to mongoose-lean-virtuals, mongoose-lean-getters, mongoose-lean-defaults #5606
+ * docs: add example for `Schema#pre(Array)` #8022 [Mangosteen-Yang](https://github.com/Mangosteen-Yang)
+ * docs(schematype): updated comment from Schema.path to proper s.path #8013 [chrisweilacker](https://github.com/chrisweilacker)
+ * chore: upgrade nyc #8015 [kolya182](https://github.com/kolya182)
+
+5.6.6 / 2019-07-22
+==================
+ * fix(populate): handle refPath returning a virtual with `Query#populate()` #7341
+ * fix(populate): handle `refPath` in discriminator when populating top-level model #5109
+ * fix(mongoose): ensure destucturing and named imports work for Mongoose singleton methods like `set()`, etc. #6039
+ * fix(query): add missing options for deleteOne and deleteMany in Query #8004 [Fonger](https://github.com/Fonger)
+ * fix(schema): make embedded discriminators `instanceof` their parent types #5005
+ * fix(array): make `validators` a private property that doesn't show up in for/in #6572
+ * docs(api): fix array API docs that vanished because of #7798 #7979
+ * docs(discriminators+api): add single nested discriminator to discriminator docs and API docs #7983
+ * docs(connection+mongoose): make option lists consistent between `mongoose.connect()`, `mongoose.createConnection()`, and `conn.openUri()` #7976
+ * docs(validation): clarify resolve(false) vs reject() for promise-based async custom validators #7761
+ * docs(guide): use correct `mongoose.set()` instead of `mongoose.use()` #7998
+ * docs: add redis cache example #7997 [usama-asfar](https://github.com/usama-asfar)
+
+5.6.5 / 2019-07-17
+==================
+ * fix(document): handle setting non-schema path to ObjectId or Decimal128 if strict: false #7973
+ * fix(connection): remove backwards-breaking multiple mongoose.connect() call for now #7977
+ * fix(schema): print invalid value in error message when a schema path is set to undefined or null #7956
+ * fix(model): throw readable error if calling `new Model.discriminator()` #7957
+ * fix(mongoose): export `cast()` function #7975 [perfectstorm88](https://github.com/perfectstorm88)
+ * docs(model): fix link to Model.inspect() and add example #7990
+ * docs: fix broken anchor links on validation tutorial #7966
+ * docs(api): fix broken links to split API pages #7978
+ * chore: create LICENSE.md #7989 [Fonger](https://github.com/Fonger)
+
+5.6.4 / 2019-07-08
+==================
+ * fix(schema): support pre(Array, Function) and post(Array, Function) #7803
+ * fix(document): load docs with a `once` property successfully #7958
+ * fix(queryhelpers): ensure parent `select` overwrites child path `select` if parent is nested #7945
+ * fix(schema): make `clone()` correctly copy array embedded discriminators #7954
+ * fix(update): fix error when update property gets casted to null #7949
+ * fix(connection): bubble up attemptReconnect event for now #7872
+ * docs(tutorials): add virtuals tutorial #7965
+ * docs(connection): add section on connection handling #6997
+
+5.6.3 / 2019-07-03
+==================
+ * fix(document): respect projection when running getters #7940
+ * fix(model): call createCollection() in syncIndexes() to ensure the collection exists #7931
+ * fix(document): consistently use post-order traversal for gathering subdocs for hooks #7929
+ * fix(schema): ensure `Schema#pathType()` returns correct path type given non-existent positional path #7935
+ * fix(ChangeStream): set `closed` if emitting close event #7930
+ * fix(connection): bubble up 'attemptReconnect' event from MongoDB connection #7872
+ * docs: fix broken .jade links on search page #7932
+ * docs: correct link to `Query#select()` #7953 [rayhatfield](https://github.com/rayhatfield)
+ * docs(README): add list of related projects #7773
+
+4.13.19 / 2019-07-02
+====================
+ * fix(aggregate): make `setOptions()` work as advertised #7950 #6011 [cdimitroulas](https://github.com/cdimitroulas)
+
+5.6.2 / 2019-06-28
+==================
+ * fix(update): allow using `update()` with immutable `createdAt` #7917
+ * fix(model): pass `doc` parameter to save() error handling middleware #7832
+ * fix(mongoose): add applyPluginsToChildSchemas option to allow opting out of global plugins for child schemas #7916
+ * docs(connection): document `useCache` option for `useDb()` #7923
+ * docs: fix broken link in FAQ #7925 [christophergeiger3](https://github.com/christophergeiger3)
+
+5.6.1 / 2019-06-24
+==================
+ * fix(update): skip setting defaults for single embedded subdocs underneath maps #7909
+ * fix(document): copy date objects correctly when strict = false #7907
+ * feat(mongoose): throw an error if calling `mongoose.connect()` multiple times while connected #7905 [Fonger](https://github.com/Fonger)
+ * fix(document): copies virtuals from array subdocs when casting array of docs with same schema #7898
+ * fix(schema): ensure clone() copies single embedded discriminators correctly #7894
+ * fix(discriminator): merge instead of overwriting conflicting nested schemas in discriminator schema #7884
+ * fix(populate): ignore nullish arguments when calling `populate()` #7913 [rayhatfield](https://github.com/rayhatfield)
+ * docs: add getters/setters tutorial #7919
+ * docs: clean up error docs so they refer to `Error` rather than `MongooseError` #7867
+ * docs: fix a couple broken links #7921 [kizmo04](https://github.com/kizmo04)
+ * refactor: remove unnecessary if #7911 [rayhatfield](https://github.com/rayhatfield)
+
+5.6.0 / 2019-06-14
+==================
+ * feat(schematype): add `immutable` option to disallow changing a given field #7671
+ * docs: split API docs into separate pages to make API documentation more Google-able #7812
+ * perf(array): remove all mixins in favor of ES6 classes, ~20% faster in basic benchmarks #7798
+ * feat(document): use promise rejection error message when async custom validator throws an error #4913
+ * feat(virtual): pass document as 3rd parameter to virtual getters and setters to enable using arrow functions #4143
+ * feat(model): add `Model.exists()` function to quickly check whether a document matching `filter` exists #6872
+ * feat(index+connection): support setting global and connection-level `maxTimeMS`
+ * feat(populate): support setting `ref` to a function for conventional populate #7669
+ * feat(document): add overwrite() function that overwrites all values in a document #7830
+ * feat(populate): support `PopulateOptions#connection` option to allow cross-db populate with refPath #6520
+ * feat(populate): add skipInvalidIds option to silently skip population if id is invalid, instead of throwing #7706
+ * feat(array): skip empty array default if there's a 2dsphere index on a geojson path #3233
+ * feat(query): add `getFilter()` as an alias of `getQuery()` to be more in line with API docs #7839
+ * feat(model): add Model.inspect() to make models not clutter `util.inspect()` #7836
+ * perf(discriminator): skip calling `createIndex()` on indexes that are defined in the base schema #7379
+ * docs: upgrade from Jade to latest Pug #7812
+ * docs(README): update reference to example schema.js #7899 [sharils](https://github.com/sharils)
+ * docs(README): improve variable name #7900 [sharils](https://github.com/sharils)
+ * chore: replace charAt(0) with startsWith #7897 [Fonger](https://github.com/Fonger)
+ * chore: replace indexOf with includes, startsWith and endsWith for String #7897 [Fonger](https://github.com/Fonger)
+
+5.5.15 / 2019-06-12
+===================
+ * fix(connection): reject initial connect promise even if there is an on('error') listener #7850
+ * fix(map): make `of` automatically convert POJOs to schemas unless typeKey is set #7859
+ * fix(update): use discriminator schema to cast update if discriminator key specified in filter #7843
+ * fix(array): copy atomics from source array #7891 #7889 [jyrkive](https://github.com/jyrkive)
+ * fix(schema): return this when Schema.prototype.add is called with Schema #7887 [Mickael-van-der-Beek](https://github.com/Mickael-van-der-Beek)
+ * fix(document): add `numAffected` and `result` to DocumentNotFoundError for better debugging #7892 #7844
+
+5.5.14 / 2019-06-08
+===================
+ * fix(query): correct this scope of setters in update query #7876 [Fonger](https://github.com/Fonger)
+ * fix(model): reset modifiedPaths after successful insertMany #7852 #7873 [Fonger](https://github.com/Fonger)
+ * fix(populate): allow using `refPath` with virtual populate #7848
+ * fix(document): prepend private methods getValue and setValue with $ #7870 [Fonger](https://github.com/Fonger)
+ * fix: update mongodb driver -> 3.2.7 #7871 [Fonger](https://github.com/Fonger)
+ * docs(tutorials): add tutorial about custom casting functions #7045
+ * docs(connection): fix outdated events document #7874 [Fonger](https://github.com/Fonger)
+ * docs: fix typo in lean docs #7875 [tannakartikey](https://github.com/tannakartikey)
+ * docs: move off of KeenIO for tracking and use self-hosted analytics instead
+
+5.5.13 / 2019-06-05
+===================
+ * fix(model): support passing deleteOne options #7860 #7857 [Fonger](https://github.com/Fonger)
+ * fix(update): run setters on array elements when doing $addToSet, $push, etc #4185
+ * fix(model): support getting discriminator by value when creating a new model #7851
+ * docs(transactions): add section about the `withTransaction()` helper #7598
+ * docs(schema): clarify relationship between Schema#static() and Schema#statics #7827
+ * docs(model): fix typo `projetion` to `projection` #7868 [dfdeagle47](https://github.com/dfdeagle47)
+ * docs(schema): correct schema options lists #7828
+
+5.5.12 / 2019-05-31
+===================
+ * fix(document): fix unexpected error when loading a document with a nested property named `schema` #7831
+ * fix(model): skip applying static hooks by default if static name conflicts with query middleware (re: mongoose-delete plugin) #7790
+ * fix(query): apply schema-level projections to the result of `findOneAndReplace()` #7654
+ * fix: upgrade mongodb driver -> 3.2.6
+ * docs(tutorials): add findOneAndUpdate() tutorial #7847
+ * docs(validation): add `updateOne()` and `updateMany()` to list of update validator operations #7845
+ * docs(model): make sure options lists in `update()` API line up #7842
+
+5.5.11 / 2019-05-23
+===================
+ * fix(discriminator): allow numeric discriminator keys for embedded discriminators #7808
+ * chore: add Node.js 12 to travis build matrix #7784
+
+5.5.10 / 2019-05-20
+===================
+ * fix(discriminator): allow user-defined discriminator path in schema #7807
+ * fix(query): ensure `findOneAndReplace()` sends `replacement` to server #7654
+ * fix(cast): allow `[]` as a value when casting `$nin` #7806
+ * docs(model): clarify that setters do run on `update()` by default #7801
+ * docs: fix typo in FAQ #7821 [jaona](https://github.com/jaona)
+
+5.5.9 / 2019-05-16
+==================
+ * fix(query): skip schema setters when casting $regexp $options #7802 [Fonger](https://github.com/Fonger)
+ * fix(populate): don't skip populating doc array properties whose name conflicts with an array method #7782
+ * fix(populate): make populated virtual return undefined if not populated #7795
+ * fix(schema): handle custom setters in arrays of document arrays #7804 [Fonger](https://github.com/Fonger)
+ * docs(tutorials): add query casting tutorial #7789
+
+5.5.8 / 2019-05-13
+==================
+ * fix(document): run pre save hooks on nested child schemas #7792
+ * fix(model): set $session() before validation middleware for bulkWrite/insertMany #7785 #7769 [Fonger](https://github.com/Fonger)
+ * fix(query): make `getPopulatedPaths()` return deeply populated paths #7757
+ * fix(query): suppress findAndModify deprecation warning when using `Model.findOneAndUpdate()` #7794
+ * fix: upgrade mongodb -> 3.2.4 #7794
+ * fix(document): handle a couple edge cases with atomics that happen when schema defines an array property named 'undefined' #7756
+ * docs(discriminator): correct function parameters #7786 [gfpacheco](https://github.com/gfpacheco)
+
+5.5.7 / 2019-05-09
+==================
+ * fix(model): set $session() before pre save middleware runs when calling save() with options #7742
+ * fix(model): set $session before pre remove hooks run when calling remove() with options #7742
+ * fix(schema): support `remove()` on nested path #2398
+ * fix(map): handle setting populated map element to doc #7745
+ * fix(query): return rawResult when inserting with options `{new:false,upsert:true,rawResult:true}` #7774 #7770 [LiaanM](https://github.com/LiaanM)
+ * fix(schematype): remove internal `validators` option because it conflicts with Backbone #7720
+
+5.5.6 / 2019-05-06
+==================
+ * fix(document): stop converting arrays to objects when setting non-schema path to array with strict: false #7733
+ * fix(array): make two Mongoose arrays `assert.deepEqual()` each other if they have the same values #7700
+ * fix(populate): support populating a path in a document array embedded in an array #7647
+ * fix(populate): set populate virtual count to 0 if local field is empty #7731
+ * fix(update): avoid throwing cast error if casting array filter that isn't in schema with strictQuery = false #7728
+ * docs: fix typo in `distinct()` description #7767 [phil-r](https://github.com/phil-r)
+
+5.5.5 / 2019-04-30
+==================
+ * fix(document): ensure nested properties within single nested subdocs get set correctly when overwriting single nested subdoc #7748
+ * fix(document): skip non-object `validators` in schema types #7720
+ * fix: bump mongodb driver -> 3.2.3 #7752
+ * fix(map): disallow setting map key with special properties #7750 [Fonger](https://github.com/Fonger)
+
+5.5.4 / 2019-04-25
+==================
+ * fix(document): avoid calling custom getters when saving #7719
+ * fix(timestamps): handle child schema timestamps correctly when reusing child schemas #7712
+ * fix(query): pass correct callback for _legacyFindAndModify #7736 [Fonger](https://github.com/Fonger)
+ * fix(model+query): allow setting `replacement` parameter for `findOneAndReplace()` #7654
+ * fix(map): make `delete()` unset the key in the database #7746 [Fonger](https://github.com/Fonger)
+ * fix(array): use symbol for `_schema` property to avoid confusing deep equality checks #7700
+ * fix(document): prevent `depopulate()` from removing fields with empty array #7741 #7740 [Fonger](https://github.com/Fonger)
+ * fix: make `MongooseArray#includes` support ObjectIds #7732 #6354 [hansemannn](https://github.com/hansemannn)
+ * fix(document): report correct validation error index when pushing onto doc array #7744 [Fonger](https://github.com/Fonger)
+
+5.5.3 / 2019-04-22
+==================
+ * fix: add findAndModify deprecation warning that references the useFindAndModify option #7644
+ * fix(document): handle pushing a doc onto a discriminator that contains a doc array #7704
+ * fix(update): run setters on array elements when doing $set #7679
+ * fix: correct usage of arguments while buffering commands #7718 [rzymek](https://github.com/rzymek)
+ * fix(document): avoid error clearing modified subpaths if doc not defined #7715 [bitflower](https://github.com/bitflower)
+ * refactor(array): move `_parent` property behind a symbol #7726 #7700
+ * docs(model): list out all operations and options for `bulkWrite()` #7055
+ * docs(aggregate): use `eachAsync()` instead of nonexistent `each()` #7699
+ * docs(validation): add CastError validation example #7514
+ * docs(query+model): list out all options and callback details for Model.updateX() and Query#updateX() #7646
+
+5.5.2 / 2019-04-16
+==================
+ * fix(document): support setting nested path to non-POJO object #7639
+ * perf(connection): remove leaked event handler in `Model.init()` so `deleteModel()` frees all memory #7682
+ * fix(timestamps): handle custom statics that conflict with built-in functions (like mongoose-delete plugin) #7698
+ * fix(populate): make `Document#populated()` work for populated subdocs #7685
+ * fix(document): support `.set()` on document array underneath embedded discriminator path #7656
+
+5.5.1 / 2019-04-11
+==================
+ * fix(document): correctly overwrite all properties when setting a single nested subdoc #7660 #7681
+ * fix(array): allow customization of array required validator #7696 [freewil](https://github.com/freewil)
+ * fix(discriminator): handle embedded discriminators when casting array defaults #7687
+ * fix(collection): ensure collection functions return a promise even if disconnected #7676
+ * fix(schematype): avoid indexing properties with `{ unique: false, index: false }` #7620
+ * fix(aggregate): make `Aggregate#model()` with no arguments return the aggregation's model #7608
+
+5.5.0 / 2019-04-08
+==================
+ * feat(model): support applying hooks to custom static functions #5982
+ * feat(populate): support specifying a function as `match` #7397
+ * perf(buffer): avoid calling `defineProperties()` in Buffer constructor #7331
+ * feat(connection): add `plugin()` for connection-scoped plugins #7378
+ * feat(model): add Model#deleteOne() and corresponding hooks #7538
+ * feat(query): support hooks for `Query#distinct()` #5938
+ * feat(model): print warning when calling create() incorrectly with a session #7535
+ * feat(document): add Document#isEmpty() and corresponding helpers for nested paths #5369
+ * feat(document): add `getters` option to Document#get() #7233
+ * feat(query): add Query#projection() to get or overwrite the current projection #7384
+ * fix(document): set full validator path on validatorProperties if `propsParameter` set on validator #7447
+ * feat(document): add Document#directModifiedPaths() #7373
+ * feat(document): add $locals property #7691
+ * feat(document): add validateUpdatedOnly option that only validates modified paths in `save()` #7492 [captaincaius](https://github.com/captaincaius)
+ * chore: upgrade MongoDB driver to v3.2.0 #7641
+ * fix(schematype): deprecate `isAsync` option for custom validators #6700
+ * chore(mongoose): deprecate global.MONGOOSE_DRIVER_PATH so we can be webpack-warning-free in 6.0 #7501
+
+5.4.23 / 2019-04-08
+===================
+ * fix(document): report cast error when string path in schema is an array in MongoDB #7619
+ * fix(query): set deletedCount on result of remove() #7629
+ * docs(subdocs): add note about parent() and ownerDocument() to subdocument docs #7576
+
+5.4.22 / 2019-04-04
+===================
+ * fix(aggregate): allow modifying options in pre('aggregate') hook #7606
+ * fix(map): correctly init maps of maps when loading from MongoDB #7630
+ * docs(model+query): add `omitUndefined` option to docs for updateX() and findOneAndX() #3486
+ * docs: removed duplicate Query.prototype.merge() reference from doc #7684 [shihabmridha](https://github.com/shihabmridha)
+ * docs(schema): fix shardKey type to object instead of bool #7668 [kyletsang](https://github.com/kyletsang)
+ * docs(api): fix `Model.prototypedelete` link #7665 [pixcai](https://github.com/pixcai)
+
+5.4.21 / 2019-04-02
+===================
+ * fix(updateValidators): run update validators correctly on Decimal128 paths #7561
+ * fix(update): cast array filters in nested doc arrays correctly #7603
+ * fix(document): allow .get() + .set() with aliased paths #7592
+ * fix(document): ensure custom getters on single nested subdocs don't get persisted if toObject.getters = true #7601
+ * fix(document): support setting subdoc path to subdoc copied using object rest `{...doc}` #7645
+ * docs(schema): correct out-of-date list of reserved words #7593
+ * docs(model+query): add link to update results docs and examples of using results of updateOne(), etc. #7582
+ * docs: use atomic as opposed to $atomic consistently #7649 [720degreeLotus](https://github.com/720degreeLotus)
+
+5.4.20 / 2019-03-25
+===================
+ * docs(tutorials): add tutorial about `lean()` #7640
+ * fix(discriminator): fix wrong modelName being used as value to partialFilterExpression index #7635 #7634 [egorovli](https://github.com/egorovli)
+ * fix(document): allow setters to modify `this` when overwriting single nested subdoc #7585
+ * fix(populate): handle count option correctly with multiple docs #7573
+ * fix(date): support declaring min/max validators as functions #7600 [ChienDevIT](https://github.com/ChienDevIT)
+ * fix(discriminator): avoid projecting in embedded discriminator if only auto-selected path is discriminator key #7574
+ * fix(discriminator): use discriminator model when using `new BaseModel()` with discriminator key #7586
+ * fix(timestamps): avoid throwing if doc array has timestamps and array is undefined #7625 [serg33v](https://github.com/serg33v)
+ * docs(document): explain DocumentNotFoundError in save() docs #7580
+ * docs(query): fix .all() param type and add example #7612 [720degreeLotus](https://github.com/720degreeLotus)
+ * docs: add useNewUrlParser to mongoose.connect for some pages #7615 [YC](https://github.com/YC)
+
+5.4.19 / 2019-03-11
+===================
+ * fix(mongoose): ensure virtuals set on subdocs in global plugins get applied #7572
+ * docs(tutorials): add "Working With Dates" tutorial #7597
+ * docs(guide): clarify that versioning only affects array fields #7555
+ * docs(model): list out all bulkWrite() options #7550
+
+5.4.18 / 2019-03-08
+===================
+ * fix(document): handle nested virtuals in populated docs when parent path is projected out #7491
+ * fix(model): make subclassed models handle discriminators correctly #7547
+ * fix(model): remove $versionError from save options for better debug output #7570
+
+5.4.17 / 2019-03-03
+===================
+ * fix(update): handle all positional operator when casting array filters #7540
+ * fix(populate): handle populating nested path where top-level path is a primitive in the db #7545
+ * fix(update): run update validators on array filters #7536
+ * fix(document): clean modified subpaths when sorting an array #7556
+ * fix(model): cast $setOnInsert correctly with nested docs #7534
+ * docs: remove extra curly brace from example #7569 [kolya182](https://github.com/kolya182)
+
+5.4.16 / 2019-02-26
+===================
+ * fix(schema): handle nested objects with `_id: false` #7524
+ * fix(schema): don't throw error if declaring a virtual that starts with a map path name #7464
+ * fix(browser): add stubbed `model()` function so code that uses model doesn't throw #7541 [caub](https://github.com/caub)
+ * fix(schema): merge virtuals correctly #7563 [yoursdearboy](https://github.com/yoursdearboy)
+ * docs(connections): add reconnectFailed to connection docs #7477
+ * docs(index): fix typo #7553 [DenrizSusam](https://github.com/DenrizSusam)
+ * refactor(schema): iterate over paths instead of depending on childSchemas #7554
+
+5.4.15 / 2019-02-22
+===================
+ * fix(update): don't call schematype validators on array if using $pull with runValidators #6971
+ * fix(schema): clone all schema types when cloning an array #7537
+ * docs(connections): improve connectTimeoutMS docs and socketTimeoutMS docs to link to Node.js net.setTimeout() #5169
+ * docs: fix setters example in migration guide #7546 [freewil](https://github.com/freewil)
+
+5.4.14 / 2019-02-19
+===================
+ * fix(populate): make `getters` option handle nested paths #7521
+ * fix(documentarray): report validation errors that occur in an array subdoc created using `create()` and then `set()` #7504
+ * docs(schema): add examples for schema functions that didn't have any #7525
+ * docs: add MongooseError to API docs and add list of error names
+ * docs(CONTRIBUTING): fix link #7530 [sarpik](https://github.com/sarpik)
+
+5.4.13 / 2019-02-15
+===================
+ * fix(query): throw handy error when using updateOne() with overwrite: true and no dollar keys #7475
+ * fix(schema): support inheriting existing schema types using Node.js `util.inherits` like mongoose-float #7486
+ * docs(connections): add list of connection events #7477
+
+5.4.12 / 2019-02-13
+===================
+ * fix(connection): dont emit reconnected due to socketTimeoutMS #7452
+ * fix(schema): revert check for `false` schema paths #7516 #7512
+ * fix(model): don't delete unaliased keys in translateAliases #7510 [chrischen](https://github.com/chrischen)
+ * fix(document): run single nested schematype validator if nested path has a default and subpath is modified #7493
+ * fix(query): copy mongoose options when using `Query#merge()` #1790
+ * fix(timestamps): don't call createdAt getters when setting updatedAt on new doc #7496
+ * docs: improve description of ValidationError #7515 [JulioJu](https://github.com/JulioJu)
+ * docs: add an asterisk before comment, otherwise the comment line is not generated #7513 [JulioJu](https://github.com/JulioJu)
+
+5.4.11 / 2019-02-09
+===================
+ * fix(schema): handle `_id: false` in schema paths as a shortcut for setting the `_id` option to `false` #7480
+ * fix(update): handle $addToSet and $push with ObjectIds and castNonArrays=false #7479
+ * docs(model): document `session` option to `save()` #7484
+ * chore: fix gitignore syntax #7498 [JulioJu](https://github.com/JulioJu)
+ * docs: document that Document#validateSync returns ValidationError #7499
+ * refactor: use consolidated `isPOJO()` function instead of constructor checks #7500
+
+5.4.10 / 2019-02-05
+===================
+ * docs: add search bar and /search page #6706
+ * fix: support dotted aliases #7478 [chrischen](https://github.com/chrischen)
+ * fix(document): copy atomics when setting document array to an existing document array #7472
+ * chore: upgrade to mongodb driver 3.1.13 #7488
+ * docs: remove confusing references to executing a query "immediately" #7461
+ * docs(guides+schematypes): link to custom schematypes docs #7407
+
+5.4.9 / 2019-02-01
+==================
+ * fix(document): make `remove()`, `updateOne()`, and `update()` use the document's associated session #7455
+ * fix(document): support passing args to hooked custom methods #7456
+ * fix(document): avoid double calling single nested getters on `toObject()` #7442
+ * fix(discriminator): handle global plugins modifying top-level discriminator options with applyPluginsToDiscriminators: true #7458
+ * docs(documents): improve explanation of documents and use more modern syntax #7463
+ * docs(middleware+api): fix a couple typos in examples #7474 [arniu](https://github.com/arniu)
+
+5.4.8 / 2019-01-30
+==================
+ * fix(query): fix unhandled error when casting object in array filters #7431
+ * fix(query): cast query $elemMatch to discriminator schema if discriminator key set #7449
+ * docs: add table of contents to all guides #7430
+
+5.4.7 / 2019-01-26
+==================
+ * fix(populate): set `populated()` when using virtual populate #7440
+ * fix(discriminator): defer applying plugins to embedded discriminators until model compilation so global plugins work #7435
+ * fix(schema): report correct pathtype underneath map so setting dotted paths underneath maps works #7448
+ * fix: get debug from options using the get helper #7451 #7446 [LucGranato](https://github.com/LucGranato)
+ * fix: use correct variable name #7443 [esben-semmle](https://github.com/esben-semmle)
+ * docs: fix broken QueryCursor link #7438 [shihabmridha](https://github.com/shihabmridha)
+
+5.4.6 / 2019-01-22
+==================
+ * fix(utils): make minimize leave empty objects in arrays instead of setting the array element to undefined #7322
+ * fix(document): support passing `{document, query}` options to Schema#pre(regex) and Schema#post(regex) #7423
+ * docs: add migrating to 5 guide to docs #7434
+ * docs(deprecations): add instructions for fixing `count()` deprecation #7419
+ * docs(middleware): add description and example for aggregate hooks #7402
+
+4.13.18 / 2019-01-21
+====================
+ * fix(model): handle setting populated path set via `Document#populate()` #7302
+ * fix(cast): backport fix from #7290 to 4.x
+
+5.4.5 / 2019-01-18
+==================
+ * fix(populate): handle nested array `foreignField` with virtual populate #7374
+ * fix(query): support not passing any arguments to `orFail()` #7409
+ * docs(query): document what the resolved value for `deleteOne()`, `deleteMany()`, and `remove()` contains #7324
+ * fix(array): allow opting out of converting non-arrays into arrays with `castNonArrays` option #7371
+ * fix(query): ensure updateOne() doesnt unintentionally double call Schema#post(regexp) #7418
+
+5.4.4 / 2019-01-14
+==================
+ * fix(query): run casting on arrayFilters option #7079
+ * fix(document): support skipping timestamps on save() with `save({ timestamps: false })` #7357
+ * fix(model): apply custom where on `Document#remove()` so we attach the shardKey #7393
+ * docs(mongoose): document `mongoose.connections` #7338
+
+5.4.3 / 2019-01-09
+==================
+ * fix(populate): handle `count` option when using `Document#populate()` on a virtual #7380
+ * fix(connection): set connection state to DISCONNECTED if replica set has no primary #7330
+ * fix(mongoose): apply global plugins to schemas nested underneath embedded discriminators #7370
+ * fix(document): make modifiedPaths() return nested paths 1 level down on initial set #7313
+ * fix(plugins): ensure sharding plugin works even if ObjectId has a `valueOf()` #7353
+
+5.4.2 / 2019-01-03
+==================
+ * fix(document): ensure Document#updateOne() returns a query but still calls hooks #7366
+ * fix(query): allow explicitly projecting out populated paths that are automatically projected in #7383
+ * fix(document): support setting `flattenMaps` option for `toObject()` and `toJSON()` at schema level #7274
+ * fix(query): handle merging objectids with `.where()` #7360
+ * fix(schema): copy `.base` when cloning #7377
+ * docs: remove links to plugins.mongoosejs.com in favor of plugins.mongoosejs.io #7364
+
+5.4.1 / 2018-12-26
+==================
+ * fix(document): ensure doc array defaults get casted #7337
+ * fix(document): make `save()` not crash if nested doc has a property 'get' #7316
+ * fix(schema): allow using Schema.Types.Map as well as Map to declare a map type #7305
+ * fix(map): make set after init mark correct path as modified #7321
+ * fix(mongoose): don't recompile model if same collection and schema passed in to `mongoose.model()` #5767
+ * fix(schema): improve error message when type is invalid #7303
+ * fix(schema): add `populated` to reserved property names #7317
+ * fix(model): don't run built-in middleware on custom methods and ensure timestamp hooks don't run if children don't have timestamps set #7342
+ * docs(schematypes): clarify that you can add arbitrary options to a SchemaType #7340
+ * docs(mongoose): clarify that passing same name+schema to `mongoose.model()` returns the model #5767
+ * docs(index): add useNewUrlParser to example #7368 [JIBIN-P](https://github.com/JIBIN-P)
+ * docs(connection): add useNewUrlParser to examples #7362 [JIBIN-P](https://github.com/JIBIN-P)
+ * docs(discriminators): add back missing example from 'recursive embedded discriminators section' #7349
+ * docs(schema): improve docs for string and boolean cast() #7351
+
+5.4.0 / 2018-12-14
+==================
+ * feat(schematype): add `SchemaType.get()`, custom getters across all instances of a schematype #6912
+ * feat(schematype): add `SchemaType.cast()`, configure casting for individual schematypes #7045
+ * feat(schematype): add `SchemaType.checkRequired()`, configure what values pass `required` check for a schematype #7186 #7150
+ * feat(model): add `Model.findOneAndReplace()` #7162
+ * feat(model): add `Model.events` emitter that emits all `error`'s that occur with a given model #7125
+ * feat(populate): add `count` option to populate virtuals, support returning # of populated docs instead of docs themselves #4469
+ * feat(aggregate): add `.catch()` helper to make aggregations full thenables #7267
+ * feat(query): add hooks for `deleteOne()` and `deleteMany()` #7195
+ * feat(document): add hooks for `updateOne()` #7133
+ * feat(query): add `Query#map()` for synchronously transforming results before post middleware runs #7142
+ * feat(schema): support passing an array of objects or schemas to `Schema` constructor #7218
+ * feat(populate): add `clone` option to ensure multiple docs don't share the same populated doc #3258
+ * feat(query): add `Query#maxTimeMS()` helper #7254
+ * fix(query): deprecate broken `Aggregate#addCursorFlag()` #7120
+ * docs(populate): fix incorrect example #7335 [zcfan](https://github.com/zcfan)
+ * docs(middleware): add `findOneAndDelete` to middleware list #7327 [danielkesselberg](https://github.com/danielkesselberg)
+
+5.3.16 / 2018-12-11
+===================
+ * fix(document): handle `__proto__` in queries #7290
+ * fix(document): use Array.isArray() instead of checking constructor name for arrays #7290
+ * docs(populate): add section about what happens when no document matches #7279
+ * fix(mongoose): avoid crash on `import mongoose, {Schema} from 'mongoose'` #5648
+
+5.3.15 / 2018-12-05
+===================
+ * fix(query): handle `orFail()` with `findOneAndUpdate()` and `findOneAndDelete()` #7297 #7280
+ * fix(document): make `save()` succeed if strict: false with a `collection` property #7276
+ * fix(document): add `flattenMaps` option for toObject() #7274
+ * docs(document): document flattenMaps option #7274
+ * fix(populate): support populating individual subdoc path in document array #7273
+ * fix(populate): ensure `model` option overrides `refPath` #7273
+ * fix(map): don't call subdoc setters on init #7272
+ * fix(document): use internal get() helper instead of lodash.get to support `null` projection param #7271
+ * fix(document): continue running validateSync() for all elements in doc array after first error #6746
+
+5.3.14 / 2018-11-27
+===================
+ * docs(api): use `openUri()` instead of legacy `open()` #7277 [artemjackson](https://github.com/artemjackson)
+ * fix(document): don't mark date underneath single nested as modified if setting to string #7264
+ * fix(update): set timestamps on subdocs if not using $set with no overwrite #7261
+ * fix(document): use symbol instead of `__parent` so user code doesn't conflict #7230
+ * fix(mongoose): allow using `mongoose.model()` without context, like `import {model} from 'mongoose'` #3768
+
+5.3.13 / 2018-11-20
+===================
+ * fix: bump mongodb driver -> 3.1.10 #7266
+ * fix(populate): support setting a model as a `ref` #7253
+ * docs(schematype): add ref() function to document what is a valid `ref` path in a schematype #7253
+ * fix(array): clean modified subpaths when calling `splice()` #7249
+ * docs(compatibility): don't show Mongoose 4.11 as compatible with MongoDB 3.6 re: MongoDB's official compatibility table #7248 [a-harrison](https://github.com/a-harrison)
+ * fix(document): report correct validation error if doc array set to primitive #7242
+ * fix(mongoose): print warning when including server-side lib with jest jsdom environment #7240
+
+5.3.12 / 2018-11-13
+===================
+ * docs(compatibility): don't show Mongoose 4.11 as compatible with MongoDB 3.6 re: MongoDB's official compatibility table #7238 [a-harrison](https://github.com/a-harrison)
+ * fix(populate): use `instanceof` rather than class name for comparison #7237 [ivanseidel](https://github.com/ivanseidel)
+ * docs(api): make options show up as a nested list #7232
+ * fix(document): don't mark array as modified on init if doc array has default #7227
+ * docs(api): link to bulk write result object in `bulkWrite()` docs #7225
+
+5.3.11 / 2018-11-09
+===================
+ * fix(model): make parent pointers non-enumerable so they don't crash JSON.stringify() #7220
+ * fix(document): allow saving docs with nested props with '.' using `checkKeys: false` #7144
+ * docs(lambda): use async/await with lambda example #7019
+
+5.3.10 / 2018-11-06
+===================
+ * fix(discriminator): support reusing a schema for multiple discriminators #7200
+ * fix(cursor): handle `lean(false)` correctly with query cursors #7197
+ * fix(document): avoid manual populate if `ref` not set #7193
+ * fix(schema): handle schema without `.base` for browser build #7170
+ * docs: add further reading section
+
+5.3.9 / 2018-11-02
+==================
+ * fix: upgrade bson dep -> 1.1.0 to match mongodb-core #7213 [NewEraCracker](https://github.com/NewEraCracker)
+ * docs(api): fix broken anchor link #7210 [gfranco93](https://github.com/gfranco93)
+ * fix: don't set parent timestamps because a child has timestamps set to false #7203 #7202 [lineus](https://github.com/lineus)
+ * fix(document): run setter only once when doing `.set()` underneath a single nested subdoc #7196
+ * fix(document): surface errors in subdoc pre validate #7187
+ * fix(query): run default functions after hydrating the loaded document #7182
+ * fix(query): handle strictQuery: 'throw' with nested path correctly #7178
+ * fix(update): update timestamps on replaceOne() #7152
+ * docs(transactions): add example of aborting a transaction #7113
+
+5.3.8 / 2018-10-30
+==================
+ * fix: bump mongodb driver -> 3.1.8 to fix connecting to +srv uri with no credentials #7191 #6881 [lineus](https://github.com/lineus)
+ * fix(document): sets defaults correctly in child docs with projection #7159
+ * fix(mongoose): handle setting custom type on a separate mongoose global #7158
+ * fix: add unnecessary files to npmignore #7157
+ * fix(model): set session when creating new subdoc #7104
+
+5.3.7 / 2018-10-26
+==================
+ * fix(browser): fix buffer usage in browser build #7184 #7173 [lineus](https://github.com/lineus)
+ * fix(document): make depopulate() work on populate virtuals and unpopulated docs #7180 #6075 [lineus](https://github.com/lineus)
+ * fix(document): only pass properties as 2nd arg to custom validator if `propsParameter` set #7145
+ * docs(schematypes): add note about nested paths with `type` getting converted to mixed #7143
+ * fix(update): run update validators on nested doc when $set on an array #7135
+ * fix(update): copy exact errors from array subdoc validation into top-level update validator error #7135
+
+5.3.6 / 2018-10-23
+==================
+ * fix(cursor): fix undefined transforms error
+
+5.3.5 / 2018-10-22
+==================
+ * fix(model): make sure versionKey on `replaceOne()` always gets set at top level to prevent cast errors #7138
+ * fix(cursor): handle non-boolean lean option in `eachAsync()` #7137
+ * fix(update): correct cast update that overwrites a map #7111
+ * fix(schema): handle arrays of mixed correctly #7109
+ * fix(query): use correct path when getting schema for child timestamp update #7106
+ * fix(document): make `$session()` propagate sessions to child docs #7104
+ * fix(document): handle user setting `schema.options.strict = 'throw'` #7103
+ * fix(types): use core Node.js buffer prototype instead of safe-buffer because safe-buffer is broken for Node.js 4.x #7102
+ * fix(document): handle setting single doc with refPath to document #7070
+ * fix(model): handle array filters when updating timestamps for subdocs #7032
+
+5.3.4 / 2018-10-15
+==================
+ * fix(schema): make `add()` and `remove()` return the schema instance #7131 [lineus](https://github.com/lineus)
+ * fix(query): don't require passing model to `cast()` #7118
+ * fix: support `useFindAndModify` as a connection-level option #7110 [lineus](https://github.com/lineus)
+ * fix(populate): handle plus path projection with virtual populate #7050
+ * fix(schema): allow using ObjectId type as schema path type #7049
+ * docs(schematypes): elaborate on how schematypes relate to types #7049
+ * docs(deprecations): add note about gridstore deprecation #6922
+ * docs(guide): add storeSubdocValidationError option to guide #6802
+
+5.3.3 / 2018-10-12
+==================
+ * fix(document): enable storing mongoose validation error in MongoDB by removing `$isValidatorError` property #7127
+ * docs(api): clarify that aggregate triggers aggregate middleware #7126 [lineus](https://github.com/lineus)
+ * fix(connection): handle Model.init() when an index exists on schema + autoCreate == true #7122 [jesstelford](https://github.com/jesstelford)
+ * docs(middleware): explain how to switch between document and query hooks for `remove()` #7093
+ * docs(api): clean up encoding issues in SchemaType.prototype.validate docs #7091
+ * docs(schema): add schema types to api docs and update links on schematypes page #7080 #7076 [lineus](https://github.com/lineus)
+ * docs(model): expand model constructor docs with examples and `fields` param #7077
+ * docs(aggregate): remove incorrect description of noCursorTimeout and add description of aggregate options #7056
+ * docs: re-add array type to API docs #7027
+ * docs(connections): add note about `members.host` errors due to bad host names in replica set #7006
+
+5.3.2 / 2018-10-07
+==================
+ * fix(query): make sure to return correct result from `orFail()` #7101 #7099 [gsandorx](https://github.com/gsandorx)
+ * fix(schema): handle `{ timestamps: false }` correctly #7088 #7074 [lineus](https://github.com/lineus)
+ * docs: fix markdown in options.useCreateIndex documentation #7085 [Cyral](https://github.com/Cyral)
+ * docs(schema): correct field name in timestamps example #7082 [kizmo04](https://github.com/kizmo04)
+ * docs(migrating_to_5): correct markdown syntax #7078 [gwuah](https://github.com/gwuah)
+ * fix(connection): add useFindAndModify option in connect #7059 [NormanPerrin](https://github.com/NormanPerrin)
+ * fix(document): dont mark single nested path as modified if setting to the same value #7048
+ * fix(populate): use WeakMap to track lean populate models rather than leanPopulateSymbol #7026
+ * fix(mongoose): avoid unhandled rejection when `mongoose.connect()` errors with a callback #6997
+ * fix(mongoose): isolate Schema.Types between custom Mongoose instances #6933
+
+5.3.1 / 2018-10-02
+==================
+ * fix(ChangeStream): expose driver's `close()` function #7068 #7022 [lineus](https://github.com/lineus)
+ * fix(model): avoid printing warning if `_id` index is set to "hashed" #7053
+ * fix(populate): handle nested populate underneath lean array correctly #7052
+ * fix(update): make timestamps not crash on a null or undefined update #7041
+ * docs(schematypes+validation): clean up links from validation docs to schematypes docs #7040
+ * fix(model): apply timestamps to nested docs in bulkWrite() #7032
+ * docs(populate): rewrite refPath docs to be simpler and more direct #7013
+ * docs(faq): explain why destructuring imports are not supported in FAQ #7009
+
+5.3.0 / 2018-09-28
+==================
+ * feat(mongoose): support `mongoose.set('debug', WritableStream)` so you can pipe debug to stderr, file, or network #7018
+ * feat(query): add useNestedStrict option #6973 #5144 [lineus](https://github.com/lineus)
+ * feat(query): add getPopulatedPaths helper to Query.prototype #6970 #6677 [lineus](https://github.com/lineus)
+ * feat(model): add `createCollection()` helper to make transactions easier #6948 #6711 [Fonger](https://github.com/Fonger)
+ * feat(schema): add ability to do `schema.add(otherSchema)` to merge hooks, virtuals, etc. #6897
+ * feat(query): add `orFail()` helper that throws an error if no documents match `filter` #6841
+ * feat(mongoose): support global toObject and toJSON #6815
+ * feat(connection): add deleteModel() to remove a model from a connection #6813
+ * feat(mongoose): add top-level mongoose.ObjectId, mongoose.Decimal128 for easier schema declarations #6760
+ * feat(aggregate+query): support for/await/of (async iterators) #6737
+ * feat(mongoose): add global `now()` function that you can stub for testing timestamps #6728
+ * feat(schema): support `schema.pre(RegExp, fn)` and `schema.post(RegExp, fn)` #6680
+ * docs(query): add better docs for the `mongooseOptions()` function #6677
+ * feat(mongoose): add support for global strict object #6858
+ * feat(schema+mongoose): add autoCreate option to automatically create collections #6489
+ * feat(update): update timestamps on nested subdocs when using `$set` #4412
+ * feat(query+schema): add query `remove` hook and ability to switch between query `remove` and document `remove` middleware #3054
+
+5.2.18 / 2018-09-27
+===================
+ * docs(migrating_to_5): add note about overwriting filter properties #7030
+ * fix(query): correctly handle `select('+c')` if c is not in schema #7017
+ * fix(document): check path exists before checking for required #6974
+ * fix(document): retain user-defined key order on initial set with nested docs #6944
+ * fix(populate): handle multiple localFields + foreignFields using `localField: function() {}` syntax #5704
+
+5.2.17 / 2018-09-21
+===================
+ * docs(guide): clarify that Mongoose only increments versionKey on `save()` and add a workaround for `findOneAndUpdate()` #7038
+ * fix(model): correctly handle `createIndex` option to `ensureIndexes()` #7036 #6922 [lineus](https://github.com/lineus)
+ * docs(migrating_to_5): add a note about changing debug output from stderr to stdout #7034 #7018 [lineus](https://github.com/lineus)
+ * fix(query): add `setUpdate()` to allow overwriting update without changing op #7024 #7012 [lineus](https://github.com/lineus)
+ * fix(update): find top-level version key even if there are `$` operators in the update #7003
+ * docs(model+query): explain which operators `count()` supports that `countDocuments()` doesn't #6911
+
+5.2.16 / 2018-09-19
+===================
+ * fix(index): use dynamic require only when needed for better webpack support #7014 #7010 [jaydp17](https://github.com/jaydp17)
+ * fix(map): handle arrays of mixed maps #6995
+ * fix(populate): leave justOne as null if populating underneath a Mixed type #6985
+ * fix(populate): add justOne option to allow overriding any bugs with justOne #6985
+ * fix(query): add option to skip adding timestamps to an update #6980
+ * docs(model+schematype): improve docs about background indexes and init() #6966
+ * fix: bump mongodb -> 3.1.6 to allow connecting to srv url without credentials #6955 #6881 [lineus](https://github.com/lineus)
+ * fix(connection): allow specifying `useCreateIndex` at the connection level, overrides global-level #6922
+ * fix(schema): throw a helpful error if setting `ref` to an invalid value #6915
+
+5.2.15 / 2018-09-15
+===================
+ * fix(populate): handle virtual justOne correctly if it isn't set #6988
+ * fix(populate): consistently use lowercase `model` instead of `Model` so double-populating works with existing docs #6978
+ * fix(model): allow calling `Model.init()` again after calling `dropDatabase()` #6967
+ * fix(populate): find correct justOne when double-populating underneath an array #6798
+ * docs(webpack): make webpack docs use es2015 preset for correct libs and use acorn to test output is valid ES5 #6740
+ * fix(populate): add selectPopulatedPaths option to opt out of auto-adding `populate()`-ed fields to `select()` #6546
+ * fix(model): set timestamps on bulkWrite `insertOne` and `replaceOne` #5708
+
+5.2.14 / 2018-09-09
+===================
+ * docs: fix wording on promise docs to not imply queries only return promises #6983 #6982 [lineus](https://github.com/lineus)
+ * fix(map): throw TypeError if keys are not string #6956
+ * fix(document): ensure you can `validate()` a child doc #6931
+ * fix(populate): avoid cast error if refPath points to localFields with 2 different types #6870
+ * fix(populate): handle populating already-populated paths #6839
+ * fix(schematype): make ObjectIds handle refPaths when checking required #6714
+ * fix(model): set timestamps on bulkWrite() updates #5708
+
+5.2.13 / 2018-09-04
+===================
+ * fix(map): throw TypeError if keys are not string #6968 [Fonger](https://github.com/Fonger)
+ * fix(update): make array op casting work with strict:false and {} #6962 #6952 [lineus](https://github.com/lineus)
+ * fix(document): add doc.deleteOne(), doc.updateOne(), doc.replaceOne() re: deprecation warnings #6959 #6940 [lineus](https://github.com/lineus)
+ * docs(faq+schematypes): add note about map keys needing to be strings #6957 #6956 [lineus](https://github.com/lineus)
+ * fix(schematype): remove unused if statement #6950 #6949 [cacothi](https://github.com/cacothi)
+ * docs: add /docs/deprecations.html for dealing with MongoDB driver deprecation warnings #6922
+ * fix(populate): handle refPath where first element in array has no refPath #6913
+ * fix(mongoose): allow setting useCreateIndex option after creating a model but before initial connection succeeds #6890
+ * fix(updateValidators): ensure $pull validators always get an array #6889
+
+5.2.12 / 2018-08-30
+===================
+ * fix(document): disallow setting `constructor` and `prototype` if strict mode false
+
+4.13.17 / 2018-08-30
+====================
+ * fix(document): disallow setting `constructor` and `prototype` if strict mode false
+
+5.2.11 / 2018-08-30
+===================
+ * fix(document): disallow setting __proto__ if strict mode false
+ * fix(document): run document middleware on docs embedded in maps #6945 #6938 [Fonger](https://github.com/Fonger)
+ * fix(query): make castForQuery return a CastError #6943 #6927 [lineus](https://github.com/lineus)
+ * fix(query): use correct `this` scope when casting query with legacy 2dsphere pairs defined in schema #6939 #6937 [Fonger](https://github.com/Fonger)
+ * fix(document): avoid crash when calling `get()` on deeply nested subdocs #6929 #6925 [jakemccloskey](https://github.com/jakemccloskey)
+ * fix(plugins): make saveSubdocs execute child post save hooks _after_ the actual save #6926
+ * docs: add dbName to api docs for .connect() #6923 [p722](https://github.com/p722)
+ * fix(populate): convert to array when schema specifies array, even if doc doesn't have an array #6908
+ * fix(populate): handle `justOne` virtual populate underneath array #6867
+ * fix(model): dont set versionKey on upsert if it is already `$set` #5973
+
+4.13.16 / 2018-08-30
+====================
+ * fix(document): disallow setting __proto__ if strict mode false
+ * feat(error): backport adding modified paths to VersionError #6928 [freewil](https://github.com/freewil)
+
+5.2.10 / 2018-08-27
+===================
+ * fix: bump mongodb driver -> 3.1.4 #6920 #6903 #6884 #6799 #6741 [Fonger](https://github.com/Fonger)
+ * fix(model): track `session` option for `save()` as the document's `$session()` #6909
+ * fix(query): add Query.getOptions() helper #6907 [Fonger](https://github.com/Fonger)
+ * fix(document): ensure array atomics get cleared after save() #6900
+ * fix(aggregate): add missing redact and readConcern helpers #6895 [Fonger](https://github.com/Fonger)
+ * fix: add global option `mongoose.set('useCreateIndex', true)` to avoid ensureIndex deprecation warning #6890
+ * fix(query): use `projection` option to avoid deprecation warnings #6888 #6880 [Fonger](https://github.com/Fonger)
+ * fix(query): use `findOneAndReplace()` internally if using `overwrite: true` with `findOneAndUpdate()` #6888 [Fonger](https://github.com/Fonger)
+ * fix(document): ensure required cache gets cleared correctly between subsequent saves #6892
+ * fix(aggregate): support session chaining correctly #6886 #6885 [Fonger](https://github.com/Fonger)
+ * fix(query): use `projection` instead of `fields` internally for `find()` and `findOne()` to avoid deprecation warning #6880
+ * fix(populate): add `getters` option to opt in to calling getters on populate #6844
+
+5.2.9 / 2018-08-17
+==================
+ * fix(document): correctly propagate write concern options in save() #6877 [Fonger](https://github.com/Fonger)
+ * fix: upgrade mongodb driver -> 3.1.3 for numerous fixes #6869 #6843 #6692 #6670 [simllll](https://github.com/simllll)
+ * fix: correct `this` scope of default functions for DocumentArray and Array #6868 #6840 [Fonger](https://github.com/Fonger)
+ * fix(types): support casting JSON form of buffers #6866 #6863 [Fonger](https://github.com/Fonger)
+ * fix(query): get global runValidators option correctly #6865 #6578
+ * fix(query): add Query.prototype.setQuery() analogous to `getQuery()` #6855 #6854
+ * docs(connections): add note about the `family` option for IPv4 vs IPv6 and add port to example URIs #6784
+ * fix(query): get global runValidators option correctly #6578
+
+4.13.15 / 2018-08-14
+====================
+ * fix(mongoose): add global `usePushEach` option for easier Mongoose 4.x + MongoDB 3.6 #6858
+ * chore: fix flakey tests for 4.x #6853 [Fonger](https://github.com/Fonger)
+ * feat(error): add version number to VersionError #6852 [freewil](https://github.com/freewil)
+
+5.2.8 / 2018-08-13
+==================
+ * docs: update `execPopulate()` code example #6851 [WJakub](https://github.com/WJakub)
+ * fix(document): allow passing callback to `execPopulate()` #6851
+ * fix(populate): populate with undefined fields without error #6848 #6845 [Fonger](https://github.com/Fonger)
+ * docs(migrating_to_5): Add `objectIdGetter` option docs #6842 [jwalton](https://github.com/jwalton)
+ * chore: run lint in parallel and only on Node.js v10 #6836 [Fonger](https://github.com/Fonger)
+ * fix(populate): throw helpful error if refPath excluded in query #6834
+ * docs(migrating_to_5): add note about removing runSettersOnQuery #6832
+ * fix: use safe-buffer to avoid buffer deprecation errors in Node.js 10 #6829 [Fonger](https://github.com/Fonger)
+ * docs(query): fix broken links #6828 [yaynick](https://github.com/yaynick)
+ * docs(defaults): clarify that defaults only run on undefined #6827
+ * chore: fix flakey tests #6824 [Fonger](https://github.com/Fonger)
+ * docs: fix custom inspect function deprecation warning in Node.js 10 #6821 [yelworc](https://github.com/yelworc)
+ * fix(document): ensure subdocs get set to init state after save() so validators can run again #6818
+ * fix(query): make sure embedded query casting always throws a CastError #6803
+ * fix(document): ensure `required` function only gets called once when validating #6801
+ * docs(connections): note that you must specify port if using `useNewUrlParser: true` #6789
+ * fix(populate): support `options.match` in virtual populate schema definition #6787
+ * fix(update): strip out virtuals from updates if strict: 'throw' rather than returning an error #6731
+
+5.2.7 / 2018-08-06
+==================
+ * fix(model): check `expireAfterSeconds` option when diffing indexes in syncIndexes() #6820 #6819 [christopherhex](https://github.com/christopherhex)
+ * chore: fix some common test flakes in travis #6816 [Fonger](https://github.com/Fonger)
+ * chore: bump eslint and webpack to avoid bad versions of eslint-scope #6814
+ * test(model): add delay to session tests to improve pass rate #6811 [Fonger](https://github.com/Fonger)
+ * fix(model): support options in `deleteMany` #6810 [Fonger](https://github.com/Fonger)
+ * fix(query): don't use $each when pushing an array into an array #6809 [lineus](https://github.com/lineus)
+ * chore: bump mquery so eslint isn't a prod dependency #6800
+ * fix(populate): correctly get schema type when calling `populate()` on already populated path #6798
+ * fix(populate): propagate readConcern options in populate from parent query #6792 #6785 [Fonger](https://github.com/Fonger)
+ * docs(connection): add description of useNewUrlParser option #6789
+ * fix(query): make select('+path') a no-op if no select prop in schema #6785
+ * docs(schematype+validation): document using function syntax for custom validator message #6772
+ * fix(update): throw CastError if updating with `$inc: null` #6770
+ * fix(connection): throw helpful error when calling `createConnection(undefined)` #6763
+
+5.2.6 / 2018-07-30
+==================
+ * fix(document): don't double-call deeply nested custom getters when using `get()` #6779 #6637
+ * fix(query): upgrade mquery for readConcern() helper #6777
+ * docs(schematypes): clean up typos #6773 [sajadtorkamani](https://github.com/sajadtorkamani)
+ * refactor(browser): fix webpack warnings #6771 #6705
+ * fix(populate): make error reported when no `localField` specified catchable #6767
+ * docs(connection): use correct form in createConnection example #6766 [lineus](https://github.com/lineus)
+ * fix(connection): throw helpful error when using legacy `mongoose.connect()` syntax #6756
+ * fix(document): handle overwriting `$session` in `execPopulate()` #6754
+ * fix(query): propagate top-level session down to `populate()` #6754
+ * fix(aggregate): add `session()` helper for consistency with query api #6752
+ * fix(map): avoid infinite recursion when update overwrites a map #6750
+ * fix(model): be consistent about passing noop callback to mongoose.model() `init()` as well as db.model() #6707
+
+5.2.5 / 2018-07-23
+==================
+ * fix(boolean): expose `convertToTrue` and `convertToFalse` for custom boolean casting #6758
+ * docs(schematypes): add note about what values are converted to booleans #6758
+ * fix(document): fix(document): report castError when setting single nested doc to array #6753
+ * docs: prefix mongoose.Schema call with new operator #6751 [sajadtorkamani](https://github.com/sajadtorkamani)
+ * docs(query): add examples and links to schema writeConcern option for writeConcern helpers #6748
+ * docs(middleware): clarify that init middleware is sync #6747
+ * perf(model): create error rather than modifying stack for source map perf #6735
+ * fix(model): throw helpful error when passing object to aggregate() #6732
+ * fix(model): pass Model instance as context to applyGetters when calling getters for virtual populate #6726 [lineus](https://github.com/lineus)
+ * fix(documentarray): remove `isNew` and `save` listeners on CastError because otherwise they never get removed #6723
+ * docs(model+query): clarify when to use `countDocuments()` vs `estimatedDocumentCount()` #6713
+ * fix(populate): correctly set virtual nestedSchemaPath when calling populate() multiple times #6644
+ * docs(connections): add note about the `family` option for IPv4 vs IPv6 and add port to example URIs #6566
+
+5.2.4 / 2018-07-16
+==================
+ * docs: Model.insertMany rawResult option in api docs #6724 [lineus](https://github.com/lineus)
+ * docs: fix typo on migrating to 5 guide #6722 [iagowp](https://github.com/iagowp)
+ * docs: update doc about keepalive #6719 #6718 [simllll](https://github.com/simllll)
+ * fix: ensure debug mode doesn't crash with sessions #6712
+ * fix(document): report castError when setting single nested doc to primitive value #6710
+ * fix(connection): throw helpful error if using `new db.model(foo)(bar)` #6698
+ * fix(model): throw readable error with better stack trace when non-cb passed to $wrapCallback() #6640
+
+5.2.3 / 2018-07-11
+==================
+ * fix(populate): if a getter is defined on the localField, use it when populating #6702 #6618 [lineus](https://github.com/lineus)
+ * docs(schema): add example of nested aliases #6671
+ * fix(query): add `session()` function to queries to avoid positional argument mistakes #6663
+ * docs(transactions): use new session() helper to make positional args less confusing #6663
+ * fix(query+model+schema): add support for `writeConcern` option and writeConcern helpers #6620
+ * docs(guide): add `writeConcern` option and re-add description for `safe` option #6620
+ * docs(schema): fix broken API links #6619
+ * docs(connections): add information re: socketTimeoutMS and connectTimeoutMS #4789
+
+5.2.2 / 2018-07-08
+==================
+ * fix(model+query): add missing estimatedDocumentCount() function #6697
+ * docs(faq): improve array-defaults section #6695 [lineus](https://github.com/lineus)
+ * docs(model): fix countDocuments() docs, bad copy/paste from count() docs #6694 #6643
+ * fix(connection): add `startSession()` helper to connection and mongoose global #6689
+ * fix: upgrade mongodb driver -> 3.1.1 for countDocuments() fix #6688 #6666
+ * docs(compatibility): add MongoDB 4 range #6685
+ * fix(populate): add ability to define refPath as a function #6683 [lineus](https://github.com/lineus)
+ * docs: add rudimentary transactions guide #6672
+ * fix(update): make setDefaultsOnInsert handle nested subdoc updates with deeply nested defaults #6665
+ * docs: use latest acquit-ignore to handle examples that start with acquit:ignore:start #6657
+ * fix(validation): format `properties.message` as well as `message` #6621
+
+5.2.1 / 2018-07-03
+==================
+ * fix(connection): allow setting the mongodb driver's useNewUrlParser option, default to false #6656 #6648 #6647
+ * fix(model): only warn on custom _id index if index only has _id key #6650
+
+5.2.0 / 2018-07-02
+==================
+ * feat(model): add `countDocuments()` #6643
+ * feat(model): make ensureIndexes() fail if specifying an index on _id #6605
+ * feat(mongoose): add `objectIdGetter` option to remove ObjectId.prototype._id #6588
+ * feat: upgrade mongodb -> 3.1.0 for full MongoDB 4.0 support #6579
+ * feat(query): support `runValidators` as a global option #6578
+ * perf(schema): use WeakMap instead of array for schema stack #6503
+ * feat(model): decorate unique discriminator indexes with partialFilterExpressions #6347
+ * feat(model): add `syncIndexes()`, drops indexes that aren't in schema #6281
+ * feat(document): add default getter/setter if virtual doesn't have one #6262
+ * feat(discriminator): support discriminators on nested doc arrays #6202
+ * feat(update): add `Query.prototype.set()` #5770
+
+5.1.8 / 2018-07-02
+==================
+ * fix: don't throw TypeError if calling save() after original save() failed with push() #6638 [evanhenke](https://github.com/evanhenke)
+ * fix(query): add explain() helper and don't hydrate explain output #6625
+ * docs(query): fix `setOptions()` lists #6624
+ * docs: add geojson docs #6607
+ * fix: bump mongodb -> 3.0.11 to avoid cyclic dependency error with retryWrites #6109
+
+5.1.7 / 2018-06-26
+==================
+ * docs: add npm badge to readme #6623 [VFedyk](https://github.com/VFedyk)
+ * fix(document): don't throw parallel save error if post save hooks in parallel #6614 #6611 [lineus](https://github.com/lineus)
+ * fix(populate): allow dynamic ref to handle >1 model getModelsMapForPopulate #6613 #6612 [jimmytsao](https://github.com/jimmytsao)
+ * fix(document): handle `push()` on triple nested document array #6602
+ * docs(validation): improve update validator doc headers #6577 [joeytwiddle](https://github.com/joeytwiddle)
+ * fix(document): handle document arrays in `modifiedPaths()` with includeChildren option #5904
+
+5.1.6 / 2018-06-19
+==================
+ * fix: upgrade mongodb -> 3.0.10
+ * docs(model+document): clarify that `save()` returns `undefined` if passed a callback #6604 [lineus](https://github.com/lineus)
+ * fix(schema): apply alias when adding fields with .add() #6593
+ * docs: add full list of guides and streamline nav #6592
+ * docs(model): add `projection` option to `findOneAndUpdate()` #6590 [lineus](https://github.com/lineus)
+ * docs: support @static JSDoc declaration #6584
+ * fix(query): use boolean casting logic for $exists #6581
+ * fix(query): cast all $text options to correct values #6581
+ * fix(model): add support synchronous pre hooks for `createModel` #6552 [profbiss](https://github.com/profbiss)
+ * docs: add note about the `applyPluginsToDiscriminators` option #4965
+
+5.1.5 / 2018-06-11
+==================
+ * docs(guide): rework query helper example #6575 [lineus](https://github.com/lineus)
+ * fix(populate): handle virtual populate with embedded discriminator under single nested subdoc #6571
+ * docs: add string option to projections that call query select #6563 [lineus](https://github.com/lineus)
+ * style: use ES6 in collection.js #6560 [l33ds](https://github.com/l33ds)
+ * fix(populate): add virtual ref function ability getModelsMapForPopulate #6559 #6554 [lineus](https://github.com/lineus)
+ * docs(queries): fix link #6557 [sun1x](https://github.com/sun1x)
+ * fix(schema): rename indexes -> getIndexes to avoid webpack duplicate declaration #6547
+ * fix(document): support `toString()` as custom method #6538
+ * docs: add @instance for instance methods to be more compliant with JSDoc #6516 [treble-snake](https://github.com/treble-snake)
+ * fix(populate): avoid converting to map when using mongoose-deep-populate #6460
+ * docs(browser): create new browser docs page #6061
+
+5.1.4 / 2018-06-04
+==================
+ * docs(faq): add hr tags for parallel save error #6550 [lineus](https://github.com/lineus)
+ * docs(connection): fix broken link #6545 [iblamefish](https://github.com/iblamefish)
+ * fix(populate): honor subpopulate options #6539 #6528 [lineus](https://github.com/lineus)
+ * fix(populate): allow population of refpath under array #6537 #6509 [lineus](https://github.com/lineus)
+ * fix(query): dont treat $set the same as the other ops in update casting #6535 [lineus](https://github.com/lineus)
+ * fix: bump async -> 2.6.1 #6534 #6505 [lineus](https://github.com/lineus)
+ * fix: support using a function as validation error message #6530 [lucandrade](https://github.com/lucandrade)
+ * fix(populate): propagate `lean()` down to subpopulate #6498 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * docs(lambda): add info on what happens if database does down between lambda function calls #6409
+ * fix(update): allow updating embedded discriminator path if discriminator key is in filter #5841
+
+5.1.3 / 2018-05-28
+==================
+ * fix(document): support set() on path underneath array embedded discriminator #6526
+ * chore: update lodash and nsp dev dependencies #6514 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix(document): throw readable error when saving the same doc instance more than once in parallel #6511 #6456 #4064 [lineus](https://github.com/lineus)
+ * fix(populate): set correct nestedSchemaPath for virtual underneath embedded discriminator #6501 #6487 [lineus](https://github.com/lineus)
+ * docs(query): add section on promises and warning about not mixing promises and callbacks #6495
+ * docs(connection): add concrete example of connecting to multiple hosts #6492 [lineus](https://github.com/lineus)
+ * fix(populate): handle virtual populate under single nested doc under embedded discriminator #6488
+ * fix(schema): collect indexes from embedded discriminators for autoIndex build #6485
+ * fix(document): handle `doc.set()` underneath embedded discriminator #6482
+ * fix(document): handle set() on path under embedded discriminator with object syntax #6482
+ * fix(document): handle setting nested property to object with only non-schema properties #6436
+
+4.13.14 / 2018-05-25
+====================
+ * fix(model): handle retainKeyOrder option in findOneAndUpdate() #6484
+
+5.1.2 / 2018-05-21
+==================
+ * docs(guide): add missing SchemaTypes #6490 [distancesprinter](https://github.com/distancesprinter)
+ * fix(map): make MongooseMap.toJSON return a serialized object #6486 #6478 [lineus](https://github.com/lineus)
+ * fix(query): make CustomQuery inherit from model.Query for hooks #6483 #6455 [lineus](https://github.com/lineus)
+ * fix(document): prevent default falses from being skipped by $__dirty #6481 #6477 [lineus](https://github.com/lineus)
+ * docs(connection): document `useDb()` #6480
+ * fix(model): skip redundant clone in insertMany #6479 [d1manson](https://github.com/d1manson)
+ * fix(aggregate): let replaceRoot accept objects as well as strings #6475 #6474 [lineus](https://github.com/lineus)
+ * docs(model): clarify `emit()` in mapReduce and how map/reduce are run #6465
+ * fix(populate): flatten array to handle multi-level nested `refPath` #6457
+ * fix(date): cast small numeric strings as years #6444 [AbdelrahmanHafez](https://github.com/AbdelrahmanHafez)
+ * fix(populate): remove unmatched ids when using virtual populate on already hydrated document #6435
+ * fix(array): use custom array class to avoid clobbered property names #6431
+ * fix(model): handle hooks for custom methods that return promises #6385
+
+4.13.13 / 2018-05-17
+====================
+ * fix(update): stop clobbering $in when casting update #6441 #6339
+ * fix: upgrade async -> 2.6.0 re: security warning
+
+5.1.1 / 2018-05-14
+==================
+ * docs(schema): add notes in api and guide about schema.methods object #6470 #6440 [lineus](https://github.com/lineus)
+ * fix(error): add modified paths to VersionError #6464 #6433 [paglias](https://github.com/paglias)
+ * fix(populate): only call populate with full param signature when match is not present #6458 #6451 [lineus](https://github.com/lineus)
+ * docs: fix geoNear link in migration guide #6450 [kawache](https://github.com/kawache)
+ * fix(discriminator): throw readable error when `create()` with a non-existent discriminator key #6434
+ * fix(populate): add `retainNullValues` option to avoid stripping out null keys #6432
+ * fix(populate): handle populate in embedded discriminators underneath nested paths #6411
+ * docs(model): add change streams and ToC, make terminology more consistent #5888
+
+5.1.0 / 2018-05-10
+==================
+ * feat(ObjectId): add `_id` getter so you can get a usable id whether or not the path is populated #6415 #6115
+ * feat(model): add Model.startSession() #6362
+ * feat(document): add doc.$session() and set session on doc after query #6362
+ * feat: add Map type that supports arbitrary keys #6287 #681
+ * feat: add `cloneSchemas` option to mongoose global to opt in to always cloning schemas before use #6274
+ * feat(model): add `findOneAndDelete()` and `findByIdAndDelete()` #6164
+ * feat(document): support `$ignore()` on single nested and array subdocs #6152
+ * feat(document): add warning about calling `save()` on subdocs #6152
+ * fix(model): make `save()` use `updateOne()` instead of `update()` #6031
+ * feat(error): add version number to VersionError #5966
+ * fix(query): allow `[]` as a value for `$in` when casting #5913
+ * fix(document): avoid running validators on single nested paths if only a child path is modified #5885
+ * feat(schema): print warning if method conflicts with mongoose internals #5860
+
+5.0.18 / 2018-05-09
+===================
+ * fix(update): stop clobbering $in when casting update #6441 #6339 [lineus](https://github.com/lineus)
+ * fix: upgrade mongodb driver -> 3.0.8 to fix session issue #6437 #6357 [simllll](https://github.com/simllll)
+ * fix: upgrade bson -> 1.0.5 re: https://snyk.io/vuln/npm:bson:20180225 #6423 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: look for `valueOf()` when casting to Decimal128 #6419 #6418 [lineus](https://github.com/lineus)
+ * fix: populate array of objects with space separated paths #6414 [lineus](https://github.com/lineus)
+ * test: add coverage for `mongoose.pluralize()` #6412 [FastDeath](https://github.com/FastDeath)
+ * fix(document): avoid running default functions on init() if path has value #6410
+ * fix(document): allow saving document with `null` id #6406
+ * fix: prevent casting of populated docs in document.init #6390 [lineus](https://github.com/lineus)
+ * fix: remove `toHexString()` helper that was added in 5.0.15 #6359
+
+5.0.17 / 2018-04-30
+===================
+ * docs(migration): certain chars in passwords may cause connection failures #6401 [markstos](https://github.com/markstos)
+ * fix(document): don't throw when `push()` on a nested doc array #6398
+ * fix(model): apply hooks to custom methods if specified #6385
+ * fix(schema): support opting out of one timestamp field but not the other for `insertMany()` #6381
+ * fix(documentarray): handle `required: true` within documentarray definition #6364
+ * fix(document): ensure `isNew` is set before default functions run on init #3793
+
+5.0.16 / 2018-04-23
+===================
+ * docs(api): sort api methods based on their string property #6374 [lineus](https://github.com/lineus)
+ * docs(connection): fix typo in `createCollection()` #6370 [mattc41190](https://github.com/mattc41190)
+ * docs(document): remove vestigial reference to `numAffected` #6367 [ekulabuhov](https://github.com/ekulabuhov)
+ * docs(schema): fix typo #6366 [dhritzkiv](https://github.com/dhritzkiv)
+ * docs(schematypes): add missing `minlength` and `maxlength` docs #6365 [treble-snake](https://github.com/treble-snake)
+ * docs(queries): fix formatting #6360 [treble-snake](https://github.com/treble-snake)
+ * docs(api): add cursors to API docs #6353 #6344 [lineus](https://github.com/lineus)
+ * docs(aggregate): remove reference to non-existent `.select()` method #6346
+ * fix(update): handle `required` array with update validators and $pull #6341
+ * fix(update): avoid setting __v in findOneAndUpdate if it is `$set` #5973
+
+5.0.15 / 2018-04-16
+===================
+ * fix: add ability for casting from number to decimal128 #6336 #6331 [lineus](https://github.com/lineus)
+ * docs(middleware): enumerate the ways to error out in a hook #6315
+ * fix(document): respect schema-level depopulate option for toObject() #6313
+ * fix: bump mongodb driver -> 3.0.6 #6310
+ * fix(number): check for `valueOf()` function to support Decimal.js #6306 #6299 [lineus](https://github.com/lineus)
+ * fix(query): run array setters on query if input value is an array #6277
+ * fix(versioning): don't require matching version when using array.pull() #6190
+ * fix(document): add `toHexString()` function so you don't need to check whether a path is populated to get an id #6115
+
+5.0.14 / 2018-04-09
+===================
+ * fix(schema): clone aliases and alternative option syntax correctly
+ * fix(query): call utils.toObject in query.count like in query.find #6325 [lineus](https://github.com/lineus)
+ * docs(populate): add middleware examples #6320 [BorntraegerMarc](https://github.com/BorntraegerMarc)
+ * docs(compatibility): fix dead link #6319 [lacivert](https://github.com/lacivert)
+ * docs(api): fix markdown parsing for parameters #6318 #6314 [lineus](https://github.com/lineus)
+ * fix(populate): handle space-delimited paths in array populate #6296 #6284 [lineus](https://github.com/lineus)
+ * fix(populate): support basic virtual populate underneath embedded discriminators #6273
+
+5.0.13 / 2018-04-05
+===================
+ * docs(faq): add middleware to faq arrow function warning #6309 [lineus](https://github.com/lineus)
+ * docs(schema): add example to loadClass() docs #6308
+ * docs: clean up misc typos #6304 [sfrieson](https://github.com/sfrieson)
+ * fix(document): apply virtuals when calling `toJSON()` on a nested path #6294
+ * refactor(connection): use `client.db()` syntax rather than double-parsing the URI #6292 #6286
+ * docs: document new behavior of required validator for arrays #6288 [daltones](https://github.com/daltones)
+ * fix(schema): treat set() options as user-provided options #6274
+ * fix(schema): clone discriminators correctly #6274
+ * fix(update): make setDefaultsOnInsert not create subdoc if only default is id #6269
+ * docs(discriminator): clarify 3rd argument to Model.discriminator() #2596
+
+5.0.12 / 2018-03-27
+===================
+ * docs(query): updating model name in query API docs #6280 [lineus](https://github.com/lineus)
+ * docs: fix typo in tests #6275 [styler](https://github.com/styler)
+ * fix: add missing `.hint()` to aggregate #6272 #6251 [lineus](https://github.com/lineus)
+ * docs(api): add headers to each API docs section for easer nav #6261
+ * fix(query): ensure hooked query functions always run on next tick for chaining #6250
+ * fix(populate): ensure populated array not set to null if it isn't set #6245
+ * fix(connection): set readyState to disconnected if initial connection fails #6244 #6131
+ * docs(model): make `create()` params show up correctly in docs #6242
+ * fix(model): make error handlers work with MongoDB server errors and `insertMany()` #6228
+ * fix(browser): ensure browser document builds defaults for embedded arrays correctly #6175
+ * fix(timestamps): set timestamps when using `updateOne()` and `updateMany()` #6282 [gualopezb](https://github.com/gualopezb)
+
+5.0.11 / 2018-03-19
+===================
+ * fix(update): handle $pull with $in in update validators #6240
+ * fix(query): don't convert undefined to null when casting so driver `ignoreUndefined` option works #6236
+ * docs(middleware): add example of using async/await with middleware #6235
+ * fix(populate): apply justOne option before `completeMany()` so it works with lean() #6234
+ * fix(query): ensure errors in user callbacks aren't caught in init #6195 #6178
+ * docs(connections): document dbName option for Atlas connections #6179
+ * fix(discriminator): make child schema nested paths overwrite parent schema paths #6076
+
+4.13.12 / 2018-03-13
+====================
+ * fix(document): make virtual get() return undefined instead of null if no getters #6223
+ * docs: fix url in useMongoClient error message #6219 #6217 [lineus](https://github.com/lineus)
+ * fix(discriminator): don't copy `discriminators` property from base schema #6122 #6064
+
+5.0.10 / 2018-03-12
+===================
+ * docs(schematype): add notes re: running setters on queries #6209
+ * docs: fix typo #6208 [kamagatos](https://github.com/kamagatos)
+ * fix(query): only call setters once on query filter props for findOneAndUpdate and findOneAndRemove #6203
+ * docs: elaborate on connection string changes in migration guide #6193
+ * fix(document): skip applyDefaults if subdoc is null #6187
+ * docs: fix schematypes docs and link to them #6176
+ * docs(faq): add FAQs re: array defaults and casting aggregation pipelines #6184 #6176 #6170 [lineus](https://github.com/lineus)
+ * fix(document): ensure primitive defaults are set and built-in default functions run before setters #6155
+ * fix(query): handle single embedded embedded discriminators in castForQuery #6027
+
+5.0.9 / 2018-03-05
+==================
+ * perf: bump mongodb -> 3.0.4 to fix SSL perf issue #6065
+
+5.0.8 / 2018-03-03
+==================
+ * docs: remove obsolete references to `emitIndexErrors` #6186 [isaackwan](https://github.com/isaackwan)
+ * fix(query): don't cast findOne() until exec() so setters don't run twice #6157
+ * fix: remove document_provider.web.js file #6186
+ * fix(discriminator): support custom discriminator model names #6100 [wentout](https://github.com/wentout)
+ * fix: support caching calls to `useDb()` #6036 [rocketspacer](https://github.com/rocketspacer)
+ * fix(query): add omitUndefined option so setDefaultsOnInsert can kick in on undefined #6034
+ * fix: upgrade mongodb -> 3.0.3 for reconnectTries: 0 blocking process exit fix #6028
+
+5.0.7 / 2018-02-23
+==================
+ * fix: support eachAsync options with aggregation cursor #6169 #6168 [vichle](https://github.com/vichle)
+ * docs: fix link to MongoDB compound indexes docs #6162 [br0p0p](https://github.com/br0p0p)
+ * docs(aggregate): use eachAsync instead of incorrect `each()` #6160 [simllll](https://github.com/simllll)
+ * chore: fix benchmarks #6158 [pradel](https://github.com/pradel)
+ * docs: remove dead link to old blog post #6154 [markstos](https://github.com/markstos)
+ * fix: don't convert dates to numbers when updating mixed path #6146 #6145 [s4rbagamble](https://github.com/s4rbagamble)
+ * feat(aggregate): add replaceRoot, count, sortByCount helpers #6142 [jakesjews](https://github.com/jakesjews)
+ * fix(document): add includedChildren flag to modifiedPaths() #6134
+ * perf: don't create wrapper function if no hooks specified #6126
+ * fix(schema): allow indexes on single nested subdocs for geoJSON #6113
+ * fix(document): allow depopulating all fields #6073
+ * feat(mongoose): add support for `useFindAndModify` option on singleton #5616
+
+5.0.6 / 2018-02-15
+==================
+ * refactor(query.castUpdate): avoid creating error until necessary #6137
+ * docs(api): fix missing api docs #6136 [lineus](https://github.com/lineus)
+ * fix(schema): copy virtuals when using `clone()` #6133
+ * fix(update): avoid digging into buffers with upsert and replaceOne #6124
+ * fix(schema): support `enum` on arrays of strings #6102
+ * fix(update): cast `$addToSet: [1, 2]` -> `$addToSet: { $each: [1, 2] }` #6086
+
+5.0.5 / 2018-02-13
+==================
+ * docs: make > show up correctly in API docs #6114
+ * fix(query): support `where()` overwriting primitive with object #6097
+ * fix(schematype): don't run internal `resetId` setter on queries with _id #6093
+ * fix(discriminator): don't copy `discriminators` property from base schema #6064
+ * fix(utils): respect `valueOf()` when merging object for update #6059
+ * docs(validation): fix typo 'maxLength' #4720
+ * fix(document): apply defaults after setting initial value so default functions don't see empty doc #3781
+
+5.0.4 / 2018-02-08
+==================
+ * docs: add lambda guide #6107
+ * fix(connection): add `dbName` option to work around `mongodb+srv` not supporting db name in URI #6106
+ * fix(schematype): fix regexp typo in ObjectId #6098 [JoshuaWise](https://github.com/JoshuaWise)
+ * perf(document): re-use the modifiedPaths list #6092 [tarun1793](https://github.com/tarun1793)
+ * fix: use console.info() instead of console.error() for debug output #6088 [yuristsepaniuk](https://github.com/yuristsepaniuk)
+ * docs(validation): clean up runValidators and isAsync options docs for 5.x #6083
+ * docs(model): use array instead of spread consistently for aggregate() #6070
+ * fix(schema): make aliases handle mongoose-lean-virtuals #6069
+ * docs(layout): add link to subdocs guide #6056
+ * fix(query): make strictQuery: true strip out fields that aren't in the schema #6032
+ * docs(guide): add notes for `strictQuery` option #6032
+
+4.13.11 / 2018-02-07
+====================
+ * docs: fix links in 4.x docs #6081
+ * chore: add release script that uses --tag for npm publish for 4.x releases #6063
+
+5.0.3 / 2018-01-31
+==================
+ * fix: consistently use process.nextTick() to avoid sinon.useFakeTimers() causing ops to hang #6074
+ * docs(aggregate): fix typo #6072 [adursun](https://github.com/adursun)
+ * chore: add return type to `mongoose.model()` docs [bryant1410](https://github.com/bryant1410)
+ * fix(document): depopulate push()-ed docs when saving #6048
+ * fix: upgrade mongodb -> 3.0.2 #6019
+
+5.0.2 / 2018-01-28
+==================
+ * fix(schema): do not overwrite default values in schema when nested timestamps are provided #6024 [cdeveas](https://github.com/cdeveas)
+ * docs: fix syntax highlighting in models.jade, schematypes.jade, subdocs.jade #6058 [lineus](https://github.com/lineus)
+ * fix: use lazy loading so we can build mongoose with webpack #5993 #5842
+ * docs(connections): clarify multi-mongos with useMongoClient for 4.x docs #5984
+ * fix(populate): handle populating embedded discriminator paths #5970
+
+4.13.10 / 2018-01-28
+====================
+ * docs(model+query): add lean() option to Model helpers #5996 [aguyinmontreal](https://github.com/aguyinmontreal)
+ * fix: use lazy loading so we can build mongoose with webpack #5993 #5842
+ * docs(connections): clarify multi-mongos with useMongoClient for 4.x docs #5984
+ * fix(populate): handle populating embedded discriminator paths #5970
+ * docs(query+aggregate): add more detail re: maxTimeMS #4066
+
+5.0.1 / 2018-01-19
+==================
+ * fix(document): make validate() not resolve to document #6014
+ * fix(model): make save() not return DocumentNotFoundError if using fire-and-forget writes #6012
+ * fix(aggregate): make options() work as advertised #6011 [spederiva](https://github.com/spederiva)
+ * docs(queries): fix code samples #6008
+
+5.0.0 / 2018-01-17
+==================
+ * test: refactor tests to use start fewer connections #5985 [fenanquin](https://github.com/fenanquin)
+ * feat: add global bufferCommands option #5879
+ * docs: new docs site and build system #5976
+ * test: increase timeout on slow test cases #5968 [fenanquin](https://github.com/fenanquin)
+ * fix: avoid casting out array filter elements #5965
+ * feat: add Model.watch() wrapper #5964
+ * chore: replace istanbul with nyc #5962 [ChristianMurphy](https://github.com/ChristianMurphy)
+
+4.13.9 / 2018-01-07
+===================
+ * chore: update marked (dev dependency) re: security vulnerability #5951 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: upgrade mongodb -> 2.2.34 for ipv6 and autoReconnect fixes #5794 #5760
+ * docs: use useMongooseAggCursor for aggregate docs #2955
+
+5.0.0-rc2 / 2018-01-04
+======================
+ * fix: add cleaner warning about no longer needing `useMongoClient` in 5.x #5961
+ * chore: update acquit -> 0.5.1 for minor security patch #5961 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs: add docs for mongoose 4.x at http://mongoosejs.com/docs/4.x #5959
+ * docs: add link to migration guide #5957
+ * chore: update eslint to version 4.14.0 #5955 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * chore: update mocha to version 4.1.0 [ChristianMurphy](https://github.com/ChristianMurphy)
+
+5.0.0-rc1 / 2018-01-02
+======================
+ * fix(index): use pluralize correctly for `mongoose.model()` #5958
+ * fix: make mquery use native promises by default #5945
+ * fix(connection): ensure 'joined' and 'left' events get bubbled up #5944
+
+5.0.0-rc0 / 2017-12-28
+======================
+ * BREAKING CHANGE: always use mongoose aggregation cursor when using `.aggregate().cursor()` #5941
+ * BREAKING CHANGE: attach query middleware when compiling model #5939
+ * BREAKING CHANGE: `emitIndexErrors` is on by default, failing index build will throw uncaught error if not handled #5910
+ * BREAKING CHANGE: remove precompiled browser bundle #5895
+ * feat: add `mongoose.pluralize()` function #5877
+ * BREAKING CHANGE: remove `passRawResult` option for `findOneAndUpdate`, use `rawResult` #5869
+ * BREAKING CHANGE: implicit async validators (based on number of function args) are removed, return a promise instead #5824
+ * BREAKING CHANGE: fail fast if user sets a unique index on `_id` #5820 [varunjayaraman](https://github.com/varunjayaraman)
+ * BREAKING CHANGE: mapReduce resolves to an object with 2 keys rather than 2 separate args #5816
+ * BREAKING CHANGE: `mongoose.connect()` returns a promise, removed MongooseThenable #5796
+ * BREAKING CHANGE: query stream removed, use `cursor()` instead #5795
+ * BREAKING CHANGE: connection `open()` and `openSet()` removed, use `openUri()` instead #5795
+ * BREAKING CHANGE: use MongoDB driver 3.0.0, drop support for MongoDB server < 3.0.0 #5791 #4740
+ * BREAKING CHANGE: remove support for `$pushAll`, remove `usePushEach` option #5670
+ * BREAKING CHANGE: make date casting use native Date #5395 [varunjayaraman](https://github.com/varunjayaraman)
+ * BREAKING CHANGE: remove `runSettersOnQuery`, always run setters on query #5340
+ * BREAKING CHANGE: array of length 0 now satisfies `required: true` for arays #5139 [wlingke](https://github.com/wlingke)
+ * BREAKING CHANGE: remove `saveErrorIfNotFound`, always error out if `save()` did not update a document #4973
+ * BREAKING CHANGE: don't execute getters in reverse order #4835
+ * BREAKING CHANGE: make boolean casting more strict #4245
+ * BREAKING CHANGE: `toObject()` and `toJSON()` option parameter merges with defaults rather than overwriting #4131
+ * feat: allow setting `default` on `_id` #4069
+ * BREAKING CHANGE: `deleteX()` and `remove()` promise resolves to the write object result #4013
+ * feat: support returning a promise from middleware functions #3779
+ * BREAKING CHANGE: don't return a promise if callback specified #3670
+ * BREAKING CHANGE: only cast `update()`, `updateX()`, `replaceOne()`, `remove()`, `deleteX()` in exec #3529
+ * BREAKING CHANGE: sync errors in middleware functions are now handled #3483
+ * BREAKING CHANGE: post hooks get flow control #3232
+ * BREAKING CHANGE: deduplicate hooks when merging discriminator schema #2945
+ * BREAKING CHANGE: use native promises by default, remove support for mpromise #2917
+ * BREAKING CHANGE: remove `retainKeyOrder`, always use forward order when iterating through objects #2749
+ * BREAKING CHANGE: `aggregate()` no longer accepts a spread #2716
+
+4.13.8 / 2017-12-27
+===================
+ * docs(guide): use more up-to-date syntax for autoIndex example #5933
+ * docs: fix grammar #5927 [abagh0703](https://github.com/abagh0703)
+ * fix: propagate lean options to child schemas #5914
+ * fix(populate): use correct model with discriminators + nested populate #5858
+
+4.13.7 / 2017-12-11
+===================
+ * docs(schematypes): fix typo #5889 [gokaygurcan](https://github.com/gokaygurcan)
+ * fix(cursor): handle `reject(null)` with eachAsync callback #5875 #5874 [ZacharyRSmith](https://github.com/ZacharyRSmith)
+ * fix: disallow setting `mongoose.connection` to invalid values #5871 [jinasonlin](https://github.com/jinasonlin)
+ * docs(middleware): suggest using `return next()` to stop middleware execution #5866
+ * docs(connection): improve connection string query param docs #5864
+ * fix(document): run validate hooks on array subdocs even if not directly modified #5861
+ * fix(discriminator): don't treat $meta as defining projection when querying #5859
+ * fix(types): handle Decimal128 when using bson-ext on server side #5850
+ * fix(document): ensure projection with only $slice isn't treated as inclusive for discriminators #4991
+ * fix(model): throw error when passing non-object to create() #2037
+
+4.13.6 / 2017-12-02
+===================
+ * fix(schema): support strictBool option in schema #5856 [ekulabuhov](https://github.com/ekulabuhov)
+ * fix(update): make upsert option consistently handle truthy values, not just booleans, for updateOne() #5839
+ * refactor: remove unnecessary constructor check #2057
+ * docs(query): correct function signature for .mod() helper #1806
+ * fix(query): report ObjectParameterError when passing non-object as filter to find() and findOne() #1698
+
+4.13.5 / 2017-11-24
+===================
+ * fix(model): handle update cast errors correctly with bulkWrite #5845 [Michael77](https://github.com/Michael77)
+ * docs: add link to bufferCommands option #5844 [ralphite](https://github.com/ralphite)
+ * fix(model): allow virtual ref function to return arrays #5834 [brunohcastro](https://github.com/brunohcastro)
+ * fix(query): don't throw uncaught error if query filter too big #5812
+ * fix(document): if setting unselected nested path, don't overwrite nested path #5800
+ * fix(document): support calling `populate()` on nested document props #5703
+ * fix: add `strictBool` option for schema type boolean #5344 #5211 #4245
+ * docs(faq): add faq re: typeKey #1886
+ * docs(query): add more detailed docs re: options #1702
+
+4.13.4 / 2017-11-17
+===================
+ * fix(aggregate): add chainable .option() helper for setting arbitrary options #5829
+ * fix(aggregate): add `.pipeline()` helper to get the current pipeline #5825
+ * docs: grammar fixes for `unique` FAQ #5823 [mfluehr](https://github.com/mfluehr)
+ * chore: add node 9 to travis #5822 [superheri](https://github.com/superheri)
+ * fix(model): fix infinite recursion with recursive embedded discriminators #5821 [Faibk](https://github.com/Faibk)
+
+4.13.3 / 2017-11-15
+===================
+ * chore: add node 8 to travis #5818 [superheri](https://github.com/superheri)
+ * fix(document): don't apply transforms to nested docs when updating already saved doc #5807
+
+4.13.2 / 2017-11-11
+===================
+ * feat(buffer): add support for subtype prop #5530
+
+4.13.1 / 2017-11-08
+===================
+ * fix: accept multiple paths or array of paths to depopulate #5798 #5797 [adamreisnz](https://github.com/adamreisnz)
+ * fix(document): pass default array as actual array rather than taking first element #5780
+ * fix(model): increment version when $set-ing it in a save() that requires a version bump #5779
+ * fix(query): don't explicitly project in discriminator key if user projected in parent path #5775 #5754
+ * fix(model): cast query option to geoNear() #5765
+ * fix(query): don't treat projection with just $slice as inclusive #5737
+ * fix(discriminator): defer applying embedded discriminator hooks until top-level model is compiled #5706
+ * docs(discriminator): add warning to always attach hooks before calling discriminator() #5706
+
+4.13.0 / 2017-11-02
+===================
+ * feat(aggregate): add $addFields helper #5740 [AyushG3112](https://github.com/AyushG3112)
+ * feat(connection): add connection-level bufferCommands #5720
+ * feat(connection): add createCollection() helper #5712
+ * feat(populate): support setting localField and foreignField to functions #5704 #5602
+ * feat(query): add multipleCastError option for aggregating cast errors when casting update #5609
+ * feat(populate): allow passing a function to virtual ref #5602
+ * feat(schema): add excludeIndexes option to optionally prevent collecting indexes from nested schemas #5575
+ * feat(model): report validation errors from `insertMany()` if using `ordered: false` and `rawResult: true` #5337
+ * feat(aggregate): add pre/post aggregate middleware #5251
+ * feat(schema): allow using `set` as a schema path #1939
+
+4.12.6 / 2017-11-01
+===================
+ * fix(schema): make clone() copy query helpers correctly #5752
+ * fix: undeprecate `ensureIndex()` and use it by default #3280
+
+4.12.5 / 2017-10-29
+===================
+ * fix(query): correctly handle `$in` and required for $pull and update validators #5744
+ * feat(aggegate): add $addFields pipeline operator #5740 [AyushG3112](https://github.com/AyushG3112)
+ * fix(document): catch sync errors in document pre hooks and report as error #5738
+ * fix(populate): handle slice projections correctly when automatically selecting populated fields #5737
+ * fix(discriminator): fix hooks for embedded discriminators #5706 [wlingke](https://github.com/wlingke)
+ * fix(model): throw sane error when customer calls `mongoose.Model()` over `mongoose.model()` #2005
+
+4.12.4 / 2017-10-21
+===================
+ * test(plugins): add coverage for idGetter with id as a schema property #5713 [wlingke](https://github.com/wlingke)
+ * fix(model): avoid copying recursive $$context object when creating discriminator after querying #5721
+ * fix(connection): ensure connection promise helpers are removed before emitting 'connected' #5714
+ * docs(schema): add notes about runSettersOnQuery to schema setters #5705
+ * fix(collection): ensure queued operations run on the next tick #5562
+
+4.12.3 / 2017-10-16
+===================
+ * fix(connection): emit 'reconnect' event as well as 'reconnected' for consistency with driver #5719
+ * fix: correctly bubble up left/joined events for replica set #5718
+ * fix(connection): allow passing in `autoIndex` as top-level option rather than requiring `config.autoIndex` #5711
+ * docs(connection): improve docs regarding reconnectTries, autoReconnect, and bufferMaxEntries #5711
+ * fix(query): handle null with addToSet/push/pull/pullAll update validators #5710
+ * fix(model): handle setDefaultsOnInsert option for bulkWrite updateOne and updateMany #5708
+ * fix(query): avoid infinite recursion edge case when cloning a buffer #5702
+
+4.12.2 / 2017-10-14
+===================
+ * docs(faq): add FAQ about using arrow functions for getters/setters, virtuals, and methods #5700
+ * docs(schema): document the childSchemas property and add to public API #5695
+ * fix(query): don't project in populated field if parent field is already projected in #5669
+ * fix: bump mongodb -> 2.2.33 for issue with autoReconnect #4513
+
+4.12.1 / 2017-10-08
+===================
+ * fix(document): create new doc when setting single nested, no more set() on copy of priorVal #5693
+ * fix(model): recursively call applyMethods on child schemas for global plugins #5690
+ * docs: fix bad promise lib example on home page #5686
+ * fix(query): handle false when checking for inclusive/exclusive projection #5685
+ * fix(discriminator): allow reusing child schema #5684
+ * fix: make addToSet() on empty array with subdoc trigger manual population #5504
+
+4.12.0 / 2017-10-02
+===================
+ * docs(validation): add docs coverage for ValidatorError.reason #5681
+ * feat(discriminator): always add discriminatorKey to base schema to allow updating #5613
+ * fix(document): make nested docs no longer inherit parent doc's schema props #5586 #5546 #5470
+ * feat(query): run update validators on $pull and $pullAll #5555
+ * feat(query): add .error() helper to query to error out in pre hooks #5520
+ * feat(connection): add dropCollection() helper #5393
+ * feat(schema): add schema-level collation option #5295
+ * feat(types): add `discriminator()` function for single nested subdocs #5244
+ * feat(document): add $isDeleted() getter/setter for better support for soft deletes #4428
+ * feat(connection): bubble up reconnectFailed event when driver gives up reconnecting #4027
+ * fix(query): report error if passing array or other non-object as filter to update query #3677
+ * fix(collection): use createIndex() instead of deprecated ensureIndex() #3280
+
+4.11.14 / 2017-09-30
+====================
+ * chore: add nsp check to the CI build #5679 [hairyhenderson](https://github.com/hairyhenderson)
+ * fix: bump mquery because of security issue with debug package #5677 #5675 [jonathanprl](https://github.com/jonathanprl)
+ * fix(populate): automatically select() populated()-ed fields #5669
+ * fix(connection): make force close work as expected #5664
+ * fix(document): treat $elemMatch as inclusive projection #5661
+ * docs(model/query): clarify which functions fire which middleware #5654
+ * fix(model): make `init()` public and return a promise that resolves when indexes are done building #5563
+
+4.11.13 / 2017-09-24
+====================
+ * fix(query): correctly run replaceOne with update validators #5665 [sime1](https://github.com/sime1)
+ * fix(schema): replace mistype in setupTimestamp method #5656 [zipp3r](https://github.com/zipp3r)
+ * fix(query): avoid throwing cast error for strict: throw with nested id in query #5640
+ * fix(model): ensure class gets combined schema when using class syntax with discriminators #5635
+ * fix(document): handle setting doc array to array of top-level docs #5632
+ * fix(model): handle casting findOneAndUpdate() with overwrite and upsert #5631
+ * fix(update): correctly handle $ in updates #5628
+ * fix(types): handle manual population consistently for unshift() and splice() #5504
+
+4.11.12 / 2017-09-18
+====================
+ * docs(model): asterisk should not render as markdown bullet #5644 [timkinnane](https://github.com/timkinnane)
+ * docs: use useMongoClient in connection example #5627 [GabrielNicolasAvellaneda](https://github.com/GabrielNicolasAvellaneda)
+ * fix(connection): call callback when initial connection failed #5626
+ * fix(query): apply select correctly if a given nested schema is used for 2 different paths #5603
+ * fix(document): add graceful fallback for setting a doc array value and `pull()`-ing a doc #3511
+
+4.11.11 / 2017-09-10
+====================
+ * fix(connection): properly set readyState in response to driver 'close' and 'reconnect' events #5604
+ * fix(document): ensure single embedded doc setters only get called once, with correct value #5601
+ * fix(timestamps): allow enabling updatedAt without createdAt #5598
+ * test: improve unique validator test by making create run before ensureIndex #5595 #5562
+ * fix(query): ensure find callback only gets called once when post init hook throws error #5592
+
+4.11.10 / 2017-09-03
+====================
+ * docs: add KeenIO tracking #5612
+ * fix(schema): ensure validators declared with `.validate()` get copied with clone() #5607
+ * fix: remove unnecessary jest warning #5480
+ * fix(discriminator): prevent implicit discriminator schema id from clobbering base schema custom id #5591
+ * fix(schema): hide schema objectid warning for non-hex strings of length 24 #5587
+ * docs(populate): use story schema defined key author instead of creator #5578 [dmric](https://github.com/dmric)
+ * docs(document): describe usage of `.set()` #5576
+ * fix(document): ensure correct scope in single nested validators #5569
+ * fix(populate): don't mark path as populated until populate() is done #5564
+ * fix(document): make push()-ing a doc onto an empty array act as manual population #5504
+ * fix(connection): emit timeout event on socket timeout #4513
+
+4.11.9 / 2017-08-27
+===================
+ * fix(error): avoid using arguments.callee because that breaks strict mode #5572
+ * docs(schematypes): fix spacing #5567
+ * fix(query): enforce binary subtype always propagates to mongodb #5551
+ * fix(query): only skip castForQuery for mongoose arrays #5536
+ * fix(browser): rely on browser entrypoint to decide whether to use BrowserDocument or NodeDocument #5480
+
+4.11.8 / 2017-08-23
+===================
+ * feat: add warning about using schema ObjectId as type ObjectId #5571 [efkan](https://github.com/efkan)
+ * fix(schema): allow setting `id` property after schema was created #5570 #5548
+ * docs(populate): remove confusing _ from populate docs #5560
+ * fix(connection): expose parsed uri fields (host, port, dbname) when using openUri() #5556
+ * docs: added type boolean to options documentation #5547 [ndabAP](https://github.com/ndabAP)
+ * test: add test coverage for stopping/starting server #5524
+ * fix(aggregate): pull read preference from schema by default #5522
+
+4.11.7 / 2017-08-14
+===================
+ * fix: correct properties when calling toJSON() on populated virtual #5544 #5442 [davidwu226](https://github.com/davidwu226)
+ * docs: fix spelling #5535 [et](https://github.com/et)
+ * fix(error): always set name before stack #5533
+ * fix: add warning about running jest in jsdom environment #5532 #5513 #4943
+ * fix(document): ensure overwriting a doc array cleans out individual docs #5523
+ * fix(schema): handle creating arrays of single nested using type key #5521
+ * fix: upgrade mongodb -> 2.2.31 to support user/pass options #5419
+
+4.11.6 / 2017-08-07
+===================
+ * fix: limiting number of async operations per time in insertMany #5529 [andresattler](https://github.com/andresattler)
+ * fix: upgrade mongodb -> 2.2.30 #5517
+ * fix(browserDocument): prevent stack overflow caused by double-wrapping embedded doc save() in jest #5513
+ * fix(document): clear single nested doc when setting to empty object #5506
+ * fix(connection): emit reconnected and disconnected events correctly with useMongoClient #5498
+ * fix(populate): ensure nested virtual populate gets set even if top-level property is null #5431
+
+4.11.5 / 2017-07-30
+===================
+ * docs: fix link to $lookup #5516 [TalhaAwan](https://github.com/TalhaAwan)
+ * fix: better parallelization for eachAsync #5502 [lchenay](https://github.com/lchenay)
+ * docs(document): copy docs for save from model to doc #5493
+ * fix(document): handle dotted virtuals in toJSON output #5473
+ * fix(populate): restore user-provided limit after mutating so cursor() works with populate limit #5468
+ * fix(query): don't throw StrictModeError if geo query with upsert #5467
+ * fix(populate): propagate readPreference from query to populate queries by default #5460
+ * docs: warn not to use arrow functions for statics and methods #5458
+ * fix(query): iterate over all condition keys for setDefaultsOnInsert #5455
+ * docs(connection): clarify server/replset/mongos option deprecation with useMongoClient #5442
+
+4.11.4 / 2017-07-23
+===================
+ * fix: handle next() errors in `eachAsync()` #5486 [lchenay](https://github.com/lchenay)
+ * fix(schema): propagate runSettersOnQuery option to implicitly created schemas #5479 [https://github.com/ValYouW]
+ * fix(query): run castConditions() correctly in update ops #5477
+ * fix(query): ensure castConditions called for findOne and findOneAnd* #5477
+ * docs: clarify relationship between $lookup and populate #5475 [TalhaAwan](https://github.com/TalhaAwan)
+ * test: add coverage for arrays of arrays [zbjornson](https://github.com/zbjornson)
+ * fix(middleware): ensure that error handlers for save get doc as 2nd param #5466
+ * fix: handle strict: false correctly #5454 #5453 [wookieb](https://github.com/wookieb)
+ * fix(query): apply schema excluded paths if only projection is a $slice #5450
+ * fix(query): correct discriminator handling for schema `select: false` fields in schema #5448
+ * fix(cursor): call next() in series when parallel option used #5446
+ * chore: load bundled driver first to avoid packaging problem #5443 [prototypeme](https://github.com/prototypeme)
+ * fix(query): defer condition casting until final exec #5434
+ * fix(aggregate): don't rely on mongodb aggregate to put a cursor in the callback #5394
+ * docs(aggregate): add useMongooseAggCursor docs #5394
+ * docs(middleware): clarify context for document, query, and model middleware #5381
+
+4.11.3 / 2017-07-14
+===================
+ * fix(connection): remove .then() before resolving to prevent infinite recursion #5471
+
+4.11.2 / 2017-07-13
+===================
+ * docs: fix comment typo in connect example #5435 [ConnorMcF](https://github.com/ConnorMcF)
+ * fix(update): correctly cast document array in update validators with exec() #5430
+ * fix(connection): handle autoIndex with useMongoClient #5423
+ * fix(schema): handle `type: [Array]` in schemas #5416
+ * fix(timestamps): if overwrite is set and there's a $set, use $set instead of top-level update #5413
+ * fix(document): don't double-validate deeply nested doc array elements #5411
+ * fix(schematype): clone default objects so default not shared across object instances unless `shared` specified #5407
+ * fix(document): reset down the nested subdocs when resetting parent doc #5406
+ * fix: don't pass error arg twice to error handlers #5405
+ * fix(connection): make openUri() return connection decorated with then() and catch() #5404
+ * fix: enforce $set on an array must be an array #5403
+ * fix(document): don't crash if calling `validateSync()` after overwriting doc array index #5389
+ * fix(discriminator): ensure discriminator key doesn't count as user-selected field for projection #4629
+
+4.11.1 / 2017-07-02
+===================
+* docs: populate virtuals fix justOne description #5427 [fredericosilva](https://github.com/fredericosilva)
+ * fix(connection): make sure to call onOpen in openUri() #5404
+ * docs(query): justOne is actually single, and it default to false #5402 [zbjornson](https://github.com/zbjornson)
+ * docs: fix small typo in lib/schema.js #5398 #5396 [pjo336](https://github.com/pjo336)
+ * fix: emit remove on single nested subdocs when removing parent #5388
+ * fix(update): handle update with defaults and overwrite but no update validators #5384
+ * fix(populate): handle undefined refPath values in middle of array #5377
+ * fix(document): ensure consistent setter context for single nested #5363
+ * fix(query): support runSettersOnQuery as query option #5350
+
+4.11.0 / 2017-06-25
+===================
+ * feat(query): execute setters with query as context for `runSettersOnQuery` #5339
+ * feat(model): add translateAliases function #5338 [rocketspacer](https://github.com/rocketspacer)
+ * feat(connection): add `useMongoClient` and `openUri` functions, deprecate current connect logic #5304
+ * refactor(schema): make id virtual not access doc internals #5279
+ * refactor: handle non-boolean lean #5279
+ * feat(cursor): add addCursorFlag() support to query and agg cursors #4814
+ * feat(cursor): add parallel option to eachAsync #4244
+ * feat(schema): allow setting custom error constructor for custom validators #4009
+
+4.10.8 / 2017-06-21
+===================
+ * docs: fix small formatting typo on schematypes #5374 [gianpaj](https://github.com/gianpaj)
+ * fix(model): allow null as an _id #5370
+ * fix(populate): don't throw async uncaught exception if model not found in populate #5364
+ * fix: correctly cast decimals in update #5361
+ * fix(error): don't use custom getter for ValidationError message #5359
+ * fix(query): handle runSettersOnQuery in built-in _id setter #5351
+ * fix(document): ensure consistent context for nested doc custom validators #5347
+
+4.10.7 / 2017-06-18
+===================
+ * docs(validation): show overriding custom validator error with 2nd cb arg #5358
+ * fix: `parseOption` mutates user passed option map #5357 [igwejk](https://github.com/igwejk)
+ * docs: fix guide.jade typo #5356 [CalebAnderson2014](https://github.com/CalebAnderson2014)
+ * fix(populate): don't set populate virtual to ids when match fails #5336
+ * fix(query): callback with cast error if remove and delete* args have a cast error #5323
+
+4.10.6 / 2017-06-12
+===================
+ * fix(cursor): handle custom model option for populate #5334
+ * fix(populate): handle empty virtual populate with Model.populate #5331
+ * fix(model): make ensureIndexes() run with autoIndex: false unless called internally #5328 #5324 #5317
+ * fix: wait for all connections to close before resolving disconnect() promise #5316
+ * fix(document): handle setting populated path with custom typeKey in schema #5313
+ * fix(error): add toJSON helper to ValidationError so `message` shows up with JSON.stringify #5309
+ * feat: add `getPromiseConstructor()` to prevent need for `mongoose.Promise.ES6` #5305
+ * fix(document): handle conditional required with undefined props #5296
+ * fix(model): clone options before inserting in save() #5294
+ * docs(populate): clarify that multiple populate() calls on same path overwrite #5274
+
+4.10.5 / 2017-06-06
+===================
+ * chore: improve contrib guide for building docs #5312
+ * fix(populate): handle init-ing nested virtuals properly #5311
+ * fix(update): report update validator error if required path under single nested doc not set
+ * fix(schema): remove default validate pre hook that was causing issues with jest #4943
+
+4.10.4 / 2017-05-29
+===================
+ * chore: dont store test data in same directory #5303
+ * chore: add data dirs to npmignore #5301 [Starfox64](https://github.com/Starfox64)
+ * docs(query): add docs about runSettersOnQuery #5300
+
+4.10.3 / 2017-05-27
+===================
+ * docs: correct inconsistent references to updateOne and replaceOne #5297 [dhritzkiv](https://github.com/dhritzkiv)
+ * docs: fix dropdowns in docs #5292 [nathanallen](https://github.com/nathanallen)
+ * docs: add description of alias option #5287
+ * fix(document): prevent infinite loop if validating nested array #5282
+ * fix(schema): correctly handle ref ObjectIds from different mongoose libs #5259
+ * fix(schema): load child class methods after base class methods to allow override #5227
+
+4.10.2 / 2017-05-22
+===================
+ * fix: bump ms -> 2.0.0 and mquery -> 2.3.1 for minor security vulnerability #5275
+
+4.10.1 / 2017-05-21
+===================
+ * fix(aggregate): handle sorting by text score correctly #5258
+ * fix(populate): handle doc.populate() with virtuals #5240
+ * fix(schema): enforce that `_id` is never null #5236
+
+4.10.0 / 2017-05-18
+===================
+ * fix(schema): update clone method to include indexes #5268 [clozanosanchez](https://github.com/clozanosanchez)
+ * feat(schema): support aliases #5184 [rocketspacer](https://github.com/rocketspacer)
+ * feat(aggregate): add mongoose-specific aggregation cursor option #5145
+ * refactor(model): make sharding into a plugin instead of core #5105
+ * fix(document): make nested doc mongoose internals not enumerable again #5078
+ * feat(model): pass params to pre hooks #5064
+ * feat(timestamps): support already defined timestamp paths in schema #4868
+ * feat(query): add runSettersOnQuery option #4569
+ * fix(query): add strictQuery option that throws when not querying on field not in schema #4136
+ * fix(update): more complete handling for overwrite option with update validators #3556
+ * feat: support `unique: true` in arrays via the mongoose-unique-array plugin #3347
+ * fix(model): always emit 'index', even if no indexes #3347
+ * fix(schema): set unique indexes on primitive arrays #3347
+ * feat(validation): include failed paths in error message and inspect output #3064 #2135
+ * fix(model): return saved docs when create() fails #2190
+
+4.9.10 / 2017-05-17
+===================
+ * fix(connection): ensure callback arg to openSet() is handled properly #5249
+ * docs: remove dead plugins repo and add content links #5247
+ * fix(model): skip index build if connecting after model init and autoIndex false #5176
+
+4.9.9 / 2017-05-13
+==================
+ * docs: correct value for Query#regex() #5230
+ * fix(connection): don't throw if .catch() on open() promise #5229
+ * fix(schema): allow update with $currentDate for updatedAt to succeed #5222
+ * fix(model): versioning doesn't fail if version key undefined #5221 [basileos](https://github.com/basileos)
+ * fix(document): don't emit model error if callback specified for consistency with docs #5216
+ * fix(document): handle errors in subdoc pre validate #5215
+
+4.9.8 / 2017-05-07
+==================
+ * docs(subdocs): rewrite subdocs guide #5217
+ * fix(document): avoid circular JSON if error in doc array under single nested subdoc #5208
+ * fix(document): set intermediate empty objects for deeply nested undefined paths before path itself #5206
+ * fix(schema): throw error if first param to schema.plugin() is not a function #5201
+ * perf(document): major speedup in validating subdocs (50x in some cases) #5191
+
+4.9.7 / 2017-04-30
+==================
+ * docs: fix typo #5204 [phutchins](https://github.com/phutchins)
+ * fix(schema): ensure correct path for deeply nested schema indexes #5199
+ * fix(schema): make remove a reserved name #5197
+ * fix(model): handle Decimal type in insertMany correctly #5190
+ * fix: upgrade kareem to handle async pre hooks correctly #5188
+ * docs: add details about unique not being a validator #5179
+ * fix(validation): handle returning a promise with isAsync: true #5171
+
+4.9.6 / 2017-04-23
+==================
+ * fix: update `parentArray` references when directly assigning document arrays #5192 [jhob](https://github.com/jhob)
+ * docs: improve schematype validator docs #5178 [milesbarr](https://github.com/milesbarr)
+ * fix(model): modify discriminator() class in place #5175
+ * fix(model): handle bulkWrite updateMany casting #5172 [tzellman](https://github.com/tzellman)
+ * docs(model): fix replaceOne example for bulkWrite #5168
+ * fix(document): don't create a new array subdoc when creating schema array #5162
+ * fix(model): merge query hooks from discriminators #5147
+ * fix(document): add parent() function to subdocument to match array subdoc #5134
+
+4.9.5 / 2017-04-16
+==================
+ * fix(query): correct $pullAll casting of null #5164 [Sebmaster](https://github.com/Sebmaster)
+ * docs: add advanced schemas docs for loadClass #5157
+ * fix(document): handle null/undefined gracefully in applyGetters() #5143
+ * fix(model): add resolveToObject option for mapReduce with ES6 promises #4945
+
+4.9.4 / 2017-04-09
+==================
+ * fix(schema): clone query middleware correctly #5153 #5141 [clozanosanchez](https://github.com/clozanosanchez)
+ * docs(aggregate): fix typo #5142
+ * fix(query): cast .$ update to underlying array type #5130
+ * fix(populate): don't mutate populate result in place #5128
+ * fix(query): handle $setOnInsert consistent with $set #5126
+ * docs(query): add strict mode option for findOneAndUpdate #5108
+
+4.9.3 / 2017-04-02
+==================
+ * docs: document.js fixes for functions prepended with `$` #5131 [krmannix](https://github.com/krmannix)
+ * fix: Avoid exception on constructor check #5129 [monkbroc](https://github.com/monkbroc)
+ * docs(schematype): explain how to use `isAsync` with validate() #5125
+ * docs(schematype): explain custom message with required function #5123
+ * fix(populate): only apply refPath duplicate id optimization if not array #5114
+ * fix(document): copy non-objects to doc when init() #5111
+ * perf(populate): dont clone whole options every time #5103
+ * feat(document): add isDirectSelected() to minimize isSelected() changes #5063
+ * docs(schematypes): explain some subtleties with arrays #5059
+
+4.9.2 / 2017-03-26
+==================
+ * fix(discriminator): handle class names consistently #5104
+ * fix(schema): make clone() work with reusing discriminator schemas #5098
+ * fix(querycursor): run pre find hooks with .cursor() #5096
+ * fix(connection): throw error if username:password includes @ or : #5091
+ * fix(timestamps): handle overwriting createdAt+updatedAt consistently #5088
+ * fix(document): ensure subdoc post save runs after parent save #5085
+ * docs(model): improve update docs #5076 [bertolo1988](https://github.com/bertolo1988)
+
+4.9.1 / 2017-03-19
+==================
+ * fix(query): handle $type for arrays #5080 #5079 [zoellner](https://github.com/zoellner)
+ * fix(model): handle ordered param for `insertMany` validation errors #5072 [sjorssnoeren](https://github.com/sjorssnoeren)
+ * fix(populate): avoid duplicate ids in dynref queries #5054
+ * fix(timestamps): dont set timestamps in update if user set it #5045
+ * fix(update): dont double-call setters on arrays #5041
+ * fix: upgrade driver -> 2.2.25 for jest fix #5033
+ * fix(model): get promise each time save() is called rather than once #5030
+ * fix(connection): make connect return value consistent #5006
+
+4.9.0 / 2017-03-13
+==================
+ * feat(document): return this from `depopulate()` #5027
+ * fix(drivers): stop emitting timeouts as errors #5026
+ * feat(schema): add a clone() function for schemas #4983
+ * feat(query): add rawResult option to replace passRawResult, deprecate passRawResult #4977 #4925
+ * feat(schematype): support isAsync validator option and handle returning promises from validators, deprecate implicit async validators #4290
+ * feat(query): add `replaceOne()`, `deleteOne()`, `deleteMany()` #3998
+ * feat(model): add `bulkWrite()` #3998
+
+4.8.7 / 2017-03-12
+==================
+ * fix(model): if last arg in spread is falsy, treat it as a callback #5061
+ * fix(document): use $hook instead of hook to enable 'hook' as a path name #5047
+ * fix(populate): dont select foreign field if parent field is selected #5037
+ * fix(populate): handle passing no args to query.populate #5036
+ * fix(update): use correct method for casting nested arrays #5032
+ * fix(discriminator): handle array discriminators when casting $push #5009
+
+4.8.6 / 2017-03-05
+==================
+ * docs(document): remove text that implies that transform is false by default #5023
+ * fix(applyHooks): dont wrap a function if it is already wrapped #5019
+ * fix(document): ensure nested docs' toObject() clones #5008
+
+4.8.5 / 2017-02-25
+==================
+ * fix: check for empty schemaPath before accessing property $isMongooseDocumentArray #5017 [https://github.com/randyhoulahan](randyhoulahan)
+ * fix(discriminators): handle create() and push() for embedded discriminators #5001
+ * fix(querycursor): ensure close emitted after last data event #4998
+ * fix(discriminators): remove fields not selected in child when querying by base model #4991
+
+4.8.4 / 2017-02-19
+==================
+ * docs(discriminators): explain embedded discriminators #4997
+ * fix(query): fix TypeError when findOneAndUpdate errors #4990
+ * fix(update): handle nested single embedded in update validators correctly #4989
+ * fix(browser): make browser doc constructor not crash #4987
+
+4.8.3 / 2017-02-15
+==================
+ * chore: upgrade mongodb driver -> 2.2.24
+ * docs(connections): addd some details about callbacks #4986
+ * fix: ensure class is created with new keyword #4972 #4947 [benhjames](https://github.com/benhjames)
+ * fix(discriminator): add applyPluginsToDiscriminators option #4965
+ * fix(update): properly cast array subdocs when casting update #4960
+ * fix(populate): ensure foreign field is selected for virtual populate #4959
+ * docs(query): document some query callback params #4949
+ * fix(document): ensure errors in validators get caught #2185
+
+4.8.2 / 2017-02-10
+==================
+ * fix(update): actually run validators on addToSet #4953
+ * fix(update): improve buffer error handling #4944 [ValYouW](https://github.com/ValYouW)
+ * fix(discriminator): handle subclassing with loadClass correctly #4942
+ * fix(query): allow passing Map to sort() #4941
+ * fix(document): handle setting discriminator doc #4935
+ * fix(schema): return correct value from pre init hook #4928
+ * fix(query): ensure consistent params in error handlers if pre hook errors #4927
+
+4.8.1 / 2017-01-30
+==================
+ * fix(query): handle $exists for arrays and embedded docs #4937
+ * fix(query): handle passing string to hint() #4931
+
+4.8.0 / 2017-01-28
+==================
+ * feat(schema): add saveErrorIfNotFound option and $where property #4924 #4004
+ * feat(query): add $in implicitly if passed an array #4912 [QuotableWater7](https://github.com/QuotableWater7)
+ * feat(aggregate): helper for $facet #4904 [varunjayaraman](https://github.com/varunjayaraman)
+ * feat(query): add collation method #4839
+ * feat(schema): propogate strict option to implicit array subschemas #4831 [dkrosso](https://github.com/dkrosso)
+ * feat(aggregate): add helper for graphLookup #4819 [varunjayaraman](https://github.com/varunjayaraman)
+ * feat(types): support Decimal128 #4759
+ * feat(aggregate): add eachAsync() to aggregate cursor #4300
+ * feat(query): add updateOne and updateMany #3997
+ * feat(model): support options for insertMany #3893
+ * fix(document): run validation on single nested docs if not directly modified #3884
+ * feat(model): use discriminator constructor based on discriminatorKey in create() #3624
+ * feat: pass collection as context to debug function #3261
+ * feat(query): support push and addToSet for update validators #2933
+ * perf(document): refactor registerHooksFromSchema so hooks are defined on doc prototype #2754
+ * feat(types): add discriminator() function to doc arrays #2723 #1856
+ * fix(populate): return an error if sorting underneath a doc array #2202
+
+4.7.9 / 2017-01-27
+==================
+ * fix(query): handle casting $exists under $not #4933
+ * chore: upgrade mongodb -> 2.2.22 re: #4931
+
+4.7.8 / 2017-01-23
+==================
+ * fix(populate): better handling for virtual populate under arrays #4923
+ * docs: upgrade contributors count #4918 [AdamZaczek](https://github.com/AdamZaczek)
+ * fix(query): don't set nested path default if setting parent path #4911
+ * docs(promise): add missing bracket #4907
+ * fix(connection): ensure error handling is consistently async #4905
+ * fix: handle authMechanism in query string #4900
+ * fix(document): ensure error handlers run for validate #4885
+
+4.7.7 / 2017-01-15
+==================
+ * fix(utils): don't crash if to[key] is null #4881
+ * fix: upgrade mongodb -> 2.2.21 #4867
+ * fix: add a toBSON to documents for easier querying #4866
+ * fix: suppress bluebird warning #4854 [davidwu226](https://github.com/davidwu226)
+ * fix(populate): handle nested virtuals in virtual populate #4851
+
+4.7.6 / 2017-01-02
+==================
+ * fix(model): allow passing non-array to insertMany #4846
+ * fix(populate): use base model name if no discriminator for backwards compat #4843
+ * fix: allow internal validate callback to be optional #4842 [arciisine](https://github.com/arciisine)
+ * fix(document): don't skip pointCut if save not defined (like in browser doc) #4841
+ * chore: improve benchmarks #4838 [billouboq](https://github.com/billouboq)
+ * perf: remove some unused parameters #4837 [billouboq](https://github.com/billouboq)
+ * fix(query): don't call error handler if passRawResult is true and no error occurred #4836
+
+4.7.5 / 2016-12-26
+==================
+ * docs(model): fix spelling mistake #4828 [paulinoj](https://github.com/paulinoj)
+ * fix(aggregate): remove unhandled rejection when using aggregate.then() #4824
+ * perf: remove try/catch that kills optimizer #4821
+ * fix(model): handles populating with discriminators that may not have a ref #4817
+ * fix(document): handle setting array of discriminators #3575
+
+4.7.4 / 2016-12-21
+==================
+ * docs: fix typo #4810 [GEEKIAM](https://github.com/GEEKIAM)
+ * fix(query): timestamps with $push + $each #4805
+ * fix(document): handle buffers correctly in minimize #4800
+ * fix: don't disallow overwriting default and cast fns #4795 [pdspicer](https://github.com/pdspicer)
+ * fix(document): don't convert single nested docs to POJOs #4793
+ * fix(connection): handle reconnect to replica set correctly #4972 [gfzabarino](https://github.com/gfzabarino)
+
+4.7.3 / 2016-12-16
+==================
+ * fix: upgrade mongodb driver -> 2.2.16 for several bug fixes and 3.4 support #4799
+ * fix(model): ensure discriminator key is correct for child schema on discriminator #4790
+ * fix(document): handle mark valid in subdocs correctly #4778
+ * fix(query): check for objects consistently #4775
+
+4.7.2 / 2016-12-07
+==================
+ * test(populate): fix justOne test #4772 [cblanc](https://github.com/cblanc)
+ * chore: fix benchmarks #4769 [billouboq](https://github.com/billouboq)
+ * fix(document): handle setting subdoc to null after setting parent doc #4766
+ * fix(query): support passRawResult with lean #4762 #4761 [mhfrantz](https://github.com/mhfrantz)
+ * fix(query): throw StrictModeError if upsert with nonexisting field in condition #4757
+ * test: fix a couple of sort tests #4756 [japod](https://github.com/japod)
+ * chore: upgrade mongodb driver -> 2.2.12 #4753 [mdlavin](https://github.com/mdlavin)
+ * fix(query): handle update with upsert and overwrite correctly #4749
+
+4.7.1 / 2016-11-30
+==================
+ * fix(schema): throw error if you use prototype as a schema path #4746
+ * fix(schema): throw helpful error if you define a virtual with the same path as a real path #4744
+ * fix(connection): make createConnection not throw rejected promises #4742
+ * fix(populate): allow specifiying options in model schema #4741
+ * fix(document): handle selected nested elements with defaults #4739
+ * fix(query): add model to cast error if possible #4729
+ * fix(query): handle timestamps with overwrite #4054
+
+4.7.0 / 2016-11-23
+==================
+ * docs: clean up schematypes #4732 [kidlj](https://github.com/kidlj)
+ * perf: only get stack when necessary with VersionError #4726 [Sebmaster](https://github.com/Sebmaster)
+ * fix(query): ensure correct casting when setting array element #4724
+ * fix(connection): ensure db name gets set when you pass 4 params #4721
+ * fix: prevent TypeError in node v7 #4719 #4706
+ * feat(document): support .set() on virtual subpaths #4716
+ * feat(populate): support populate virtuals on nested schemas #4715
+ * feat(querycursor): support transform option and .map() #4714 #4705 [cblanc](https://github.com/cblanc)
+ * fix(document): dont set defaults on not-selected nested paths #4707
+ * fix(populate): don't throw if empty string passed to populate #4702
+ * feat(model): add `loadClass()` function for importing schema from ES6 class #4668 [rockmacaca](https://github.com/rockmacaca)
+
+4.6.8 / 2016-11-14
+==================
+ * fix(querycursor): clear stack when iterating onto next doc #4697
+ * fix: handle null keys in validation error #4693 #4689 [arciisine](https://github.com/arciisine)
+ * fix(populate): handle pre init middleware correctly with populate virtuals #4683
+ * fix(connection): ensure consistent return value for open and openSet #4659
+ * fix(schema): handle falsy defaults for arrays #4620
+
+4.6.7 / 2016-11-10
+==================
+ * fix(document): only invalidate in subdoc if using update validators #4681
+ * fix(document): don't create subdocs when excluded in projection #4669
+ * fix(document): ensure single embedded schema validator runs with correct context #4663
+ * fix(document): make sure to depopulate top level for sharding #4658
+ * fix(connection): throw more helpful error when .model() called incorrectly #4652
+ * fix(populate): throw more descriptive error when trying to populate a virtual that doesn't have proper options #4602
+ * fix(document): ensure subtype gets set properly when saving with a buffer id #4506
+ * fix(query): handle setDefaultsOnInsert with defaults on doc arrays #4456
+ * fix(drivers): make debug output better by calling toBSON() #4356
+
+4.6.6 / 2016-11-03
+==================
+ * chore: upgrade deps #4674 [TrejGun](https://github.com/TrejGun)
+ * chore: run tests on node v7 #4673 [TrejGun](https://github.com/TrejGun)
+ * perf: make setDefaultsOnInsert more efficient if upsert is off #4672 [CamHenlin](https://github.com/CamHenlin)
+ * fix(populate): ensure document array is returned #4656
+ * fix(query): cast doc arrays with positionals correctly for update #4655
+ * fix(document): ensure single nested doc validators run with correct context #4654
+ * fix: handle reconnect failed error in new version of driver #4653 [loris](https://github.com/loris)
+ * fix(populate): if setting a populated doc, take its id #4632
+ * fix(populate): handle populated virtuals in init #4618
+
+4.6.5 / 2016-10-23
+==================
+ * docs: fix grammar issues #4642 #4640 #4639 [silvermanj7](https://github.com/silvermanj7)
+ * fix(populate): filter out nonexistant values for dynref #4637
+ * fix(query): handle $type as a schematype operator #4632
+ * fix(schema): better handling for uppercase: false and lowercase: false #4622
+ * fix(query): don't run transforms on updateForExec() #4621
+ * fix(query): handle id = 0 in findById #4610
+ * fix(query): handle buffers in mergeClone #4609
+ * fix(document): handle undefined with conditional validator for validateSync #4607
+ * fix: upgrade to mongodb driver 2.2.11 #4581
+ * docs(schematypes): clarify schema.path() #4518
+ * fix(query): ensure path is defined before checking in timestamps #4514
+ * fix(model): set version key in upsert #4505
+ * fix(document): never depopulate top-level doc #3057
+ * refactor: ensure sync for setting non-capped collections #2690
+
+4.6.4 / 2016-10-16
+==================
+ * fix(query): cast $not correctly #4616 #4592 [prssn](https://github.com/prssn)
+ * fix: address issue with caching global plugins #4608 #4601 [TrejGun](https://github.com/TrejGun)
+ * fix(model): make sure to depopulate in insertMany #4590
+ * fix(model): buffer autoIndex if bufferCommands disabled #4589
+ * fix(populate): copy ids array before modifying #4585
+ * feat(schema): add retainKeyOrder prop #4542
+ * fix(document): return isModified true for children of direct modified paths #4528
+ * fix(connection): add dropDatabase() helper #4490
+ * fix(model): add usePushEach option for schemas #4455
+ * docs(connections): add some warnings about buffering #4413
+ * fix: add ability to set promise implementation in browser #4395
+
+4.6.3 / 2016-10-05
+==================
+ * fix(document): ensure single nested docs get initialized correctly when setting nested paths #4578
+ * fix: turn off transforms when writing nested docs to db #4574
+ * fix(document): don't set single nested subdocs to null when removing parent doc #4566
+ * fix(model): ensure versionKey gets set in insertMany #4561
+ * fix(schema): handle typeKey in arrays #4548
+ * feat(schema): set $implicitlyCreated on schema if created by interpretAsType #4443
+
+4.6.2 / 2016-09-30
+==================
+ * chore: upgrade to async 2.0.1 internally #4579 [billouboq](https://github.com/billouboq)
+ * fix(types): ensure nested single doc schema errors reach update validators #4557 #4519
+ * fix(connection): handle rs names with leading numbers (muri 1.1.1) #4556
+ * fix(model): don't throw if method name conflicts with Object.prototype prop #4551
+ * docs: fix broken link #4544 [VFedyk](https://github.com/VFedyk)
+ * fix: allow overwriting model on mongoose singleton #4541 [Nainterceptor](https://github.com/Nainterceptor)
+ * fix(document): don't use init: true when building doc defaults #4540
+ * fix(connection): use replSet option if replset not specified #4535
+ * fix(query): cast $not objects #4495
+
+4.6.1 / 2016-09-20
+==================
+ * fix(query): improve handling of $not with $elemMatch #4531 #3719 [timbowhite](https://github.com/timbowhite)
+ * fix: upgrade mongodb -> 2.2.10 #4517
+ * chore: fix webpack build issue #4512 [saiichihashimoto](https://github.com/saiichihashimoto)
+ * fix(query): emit error on next tick when exec callback errors #4500
+ * test: improve test case #4496 [isayme](https://github.com/isayme)
+ * fix(schema): use same check for array types and top-level types #4493
+ * style: fix indentation in docs #4489 [dhurlburtusa](https://github.com/dhurlburtusa)
+ * fix(schema): expose original object passed to constructor #4486
+ * fix(query): handle findOneAndUpdate with array of arrays #4484 #4470 [fedotov](https://github.com/fedotov)
+ * feat(document): add $ignore to make a path ignored #4480
+ * fix(query): properly handle setting single embedded in update #4475 #4466 #4465
+ * fix(updateValidators): handle single nested schema subpaths correctly #4479
+ * fix(model): throw handy error when method name conflicts with property name #4475
+ * fix(schema): handle .set() with array field #4472
+ * fix(query): check nested path when avoiding double-validating Mixed #4441
+ * fix(schema): handle calling path.trim() with no args correctly #4042
+
+4.6.0 / 2016-09-02
+==================
+ * docs(document): clarify the findById and findByIdAndUpdate examples #4471 [mdcanham](https://github.com/mdcanham)
+ * docs(schematypes): add details re: options #4452
+ * docs(middleware): add docs for insertMany hooks #4451
+ * fix(schema): create new array when copying from existing object to preserve change tracking #4449
+ * docs: fix typo in index.jade #4448
+ * fix(query): allow array for populate options #4446
+ * fix(model): create should not cause unhandle reject promise #4439
+ * fix: upgrade to mongodb driver 2.2.9 #4363 #4341 #4311 (see [comments here](https://github.com/mongodb/js-bson/commit/aa0b54597a0af28cce3530d2144af708e4b66bf0#commitcomment-18850498) if you use node 0.10)
+
+4.5.10 / 2016-08-23
+===================
+ * docs: fix typo on documents.jade #4444 [Gabri3l](https://github.com/Gabri3l)
+ * chore: upgrade mocha to 3.0.2 #4437 [TrejGun](https://github.com/TrejGun)
+ * fix: subdocuments causing error with parent timestamp on update #4434 [dyang108](https://github.com/dyang108)
+ * fix(query): don't crash if timestamps on and update doesn't have a path #4425 #4424 #4418
+ * fix(query): ensure single nested subdoc is hydrated when running update validators #4420
+ * fix(query): cast non-$geometry operators for $geoWithin #4419
+ * docs: update contributor count #4415 [AdamZaczek](https://github.com/AdamZaczek)
+ * docs: add more clarification re: the index event #4410
+ * fix(document): only skip modifying subdoc path if parent is direct modified #4405
+ * fix(schema): throw cast error if provided date invalid #4404
+ * feat(error): use util.inspect() so CastError never prints "[object Object]" #4398
+ * fix(model): dont error if the discriminator key is unchanged #4387
+ * fix(query): don't throw unhandled rejection with bluebird when using cbs #4379
+
+4.5.9 / 2016-08-14
+==================
+ * docs: add mixed schema doc for Object literal #4400 [Kikobeats](https://github.com/Kikobeats)
+ * fix(query): cast $geoWithin and convert mongoose objects to POJOs before casting #4392
+ * fix(schematype): dont cast defaults without parent doc #4390
+ * fix(query): disallow passing empty string to findOne() #4378
+ * fix(document): set single nested doc isNew correctly #4369
+ * fix(types): checks field name correctly with nested arrays and populate #4365
+ * fix(drivers): make debug output copy-pastable into mongodb shell #4352
+ * fix(services): run update validators on nested paths #4332
+ * fix(model): handle typeKey with discriminators #4339
+ * fix(query): apply timestamps to child schemas when explicitly specified in update #4049
+ * fix(schema): set prefix as nested path with add() #1730
+
+4.5.8 / 2016-08-01
+==================
+ * fix(model): make changing the discriminator key cause a cast error #4374
+ * fix(query): pass projection fields to cursor #4371 #4342 [Corei13](https://github.com/Corei13)
+ * fix(document): support multiple paths for isModified #4370 [adambuczynski](https://github.com/adambuczynski)
+ * fix(querycursor): always cast fields before returning cursor #4355
+ * fix(query): support projection as alias for fields in findOneAndUpdate #4315
+ * fix(schema): treat index false + unique false as no index #4304
+ * fix(types): dont mark single nested subpath as modified if whole doc already modified #4224
+
+4.5.7 / 2016-07-25
+==================
+ * fix(document): ensure no unhandled rejections if callback specified for save #4364
+
+4.5.6 / 2016-07-23
+==================
+ * fix(schema): don't overwrite createdAt if it isn't selected #4351 [tusbar](https://github.com/tusbar)
+ * docs(api): fix link to populate() and add a new one from depopulate() #4345 [Delapouite](https://github.com/Delapouite)
+ * fix(types): ownerDocument() works properly with single nested docs #4344 [vichle](https://github.com/vichle)
+ * fix(populate): dont use findOne when justOne option set #4329
+ * fix(document): dont trigger .then() deprecated warning when calling doc.remove() #4291
+ * docs(connection): add promiseLibrary option #4280
+ * fix(plugins): apply global plugins to subschemas #4271
+ * fix(model): ensure `ensureIndex()` never calls back in the same tick #4246
+ * docs(schema): improve post hook docs on schema #4238
+
+4.5.5 / 2016-07-18
+==================
+ * fix(document): handle setting root to empty obj if minimize false #4337
+ * fix: downgrade to mongodb 2.1.18 #4335 #4334 #4328 #4323
+ * perf(types): remove defineProperty usage in documentarray #4333
+ * fix(query): correctly pass model in .toConstructor() #4318
+ * fix(services): avoid double-validating mixed types with update validators #4305
+ * docs(middleware): add docs describing error handling middleware #4229
+ * fix(types): throw correct error when invalidating doc array #3602
+
+4.5.4 / 2016-07-11
+==================
+ * fix(types): fix removing embedded documents #4309 [RoCat](https://github.com/RoCat)
+ * docs: various docs improvements #4302 #4294 [simonxca](https://github.com/simonxca)
+ * fix: upgrade mongodb -> 2.1.21 #4295 #4202 [RoCat](https://github.com/RoCat)
+ * fix(populate): convert single result to array for virtual populate because of lean #4288
+ * fix(populate): handle empty results for populate virtuals properly #4285 #4284
+ * fix(query): dont cast $inc to number if type is long #4283
+ * fix(types): allow setting single nested doc to null #4281
+ * fix(populate): handle deeply nested virtual populate #4278
+ * fix(document): allow setting empty obj if strict mode is false #4274
+ * fix(aggregate): allow passing obj to .unwind() #4239
+ * docs(document): add return statements to transform examples #1963
+
+4.5.3 / 2016-06-30
+==================
+ * fix(query): pass correct options to QueryCursor #4277 #4266
+ * fix(querycursor): handle lean option correctly #4276 [gchudnov](https://github.com/gchudnov)
+ * fix(document): fix error handling when no error occurred #4275
+ * fix(error): use strict mode for version error #4272
+ * docs(populate): fix crashing compilation for populate.jade #4267
+ * fix(populate): support `justOne` option for populate virtuals #4263
+ * fix(populate): ensure model param gets used for populate virtuals #4261 #4243
+ * fix(querycursor): add ability to properly close the cursor #4258
+ * docs(model): correct link to Document #4250
+ * docs(populate): correct path for refPath populate #4240
+ * fix(document): support validator.isEmail as validator #4064
+
+4.5.2 / 2016-06-24
+==================
+ * fix(connection): add checks for collection presence for `onOpen` and `onClose` #4259 [nodkz](https://github.com/nodkz)
+ * fix(cast): allow strings for $type operator #4256
+ * fix(querycursor): support lean() #4255 [pyramation](https://github.com/pyramation)
+ * fix(aggregate): allow setting noCursorTimeout option #4241
+ * fix(document): handle undefined for Array.pull #4222 [Sebmaster](https://github.com/Sebmaster)
+ * fix(connection): ensure promise.catch() catches initial connection error #4135
+ * fix(document): show additional context for VersionError #2633
+
+4.5.1 / 2016-06-18
+==================
+ * fix(model): ensure wrapped insertMany() returns a promise #4237
+ * fix(populate): dont overwrite populateVirtuals when populating multiple paths #4234
+ * docs(model): clarify relationship between create() and save() #4233
+ * fix(types): handle option param in subdoc remove() #4231 [tdebarochez](https://github.com/tdebarochez)
+ * fix(document): dedupe modified paths #4226 #4223 [adambuczynski](https://github.com/adambuczynski)
+ * fix(model): don't modify user-provided options object #4221
+ * fix(document): handle setting nested path to empty object #4218 #4182
+ * fix(document): clean subpaths when removing single nested #4216
+ * fix(document): don't force transform on subdocs with inspect #4213
+ * fix(error): allow setting .messages object #4207
+
+4.5.0 / 2016-06-13
+==================
+ * feat(query): added Query.prototype.catch() #4215 #4173 [adambuczynski](https://github.com/adambuczynski)
+ * feat(query): add Query.prototype.cursor() as a .stream() alternative #4117 #3637 #1907
+ * feat(document): add markUnmodified() function #4092 [vincentcr](https://github.com/vincentcr)
+ * feat(aggregate): convert aggregate object to a thenable #3995 #3946 [megagon](https://github.com/megagon)
+ * perf(types): remove defineProperties call for array (**Note:** Because of this, a mongoose array will no longer `assert.deepEqual()` a plain old JS array) #3886
+ * feat(model): add hooks for insertMany() #3846
+ * feat(schema): add support for custom query methods #3740 #2372
+ * feat(drivers): emit error on 'serverClosed' because that means that reconnect failed #3615
+ * feat(model): emit error event when callback throws exception #3499
+ * feat(model): inherit options from discriminator base schema #3414 #1818
+ * feat(populate): expose mongoose-populate-virtuals inspired populate API #2562
+ * feat(document): trigger remove hooks on subdocs when removing parent #2348
+ * feat(schema): add support for express-style error handling middleware #2284
+ * fix(model): disallow setting discriminator key #2041
+ * feat(schema): add support for nested arrays #1361
+
+4.4.20 / 2016-06-05
+===================
+ * docs: clarify command buffering when using driver directly #4195
+ * fix(promise): correct broken mpromise .catch() #4189
+ * fix(document): clean modified subpaths when set path to empty obj #4182
+ * fix(query): support minDistance with query casting and `.near()` #4179
+ * fix(model): remove unnecessary .save() promise #4177
+ * fix(schema): cast all valid ObjectId strings to object ids #3365
+ * docs: remove unclear "unsafe" term in query docs #3282
+
+4.4.19 / 2016-05-21
+===================
+ * fix(model): handle insertMany if timestamps not set #4171
+
+4.4.18 / 2016-05-21
+===================
+ * docs: add missing period #4170 [gitname](https://github.com/gitname)
+ * docs: change build badge to svg #4158 [a0viedo](https://github.com/a0viedo)
+ * fix(model): update timestamps when setting `createdAt` #4155
+ * fix(utils): make sure to require in document properly #4152
+ * fix(model): throw overwrite error when discriminator name conflicts #4148
+
+4.4.17 / 2016-05-13
+===================
+ * docs: remove repetition in QueryStream docs #4147 [hugoabonizio](https://github.com/hugoabonizio)
+ * fix(document): dont double-validate doc array elements #4145
+ * fix(document): call required function with correct scope #4142 [JedWatson](https://github.com/JedWatson)
+
+4.4.16 / 2016-05-09
+===================
+ * refactor(document): use function reference #4133 [dciccale](https://github.com/dciccale)
+ * docs(querystream): clarify `destroy()` and close event #4126 [AnthonyCC](https://github.com/AnthonyCC)
+ * test: make before hook fail fast if it can't connect #4121
+ * docs: add description of CastError constructor params #4120
+ * fix(schematype): ensure single embedded defaults have $parent #4115
+ * fix(document): mark nested paths for validation #4111
+ * fix(schema): make sure element is always a subdoc in doc array validation #3816
+
+4.4.15 / 2016-05-06
+===================
+ * fix(schema): support overwriting array default #4109
+ * fix(populate): assign values when resolving each populate #4104
+ * fix(aggregate): dont send async option to server #4101
+ * fix(model): ensure isNew set to false after insertMany #4099
+ * fix(connection): emit on error if listeners and no callback #4098
+ * fix(document): treat required fn that returns false as required: false #4094
+
+4.4.14 / 2016-04-27
+===================
+ * fix: upgrade mongodb -> 2.1.18 #4102
+ * feat(connection): allow setting mongos as a uri query param #4093 #4035 [burtonjc](https://github.com/burtonjc)
+ * fix(populate): make sure to use correct assignment order for each model #4073
+ * fix(schema): add complete set of geospatial operators for single embedded subdocs #4014
+
+3.8.40 / 2016-04-24
+===================
+ * upgraded; mquery -> 1.10.0 #3989
+
+4.4.13 / 2016-04-21
+===================
+ * docs: add docs favicons #4082 [robertjustjones](https://github.com/robertjustjones)
+ * docs(model): correct Model.remove() return value #4075 [Jokero](https://github.com/Jokero)
+ * fix(query): add $geoWithin query casting for single embedded docs #4044
+ * fix(schema): handle setting trim option to falsy #4042
+ * fix(query): handle setDefaultsOnInsert with empty update #3835
+
+4.4.12 / 2016-04-08
+===================
+ * docs(query): document context option for update and findOneAndUpdate #4055
+ * docs(query): correct link to $geoWithin docs #4050
+ * fix(project): upgrade to mongodb driver 2.1.16 #4048 [schmalliso](https://github.com/schmalliso)
+ * docs(validation): fix validation docs #4028
+ * fix(types): improve .id() check for document arrays #4011
+ * fix(query): remove premature return when using $rename #3171
+ * docs(connection): clarify relationship between models and connections #2157
+
+4.4.11 / 2016-04-03
+===================
+ * fix: upgrade to mongodb driver 2.1.14 #4036 #4030 #3945
+ * fix(connection): allow connecting with { mongos: true } to handle query params #4032 [burtonjc](https://github.com/burtonjc)
+ * docs(connection): add autoIndex example #4026 [tilleps](https://github.com/tilleps)
+ * fix(query): handle passRawResult option when zero results #4023
+ * fix(populate): clone options before modifying #4022
+ * docs: add missing whitespace #4019 [chenxsan](https://github.com/chenxsan)
+ * chore: upgrade to ESLint 2.4.0 #4015 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix(types): single nested subdocs get ids by default #4008
+ * chore(project): add dependency status badge #4007 [Maheshkumar-Kakade](http://github.com/Maheshkumar-Kakade)
+ * fix: make sure timestamps don't trigger unnecessary updates #4005 #3991 [tommarien](https://github.com/tommarien)
+ * fix(document): inspect inherits schema options #4001
+ * fix(populate): don't mark populated path as modified if setting to object w/ same id #3992
+ * fix(document): support kind argument to invalidate #3965
+
+4.4.10 / 2016-03-24
+===================
+ * fix(document): copy isNew when copying a document #3982
+ * fix(document): don't override defaults with undefined keys #3981
+ * fix(populate): merge multiple deep populate options for the same path #3974
+
+4.4.9 / 2016-03-22
+==================
+ * fix: upgrade mongodb -> 2.1.10 re https://jira.mongodb.org/browse/NODE-679 #4010
+ * docs: add syntax highlighting for acquit examples #3975
+
+4.4.8 / 2016-03-18
+==================
+ * docs(aggregate): clarify promises #3990 [megagon](https://github.com/megagon)
+ * fix: upgrade mquery -> 1.10 #3988 [matskiv](https://github.com/matskiv)
+ * feat(connection): 'all' event for repl sets #3986 [xizhibei](https://github.com/xizhibei)
+ * docs(types): clarify Array.pull #3985 [seriousManual](https://github.com/seriousManual)
+ * feat(query): support array syntax for .sort() via mquery 1.9 #3980
+ * fix(populate): support > 3 level nested populate #3973
+ * fix: MongooseThenable exposes connection correctly #3972
+ * docs(connection): add note about reconnectTries and reconnectInterval #3969
+ * feat(document): invalidate returns the new validationError #3964
+ * fix(query): .eq() as shorthand for .equals #3953 [Fonger](https://github.com/Fonger)
+ * docs(connection): clarify connection string vs passed options #3941
+ * docs(query): select option for findOneAndUpdate #3933
+ * fix(error): ValidationError.properties no longer enumerable #3925
+ * docs(validation): clarify how required validators work with nested schemas #3915
+ * fix: upgrade mongodb driver -> 2.1.8 to make partial index errors more sane #3864
+
+4.4.7 / 2016-03-11
+==================
+ * fix(query): stop infinite recursion caused by merging a mongoose buffer #3961
+ * fix(populate): handle deep populate array -> array #3954
+ * fix(schema): allow setting timestamps with .set() #3952 #3951 #3907 [Fonger](https://github.com/Fonger)
+ * fix: MongooseThenable doesn't overwrite constructors #3940
+ * fix(schema): don't cast boolean to date #3935
+ * fix(drivers): support sslValidate in connection string #3929
+ * fix(types): correct markModified() for single nested subdocs #3910
+ * fix(drivers): catch and report any errors that occur in driver methods #3906
+ * fix(populate): get subpopulate model correctly when array under nested #3904
+ * fix(document): allow fields named 'pre' and 'post' #3902
+ * docs(query): clarify runValidators and setDefaultsOnInsert options #3892
+ * docs(validation): show how to use custom required messages in schema #2616
+
+4.4.6 / 2016-03-02
+==================
+ * fix: upgrade mongodb driver to 2.1.7 #3938
+ * docs: fix plugins link #3917 #3909 [fbertone](https://github.com/fbertone)
+ * fix(query): sort+select with count works #3914
+ * fix(query): improve mergeUpdate's ability to handle nested docs #3890
+
+4.4.5 / 2016-02-24
+==================
+ * fix(query): ability to select a length field (upgrade to mquery 1.7.0) #3903
+ * fix: include nested CastError as reason for array CastError #3897 [kotarou3](https://github.com/kotarou3)
+ * fix(schema): check for doc existence before taking fields #3889
+ * feat(schema): useNestedStrict option to take nested strict mode for update #3883
+ * docs(validation): clarify relationship between required and checkRequired #3822
+ * docs(populate): dynamic reference docs #3809
+ * docs: expand dropdown when clicking on file name #3807
+ * docs: plugins.mongoosejs.io is up #3127
+ * fix(schema): ability to add a virtual with same name as removed path #2398
+
+4.4.4 / 2016-02-17
+==================
+ * fix(schema): handle field selection when casting single nested subdocs #3880
+ * fix(populate): populating using base model with multiple child models in result #3878
+ * fix: ability to properly use return value of `mongoose.connect()` #3874
+ * fix(populate): dont hydrate populated subdoc if lean option set #3873
+ * fix(connection): dont re-auth if already connected with useDb #3871
+ * docs: cover how to set underlying driver's promise lib #3869
+ * fix(document): handle conflicting names in validation errors with subdocs #3867
+ * fix(populate): set undefined instead of null consistently when populate couldn't find results #3859
+ * docs: link to `execPopulate()` in `doc.populate()` docs #3836
+ * docs(plugin): link to the `mongoose.plugin()` function #3732
+
+4.4.3 / 2016-02-09
+==================
+ * fix: upgrade to mongodb 2.1.6 to remove kerberos log output #3861 #3860 [cartuchogl](https://github.com/cartuchogl)
+ * fix: require('mongoose') is no longer a pseudo-promise #3856
+ * fix(query): update casting for single nested docs #3820
+ * fix(populate): deep populating multiple paths with same options #3808
+ * docs(middleware): clarify save/validate hook order #1149
+
+4.4.2 / 2016-02-05
+==================
+ * fix(aggregate): handle calling .cursor() with no options #3855
+ * fix: upgrade mongodb driver to 2.1.5 for GridFS memory leak fix #3854
+ * docs: fix schematype.html conflict #3853 #3850 #3843
+ * fix(model): bluebird unhandled rejection with ensureIndexes() on init #3837
+ * docs: autoIndex option for createConnection #3805
+
+4.4.1 / 2016-02-03
+==================
+ * fix: linting broke some cases where we use `== null` as shorthand #3852
+ * docs: fix up schematype.html conflict #3848 #3843 [mynameiscoffey](https://github.com/mynameiscoffey)
+ * fix: backwards breaking change with `.connect()` return value #3847
+ * docs: downgrade dox and highlight.js to fix docs build #3845
+ * docs: clean up typo #3842 [Flash-](https://github.com/Flash-)
+ * fix(document): storeShard handles undefined values #3841
+ * chore: more linting #3838 [TrejGun](https://github.com/TrejGun)
+ * fix(schema): handle `text: true` as a way to declare a text index #3824
+
+4.4.0 / 2016-02-02
+==================
+ * docs: fix expireAfterSeconds index option name #3831 [Flash-](https://github.com/Flash-)
+ * chore: run lint after test #3829 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * chore: use power-assert instead of assert #3828 [TrejGun](https://github.com/TrejGun)
+ * chore: stricter lint #3827 [TrejGun](https://github.com/TrejGun)
+ * feat(types): casting moment to date #3813 [TrejGun](https://github.com/TrejGun)
+ * chore: comma-last lint for test folder #3810 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: upgrade async mpath, mpromise, muri, and sliced #3801 [TrejGun](https://github.com/TrejGun)
+ * fix(query): geo queries now return proper ES2015 promises #3800 [TrejGun](https://github.com/TrejGun)
+ * perf(types): use `Object.defineProperties()` for array #3799 [TrejGun](https://github.com/TrejGun)
+ * fix(model): mapReduce, ensureIndexes, remove, and save properly return ES2015 promises #3795 #3628 #3595 [TrejGun](https://github.com/TrejGun)
+ * docs: fixed dates in History.md #3791 [Jokero](https://github.com/Jokero)
+ * feat: connect, open, openSet, and disconnect return ES2015 promises #3790 #3622 [TrejGun](https://github.com/TrejGun)
+ * feat: custom type for int32 via mongoose-int32 npm package #3652 #3102
+ * feat: basic custom schema type API #995
+ * feat(model): `insertMany()` for more performant bulk inserts #723
+
+4.3.7 / 2016-01-23
+==================
+ * docs: grammar fix in timestamps docs #3786 [zclancy](https://github.com/zclancy)
+ * fix(document): setting nested populated docs #3783 [slamuu](https://github.com/slamuu)
+ * fix(document): don't call post save hooks twice for pushed docs #3780
+ * fix(model): handle `_id=0` correctly #3776
+ * docs(middleware): async post hooks #3770
+ * docs: remove confusing sentence #3765 [marcusmellis89](https://github.com/marcusmellis89)
+
+3.8.39 / 2016-01-15
+===================
+ * fixed; casting a number to a buffer #3764
+ * fixed; enumerating virtual property with nested objects #3743 [kusold](https://github.com/kusold)
+
+4.3.6 / 2016-01-15
+==================
+ * fix(types): casting a number to a buffer #3764
+ * fix: add "listener" to reserved keywords #3759
+ * chore: upgrade uglify #3757 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix: broken execPopulate() in 4.3.5 #3755 #3753
+ * fix: ability to remove() a single embedded doc #3754
+ * style: comma-last in test folder #3751 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs: clarify versionKey option #3747
+ * fix: improve colorization for arrays #3744 [TrejGun](https://github.com/TrejGun)
+ * fix: webpack build #3713
+
+4.3.5 / 2016-01-09
+==================
+ * fix(query): throw when 4th parameter to update not a function #3741 [kasselTrankos](https://github.com/kasselTrankos)
+ * fix(document): separate error type for setting an object to a primitive #3735
+ * fix(populate): Model.populate returns ES6 promise #3734
+ * fix(drivers): re-register event handlers after manual reconnect #3729
+ * docs: broken links #3727
+ * fix(validation): update validators run array validation #3724
+ * docs: clarify the need to use markModified with in-place date ops #3722
+ * fix(document): mark correct path as populated when manually populating array #3721
+ * fix(aggregate): support for array pipeline argument to append #3718 [dbkup](https://github.com/dbkup)
+ * docs: clarify `.connect()` callback #3705
+ * fix(schema): properly validate nested single nested docs #3702
+ * fix(types): handle setting documentarray of wrong type #3701
+ * docs: broken links #3700
+ * fix(drivers): debug output properly displays '0' #3689
+
+3.8.38 / 2016-01-07
+===================
+ * fixed; aggregate.append an array #3730 [dbkup](https://github.com/dbkup)
+
+4.3.4 / 2015-12-23
+==================
+ * fix: upgrade mongodb driver to 2.1.2 for repl set error #3712 [sansmischevia](https://github.com/sansmischevia)
+ * docs: validation docs typo #3709 [ivanmaeder](https://github.com/ivanmaeder)
+ * style: remove unused variables #3708 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix(schema): duck-typing for schemas #3703 [mgcrea](https://github.com/mgcrea)
+ * docs: connection sample code issue #3697
+ * fix(schema): duck-typing for schemas #3693 [mgcrea](https://github.com/mgcrea)
+ * docs: clarify id schema option #3638
+
+4.3.3 / 2015-12-18
+==================
+ * fix(connection): properly support 'replSet' as well as 'replset' #3688 [taxilian](https://github.com/taxilian)
+ * fix(document): single nested doc pre hooks called before nested doc array #3687 [aliatsis](https://github.com/aliatsis)
+
+4.3.2 / 2015-12-17
+==================
+ * fix(document): .set() into single nested schemas #3686
+ * fix(connection): support 'replSet' as well as 'replset' option #3685
+ * fix(document): bluebird unhandled rejection when validating doc arrays #3681
+ * fix(document): hooks for doc arrays in single nested schemas #3680
+ * fix(document): post hooks for single nested schemas #3679
+ * fix: remove unused npm module #3674 [sybarite](https://github.com/sybarite)
+ * fix(model): don't swallow exceptions in nested doc save callback #3671
+ * docs: update keepAlive info #3667 [ChrisZieba](https://github.com/ChrisZieba)
+ * fix(document): strict 'throw' throws a specific mongoose error #3662
+ * fix: flakey test #3332
+ * fix(query): more robust check for RegExp #2969
+
+4.3.1 / 2015-12-11
+==================
+ * feat(aggregate): `.sample()` helper #3665
+ * fix(query): bitwise query operators with buffers #3663
+ * docs(migration): clarify `new` option and findByIdAndUpdate #3661
+
+4.3.0 / 2015-12-09
+==================
+ * feat(query): support for mongodb 3.2 bitwise query operators #3660
+ * style: use comma-last style consistently #3657 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * feat: upgrade mongodb driver to 2.1.0 for full MongoDB 3.2 support #3656
+ * feat(aggregate): `.lookup()` helper #3532
+
+4.2.10 / 2015-12-08
+===================
+ * fixed; upgraded marked #3653 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs; cross-db populate #3648
+ * docs; update mocha URL #3646 [ojhaujjwal](https://github.com/ojhaujjwal)
+ * fixed; call close callback asynchronously #3645
+ * docs; virtuals.html issue #3644 [Psarna94](https://github.com/Psarna94)
+ * fixed; single embedded doc casting on init #3642
+ * docs; validation docs improvements #3640
+
+4.2.9 / 2015-12-02
+==================
+ * docs; defaults docs #3625
+ * fix; nested numeric keys causing an embedded document crash #3623
+ * fix; apply path getters before virtual getters #3618
+ * fix; casting for arrays in single nested schemas #3616
+
+4.2.8 / 2015-11-25
+==================
+ * docs; clean up README links #3612 [ReadmeCritic](https://github.com/ReadmeCritic)
+ * fix; ESLint improvements #3605 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fix; assigning single nested subdocs #3601
+ * docs; describe custom logging functions in `mongoose.set()` docs #3557
+
+4.2.7 / 2015-11-20
+==================
+ * fixed; readPreference connection string option #3600
+ * fixed; pulling from manually populated arrays #3598 #3579
+ * docs; FAQ about OverwriteModelError #3597 [stcruy](https://github.com/stcruy)
+ * fixed; setting single embedded schemas to null #3596
+ * fixed; indexes for single embedded schemas #3594
+ * docs; clarify projection for `findOne()` #3593 [gunar](https://github.com/gunar)
+ * fixed; .ownerDocument() method on single embedded schemas #3589
+ * fixed; properly throw casterror for query on single embedded schema #3580
+ * upgraded; mongodb driver -> 2.0.49 for reconnect issue fix #3481
+
+4.2.6 / 2015-11-16
+==================
+ * fixed; ability to manually populate an array #3575
+ * docs; clarify `isAsync` parameter to hooks #3573
+ * fixed; use captureStackTrace if possible instead #3571
+ * fixed; crash with buffer and update validators #3565 [johnpeb](https://github.com/johnpeb)
+ * fixed; update casting with operators overwrite: true #3564
+ * fixed; validation with single embedded docs #3562
+ * fixed; inline docs inherit parents $type key #3560
+ * docs; bad grammar in populate docs #3559 [amaurymedeiros](https://github.com/amaurymedeiros)
+ * fixed; properly handle populate option for find() #2321
+
+3.8.37 / 2015-11-16
+===================
+ * fixed; use retainKeyOrder for cloning update op #3572
+
+4.2.5 / 2015-11-09
+==================
+ * fixed; handle setting fields in pre update hooks with exec #3549
+ * upgraded; ESLint #3547 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; bluebird unhandled rejections with cast errors and .exec #3543
+ * fixed; min/max validators handling undefined #3539
+ * fixed; standalone mongos connections #3537
+ * fixed; call `.toObject()` when setting a single nested doc #3535
+ * fixed; single nested docs now have methods #3534
+ * fixed; single nested docs with .create() #3533 #3521 [tusbar](https://github.com/tusbar)
+ * docs; deep populate docs #3528
+ * fixed; deep populate schema ref handling #3507
+ * upgraded; mongodb driver -> 2.0.48 for sort overflow issue #3493
+ * docs; clarify default ids for discriminators #3482
+ * fixed; properly support .update(doc) #3221
+
+4.2.4 / 2015-11-02
+==================
+ * fixed; upgraded `ms` package for security vulnerability #3524 [fhemberger](https://github.com/fhemberger)
+ * fixed; ESlint rules #3517 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * docs; typo in aggregation docs #3513 [rafakato](https://github.com/rafakato)
+ * fixed; add `dontThrowCastError` option to .update() for promises #3512
+ * fixed; don't double-cast buffers in node 4.x #3510 #3496
+ * fixed; population with single embedded schemas #3501
+ * fixed; pre('set') hooks work properly #3479
+ * docs; promises guide #3441
+
+4.2.3 / 2015-10-26
+==================
+ * docs; remove unreferenced function in middleware.jade #3506
+ * fixed; handling auth with no username/password #3500 #3498 #3484 [mleanos](https://github.com/mleanos)
+ * fixed; more ESlint rules #3491 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; swallowing exceptions in save callback #3478
+ * docs; fixed broken links in subdocs guide #3477
+ * fixed; casting booleans to numbers #3475
+ * fixed; report CastError for subdoc arrays in findOneAndUpdate #3468
+ * fixed; geoNear returns ES6 promise #3458
+
+4.2.2 / 2015-10-22
+==================
+ * fixed; go back to old pluralization code #3490
+
+4.2.1 / 2015-10-22
+==================
+ * fixed; pluralization issues #3492 [ChristianMurphy](https://github.com/ChristianMurphy)
+
+4.2.0 / 2015-10-22
+==================
+ * added; support for skipVersioning for document arrays #3467 [chazmo03](https://github.com/chazmo03)
+ * added; ability to customize schema 'type' key #3459 #3245
+ * fixed; writeConcern for index builds #3455
+ * added; emit event when individual index build starts #3440 [objectiveSee](https://github.com/objectiveSee)
+ * added; 'context' option for update validators #3430
+ * refactor; pluralization now in separate pluralize-mongoose npm module #3415 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * added; customizable error validation messages #3406 [geronime](https://github.com/geronime)
+ * added; support for passing 'minimize' option to update #3381
+ * added; ability to customize debug logging format #3261
+ * added; baseModelName property for discriminator models #3202
+ * added; 'emitIndexErrors' option #3174
+ * added; 'async' option for aggregation cursor to support buffering #3160
+ * added; ability to skip validation for individual save() calls #2981
+ * added; single embedded schema support #2689 #585
+ * added; depopulate function #2509
+
+4.1.12 / 2015-10-19
+===================
+ * docs; use readPreference instead of slaveOk for Query.setOptions docs #3471 [buunguyen](https://github.com/buunguyen)
+ * fixed; more helpful error when regexp contains null bytes #3456
+ * fixed; x509 auth issue #3454 [NoxHarmonium](https://github.com/NoxHarmonium)
+
+3.8.36 / 2015-10-18
+===================
+ * fixed; Make array props non-enumerable #3461 [boblauer](https://github.com/boblauer)
+
+4.1.11 / 2015-10-12
+===================
+ * fixed; update timestamps for update() if they're enabled #3450 [isayme](https://github.com/isayme)
+ * fixed; unit test error on node 0.10 #3449 [isayme](https://github.com/isayme)
+ * docs; timestamp option docs #3448 [isayme](https://github.com/isayme)
+ * docs; fix unexpected indent #3443 [isayme](https://github.com/isayme)
+ * fixed; use ES6 promises for Model.prototype.remove() #3442
+ * fixed; don't use unused 'safe' option for index builds #3439
+ * fixed; elemMatch casting bug #3437 #3435 [DefinitelyCarter](https://github.com/DefinitelyCarter)
+ * docs; schema.index docs #3434
+ * fixed; exceptions in save() callback getting swallowed on mongodb 2.4 #3371
+
+4.1.10 / 2015-10-05
+===================
+ * docs; improve virtuals docs to explain virtuals schema option #3433 [zoyaH](https://github.com/zoyaH)
+ * docs; MongoDB server version compatibility guide #3427
+ * docs; clarify that findById and findByIdAndUpdate fire hooks #3422
+ * docs; clean up Model.save() docs #3420
+ * fixed; properly handle projection with just id #3407 #3412
+ * fixed; infinite loop when database document is corrupted #3405
+ * docs; clarify remove middleware #3388
+
+4.1.9 / 2015-09-28
+==================
+ * docs; minlength and maxlength string validation docs #3368 #3413 [cosmosgenius](https://github.com/cosmosgenius)
+ * fixed; linting for infix operators #3397 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; proper casting for $all #3394
+ * fixed; unhandled rejection warnings with .create() #3391
+ * docs; clarify update validators on paths that aren't explicitly set #3386
+ * docs; custom validator examples #2778
+
+4.1.8 / 2015-09-21
+==================
+ * docs; fixed typo in example #3390 [kmctown](https://github.com/kmctown)
+ * fixed; error in toObject() #3387 [guumaster](https://github.com/guumaster)
+ * fixed; handling for casting null dates #3383 [alexmingoia](https://github.com/alexmingoia)
+ * fixed; passing composite ids to `findByIdAndUpdate` #3380
+ * fixed; linting #3376 #3375 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; added NodeJS v4 to Travis #3374 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; casting $elemMatch inside of $not #3373 [gaguirre](https://github.com/gaguirre)
+ * fixed; handle case where $slice is 0 #3369
+ * fixed; avoid running getters if path is populated #3357
+ * fixed; cast documents to objects when setting to a nested path #3346
+
+4.1.7 / 2015-09-14
+==================
+ * docs; typos in SchemaType documentation #3367 [jasson15](https://github.com/jasson15)
+ * fixed; MONGOOSE_DRIVER_PATH env variable again #3360
+ * docs; added validateSync docs #3353
+ * fixed; set findOne op synchronously in query #3344
+ * fixed; handling for `.pull()` on a documentarray without an id #3341
+ * fixed; use natural order for cloning update conditions #3338
+ * fixed; issue with strict mode casting for mixed type updates #3337
+
+4.1.6 / 2015-09-08
+==================
+ * fixed; MONGOOSE_DRIVER_PATH env variable #3345 [g13013](https://github.com/g13013)
+ * docs; global autoIndex option #3335 [albertorestifo](https://github.com/albertorestifo)
+ * docs; model documentation typos #3330
+ * fixed; report reason for CastError #3320
+ * fixed; .populate() no longer returns true after re-assigning #3308
+ * fixed; discriminators with aggregation geoNear #3304
+ * docs; discriminator docs #2743
+
+4.1.5 / 2015-09-01
+==================
+ * fixed; document.remove() removing all docs #3326 #3325
+ * fixed; connect() checks for rs_name in options #3299
+ * docs; examples for schema.set() #3288
+ * fixed; checkKeys issue with bluebird #3286 [gregthegeek](https://github.com/gregthegeek)
+
+4.1.4 / 2015-08-31
+==================
+ * fixed; ability to set strict: false for update #3305
+ * fixed; .create() properly uses ES6 promises #3297
+ * fixed; pre hooks on nested subdocs #3291 #3284 [aliatsis](https://github.com/aliatsis)
+ * docs; remove unclear text in .remove() docs #3282
+ * fixed; pre hooks called twice for 3rd-level nested doc #3281
+ * fixed; nested transforms #3279
+ * upgraded; mquery -> 1.6.3 #3278 #3272
+ * fixed; don't swallow callback errors by default #3273 #3222
+ * fixed; properly get nested paths from nested schemas #3265
+ * fixed; remove() with id undefined deleting all docs #3260 [thanpolas](https://github.com/thanpolas)
+ * fixed; handling for non-numeric projections #3256
+ * fixed; findById with id undefined returning first doc #3255
+ * fixed; use retainKeyOrder for update #3215
+ * added; passRawResult option to findOneAndUpdate for backwards compat #3173
+
+4.1.3 / 2015-08-16
+==================
+ * fixed; getUpdate() in pre update hooks #3520 [gregthegeek](https://github.com/gregthegeek)
+ * fixed; handleArray() ensures arg is an array #3238 [jloveridge](https://github.com/jloveridge)
+ * fixed; refresh required path cache when recreating docs #3199
+ * fixed; $ operator on unwind aggregation helper #3197
+ * fixed; findOneAndUpdate() properly returns raw result as third arg to callback #3173
+ * fixed; querystream with dynamic refs #3108
+
+3.8.35 / 2015-08-14
+===================
+ * fixed; handling for minimize on nested objects #2930
+ * fixed; don't crash when schema.path.options undefined #1824
+
+4.1.2 / 2015-08-10
+==================
+ * fixed; better handling for Jade templates #3241 [kbadk](https://github.com/kbadk)
+ * added; ESlint trailing spaces #3234 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * added; ESlint #3191 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; properly emit event on disconnect #3183
+ * fixed; copy options properly using Query.toConstructor() #3176
+ * fixed; setMaxListeners() issue in browser build #3170
+ * fixed; node driver -> 2.0.40 to not store undefined keys as null #3169
+ * fixed; update validators handle positional operator #3167
+ * fixed; handle $all + $elemMatch query casting #3163
+ * fixed; post save hooks don't swallow extra args #3155
+ * docs; spelling mistake in index.jade #3154
+ * fixed; don't crash when toObject() has no fields #3130
+ * fixed; apply toObject() recursively for find and update queries #3086 [naoina](https://github.com/naoina)
+
+4.1.1 / 2015-08-03
+==================
+ * fixed; aggregate exec() crash with no callback #3212 #3198 [jpgarcia](https://github.com/jpgarcia)
+ * fixed; pre init hooks now properly synchronous #3207 [burtonjc](https://github.com/burtonjc)
+ * fixed; updateValidators doesn't flatten dates #3206 #3194 [victorkohl](https://github.com/victorkohl)
+ * fixed; default fields don't make document dirty between saves #3205 [burtonjc](https://github.com/burtonjc)
+ * fixed; save passes 0 as numAffected rather than undefined when no change #3195 [burtonjc](https://github.com/burtonjc)
+ * fixed; better handling for positional operator in update #3185
+ * fixed; use Travis containers #3181 [ChristianMurphy](https://github.com/ChristianMurphy)
+ * fixed; leaked variable #3180 [ChristianMurphy](https://github.com/ChristianMurphy)
+
+4.1.0 / 2015-07-24
+==================
+ * added; `schema.queue()` now public #3193
+ * added; raw result as third parameter to findOneAndX callback #3173
+ * added; ability to run validateSync() on only certain fields #3153
+ * added; subPopulate #3103 [timbur](https://github.com/timbur)
+ * added; $isDefault function on documents #3077
+ * added; additional properties for built-in validator messages #3063 [KLicheR](https://github.com/KLicheR)
+ * added; getQuery() and getUpdate() functions for Query #3013
+ * added; export DocumentProvider #2996
+ * added; ability to remove path from schema #2993 [JohnnyEstilles](https://github.com/JohnnyEstilles)
+ * added; .explain() helper for aggregate #2714
+ * added; ability to specify which ES6-compatible promises library mongoose uses #2688
+ * added; export Aggregate #1910
+
+4.0.8 / 2015-07-20
+==================
+ * fixed; assignment with document arrays #3178 [rosston](https://github.com/rosston)
+ * docs; remove duplicate paragraph #3164 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * docs; improve findOneAndXYZ parameter descriptions #3159 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * docs; add findOneAndRemove to list of supported middleware #3158
+ * docs; clarify ensureIndex #3156
+ * fixed; refuse to save/remove document without id #3118
+ * fixed; hooks next() no longer accidentally returns promise #3104
+ * fixed; strict mode for findOneAndUpdate #2947
+ * added; .min.js.gz file for browser component #2806
+
+3.8.34 / 2015-07-20
+===================
+ * fixed; allow using $rename #3171
+ * fixed; no longer modifies update arguments #3008
+
+4.0.7 / 2015-07-11
+==================
+ * fixed; documentarray id method when using object id #3157 [siboulet](https://github.com/siboulet)
+ * docs; improve findById docs #3147
+ * fixed; update validators handle null properly #3136 [odeke-em](https://github.com/odeke-em)
+ * docs; jsdoc syntax errors #3128 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * docs; fix typo #3126 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * docs; proper formatting in queries.jade #3121 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * docs; correct example for string maxlength validator #3111 [rhmeeuwisse](https://github.com/rhmeeuwisse)
+ * fixed; setDefaultsOnInsert with arrays #3107
+ * docs; LearnBoost -> Automattic in package.json #3099
+ * docs; pre update hook example #3094 [danpe](https://github.com/danpe)
+ * docs; clarify query middleware example #3051
+ * fixed; ValidationErrors in strict mode #3046
+ * fixed; set findOneAndUpdate properties before hooks run #3024
+
+3.8.33 / 2015-07-10
+===================
+ * upgraded; node driver -> 1.4.38
+ * fixed; dont crash when `match` validator undefined
+
+4.0.6 / 2015-06-21
+==================
+ * upgraded; node driver -> 2.0.34 #3087
+ * fixed; apply setters on addToSet, etc #3067 [victorkohl](https://github.com/victorkohl)
+ * fixed; missing semicolons #3065 [sokolikp](https://github.com/sokolikp)
+ * fixed; proper handling for async doc hooks #3062 [gregthegeek](https://github.com/gregthegeek)
+ * fixed; dont set failed populate field to null if other docs are successfully populated #3055 [eloytoro](https://github.com/eloytoro)
+ * fixed; setDefaultsOnInsert with document arrays #3034 [taxilian](https://github.com/taxilian)
+ * fixed; setters fired on array items #3032
+ * fixed; stop validateSync() on first error #3025 [victorkohl](https://github.com/victorkohl)
+ * docs; improve query docs #3016
+ * fixed; always exclude _id when its deselected #3010
+ * fixed; enum validator kind property #3009
+ * fixed; mquery collection names #3005
+ * docs; clarify mongos option #3000
+ * docs; clarify that query builder has a .then() #2995
+ * fixed; race condition in dynamic ref #2992
+
+3.8.31 / 2015-06-20
+===================
+ * fixed; properly handle text search with discriminators and $meta #2166
+
+4.0.5 / 2015-06-05
+==================
+ * fixed; ObjectIds and buffers when mongodb driver is a sibling dependency #3050 #3048 #3040 #3031 #3020 #2988 #2951
+ * fixed; warn user when 'increment' is used in schema #3039
+ * fixed; setDefaultsOnInsert with array in schema #3035
+ * fixed; dont use default Object toString to cast to string #3030
+ * added; npm badge #3020 [odeke-em](https://github.com/odeke-em)
+ * fixed; proper handling for calling .set() with a subdoc #2782
+ * fixed; dont throw cast error when using $rename on non-string path #1845
+
+3.8.30 / 2015-06-05
+===================
+ * fixed; enable users to set all options with tailable() #2883
+
+4.0.4 / 2015-05-28
+==================
+ * docs; findAndModify new parameter correct default value #3012 [JonForest](https://github.com/JonForest)
+ * docs; clarify pluralization rules #2999 [anonmily](https://github.com/anonmily)
+ * fix; discriminators with schema methods #2978
+ * fix; make `isModified` a schema reserved keyword #2975
+ * fix; properly fire setters when initializing path with object #2943
+ * fix; can use `setDefaultsOnInsert` without specifying `runValidators` #2938
+ * fix; always set validation errors `kind` property #2885
+ * upgraded; node driver -> 2.0.33 #2865
+
+3.8.29 / 2015-05-27
+===================
+ * fixed; Handle JSON.stringify properly for nested docs #2990
+
+4.0.3 / 2015-05-13
+==================
+ * upgraded; mquery -> 1.5.1 #2983
+ * docs; clarify context for query middleware #2974
+ * docs; fix missing type -> kind rename in History.md #2961
+ * fixed; broken ReadPreference include on Heroku #2957
+ * docs; correct form for cursor aggregate option #2955
+ * fixed; sync post hooks now properly called after function #2949 #2925
+ * fixed; fix sub-doc validate() function #2929
+ * upgraded; node driver -> 2.0.30 #2926
+ * docs; retainKeyOrder for save() #2924
+ * docs; fix broken class names #2913
+ * fixed; error when using node-clone on a doc #2909
+ * fixed; no more hard references to bson #2908 #2906
+ * fixed; dont overwrite array values #2907 [naoina](https://github.com/naoina)
+ * fixed; use readPreference=primary for findOneAndUpdate #2899 #2823
+ * docs; clarify that update validators only run on $set and $unset #2889
+ * fixed; set kind consistently for built-in validators #2885
+ * docs; single field populated documents #2884
+ * fixed; nested objects are now enumerable #2880 [toblerpwn](https://github.com/toblerpwn)
+ * fixed; properly populate field when ref, lean, stream used together #2841
+ * docs; fixed migration guide jade error #2807
+
+3.8.28 / 2015-05-12
+===================
+ * fixed; proper handling for toJSON options #2910
+ * fixed; dont attach virtuals to embedded docs in update() #2046
+
+4.0.2 / 2015-04-23
+==================
+ * fixed; error thrown when calling .validate() on subdoc not in an array #2902
+ * fixed; rename define() to play nice with webpack #2900 [jspears](https://github.com/jspears)
+ * fixed; pre validate called twice with discriminators #2892
+ * fixed; .inspect() on mongoose.Types #2875
+ * docs; correct callback params for Model.update #2872
+ * fixed; setDefaultsOnInsert now works when runValidators not specified #2870
+ * fixed; Document now wraps EventEmitter.addListener #2867
+ * fixed; call non-hook functions in schema queue #2856
+ * fixed; statics can be mocked out for tests #2848 [ninelb](https://github.com/ninelb)
+ * upgraded; mquery 1.4.0 for bluebird bug fix #2846
+ * fixed; required validators run first #2843
+ * docs; improved docs for new option to findAndMody #2838
+ * docs; populate example now uses correct field #2837 [swilliams](https://github.com/swilliams)
+ * fixed; pre validate changes causing VersionError #2835
+ * fixed; get path from correct place when setting CastError #2832
+ * docs; improve docs for Model.update() function signature #2827 [irnc](https://github.com/irnc)
+ * fixed; populating discriminators #2825 [chetverikov](https://github.com/chetverikov)
+ * fixed; discriminators with nested schemas #2821
+ * fixed; CastErrors with embedded docs #2819
+ * fixed; post save hook context #2816
+ * docs; 3.8.x -> 4.x migration guide #2807
+ * fixed; proper _distinct copying for query #2765 [cdelauder](https://github.com/cdelauder)
+
+3.8.27 / 2015-04-22
+===================
+ * fixed; dont duplicate db calls on Q.ninvoke() #2864
+ * fixed; Model.find arguments naming in docs #2828
+ * fixed; Support ipv6 in connection strings #2298
+
+3.8.26 / 2015-04-07
+===================
+ * fixed; TypeError when setting date to undefined #2833
+ * fixed; handle CastError properly in distinct() with no callback #2786
+ * fixed; broken links in queries docs #2779
+ * fixed; dont mark buffer as modified when setting type initially #2738
+ * fixed; dont crash when using slice with populate #1934
+
+4.0.1 / 2015-03-28
+==================
+ * fixed; properly handle empty cast doc in update() with promises #2796
+ * fixed; unstable warning #2794
+ * fixed; findAndModify docs now show new option is false by default #2793
+
+4.0.0 / 2015-03-25
+==================
+ * fixed; on-the-fly schema docs typo #2783 [artiifix](https://github.com/artiifix)
+ * fixed; cast error validation handling #2775 #2766 #2678
+ * fixed; discriminators with populate() #2773 #2719 [chetverikov](https://github.com/chetverikov)
+ * fixed; increment now a reserved path #2709
+ * fixed; avoid sending duplicate object ids in populate() #2683
+ * upgraded; mongodb to 2.0.24 to properly emit reconnect event multiple times #2656
+
+4.0.0-rc4 / 2015-03-14
+======================
+ * fixed; toObject virtuals schema option handled properly #2751
+ * fixed; update validators work on document arrays #2733
+ * fixed; check for cast errors on $set #2729
+ * fixed; instance field set for all schema types #2727 [csdco](https://github.com/csdco)
+ * fixed; dont run other validators if required fails #2725
+ * fixed; custom getters execute on ref paths #2610
+ * fixed; save defaults if they were set when doc was loaded from db #2558
+ * fixed; pre validate now runs before pre save #2462
+ * fixed; no longer throws errors with --use_strict #2281
+
+3.8.25 / 2015-03-13
+===================
+ * fixed; debug output reverses order of aggregation keys #2759
+ * fixed; $eq is a valid query selector in 3.0 #2752
+ * fixed; upgraded node driver to 1.4.32 for handling non-numeric poolSize #2682
+ * fixed; update() with overwrite sets _id for nested docs #2658
+ * fixed; casting for operators in $elemMatch #2199
+
+4.0.0-rc3 / 2015-02-28
+======================
+ * fixed; update() pre hooks run before validators #2706
+ * fixed; setters not called on arrays of refs #2698 [brandom](https://github.com/brandom)
+ * fixed; use node driver 2.0.18 for nodejs 0.12 support #2685
+ * fixed; comments reference file that no longer exists #2681
+ * fixed; populated() returns _id of manually populated doc #2678
+ * added; ability to exclude version key in toObject() #2675
+ * fixed; dont allow setting nested path to a string #2592
+ * fixed; can cast objects with _id field to ObjectIds #2581
+ * fixed; on-the-fly schema getters #2360
+ * added; strict option for findOneAndUpdate() #1967
+
+3.8.24 / 2015-02-25
+===================
+ * fixed; properly apply child schema transforms #2691
+ * fixed; make copy of findOneAndUpdate options before modifying #2687
+ * fixed; apply defaults when parent path is selected #2670 #2629
+ * fixed; properly get ref property for nested paths #2665
+ * fixed; node driver makes copy of authenticate options before modifying them #2619
+ * fixed; dont block process exit when auth fails #2599
+ * fixed; remove redundant clone in update() #2537
+
+4.0.0-rc2 / 2015-02-10
+======================
+ * added; io.js to travis build
+ * removed; browser build dependencies not installed by default
+ * added; dynamic refpaths #2640 [chetverikov](https://github.com/chetverikov)
+ * fixed; dont call child schema transforms on parent #2639 [chetverikov](https://github.com/chetverikov)
+ * fixed; get rid of remove option if new is set in findAndModify #2598
+ * fixed; aggregate all document array validation errors #2589
+ * fixed; custom setters called when setting value to undefined #1892
+
+3.8.23 / 2015-02-06
+===================
+ * fixed; unset opts.remove when upsert is true #2519
+ * fixed; array saved as object when path is object in array #2442
+ * fixed; inline transforms #2440
+ * fixed; check for callback in count() #2204
+ * fixed; documentation for selecting fields #1534
+
+4.0.0-rc1 / 2015-02-01
+======================
+ * fixed; use driver 2.0.14
+ * changed; use transform: true by default #2245
+
+4.0.0-rc0 / 2015-01-31
+===================
+ * fixed; wrong order for distinct() params #2628
+ * fixed; handling no query argument to remove() #2627
+ * fixed; createModel and discriminators #2623 [ashaffer](https://github.com/ashaffer)
+ * added; pre('count') middleware #2621
+ * fixed; double validation calls on document arrays #2618
+ * added; validate() catches cast errors #2611
+ * fixed; respect replicaSet parameter in connection string #2609
+ * added; can explicitly exclude paths from versioning #2576 [csabapalfi](https://github.com/csabapalfi)
+ * upgraded; driver to 2.0.15 #2552
+ * fixed; save() handles errors more gracefully in ES6 #2371
+ * fixed; undefined is now a valid argument to findOneAndUpdate #2272
+ * changed; `new` option to findAndModify ops is false by default #2262
+
+3.8.22 / 2015-01-24
+===================
+ * upgraded; node-mongodb-native to 1.4.28 #2587 [Climax777](https://github.com/Climax777)
+ * added; additional documentation for validators #2449
+ * fixed; stack overflow when creating massive arrays #2423
+ * fixed; undefined is a valid id for queries #2411
+ * fixed; properly create nested schema index when same schema used twice #2322
+ * added; link to plugin generator in docs #2085 [huei90](https://github.com/huei90)
+ * fixed; optional arguments documentation for findOne() #1971 [nachinius](https://github.com/nachinius)
+
+3.9.7 / 2014-12-19
+===================
+ * added; proper cursors for aggregate #2539 [changyy](https://github.com/changyy)
+ * added; min/max built-in validators for dates #2531 [bshamblen](https://github.com/bshamblen)
+ * fixed; save and validate are now reserved keywords #2380
+ * added; basic documentation for browser component #2256
+ * added; find and findOne hooks (query middleware) #2138
+ * fixed; throw a DivergentArrayError when saving positional operator queries #2031
+ * added; ability to use options as a document property #1416
+ * fixed; document no longer inherits from event emitter and so domain and _events are no longer reserved #1351
+ * removed; setProfiling #1349
+
+3.8.21 / 2014-12-18
+===================
+ * fixed; syntax in index.jade #2517 [elderbas](https://github.com/elderbas)
+ * fixed; writable statics #2510 #2528
+ * fixed; overwrite and explicit $set casting #2515
+
+3.9.6 / 2014-12-05
+===================
+ * added; correctly run validators on each element of array when entire array is modified #661 #1227
+ * added; castErrors in validation #1013 [jondavidjohn](https://github.com/jondavidjohn)
+ * added; specify text indexes in schema fields #1401 [sr527](https://github.com/sr527)
+ * added; ability to set field with validators to undefined #1594 [alabid](https://github.com/alabid)
+ * added; .create() returns an array when passed an array #1746 [alabid](https://github.com/alabid)
+ * added; test suite and docs for use with co and yield #2177 #2474
+ * fixed; subdocument toObject() transforms #2447 [chmanie](https://github.com/chmanie)
+ * fixed; Model.create() with save errors #2484
+ * added; pass options to .save() and .remove() #2494 [jondavidjohn](https://github.com/jondavidjohn)
+
+3.8.20 / 2014-12-01
+===================
+ * fixed; recursive readPref #2490 [kjvalencik](https://github.com/kjvalencik)
+ * fixed; make sure to copy parameters to update() before modifying #2406 [alabid](https://github.com/alabid)
+ * fixed; unclear documentation about query callbacks #2319
+ * fixed; setting a schema-less field to an empty object #2314 [alabid](https://github.com/alabid)
+ * fixed; registering statics and methods for discriminators #2167 [alabid](https://github.com/alabid)
+
+3.9.5 / 2014-11-10
+===================
+ * added; ability to disable autoIndex on a per-connection basis #1875 [sr527](https://github.com/sr527)
+ * fixed; `geoNear()` no longer enforces legacy coordinate pairs - supports GeoJSON #1987 [alabid](https://github.com/alabid)
+ * fixed; browser component works when minified with mangled variable names #2302
+ * fixed; `doc.errors` now cleared before `validate()` called #2302
+ * added; `execPopulate()` function to make `doc.populate()` compatible with promises #2317
+ * fixed; `count()` no longer throws an error when used with `sort()` #2374
+ * fixed; `save()` no longer recursively calls `save()` on populated fields #2418
+
+3.8.19 / 2014-11-09
+===================
+ * fixed; make sure to not override subdoc _ids on find #2276 [alabid](https://github.com/alabid)
+ * fixed; exception when comparing two documents when one lacks _id #2333 [slawo](https://github.com/slawo)
+ * fixed; getters for properties with non-strict schemas #2439 [alabid](https://github.com/alabid)
+ * fixed; inconsistent URI format in docs #2414 [sr527](https://github.com/sr527)
+
+3.9.4 / 2014-10-25
+==================
+ * fixed; statics no longer can be overwritten #2343 [nkcmr](https://github.com/chetverikov)
+ * added; ability to set single populated paths to documents #1530
+ * added; setDefaultsOnInsert and runValidator options for findOneAndUpdate() #860
+
+3.8.18 / 2014-10-22
+==================
+ * fixed; Dont use all toObject options in save #2340 [chetverikov](https://github.com/chetverikov)
+
+3.9.3 / 2014-10-01
+=================
+ * added; support for virtuals that return objects #2294
+ * added; ability to manually hydrate POJOs into mongoose objects #2292
+ * added; setDefaultsOnInsert and runValidator options for update() #860
+
+3.8.17 / 2014-09-29
+==================
+ * fixed; use schema options retainKeyOrder in save() #2274
+ * fixed; fix skip in populate when limit is set #2252
+ * fixed; fix stack overflow when passing MongooseArray to findAndModify #2214
+ * fixed; optimize .length usage in populate #2289
+
+3.9.2 / 2014-09-08
+==================
+ * added; test coverage for browser component #2255
+ * added; in-order execution of validators #2243
+ * added; custom fields for validators #2132
+ * removed; exception thrown when find() used with count() #1950
+
+3.8.16 / 2014-09-08
+==================
+ * fixed; properly remove modified array paths if array has been overwritten #1638
+ * fixed; key check errors #1884
+ * fixed; make sure populate on an array always returns a Mongoose array #2214
+ * fixed; SSL connections with node 0.11 #2234
+ * fixed; return sensible strings for promise errors #2239
+
+3.9.1 / 2014-08-17
+==================
+ * added; alpha version of browser-side schema validation #2254
+ * added; support passing a function to schemas `required` field #2247
+ * added; support for setting updatedAt and createdAt timestamps #2227
+ * added; document.validate() returns a promise #2131
+
+3.8.15 / 2014-08-17
+==================
+ * fixed; Replica set connection string example in docs #2246
+ * fixed; bubble up parseError event #2229
+ * fixed; removed buggy populate cache #2176
+ * fixed; dont $inc versionKey if its being $set #1933
+ * fixed; cast $or and $and in $pull #1932
+ * fixed; properly cast to schema in stream() #1862
+ * fixed; memory leak in nested objects #1565 #2211 [devongovett](https://github.com/devongovett)
+
+3.8.14 / 2014-07-26
+==================
+ * fixed; stringifying MongooseArray shows nested arrays #2002
+ * fixed; use populated doc schema in toObject and toJSON by default #2035
+ * fixed; dont crash on arrays containing null #2140
+ * fixed; model.update w/ upsert has same return values on .exec and promise #2143
+ * fixed; better handling for populate limit with multiple documents #2151
+ * fixed; dont prevent users from adding weights to text index #2183
+ * fixed; helper for aggregation cursor #2187
+ * updated; node-mongodb-native to 1.4.7
+
+3.8.13 / 2014-07-15
+==================
+ * fixed; memory leak with isNew events #2159
+ * fixed; docs for overwrite option for update() #2144
+ * fixed; storeShard() handles dates properly #2127
+ * fixed; sub-doc changes not getting persisted to db after save #2082
+ * fixed; populate with _id: 0 actually removes _id instead of setting to undefined #2123
+ * fixed; save versionKey on findOneAndUpdate w/ upsert #2122
+ * fixed; fix typo in 2.8 docs #2120 [shakirullahi](https://github.com/shakirullahi)
+ * fixed; support maxTimeMs #2102 [yuukinajima](https://github.com/yuukinajima)
+ * fixed; support $currentDate #2019
+ * fixed; $addToSet handles objects without _ids properly #1973
+ * fixed; dont crash on invalid nearSphere query #1874
+
+3.8.12 / 2014-05-30
+==================
+ * fixed; single-server reconnect event fires #1672
+ * fixed; sub-docs not saved when pushed into populated array #1794
+ * fixed; .set() sometimes converts embedded docs to pojos #1954 [archangel-irk](https://github.com/archangel-irk)
+ * fixed; sub-doc changes not getting persisted to db after save #2082
+ * fixed; custom getter might cause mongoose to mistakenly think a path is dirty #2100 [pgherveou](https://github.com/pgherveou)
+ * fixed; chainable helper for allowDiskUse option in aggregation #2114
+
+3.9.0 (unstable) / 2014-05-22
+==================
+ * changed; added `domain` to reserved keywords #1338 #2052 [antoinepairet](https://github.com/antoinepairet)
+ * added; asynchronous post hooks #1977 #2081 [chopachom](https://github.com/chopachom) [JasonGhent](https://github.com/JasonGhent)
+ * added; using model for population, cross-db populate [mihai-chiorean](https://github.com/mihai-chiorean)
+ * added; can define a type for schema validators
+ * added; `doc.remove()` returns a promise #1619 [refack](https://github.com/refack)
+ * added; internal promises for hooks, pre-save hooks run in parallel #1732 [refack](https://github.com/refack)
+ * fixed; geoSearch hanging when no results returned #1846 [ghartnett](https://github.com/ghartnett)
+ * fixed; do not set .type property on ValidationError, use .kind instead #1323
+
+3.8.11 / 2014-05-22
+==================
+ * updated; node-mongodb-native to 1.4.5
+ * reverted; #2052, fixes #2097
+
+3.8.10 / 2014-05-20
+==================
+
+ * updated; node-mongodb-native to 1.4.4
+ * fixed; _.isEqual false negatives bug in js-bson #2070
+ * fixed; missing check for schema.options #2014
+ * fixed; missing support for $position #2024
+ * fixed; options object corruption #2049
+ * fixed; improvements to virtuals docs #2055
+ * fixed; added `domain` to reserved keywords #2052 #1338
+
+3.8.9 / 2014-05-08
+==================
+
+ * updated; mquery to 0.7.0
+ * updated; node-mongodb-native to 1.4.3
+ * fixed; $near failing against MongoDB 2.6
+ * fixed; relying on .options() to determine if collection exists
+ * fixed; $out aggregate helper
+ * fixed; all test failures against MongoDB 2.6.1, with caveat #2065
+
+3.8.8 / 2014-02-22
+==================
+
+ * fixed; saving Buffers #1914
+ * updated; expose connection states for user-land #1926 [yorkie](https://github.com/yorkie)
+ * updated; mquery to 0.5.3
+ * updated; added get / set to reserved path list #1903 [tstrimple](https://github.com/tstrimple)
+ * docs; README code highlighting, syntax fixes #1930 [IonicaBizau](https://github.com/IonicaBizau)
+ * docs; fixes link in the doc at #1925 [kapeels](https://github.com/kapeels)
+ * docs; add a missed word 'hook' for the description of the post-hook api #1924 [ipoval](https://github.com/ipoval)
+
+3.8.7 / 2014-02-09
+==================
+
+ * fixed; sending safe/read options in Query#exec #1895
+ * fixed; findOneAnd..() with sort #1887
+
+3.8.6 / 2014-01-30
+==================
+
+ * fixed; setting readPreferences #1895
+
+3.8.5 / 2014-01-23
+==================
+
+ * fixed; ssl setting when using URI #1882
+ * fixed; findByIdAndUpdate now respects the overwrite option #1809 [owenallenaz](https://github.com/owenallenaz)
+
+3.8.4 / 2014-01-07
+==================
+
+ * updated; mongodb driver to 1.3.23
+ * updated; mquery to 0.4.1
+ * updated; mpromise to 0.4.3
+ * fixed; discriminators now work when selecting fields #1820 [daemon1981](https://github.com/daemon1981)
+ * fixed; geoSearch with no results timeout #1846 [ghartnett](https://github.com/ghartnett)
+ * fixed; infitite recursion in ValidationError #1834 [chetverikov](https://github.com/chetverikov)
+
+3.8.3 / 2013-12-17
+==================
+
+ * fixed; setting empty array with model.update #1838
+ * docs; fix url
+
+3.8.2 / 2013-12-14
+==================
+
+ * fixed; enum validation of multiple values #1778 [heroicyang](https://github.com/heroicyang)
+ * fixed; global var leak #1803
+ * fixed; post remove now fires on subdocs #1810
+ * fixed; no longer set default empty array for geospatial-indexed fields #1668 [shirish87](https://github.com/shirish87)
+ * fixed; model.stream() not hydrating discriminators correctly #1792 [j](https://github.com/j)
+ * docs: Stablility -> Stability [nikmartin](https://github.com/nikmartin)
+ * tests; improve shard error handling
+
+3.8.1 / 2013-11-19
+==================
+
+ * fixed; mishandling of Dates with minimize/getters #1764
+ * fixed; Normalize bugs.email, so `npm` will shut up #1769 [refack](https://github.com/refack)
+ * docs; Improve the grammar where "lets us" was used #1777 [alexyoung](https://github.com/alexyoung)
+ * docs; Fix some grammatical issues in the documentation #1777 [alexyoung](https://github.com/alexyoung)
+ * docs; fix Query api exposure
+ * docs; fix return description
+ * docs; Added Notes on findAndUpdate() #1750 [sstadelman](https://github.com/sstadelman)
+ * docs; Update version number in README #1762 [Fodi69](https://github.com/Fodi69)
+
+3.8.0 / 2013-10-31
+==================
+
+ * updated; warn when using an unstable version
+ * updated; error message returned in doc.save() #1595
+ * updated; mongodb driver to 1.3.19 (fix error swallowing behavior)
+ * updated; mquery to 0.3.2
+ * updated; mocha to 1.12.0
+ * updated; mpromise 0.3.0
+ * updated; sliced 0.0.5
+ * removed; mongoose.Error.DocumentError (never used)
+ * removed; namedscope (undocumented and broken) #679 #642 #455 #379
+ * changed; no longer offically supporting node 0.6.x
+ * changed; query.within getter is now a method -> query.within()
+ * changed; query.intersects getter is now a method -> query.intersects()
+ * added; custom error msgs for built-in validators #747
+ * added; discriminator support #1647 #1003 [j](https://github.com/j)
+ * added; support disabled collection name pluralization #1350 #1707 [refack](https://github.com/refack)
+ * added; support for GeoJSON to Query#near [ebensing](https://github.com/ebensing)
+ * added; stand-alone base query support - query.toConstructor() [ebensing](https://github.com/ebensing)
+ * added; promise support to geoSearch #1614 [ebensing](https://github.com/ebensing)
+ * added; promise support for geoNear #1614 [ebensing](https://github.com/ebensing)
+ * added; connection.useDb() #1124 [ebensing](https://github.com/ebensing)
+ * added; promise support to model.mapReduce()
+ * added; promise support to model.ensureIndexes()
+ * added; promise support to model.populate()
+ * added; benchmarks [ebensing](https://github.com/ebensing)
+ * added; publicly exposed connection states #1585
+ * added; $geoWithin support #1529 $1455 [ebensing](https://github.com/ebensing)
+ * added; query method chain validation
+ * added; model.update `overwrite` option
+ * added; model.geoNear() support #1563 [ebensing](https://github.com/ebensing)
+ * added; model.geoSearch() support #1560 [ebensing](https://github.com/ebensing)
+ * added; MongooseBuffer#subtype()
+ * added; model.create() now returns a promise #1340
+ * added; support for `awaitdata` query option
+ * added; pass the doc to doc.remove() callback #1419 [JoeWagner](https://github.com/JoeWagner)
+ * added; aggregation query builder #1404 [njoyard](https://github.com/njoyard)
+ * fixed; document.toObject when using `minimize` and `getters` options #1607 [JedWatson](https://github.com/JedWatson)
+ * fixed; Mixed types can now be required #1722 [Reggino](https://github.com/Reggino)
+ * fixed; do not pluralize model names not ending with letters #1703 [refack](https://github.com/refack)
+ * fixed; repopulating modified populated paths #1697
+ * fixed; doc.equals() when _id option is set to false #1687
+ * fixed; strict mode warnings #1686
+ * fixed; $near GeoJSON casting #1683
+ * fixed; nearSphere GeoJSON query builder
+ * fixed; population field selection w/ strings #1669
+ * fixed; setters not firing on null values #1445 [ebensing](https://github.com/ebensing)
+ * fixed; handle another versioning edge case #1520
+ * fixed; excluding subdocument fields #1280 [ebensing](https://github.com/ebensing)
+ * fixed; allow array properties to be set to null with findOneAndUpdate [aheuermann](https://github.com/aheuermann)
+ * fixed; subdocuments now use own toJSON opts #1376 [ebensing](https://github.com/ebensing)
+ * fixed; model#geoNear fulfills promise when results empty #1658 [ebensing](https://github.com/ebensing)
+ * fixed; utils.merge no longer overrides props and methods #1655 [j](https://github.com/j)
+ * fixed; subdocuments now use their own transform #1412 [ebensing](https://github.com/ebensing)
+ * fixed; model.remove() removes only what is necessary #1649
+ * fixed; update() now only runs with cb or explicit true #1644
+ * fixed; casting ref docs on creation #1606 [ebensing](https://github.com/ebensing)
+ * fixed; model.update "overwrite" option works as documented
+ * fixed; query#remove() works as documented
+ * fixed; "limit" correctly applies to individual items on population #1490 [ebensing](https://github.com/ebensing)
+ * fixed; issue with positional operator on ref docs #1572 [ebensing](https://github.com/ebensing)
+ * fixed; benchmarks to actually output valid json
+ * deprecated; promise#addBack (use promise#onResolve)
+ * deprecated; promise#complete (use promise#fulfill)
+ * deprecated; promise#addCallback (use promise#onFulFill)
+ * deprecated; promise#addErrback (use promise#onReject)
+ * deprecated; query.nearSphere() (use query.near)
+ * deprecated; query.center() (use query.circle)
+ * deprecated; query.centerSphere() (use query.circle)
+ * deprecated; query#slaveOk (use query#read)
+ * docs; custom validator messages
+ * docs; 10gen -> MongoDB
+ * docs; add Date method caveats #1598
+ * docs; more validation details
+ * docs; state which branch is stable/unstable
+ * docs; mention that middleware does not run on Models
+ * docs; promise.fulfill()
+ * docs; fix readme spelling #1483 [yorchopolis](https://github.com/yorchopolis)
+ * docs; fixed up the README and examples [ebensing](https://github.com/ebensing)
+ * website; add "show code" for properties
+ * website; move "show code" links down
+ * website; update guide
+ * website; add unstable docs
+ * website; many improvements
+ * website; fix copyright #1439
+ * website; server.js -> static.js #1546 [nikmartin](https://github.com/nikmartin)
+ * tests; refactor 1703
+ * tests; add test generator
+ * tests; validate formatMessage() throws
+ * tests; add script for continuously running tests
+ * tests; fixed versioning tests
+ * tests; race conditions in tests
+ * tests; added for nested and/or queries
+ * tests; close some test connections
+ * tests; validate db contents
+ * tests; remove .only
+ * tests; close some test connections
+ * tests; validate db contents
+ * tests; remove .only
+ * tests; replace deprecated method names
+ * tests; convert id to string
+ * tests; fix sharding tests for MongoDB 2.4.5
+ * tests; now 4-5 seconds faster
+ * tests; fix race condition
+ * make; suppress warning msg in test
+ * benchmarks; updated for pull requests
+ * examples; improved and expanded [ebensing](https://github.com/ebensing)
+
+3.7.4 (unstable) / 2013-10-01
+=============================
+
+ * updated; mquery to 0.3.2
+ * removed; mongoose.Error.DocumentError (never used)
+ * added; custom error msgs for built-in validators #747
+ * added; discriminator support #1647 #1003 [j](https://github.com/j)
+ * added; support disabled collection name pluralization #1350 #1707 [refack](https://github.com/refack)
+ * fixed; do not pluralize model names not ending with letters #1703 [refack](https://github.com/refack)
+ * fixed; repopulating modified populated paths #1697
+ * fixed; doc.equals() when _id option is set to false #1687
+ * fixed; strict mode warnings #1686
+ * fixed; $near GeoJSON casting #1683
+ * fixed; nearSphere GeoJSON query builder
+ * fixed; population field selection w/ strings #1669
+ * docs; custom validator messages
+ * docs; 10gen -> MongoDB
+ * docs; add Date method caveats #1598
+ * docs; more validation details
+ * website; add "show code" for properties
+ * website; move "show code" links down
+ * tests; refactor 1703
+ * tests; add test generator
+ * tests; validate formatMessage() throws
+
+3.7.3 (unstable) / 2013-08-22
+=============================
+
+ * updated; warn when using an unstable version
+ * updated; mquery to 0.3.1
+ * updated; mocha to 1.12.0
+ * updated; mongodb driver to 1.3.19 (fix error swallowing behavior)
+ * changed; no longer offically supporting node 0.6.x
+ * added; support for GeoJSON to Query#near [ebensing](https://github.com/ebensing)
+ * added; stand-alone base query support - query.toConstructor() [ebensing](https://github.com/ebensing)
+ * added; promise support to geoSearch #1614 [ebensing](https://github.com/ebensing)
+ * added; promise support for geoNear #1614 [ebensing](https://github.com/ebensing)
+ * fixed; setters not firing on null values #1445 [ebensing](https://github.com/ebensing)
+ * fixed; handle another versioning edge case #1520
+ * fixed; excluding subdocument fields #1280 [ebensing](https://github.com/ebensing)
+ * fixed; allow array properties to be set to null with findOneAndUpdate [aheuermann](https://github.com/aheuermann)
+ * fixed; subdocuments now use own toJSON opts #1376 [ebensing](https://github.com/ebensing)
+ * fixed; model#geoNear fulfills promise when results empty #1658 [ebensing](https://github.com/ebensing)
+ * fixed; utils.merge no longer overrides props and methods #1655 [j](https://github.com/j)
+ * fixed; subdocuments now use their own transform #1412 [ebensing](https://github.com/ebensing)
+ * make; suppress warning msg in test
+ * docs; state which branch is stable/unstable
+ * docs; mention that middleware does not run on Models
+ * tests; add script for continuously running tests
+ * tests; fixed versioning tests
+ * benchmarks; updated for pull requests
+
+3.7.2 (unstable) / 2013-08-15
+==================
+
+ * fixed; model.remove() removes only what is necessary #1649
+ * fixed; update() now only runs with cb or explicit true #1644
+ * tests; race conditions in tests
+ * website; update guide
+
+3.7.1 (unstable) / 2013-08-13
+=============================
+
+ * updated; driver to 1.3.18 (fixes memory leak)
+ * added; connection.useDb() #1124 [ebensing](https://github.com/ebensing)
+ * added; promise support to model.mapReduce()
+ * added; promise support to model.ensureIndexes()
+ * added; promise support to model.populate()
+ * fixed; casting ref docs on creation #1606 [ebensing](https://github.com/ebensing)
+ * fixed; model.update "overwrite" option works as documented
+ * fixed; query#remove() works as documented
+ * fixed; "limit" correctly applies to individual items on population #1490 [ebensing](https://github.com/ebensing)
+ * fixed; issue with positional operator on ref docs #1572 [ebensing](https://github.com/ebensing)
+ * fixed; benchmarks to actually output valid json
+ * tests; added for nested and/or queries
+ * tests; close some test connections
+ * tests; validate db contents
+ * tests; remove .only
+ * tests; close some test connections
+ * tests; validate db contents
+ * tests; remove .only
+ * tests; replace deprecated method names
+ * tests; convert id to string
+ * docs; promise.fulfill()
+
+3.7.0 (unstable) / 2013-08-05
+===================
+
+ * changed; query.within getter is now a method -> query.within()
+ * changed; query.intersects getter is now a method -> query.intersects()
+ * deprecated; promise#addBack (use promise#onResolve)
+ * deprecated; promise#complete (use promise#fulfill)
+ * deprecated; promise#addCallback (use promise#onFulFill)
+ * deprecated; promise#addErrback (use promise#onReject)
+ * deprecated; query.nearSphere() (use query.near)
+ * deprecated; query.center() (use query.circle)
+ * deprecated; query.centerSphere() (use query.circle)
+ * deprecated; query#slaveOk (use query#read)
+ * removed; namedscope (undocumented and broken) #679 #642 #455 #379
+ * added; benchmarks [ebensing](https://github.com/ebensing)
+ * added; publicly exposed connection states #1585
+ * added; $geoWithin support #1529 $1455 [ebensing](https://github.com/ebensing)
+ * added; query method chain validation
+ * added; model.update `overwrite` option
+ * added; model.geoNear() support #1563 [ebensing](https://github.com/ebensing)
+ * added; model.geoSearch() support #1560 [ebensing](https://github.com/ebensing)
+ * added; MongooseBuffer#subtype()
+ * added; model.create() now returns a promise #1340
+ * added; support for `awaitdata` query option
+ * added; pass the doc to doc.remove() callback #1419 [JoeWagner](https://github.com/JoeWagner)
+ * added; aggregation query builder #1404 [njoyard](https://github.com/njoyard)
+ * updated; integrate mquery #1562 [ebensing](https://github.com/ebensing)
+ * updated; error msg in doc.save() #1595
+ * updated; bump driver to 1.3.15
+ * updated; mpromise 0.3.0
+ * updated; sliced 0.0.5
+ * tests; fix sharding tests for MongoDB 2.4.5
+ * tests; now 4-5 seconds faster
+ * tests; fix race condition
+ * docs; fix readme spelling #1483 [yorchopolis](https://github.com/yorchopolis)
+ * docs; fixed up the README and examples [ebensing](https://github.com/ebensing)
+ * website; add unstable docs
+ * website; many improvements
+ * website; fix copyright #1439
+ * website; server.js -> static.js #1546 [nikmartin](https://github.com/nikmartin)
+ * examples; improved and expanded [ebensing](https://github.com/ebensing)
+
+3.6.20 (stable) / 2013-09-23
+===================
+
+ * fixed; repopulating modified populated paths #1697
+ * fixed; doc.equals w/ _id false #1687
+ * fixed; strict mode warning #1686
+ * docs; near/nearSphere
+
+3.6.19 (stable) / 2013-09-04
+==================
+
+ * fixed; population field selection w/ strings #1669
+ * docs; Date method caveats #1598
+
+3.6.18 (stable) / 2013-08-22
+===================
+
+ * updated; warn when using an unstable version of mongoose
+ * updated; mocha to 1.12.0
+ * updated; mongodb driver to 1.3.19 (fix error swallowing behavior)
+ * fixed; setters not firing on null values #1445 [ebensing](https://github.com/ebensing)
+ * fixed; properly exclude subdocument fields #1280 [ebensing](https://github.com/ebensing)
+ * fixed; cast error in findAndModify #1643 [aheuermann](https://github.com/aheuermann)
+ * website; update guide
+ * website; added documentation for safe:false and versioning interaction
+ * docs; mention that middleware dont run on Models
+ * docs; fix indexes link
+ * make; suppress warning msg in test
+ * tests; moar
+
+3.6.17 / 2013-08-13
+===================
+
+ * updated; driver to 1.3.18 (fixes memory leak)
+ * fixed; casting ref docs on creation #1606
+ * docs; query options
+
+3.6.16 / 2013-08-08
+===================
+
+ * added; publicly expose connection states #1585
+ * fixed; limit applies to individual items on population #1490 [ebensing](https://github.com/ebensing)
+ * fixed; positional operator casting in updates #1572 [ebensing](https://github.com/ebensing)
+ * updated; MongoDB driver to 1.3.17
+ * updated; sliced to 0.0.5
+ * website; tweak homepage
+ * tests; fixed + added
+ * docs; fix some examples
+ * docs; multi-mongos support details
+ * docs; auto open browser after starting static server
+
+3.6.15 / 2013-07-16
+==================
+
+ * added; mongos failover support #1037
+ * updated; make schematype return vals return self #1580
+ * docs; add note to model.update #571
+ * docs; document third param to document.save callback #1536
+ * tests; tweek mongos test timeout
+
+3.6.14 / 2013-07-05
+===================
+
+ * updated; driver to 1.3.11
+ * fixed; issue with findOneAndUpdate not returning null on upserts #1533 [ebensing](https://github.com/ebensing)
+ * fixed; missing return statement in SchemaArray#$geoIntersects() #1498 [bsrykt](https://github.com/bsrykt)
+ * fixed; wrong isSelected() behavior #1521 [kyano](https://github.com/kyano)
+ * docs; note about toObject behavior during save()
+ * docs; add callbacks details #1547 [nikmartin](https://github.com/nikmartin)
+
+3.6.13 / 2013-06-27
+===================
+
+ * fixed; calling model.distinct without conditions #1541
+ * fixed; regression in Query#count() #1542
+ * now working on 3.6.13
+
+3.6.12 / 2013-06-25
+===================
+
+ * updated; driver to 1.3.10
+ * updated; clearer capped collection error message #1509 [bitmage](https://github.com/bitmage)
+ * fixed; MongooseBuffer subtype loss during casting #1517 [zedgu](https://github.com/zedgu)
+ * fixed; docArray#id when doc.id is disabled #1492
+ * fixed; docArray#id now supports matches on populated arrays #1492 [pgherveou](https://github.com/pgherveou)
+ * website; fix example
+ * website; improve _id disabling example
+ * website; fix typo #1494 [dejj](https://github.com/dejj)
+ * docs; added a 'Requesting new features' section #1504 [shovon](https://github.com/shovon)
+ * docs; improve subtypes description
+ * docs; clarify _id disabling
+ * docs: display by alphabetical order the methods list #1508 [nicolasleger](https://github.com/nicolasleger)
+ * tests; refactor isSelected checks
+ * tests; remove pointless test
+ * tests; fixed timeouts
+
+3.6.11 / 2013-05-15
+===================
+
+ * updated; driver to 1.3.5
+ * fixed; compat w/ Object.create(null) #1484 #1485
+ * fixed; cloning objects w/ missing constructors
+ * fixed; prevent multiple min number validators #1481 [nrako](https://github.com/nrako)
+ * docs; add doc.increment() example
+ * docs; add $size example
+ * docs; add "distinct" example
+
+3.6.10 / 2013-05-09
+==================
+
+ * update driver to 1.3.3
+ * fixed; increment() works without other changes #1475
+ * website; fix links to posterous
+ * docs; fix link #1472
+
+3.6.9 / 2013-05-02
+==================
+
+ * fixed; depopulation of mixed documents #1471
+ * fixed; use of $options in array #1462
+ * tests; fix race condition
+ * docs; fix default example
+
+3.6.8 / 2013-04-25
+==================
+
+ * updated; driver to 1.3.0
+ * fixed; connection.model should retain options #1458 [vedmalex](https://github.com/vedmalex)
+ * tests; 4-5 seconds faster
+
+3.6.7 / 2013-04-19
+==================
+
+ * fixed; population regression in 3.6.6 #1444
+
+3.6.6 / 2013-04-18
+==================
+
+ * fixed; saving populated new documents #1442
+ * fixed; population regession in 3.6.5 #1441
+ * website; fix copyright #1439
+
+3.6.5 / 2013-04-15
+==================
+
+ * fixed; strict:throw edge case using .set(path, val)
+ * fixed; schema.pathType() on some numbericAlpha paths
+ * fixed; numbericAlpha path versioning
+ * fixed; setting nested mixed paths #1418
+ * fixed; setting nested objects with null prop #1326
+ * fixed; regression in v3.6 population performance #1426 [vedmalex](https://github.com/vedmalex)
+ * fixed; read pref typos #1422 [kyano](https://github.com/kyano)
+ * docs; fix method example
+ * website; update faq
+ * website; add more deep links
+ * website; update poolSize docs
+ * website; add 3.6 release notes
+ * website; note about keepAlive
+
+3.6.4 / 2013-04-03
+==================
+
+ * fixed; +field conflict with $slice #1370
+ * fixed; nested deselection conflict #1333
+ * fixed; RangeError in ValidationError.toString() #1296
+ * fixed; do not save user defined transforms #1415
+ * tests; fix race condition
+
+3.6.3 / 2013-04-02
+==================
+
+ * fixed; setting subdocuments deeply nested fields #1394
+ * fixed; regression: populated streams #1411
+ * docs; mention hooks/validation with findAndModify
+ * docs; mention auth
+ * docs; add more links
+ * examples; add document methods example
+ * website; display "see" links for properties
+ * website; clean up homepage
+
+3.6.2 / 2013-03-29
+==================
+
+ * fixed; corrupted sub-doc array #1408
+ * fixed; document#update returns a Query #1397
+ * docs; readpref strategy
+
+3.6.1 / 2013-03-27
+==================
+
+ * added; populate support to findAndModify varients #1395
+ * added; text index type to schematypes
+ * expose allowed index types as Schema.indexTypes
+ * fixed; use of `setMaxListeners` as path
+ * fixed; regression in node 0.6 on docs with > 10 arrays
+ * fixed; do not alter schema arguments #1364
+ * fixed; subdoc#ownerDocument() #1385
+ * website; change search id
+ * website; add search from google [jackdbernier](https://github.com/jackdbernier)
+ * website; fix link
+ * website; add 3.5.x docs release
+ * website; fix link
+ * docs; fix geometry
+ * docs; hide internal constructor
+ * docs; aggregation does not cast arguments #1399
+ * docs; querystream options
+ * examples; added for population
+
+3.6.0 / 2013-03-18
+==================
+
+ * changed; cast 'true'/'false' to boolean #1282 [mgrach](https://github.com/mgrach)
+ * changed; Buffer arrays can now contain nulls
+ * added; QueryStream transform option
+ * added; support for authSource driver option
+ * added; {mongoose,db}.modelNames()
+ * added; $push w/ $slice,$sort support (MongoDB 2.4)
+ * added; hashed index type (MongoDB 2.4)
+ * added; support for mongodb 2.4 geojson (MongoDB 2.4)
+ * added; value at time of validation error
+ * added; support for object literal schemas
+ * added; bufferCommands schema option
+ * added; allow auth option in connections #1360 [geoah](https://github.com/geoah)
+ * added; performance improvements to populate() [263ece9](https://github.com/LearnBoost/mongoose/commit/263ece9)
+ * added; allow adding uncasted docs to populated arrays and properties #570
+ * added; doc#populated(path) stores original populated _ids
+ * added; lean population #1260
+ * added; query.populate() now accepts an options object
+ * added; document#populate(opts, callback)
+ * added; Model.populate(docs, opts, callback)
+ * added; support for rich nested path population
+ * added; doc.array.remove(value) subdoc with _id value support #1278
+ * added; optionally allow non-strict sets and updates
+ * added; promises/A+ comformancy with [mpromise](https://github.com/aheckmann/mpromise)
+ * added; promise#then
+ * added; promise#end
+ * fixed; use of `model` as doc property
+ * fixed; lean population #1382
+ * fixed; empty object mixed defaults #1380
+ * fixed; populate w/ deselected _id using string syntax
+ * fixed; attempted save of divergent populated arrays #1334 related
+ * fixed; better error msg when attempting toObject as property name
+ * fixed; non population buffer casting from doc
+ * fixed; setting populated paths #570
+ * fixed; casting when added docs to populated arrays #570
+ * fixed; prohibit updating arrays selected with $elemMatch #1334
+ * fixed; pull / set subdoc combination #1303
+ * fixed; multiple bg index creation #1365
+ * fixed; manual reconnection to single mongod
+ * fixed; Constructor / version exposure #1124
+ * fixed; CastError race condition
+ * fixed; no longer swallowing misuse of subdoc#invalidate()
+ * fixed; utils.clone retains RegExp opts
+ * fixed; population of non-schema property
+ * fixed; allow updating versionKey #1265
+ * fixed; add EventEmitter props to reserved paths #1338
+ * fixed; can now deselect populated doc _ids #1331
+ * fixed; properly pass subtype to Binary in MongooseBuffer
+ * fixed; casting _id from document with non-ObjectId _id
+ * fixed; specifying schema type edge case { path: [{type: "String" }] }
+ * fixed; typo in schemdate #1329 [jplock](https://github.com/jplock)
+ * updated; driver to 1.2.14
+ * updated; muri to 0.3.1
+ * updated; mpromise to 0.2.1
+ * updated; mocha 1.8.1
+ * updated; mpath to 0.1.1
+ * deprecated; pluralization will die in 4.x
+ * refactor; rename private methods to something unusable as doc properties
+ * refactor MongooseArray#remove
+ * refactor; move expires index to SchemaDate #1328
+ * refactor; internal document properties #1171 #1184
+ * tests; added
+ * docs; indexes
+ * docs; validation
+ * docs; populate
+ * docs; populate
+ * docs; add note about stream compatibility with node 0.8
+ * docs; fix for private names
+ * docs; Buffer -> mongodb.Binary #1363
+ * docs; auth options
+ * docs; improved
+ * website; update FAQ
+ * website; add more api links
+ * website; add 3.5.x docs to prior releases
+ * website; Change mongoose-types to an active repo [jackdbernier](https://github.com/jackdbernier)
+ * website; compat with node 0.10
+ * website; add news section
+ * website; use T for generic type
+ * benchmark; make adjustable
+
+3.6.0rc1 / 2013-03-12
+======================
+
+ * refactor; rename private methods to something unusable as doc properties
+ * added; {mongoose,db}.modelNames()
+ * added; $push w/ $slice,$sort support (MongoDB 2.4)
+ * added; hashed index type (MongoDB 2.4)
+ * added; support for mongodb 2.4 geojson (MongoDB 2.4)
+ * added; value at time of validation error
+ * added; support for object literal schemas
+ * added; bufferCommands schema option
+ * added; allow auth option in connections #1360 [geoah](https://github.com/geoah)
+ * fixed; lean population #1382
+ * fixed; empty object mixed defaults #1380
+ * fixed; populate w/ deselected _id using string syntax
+ * fixed; attempted save of divergent populated arrays #1334 related
+ * fixed; better error msg when attempting toObject as property name
+ * fixed; non population buffer casting from doc
+ * fixed; setting populated paths #570
+ * fixed; casting when added docs to populated arrays #570
+ * fixed; prohibit updating arrays selected with $elemMatch #1334
+ * fixed; pull / set subdoc combination #1303
+ * fixed; multiple bg index creation #1365
+ * fixed; manual reconnection to single mongod
+ * fixed; Constructor / version exposure #1124
+ * fixed; CastError race condition
+ * fixed; no longer swallowing misuse of subdoc#invalidate()
+ * fixed; utils.clone retains RegExp opts
+ * fixed; population of non-schema property
+ * fixed; allow updating versionKey #1265
+ * fixed; add EventEmitter props to reserved paths #1338
+ * fixed; can now deselect populated doc _ids #1331
+ * updated; muri to 0.3.1
+ * updated; driver to 1.2.12
+ * updated; mpromise to 0.2.1
+ * deprecated; pluralization will die in 4.x
+ * docs; Buffer -> mongodb.Binary #1363
+ * docs; auth options
+ * docs; improved
+ * website; add news section
+ * benchmark; make adjustable
+
+3.6.0rc0 / 2013-02-03
+======================
+
+ * changed; cast 'true'/'false' to boolean #1282 [mgrach](https://github.com/mgrach)
+ * changed; Buffer arrays can now contain nulls
+ * fixed; properly pass subtype to Binary in MongooseBuffer
+ * fixed; casting _id from document with non-ObjectId _id
+ * fixed; specifying schema type edge case { path: [{type: "String" }] }
+ * fixed; typo in schemdate #1329 [jplock](https://github.com/jplock)
+ * refactor; move expires index to SchemaDate #1328
+ * refactor; internal document properties #1171 #1184
+ * added; performance improvements to populate() [263ece9](https://github.com/LearnBoost/mongoose/commit/263ece9)
+ * added; allow adding uncasted docs to populated arrays and properties #570
+ * added; doc#populated(path) stores original populated _ids
+ * added; lean population #1260
+ * added; query.populate() now accepts an options object
+ * added; document#populate(opts, callback)
+ * added; Model.populate(docs, opts, callback)
+ * added; support for rich nested path population
+ * added; doc.array.remove(value) subdoc with _id value support #1278
+ * added; optionally allow non-strict sets and updates
+ * added; promises/A+ comformancy with [mpromise](https://github.com/aheckmann/mpromise)
+ * added; promise#then
+ * added; promise#end
+ * updated; mocha 1.8.1
+ * updated; muri to 0.3.0
+ * updated; mpath to 0.1.1
+ * updated; docs
+
+3.5.16 / 2013-08-13
+===================
+
+ * updated; driver to 1.3.18
+
+3.5.15 / 2013-07-26
+==================
+
+ * updated; sliced to 0.0.5
+ * updated; driver to 1.3.12
+ * fixed; regression in Query#count() due to driver change
+ * tests; fixed timeouts
+ * tests; handle differing test uris
+
+3.5.14 / 2013-05-15
+===================
+
+ * updated; driver to 1.3.5
+ * fixed; compat w/ Object.create(null) #1484 #1485
+ * fixed; cloning objects missing constructors
+ * fixed; prevent multiple min number validators #1481 [nrako](https://github.com/nrako)
+
+3.5.13 / 2013-05-09
+==================
+
+ * update driver to 1.3.3
+ * fixed; use of $options in array #1462
+
+3.5.12 / 2013-04-25
+===================
+
+ * updated; driver to 1.3.0
+ * fixed; connection.model should retain options #1458 [vedmalex](https://github.com/vedmalex)
+ * fixed; read pref typos #1422 [kyano](https://github.com/kyano)
+
+3.5.11 / 2013-04-03
+==================
+
+ * fixed; +field conflict with $slice #1370
+ * fixed; RangeError in ValidationError.toString() #1296
+ * fixed; nested deselection conflict #1333
+ * remove time from Makefile
+
+3.5.10 / 2013-04-02
+==================
+
+ * fixed; setting subdocuments deeply nested fields #1394
+ * fixed; do not alter schema arguments #1364
+
+3.5.9 / 2013-03-15
+==================
+
+ * updated; driver to 1.2.14
+ * added; support for authSource driver option (mongodb 2.4)
+ * added; QueryStream transform option (node 0.10 helper)
+ * fixed; backport for saving required populated buffers
+ * fixed; pull / set subdoc combination #1303
+ * fixed; multiple bg index creation #1365
+ * test; added for saveable required populated buffers
+ * test; added for #1365
+ * test; add authSource test
+
+3.5.8 / 2013-03-12
+==================
+
+ * added; auth option in connection [geoah](https://github.com/geoah)
+ * fixed; CastError race condition
+ * docs; add note about stream compatibility with node 0.8
+
+3.5.7 / 2013-02-22
+==================
+
+ * updated; driver to 1.2.13
+ * updated; muri to 0.3.1 #1347
+ * fixed; utils.clone retains RegExp opts #1355
+ * fixed; deepEquals RegExp support
+ * tests; fix a connection test
+ * website; clean up docs [afshinm](https://github.com/afshinm)
+ * website; update homepage
+ * website; migragtion: emphasize impact of strict docs #1264
+
+3.5.6 / 2013-02-14
+==================
+
+ * updated; driver to 1.2.12
+ * fixed; properly pass Binary subtype
+ * fixed; add EventEmitter props to reserved paths #1338
+ * fixed; use correct node engine version
+ * fixed; display empty docs as {} in log output #953 follow up
+ * improved; "bad $within $box argument" error message
+ * populate; add unscientific benchmark
+ * website; add stack overflow to help section
+ * website; use better code font #1336 [risseraka](https://github.com/risseraka)
+ * website; clarify where help is available
+ * website; fix source code links #1272 [floatingLomas](https://github.com/floatingLomas)
+ * docs; be specific about _id schema option #1103
+ * docs; add ensureIndex error handling example
+ * docs; README
+ * docs; CONTRIBUTING.md
+
+3.5.5 / 2013-01-29
+==================
+
+ * updated; driver to 1.2.11
+ * removed; old node < 0.6x shims
+ * fixed; documents with Buffer _ids equality
+ * fixed; MongooseBuffer properly casts numbers
+ * fixed; reopening closed connection on alt host/port #1287
+ * docs; fixed typo in Readme #1298 [rened](https://github.com/rened)
+ * docs; fixed typo in migration docs [Prinzhorn](https://github.com/Prinzhorn)
+ * docs; fixed incorrect annotation in SchemaNumber#min [bilalq](https://github.com/bilalq)
+ * docs; updated
+
+3.5.4 / 2013-01-07
+==================
+
+ * changed; "_pres" & "_posts" are now reserved pathnames #1261
+ * updated; driver to 1.2.8
+ * fixed; exception when reopening a replica set. #1263 [ethankan](https://github.com/ethankan)
+ * website; updated
+
+3.5.3 / 2012-12-26
+==================
+
+ * added; support for geo object notation #1257
+ * fixed; $within query casting with arrays
+ * fixed; unix domain socket support #1254
+ * updated; driver to 1.2.7
+ * updated; muri to 0.0.5
+
+3.5.2 / 2012-12-17
+==================
+
+ * fixed; using auth with replica sets #1253
+
+3.5.1 / 2012-12-12
+==================
+
+ * fixed; regression when using subdoc with `path` as pathname #1245 [daeq](https://github.com/daeq)
+ * fixed; safer db option checks
+ * updated; driver to 1.2.5
+ * website; add more examples
+ * website; clean up old docs
+ * website; fix prev release urls
+ * docs; clarify streaming with HTTP responses
+
+3.5.0 / 2012-12-10
+==================
+
+ * added; paths to CastErrors #1239
+ * added; support for mongodb connection string spec #1187
+ * added; post validate event
+ * added; Schema#get (to retrieve schema options)
+ * added; VersionError #1071
+ * added; npmignore [hidekiy](https://github.com/hidekiy)
+ * update; driver to 1.2.3
+ * fixed; stackoverflow in setter #1234
+ * fixed; utils.isObject()
+ * fixed; do not clobber user specified driver writeConcern #1227
+ * fixed; always pass current document to post hooks
+ * fixed; throw error when user attempts to overwrite a model
+ * fixed; connection.model only caches on connection #1209
+ * fixed; respect conn.model() creation when matching global model exists #1209
+ * fixed; passing model name + collection name now always honors collection name
+ * fixed; setting virtual field to an empty object #1154
+ * fixed; subclassed MongooseErrors exposure, now available in mongoose.Error.xxxx
+ * fixed; model.remove() ignoring callback when executed twice [daeq](https://github.com/daeq) #1210
+ * docs; add collection option to schema api docs #1222
+ * docs; NOTE about db safe options
+ * docs; add post hooks docs
+ * docs; connection string options
+ * docs; middleware is not executed with Model.remove #1241
+ * docs; {g,s}etter introspection #777
+ * docs; update validation docs
+ * docs; add link to plugins page
+ * docs; clarify error returned by unique indexes #1225
+ * docs; more detail about disabling autoIndex behavior
+ * docs; add homepage section to package (npm docs mongoose)
+ * docs; more detail around collection name pluralization #1193
+ * website; add .important css
+ * website; update models page
+ * website; update getting started
+ * website; update quick start
+
+3.4.0 / 2012-11-10
+==================
+
+ * added; support for generic toJSON/toObject transforms #1160 #1020 #1197
+ * added; doc.set() merge support #1148 [NuORDER](https://github.com/NuORDER)
+ * added; query#add support #1188 [aleclofabbro](https://github.com/aleclofabbro)
+ * changed; adding invalid nested paths to non-objects throws 4216f14
+ * changed; fixed; stop invalid function cloning (internal fix)
+ * fixed; add query $and casting support #1180 [anotheri](https://github.com/anotheri)
+ * fixed; overwriting of query arguments #1176
+ * docs; fix expires examples
+ * docs; transforms
+ * docs; schema `collection` option docs [hermanjunge](https://github.com/hermanjunge)
+ * website; updated
+ * tests; added
+
+3.3.1 / 2012-10-11
+==================
+
+ * fixed; allow goose.connect(uris, dbname, opts) #1144
+ * docs; persist API private checked state across page loads
+
+3.3.0 / 2012-10-10
+==================
+
+ * fixed; passing options as 2nd arg to connect() #1144
+ * fixed; race condition after no-op save #1139
+ * fixed; schema field selection application in findAndModify #1150
+ * fixed; directly setting arrays #1126
+ * updated; driver to 1.1.11
+ * updated; collection pluralization rules [mrickard](https://github.com/mrickard)
+ * tests; added
+ * docs; updated
+
+3.2.2 / 2012-10-08
+==================
+
+ * updated; driver to 1.1.10 #1143
+ * updated; use sliced 0.0.3
+ * fixed; do not recast embedded docs unnecessarily
+ * fixed; expires schema option helper #1132
+ * fixed; built in string setters #1131
+ * fixed; debug output for Dates/ObjectId properties #1129
+ * docs; fixed Javascript syntax error in example [olalonde](https://github.com/olalonde)
+ * docs; fix toJSON example #1137
+ * docs; add ensureIndex production notes
+ * docs; fix spelling
+ * docs; add blogposts about v3
+ * website; updated
+ * removed; undocumented inGroupsOf util
+ * tests; added
+
+3.2.1 / 2012-09-28
+==================
+
+ * fixed; remove query batchSize option default of 1000 https://github.com/learnboost/mongoose/commit/3edaa8651
+ * docs; updated
+ * website; updated
+
+3.2.0 / 2012-09-27
+==================
+
+ * added; direct array index assignment with casting support `doc.array.set(index, value)`
+ * fixed; QueryStream#resume within same tick as pause() #1116
+ * fixed; default value validatation #1109
+ * fixed; array splice() not casting #1123
+ * fixed; default array construction edge case #1108
+ * fixed; query casting for inequalities in arrays #1101 [dpatti](https://github.com/dpatti)
+ * tests; added
+ * website; more documentation
+ * website; fixed layout issue #1111 [SlashmanX](https://github.com/SlashmanX)
+ * website; refactored [guille](https://github.com/guille)
+
+3.1.2 / 2012-09-10
+==================
+
+ * added; ReadPreferrence schema option #1097
+ * updated; driver to 1.1.7
+ * updated; default query batchSize to 1000
+ * fixed; we now cast the mapReduce query option #1095
+ * fixed; $elemMatch+$in with field selection #1091
+ * fixed; properly cast $elemMatch+$in conditions #1100
+ * fixed; default field application of subdocs #1027
+ * fixed; querystream prematurely dying #1092
+ * fixed; querystream never resumes when paused at getMore boundries #1092
+ * fixed; querystream occasionally emits data events after destroy #1092
+ * fixed; remove unnecessary ObjectId creation in querystream
+ * fixed; allow ne(boolean) again #1093
+ * docs; add populate/field selection syntax notes
+ * docs; add toObject/toJSON options detail
+ * docs; `read` schema option
+
+3.1.1 / 2012-08-31
+==================
+
+ * updated; driver to 1.1.6
+
+3.1.0 / 2012-08-29
+==================
+
+ * changed; fixed; directly setting nested objects now overwrites entire object (previously incorrectly merged them)
+ * added; read pref support (mongodb 2.2) 205a709c
+ * added; aggregate support (mongodb 2.2) f3a5bd3d
+ * added; virtual {g,s}etter introspection (#1070)
+ * updated; docs [brettz9](https://github.com/brettz9)
+ * updated; driver to 1.1.5
+ * fixed; retain virtual setter return values (#1069)
+
+3.0.3 / 2012-08-23
+==================
+
+ * fixed; use of nested paths beginning w/ numbers #1062
+ * fixed; query population edge case #1053 #1055 [jfremy](https://github.com/jfremy)
+ * fixed; simultaneous top and sub level array modifications #1073
+ * added; id and _id schema option aliases + tests
+ * improve debug formatting to allow copy/paste logged queries into mongo shell [eknkc](https://github.com/eknkc)
+ * docs
+
+3.0.2 / 2012-08-17
+==================
+
+ * added; missing support for v3 sort/select syntax to findAndModify helpers (#1058)
+ * fixed; replset fullsetup event emission
+ * fixed; reconnected event for replsets
+ * fixed; server reconnection setting discovery
+ * fixed; compat with non-schema path props using positional notation (#1048)
+ * fixed; setter/casting order (#665)
+ * docs; updated
+
+3.0.1 / 2012-08-11
+==================
+
+ * fixed; throw Error on bad validators (1044)
+ * fixed; typo in EmbeddedDocument#parentArray [lackac]
+ * fixed; repair mongoose.SchemaTypes alias
+ * updated; docs
+
+3.0.0 / 2012-08-07
+==================
+
+ * removed; old subdocument#commit method
+ * fixed; setting arrays of matching docs [6924cbc2]
+ * fixed; doc!remove event now emits in save order as save for consistency
+ * fixed; pre-save hooks no longer fire on subdocuments when validation fails
+ * added; subdoc#parent() and subdoc#parentArray() to access subdocument parent objects
+ * added; query#lean() helper
+
+3.0.0rc0 / 2012-08-01
+=====================
+
+ * fixed; allow subdoc literal declarations containing "type" pathname (#993)
+ * fixed; unsetting a default array (#758)
+ * fixed; boolean $in queries (#998)
+ * fixed; allow use of `options` as a pathname (#529)
+ * fixed; `model` is again a permitted schema path name
+ * fixed; field selection option on subdocs (#1022)
+ * fixed; handle another edge case with subdoc saving (#975)
+ * added; emit save err on model if listening
+ * added; MongoDB TTL collection support (#1006)
+ * added; $center options support
+ * added; $nearSphere and $polygon support
+ * updated; driver version to 1.1.2
+
+3.0.0alpha2 / 2012-07-18
+=========================
+
+ * changed; index errors are now emitted on their model and passed to an optional callback (#984)
+ * fixed; specifying index along with sparse/unique option no longer overwrites (#1004)
+ * fixed; never swallow connection errors (#618)
+ * fixed; creating object from model with emded object no longer overwrites defaults [achurkin] (#859)
+ * fixed; stop needless validation of unchanged/unselected fields (#891)
+ * fixed; document#equals behavior of objectids (#974)
+ * fixed; honor the minimize schema option (#978)
+ * fixed; provide helpful error msgs when reserved schema path is used (#928)
+ * fixed; callback to conn#disconnect is optional (#875)
+ * fixed; handle missing protocols in connection urls (#987)
+ * fixed; validate args to query#where (#969)
+ * fixed; saving modified/removed subdocs (#975)
+ * fixed; update with $pull from Mixed array (#735)
+ * fixed; error with null shard key value
+ * fixed; allow unsetting enums (#967)
+ * added; support for manual index creation (#984)
+ * added; support for disabled auto-indexing (#984)
+ * added; support for preserving MongooseArray#sort changes (#752)
+ * added; emit state change events on connection
+ * added; support for specifying BSON subtype in MongooseBuffer#toObject [jcrugzz]
+ * added; support for disabled versioning (#977)
+ * added; implicit "new" support for models and Schemas
+
+3.0.0alpha1 / 2012-06-15
+=========================
+
+ * removed; doc#commit (use doc#markModified)
+ * removed; doc.modified getter (#950)
+ * removed; mongoose{connectSet,createSetConnection}. use connect,createConnection instead
+ * removed; query alias methods 1149804c
+ * removed; MongooseNumber
+ * changed; now creating indexes in background by default
+ * changed; strict mode now enabled by default (#952)
+ * changed; doc#modifiedPaths is now a method (#950)
+ * changed; getters no longer cast (#820); casting happens during set
+ * fixed; no need to pass updateArg to findOneAndUpdate (#931)
+ * fixed: utils.merge bug when merging nested non-objects. [treygriffith]
+ * fixed; strict:throw should produce errors in findAndModify (#963)
+ * fixed; findAndUpdate no longer overwrites document (#962)
+ * fixed; setting default DocumentArrays (#953)
+ * fixed; selection of _id with schema deselection (#954)
+ * fixed; ensure promise#error emits instanceof Error
+ * fixed; CursorStream: No stack overflow on any size result (#929)
+ * fixed; doc#remove now passes safe options
+ * fixed; invalid use of $set during $pop
+ * fixed; array#{$pop,$shift} mirror MongoDB behavior
+ * fixed; no longer test non-required vals in string match (#934)
+ * fixed; edge case with doc#inspect
+ * fixed; setter order (#665)
+ * fixed; setting invalid paths in strict mode (#916)
+ * fixed; handle docs without id in DocumentArray#id method (#897)
+ * fixed; do not save virtuals during model.update (#894)
+ * fixed; sub doc toObject virtuals application (#889)
+ * fixed; MongooseArray#pull of ObjectId (#881)
+ * fixed; handle passing db name with any repl set string
+ * fixed; default application of selected fields (#870)
+ * fixed; subdoc paths reported in validation errors (#725)
+ * fixed; incorrect reported num of affected docs in update ops (#862)
+ * fixed; connection assignment in Model#model (#853)
+ * fixed; stringifying arrays of docs (#852)
+ * fixed; modifying subdoc and parent array works (#842)
+ * fixed; passing undefined to next hook (#785)
+ * fixed; Query#{update,remove}() works without callbacks (#788)
+ * fixed; set/updating nested objects by parent pathname (#843)
+ * fixed; allow null in number arrays (#840)
+ * fixed; isNew on sub doc after insertion error (#837)
+ * fixed; if an insert fails, set isNew back to false [boutell]
+ * fixed; isSelected when only _id is selected (#730)
+ * fixed; setting an unset default value (#742)
+ * fixed; query#sort error messaging (#671)
+ * fixed; support for passing $options with $regex
+ * added; array of object literal notation in schema creates DocumentArrays
+ * added; gt,gte,lt,lte query support for arrays (#902)
+ * added; capped collection support (#938)
+ * added; document versioning support
+ * added; inclusion of deselected schema path (#786)
+ * added; non-atomic array#pop
+ * added; EmbeddedDocument constructor is now exposed in DocArray#create 7cf8beec
+ * added; mapReduce support (#678)
+ * added; support for a configurable minimize option #to{Object,JSON}(option) (#848)
+ * added; support for strict: `throws` [regality]
+ * added; support for named schema types (#795)
+ * added; to{Object,JSON} schema options (#805)
+ * added; findByIdAnd{Update,Remove}()
+ * added; findOneAnd{Update,Remove}()
+ * added; query.setOptions()
+ * added; instance.update() (#794)
+ * added; support specifying model in populate() [DanielBaulig]
+ * added; `lean` query option [gitfy]
+ * added; multi-atomic support to MongooseArray#nonAtomicPush
+ * added; support for $set + other $atomic ops on single array
+ * added; tests
+ * updated; driver to 1.0.2
+ * updated; query.sort() syntax to mirror query.select()
+ * updated; clearer cast error msg for array numbers
+ * updated; docs
+ * updated; doc.clone 3x faster (#950)
+ * updated; only create _id if necessary (#950)
+
+2.7.3 / 2012-08-01
+==================
+
+ * fixed; boolean $in queries (#998)
+ * fixed field selection option on subdocs (#1022)
+
+2.7.2 / 2012-07-18
+==================
+
+ * fixed; callback to conn#disconnect is optional (#875)
+ * fixed; handle missing protocols in connection urls (#987)
+ * fixed; saving modified/removed subdocs (#975)
+ * updated; tests
+
+2.7.1 / 2012-06-26
+===================
+
+ * fixed; sharding: when a document holds a null as a value of the shard key
+ * fixed; update() using $pull on an array of Mixed (gh-735)
+ * deprecated; MongooseNumber#{inc, increment, decrement} methods
+ * tests; now using mocha
+
+2.7.0 / 2012-06-14
+===================
+
+ * added; deprecation warnings to methods being removed in 3.x
+
+2.6.8 / 2012-06-14
+===================
+
+ * fixed; edge case when using 'options' as a path name (#961)
+
+2.6.7 / 2012-06-08
+===================
+
+ * fixed; ensure promise#error always emits instanceof Error
+ * fixed; selection of _id w/ another excluded path (#954)
+ * fixed; setting default DocumentArrays (#953)
+
+2.6.6 / 2012-06-06
+===================
+
+ * fixed; stack overflow in query stream with large result sets (#929)
+ * added; $gt, $gte, $lt, $lte support to arrays (#902)
+ * fixed; pass option `safe` along to doc#remove() calls
+
+2.6.5 / 2012-05-24
+===================
+
+ * fixed; do not save virtuals in Model.update (#894)
+ * added; missing $ prefixed query aliases (going away in 3.x) (#884) [timoxley]
+ * fixed; setting invalid paths in strict mode (#916)
+ * fixed; resetting isNew after insert failure (#837) [boutell]
+
+2.6.4 / 2012-05-15
+===================
+
+ * updated; backport string regex $options to 2.x
+ * updated; use driver 1.0.2 (performance improvements) (#914)
+ * fixed; calling MongooseDocumentArray#id when the doc has no _id (#897)
+
+2.6.3 / 2012-05-03
+===================
+
+ * fixed; repl-set connectivity issues during failover on MongoDB 2.0.1
+ * updated; driver to 1.0.0
+ * fixed; virtuals application of subdocs when using toObject({ virtuals: true }) (#889)
+ * fixed; MongooseArray#pull of ObjectId correctly updates the array itself (#881)
+
+2.6.2 / 2012-04-30
+===================
+
+ * fixed; default field application of selected fields (#870)
+
+2.6.1 / 2012-04-30
+===================
+
+ * fixed; connection assignment in mongoose#model (#853, #877)
+ * fixed; incorrect reported num of affected docs in update ops (#862)
+
+2.6.0 / 2012-04-19
+===================
+
+ * updated; hooks.js to 0.2.1
+ * fixed; issue with passing undefined to a hook callback. thanks to [chrisleishman] for reporting.
+ * fixed; updating/setting nested objects in strict schemas (#843) as reported by [kof]
+ * fixed; Query#{update,remove}() work without callbacks again (#788)
+ * fixed; modifying subdoc along with parent array $atomic op (#842)
+
+2.5.14 / 2012-04-13
+===================
+
+ * fixed; setting an unset default value (#742)
+ * fixed; doc.isSelected(otherpath) when only _id is selected (#730)
+ * updated; docs
+
+2.5.13 / 2012-03-22
+===================
+
+ * fixed; failing validation of unselected required paths (#730,#713)
+ * fixed; emitting connection error when only one listener (#759)
+ * fixed; MongooseArray#splice was not returning values (#784) [chrisleishman]
+
+2.5.12 / 2012-03-21
+===================
+
+ * fixed; honor the `safe` option in all ensureIndex calls
+ * updated; node-mongodb-native driver to 0.9.9-7
+
+2.5.11 / 2012-03-15
+===================
+
+ * added; introspection for getters/setters (#745)
+ * updated; node-mongodb-driver to 0.9.9-5
+ * added; tailable method to Query (#769) [holic]
+ * fixed; Number min/max validation of null (#764) [btamas]
+ * added; more flexible user/password connection options (#738) [KarneAsada]
+
+2.5.10 / 2012-03-06
+===================
+
+ * updated; node-mongodb-native driver to 0.9.9-4
+ * added; Query#comment()
+ * fixed; allow unsetting arrays
+ * fixed; hooking the set method of subdocuments (#746)
+ * fixed; edge case in hooks
+ * fixed; allow $id and $ref in queries (fixes compatibility with mongoose-dbref) (#749) [richtera]
+ * added; default path selection to SchemaTypes
+
+2.5.9 / 2012-02-22
+===================
+
+ * fixed; properly cast nested atomic update operators for sub-documents
+
+2.5.8 / 2012-02-21
+===================
+
+ * added; post 'remove' middleware includes model that was removed (#729) [timoxley]
+
+2.5.7 / 2012-02-09
+===================
+
+ * fixed; RegExp validators on node >= v0.6.x
+
+2.5.6 / 2012-02-09
+===================
+
+ * fixed; emit errors returned from db.collection() on the connection (were being swallowed)
+ * added; can add multiple validators in your schema at once (#718) [diogogmt]
+ * fixed; strict embedded documents (#717)
+ * updated; docs [niemyjski]
+ * added; pass number of affected docs back in model.update/save
+
+2.5.5 / 2012-02-03
+===================
+
+ * fixed; RangeError: maximum call stack exceed error when removing docs with Number _id (#714)
+
+2.5.4 / 2012-02-03
+===================
+
+ * fixed; RangeError: maximum call stack exceed error (#714)
+
+2.5.3 / 2012-02-02
+===================
+
+ * added; doc#isSelected(path)
+ * added; query#equals()
+ * added; beta sharding support
+ * added; more descript error msgs (#700) [obeleh]
+ * added; document.modifiedPaths (#709) [ljharb]
+ * fixed; only functions can be added as getters/setters (#707,704) [ljharb]
+
+2.5.2 / 2012-01-30
+===================
+
+ * fixed; rollback -native driver to 0.9.7-3-5 (was causing timeouts and other replica set weirdness)
+ * deprecated; MongooseNumber (will be moved to a separate repo for 3.x)
+ * added; init event is emitted on schemas
+
+2.5.1 / 2012-01-27
+===================
+
+ * fixed; honor strict schemas in Model.update (#699)
+
+2.5.0 / 2012-01-26
+===================
+
+ * added; doc.toJSON calls toJSON on embedded docs when exists [jerem]
+ * added; populate support for refs of type Buffer (#686) [jerem]
+ * added; $all support for ObjectIds and Dates (#690)
+ * fixed; virtual setter calling on instantiation when strict: true (#682) [hunterloftis]
+ * fixed; doc construction triggering getters (#685)
+ * fixed; MongooseBuffer check in deepEquals (#688)
+ * fixed; range error when using Number _ids with `instance.save()` (#691)
+ * fixed; isNew on embedded docs edge case (#680)
+ * updated; driver to 0.9.8-3
+ * updated; expose `model()` method within static methods
+
+2.4.10 / 2012-01-10
+===================
+
+ * added; optional getter application in .toObject()/.toJSON() (#412)
+ * fixed; nested $operators in $all queries (#670)
+ * added; $nor support (#674)
+ * fixed; bug when adding nested schema (#662) [paulwe]
+
+2.4.9 / 2012-01-04
+===================
+
+ * updated; driver to 0.9.7-3-5 to fix Linux performance degradation on some boxes
+
+2.4.8 / 2011-12-22
+===================
+
+ * updated; bump -native to 0.9.7.2-5
+ * fixed; compatibility with date.js (#646) [chrisleishman]
+ * changed; undocumented schema "lax" option to "strict"
+ * fixed; default value population for strict schemas
+ * updated; the nextTick helper for small performance gain. 1bee2a2
+
+2.4.7 / 2011-12-16
+===================
+
+ * fixed; bug in 2.4.6 with path setting
+ * updated; bump -native to 0.9.7.2-1
+ * added; strict schema option [nw]
+
+2.4.6 / 2011-12-16
+===================
+
+ * fixed; conflicting mods on update bug [sirlantis]
+ * improved; doc.id getter performance
+
+2.4.5 / 2011-12-14
+===================
+
+ * fixed; bad MongooseArray behavior in 2.4.2 - 2.4.4
+
+2.4.4 / 2011-12-14
+===================
+
+ * fixed; MongooseArray#doAtomics throwing after sliced
+
+2.4.3 / 2011-12-14
+===================
+
+ * updated; system.profile schema for MongoDB 2x
+
+2.4.2 / 2011-12-12
+===================
+
+ * fixed; partially populating multiple children of subdocs (#639) [kenpratt]
+ * fixed; allow Update of numbers to null (#640) [jerem]
+
+2.4.1 / 2011-12-02
+===================
+
+ * added; options support for populate() queries
+ * updated; -native driver to 0.9.7-1.4
+
+2.4.0 / 2011-11-29
+===================
+
+ * added; QueryStreams (#614)
+ * added; debug print mode for development
+ * added; $within support to Array queries (#586) [ggoodale]
+ * added; $centerSphere query support
+ * fixed; $within support
+ * added; $unset is now used when setting a path to undefined (#519)
+ * added; query#batchSize support
+ * updated; docs
+ * updated; -native driver to 0.9.7-1.3 (provides Windows support)
+
+2.3.13 / 2011-11-15
+===================
+
+ * fixed; required validation for Refs (#612) [ded]
+ * added; $nearSphere support for Arrays (#610)
+
+2.3.12 / 2011-11-09
+===================
+
+ * fixed; regression, objects passed to Model.update should not be changed (#605)
+ * fixed; regression, empty Model.update should not be executed
+
+2.3.11 / 2011-11-08
+===================
+
+ * fixed; using $elemMatch on arrays of Mixed types (#591)
+ * fixed; allow using $regex when querying Arrays (#599)
+ * fixed; calling Model.update with no atomic keys (#602)
+
+2.3.10 / 2011-11-05
+===================
+
+ * fixed; model.update casting for nested paths works (#542)
+
+2.3.9 / 2011-11-04
+==================
+
+ * fixed; deepEquals check for MongooseArray returned false
+ * fixed; reset modified flags of embedded docs after save [gitfy]
+ * fixed; setting embedded doc with identical values no longer marks modified [gitfy]
+ * updated; -native driver to 0.9.6.23 [mlazarov]
+ * fixed; Model.update casting (#542, #545, #479)
+ * fixed; populated refs no longer fail required validators (#577)
+ * fixed; populating refs of objects with custom ids works
+ * fixed; $pop & $unset work with Model.update (#574)
+ * added; more helpful debugging message for Schema#add (#578)
+ * fixed; accessing .id when no _id exists now returns null (#590)
+
+2.3.8 / 2011-10-26
+==================
+
+ * added; callback to query#findOne is now optional (#581)
+
+2.3.7 / 2011-10-24
+==================
+
+ * fixed; wrapped save/remove callbacks in nextTick to mitigate -native swallowing thrown errors
+
+2.3.6 / 2011-10-21
+==================
+
+ * fixed; exclusion of embedded doc _id from query results (#541)
+
+2.3.5 / 2011-10-19
+==================
+
+ * fixed; calling queries without passing a callback works (#569)
+ * fixed; populate() works with String and Number _ids too (#568)
+
+2.3.4 / 2011-10-18
+==================
+
+ * added; Model.create now accepts an array as a first arg
+ * fixed; calling toObject on a DocumentArray with nulls no longer throws
+ * fixed; calling inspect on a DocumentArray with nulls no longer throws
+ * added; MongooseArray#unshift support
+ * fixed; save hooks now fire on embedded documents [gitfy] (#456)
+ * updated; -native driver to 0.9.6-22
+ * fixed; correctly pass $addToSet op instead of $push
+ * fixed; $addToSet properly detects dates
+ * fixed; $addToSet with multiple items works
+ * updated; better node 0.6 Buffer support
+
+2.3.3 / 2011-10-12
+==================
+
+ * fixed; population conditions in multi-query settings [vedmalex] (#563)
+ * fixed; now compatible with Node v0.5.x
+
+2.3.2 / 2011-10-11
+==================
+
+ * fixed; population of null subdoc properties no longer hangs (#561)
+
+2.3.1 / 2011-10-10
+==================
+
+ * added; support for Query filters to populate() [eneko]
+ * fixed; querying with number no longer crashes mongodb (#555) [jlbyrey]
+ * updated; version of -native driver to 0.9.6-21
+ * fixed; prevent query callbacks that throw errors from corrupting -native connection state
+
+2.3.0 / 2011-10-04
+==================
+
+ * fixed; nulls as default values for Boolean now works as expected
+ * updated; version of -native driver to 0.9.6-20
+
+2.2.4 / 2011-10-03
+==================
+
+ * fixed; populate() works when returned array contains undefined/nulls
+
+2.2.3 / 2011-09-29
+==================
+
+ * updated; version of -native driver to 0.9.6-19
+
+2.2.2 / 2011-09-28
+==================
+
+ * added; $regex support to String [davidandrewcope]
+ * added; support for other contexts like repl etc (#535)
+ * fixed; clear modified state properly after saving
+ * added; $addToSet support to Array
+
+2.2.1 / 2011-09-22
+==================
+
+ * more descript error when casting undefined to string
+ * updated; version of -native driver to 0.9.6-18
+
+2.2.0 / 2011-09-22
+==================
+
+ * fixed; maxListeners warning on schemas with many arrays (#530)
+ * changed; return / apply defaults based on fields selected in query (#423)
+ * fixed; correctly detect Mixed types within schema arrays (#532)
+
+2.1.4 / 2011-09-20
+==================
+
+ * fixed; new private methods that stomped on users code
+ * changed; finished removing old "compat" support which did nothing
+
+2.1.3 / 2011-09-16
+==================
+
+ * updated; version of -native driver to 0.9.6-15
+ * added; emit `error` on connection when open fails [edwardhotchkiss]
+ * added; index support to Buffers (thanks justmoon for helping track this down)
+ * fixed; passing collection name via schema in conn.model() now works (thanks vedmalex for reporting)
+
+2.1.2 / 2011-09-07
+==================
+
+ * fixed; Query#find with no args no longer throws
+
+2.1.1 / 2011-09-07
+==================
+
+ * added; support Model.count(fn)
+ * fixed; compatibility with node >=0.4.0 < 0.4.3
+ * added; pass model.options.safe through with .save() so w:2, wtimeout:5000 options work [andrewjstone]
+ * added; support for $type queries
+ * added; support for Query#or
+ * added; more tests
+ * optimized populate queries
+
+2.1.0 / 2011-09-01
+==================
+
+ * changed; document#validate is a public method
+ * fixed; setting number to same value no longer marks modified (#476) [gitfy]
+ * fixed; Buffers shouldn't have default vals
+ * added; allow specifying collection name in schema (#470) [ixti]
+ * fixed; reset modified paths and atomics after saved (#459)
+ * fixed; set isNew on embedded docs to false after save
+ * fixed; use self to ensure proper scope of options in doOpenSet (#483) [andrewjstone]
+
+2.0.4 / 2011-08-29
+==================
+
+ * Fixed; Only send the depopulated ObjectId instead of the entire doc on save (DBRefs)
+ * Fixed; Properly cast nested array values in Model.update (the data was stored in Mongo incorrectly but recast on document fetch was "fixing" it)
+
+2.0.3 / 2011-08-28
+==================
+
+ * Fixed; manipulating a populated array no longer causes infinite loop in BSON serializer during save (#477)
+ * Fixed; populating an empty array no longer hangs foreeeeeeeever (#481)
+
+2.0.2 / 2011-08-25
+==================
+
+ * Fixed; Maintain query option key order (fixes 'bad hint' error from compound query hints)
+
+2.0.1 / 2011-08-25
+==================
+
+ * Fixed; do not over-write the doc when no valide props exist in Model.update (#473)
+
+2.0.0 / 2011-08-24
+===================
+
+ * Added; support for Buffers [justmoon]
+ * Changed; improved error handling [maelstrom]
+ * Removed: unused utils.erase
+ * Fixed; support for passing other context object into Schemas (#234) [Sija]
+ * Fixed; getters are no longer circular refs to themselves (#366)
+ * Removed; unused compat.js
+ * Fixed; getter/setter scopes are set properly
+ * Changed; made several private properties more obvious by prefixing _
+ * Added; DBRef support [guille]
+ * Changed; removed support for multiple collection names per model
+ * Fixed; no longer applying setters when document returned from db
+ * Changed; default auto_reconnect to true
+ * Changed; Query#bind no longer clones the query
+ * Fixed; Model.update now accepts $pull, $inc and friends (#404)
+ * Added; virtual type option support [nw]
+
+1.8.4 / 2011-08-21
+===================
+
+ * Fixed; validation bug when instantiated with non-schema properties (#464) [jmreidy]
+
+1.8.3 / 2011-08-19
+===================
+
+ * Fixed; regression in connection#open [jshaw86]
+
+1.8.2 / 2011-08-17
+===================
+
+ * fixed; reset connection.readyState after failure [tomseago]
+ * fixed; can now query positionally for non-embedded docs (arrays of numbers/strings etc)
+ * fixed; embedded document query casting
+ * added; support for passing options to node-mongo-native db, server, and replsetserver [tomseago]
+
+1.8.1 / 2011-08-10
+===================
+
+ * fixed; ObjectIds were always marked modified
+ * fixed; can now query using document instances
+ * fixed; can now query/update using documents with subdocs
+
+1.8.0 / 2011-08-04
+===================
+
+ * fixed; can now use $all with String and Number
+ * fixed; can query subdoc array with $ne: null
+ * fixed; instance.subdocs#id now works with custom _ids
+ * fixed; do not apply setters when doc returned from db (change in bad behavior)
+
+1.7.4 / 2011-07-25
+===================
+
+ * fixed; sparse now a valid seperate schema option
+ * fixed; now catching cast errors in queries
+ * fixed; calling new Schema with object created in vm.runInNewContext now works (#384) [Sija]
+ * fixed; String enum was disallowing null
+ * fixed; Find by nested document _id now works (#389)
+
+1.7.3 / 2011-07-16
+===================
+
+ * fixed; MongooseArray#indexOf now works with ObjectIds
+ * fixed; validation scope now set properly (#418)
+ * fixed; added missing colors dependency (#398)
+
+1.7.2 / 2011-07-13
+===================
+
+ * changed; node-mongodb-native driver to v0.9.6.7
+
+1.7.1 / 2011-07-12
+===================
+
+ * changed; roll back node-mongodb-native driver to v0.9.6.4
+
+1.7.0 / 2011-07-12
+===================
+
+ * fixed; collection name misspelling [mathrawka]
+ * fixed; 2nd param is required for ReplSetServers [kevinmarvin]
+ * fixed; MongooseArray behaves properly with Object.keys
+ * changed; node-mongodb-native driver to v0.9.6.6
+ * fixed/changed; Mongodb segfault when passed invalid ObjectId (#407)
+ - This means invalid data passed to the ObjectId constructor will now error
+
+1.6.0 / 2011-07-07
+===================
+
+ * changed; .save() errors are now emitted on the instances db instead of the instance 9782463fc
+ * fixed; errors occurring when creating indexes now properly emit on db
+ * added; $maxDistance support to MongooseArrays
+ * fixed; RegExps now work with $all
+ * changed; node-mongodb-native driver to v0.9.6.4
+ * fixed; model names are now accessible via .modelName
+ * added; Query#slaveOk support
+
+1.5.0 / 2011-06-27
+===================
+
+ * changed; saving without a callback no longer ignores the error (@bnoguchi)
+ * changed; hook-js version bump to 0.1.9
+ * changed; node-mongodb-native version bumped to 0.9.6.1 - When .remove() doesn't
+ return an error, null is no longer passed.
+ * fixed; two memory leaks (@justmoon)
+ * added; sparse index support
+ * added; more ObjectId conditionals (gt, lt, gte, lte) (@phillyqueso)
+ * added; options are now passed in model#remote (@JerryLuke)
+
+1.4.0 / 2011-06-10
+===================
+
+ * bumped hooks-js dependency (fixes issue passing null as first arg to next())
+ * fixed; document#inspect now works properly with nested docs
+ * fixed; 'set' now works as a schema attribute (GH-365)
+ * fixed; _id is now set properly within pre-init hooks (GH-289)
+ * added; Query#distinct / Model#distinct support (GH-155)
+ * fixed; embedded docs now can use instance methods (GH-249)
+ * fixed; can now overwrite strings conflicting with schema type
+
+1.3.7 / 2011-06-03
+===================
+
+ * added MongooseArray#splice support
+ * fixed; 'path' is now a valid Schema pathname
+ * improved hooks (utilizing https://github.com/bnoguchi/hooks-js)
+ * fixed; MongooseArray#$shift now works (never did)
+ * fixed; Document.modified no longer throws
+ * fixed; modifying subdoc property sets modified paths for subdoc and parent doc
+ * fixed; marking subdoc path as modified properly persists the value to the db
+ * fixed; RexExps can again be saved ( #357 )
+
+1.3.6 / 2011-05-18
+===================
+
+ * fixed; corrected casting for queries against array types
+ * added; Document#set now accepts Document instances
+
+1.3.5 / 2011-05-17
+===================
+
+ * fixed; $ne queries work properly with single vals
+ * added; #inspect() methods to improve console.log output
+
+1.3.4 / 2011-05-17
+===================
+
+ * fixed; find by Date works as expected (#336)
+ * added; geospatial 2d index support
+ * added; support for $near (#309)
+ * updated; node-mongodb-native driver
+ * fixed; updating numbers work (#342)
+ * added; better error msg when try to remove an embedded doc without an _id (#307)
+ * added; support for 'on-the-fly' schemas (#227)
+ * changed; virtual id getters can now be skipped
+ * fixed; .index() called on subdoc schema now works as expected
+ * fixed; db.setProfile() now buffers until the db is open (#340)
+
+1.3.3 / 2011-04-27
+===================
+
+ * fixed; corrected query casting on nested mixed types
+
+1.3.2 / 2011-04-27
+===================
+
+ * fixed; query hints now retain key order
+
+1.3.1 / 2011-04-27
+===================
+
+ * fixed; setting a property on an embedded array no longer overwrites entire array (GH-310)
+ * fixed; setting nested properties works when sibling prop is named "type"
+ * fixed; isModified is now much finer grained when .set() is used (GH-323)
+ * fixed; mongoose.model() and connection.model() now return the Model (GH-308, GH-305)
+ * fixed; can now use $gt, $lt, $gte, $lte with String schema types (GH-317)
+ * fixed; .lowercase() -> .toLowerCase() in pluralize()
+ * fixed; updating an embedded document by index works (GH-334)
+ * changed; .save() now passes the instance to the callback (GH-294, GH-264)
+ * added; can now query system.profile and system.indexes collections
+ * added; db.model('system.profile') is now included as a default Schema
+ * added; db.setProfiling(level, ms, callback)
+ * added; Query#hint() support
+ * added; more tests
+ * updated node-mongodb-native to 0.9.3
+
+1.3.0 / 2011-04-19
+===================
+
+ * changed; save() callbacks now fire only once on failed validation
+ * changed; Errors returned from save() callbacks now instances of ValidationError
+ * fixed; MongooseArray#indexOf now works properly
+
+1.2.0 / 2011-04-11
+===================
+
+ * changed; MongooseNumber now casts empty string to null
+
+1.1.25 / 2011-04-08
+===================
+
+ * fixed; post init now fires at proper time
+
+1.1.24 / 2011-04-03
+===================
+
+ * fixed; pushing an array onto an Array works on existing docs
+
+1.1.23 / 2011-04-01
+===================
+
+ * Added Model#model
+
+1.1.22 / 2011-03-31
+===================
+
+ * Fixed; $in queries on mixed types now work
+
+1.1.21 / 2011-03-31
+===================
+
+ * Fixed; setting object root to null/undefined works
+
+1.1.20 / 2011-03-31
+===================
+
+ * Fixed; setting multiple props on null field works
+
+1.1.19 / 2011-03-31
+===================
+
+ * Fixed; no longer using $set on paths to an unexisting fields
+
+1.1.18 / 2011-03-30
+===================
+
+ * Fixed; non-mixed type object setters work after initd from null
+
+1.1.17 / 2011-03-30
+===================
+
+ * Fixed; nested object property access works when root initd with null value
+
+1.1.16 / 2011-03-28
+===================
+
+ * Fixed; empty arrays are now saved
+
+1.1.15 / 2011-03-28
+===================
+
+ * Fixed; `null` and `undefined` are set atomically.
+
+1.1.14 / 2011-03-28
+===================
+
+ * Changed; more forgiving date casting, accepting '' as null.
+
+1.1.13 / 2011-03-26
+===================
+
+ * Fixed setting values as `undefined`.
+
+1.1.12 / 2011-03-26
+===================
+
+ * Fixed; nested objects now convert to JSON properly
+ * Fixed; setting nested objects directly now works
+ * Update node-mongodb-native
+
+1.1.11 / 2011-03-25
+===================
+
+ * Fixed for use of `type` as a key.
+
+1.1.10 / 2011-03-23
+===================
+
+ * Changed; Make sure to only ensure indexes while connected
+
+1.1.9 / 2011-03-2
+==================
+
+ * Fixed; Mixed can now default to empty arrays
+ * Fixed; keys by the name 'type' are now valid
+ * Fixed; null values retrieved from the database are hydrated as null values.
+ * Fixed repeated atomic operations when saving a same document twice.
+
+1.1.8 / 2011-03-23
+==================
+
+ * Fixed 'id' overriding. [bnoguchi]
+
+1.1.7 / 2011-03-22
+==================
+
+ * Fixed RegExp query casting when querying against an Array of Strings [bnoguchi]
+ * Fixed getters/setters for nested virtualsl. [bnoguchi]
+
+1.1.6 / 2011-03-22
+==================
+
+ * Only doValidate when path exists in Schema [aheckmann]
+ * Allow function defaults for Array types [aheckmann]
+ * Fix validation hang [aheckmann]
+ * Fix setting of isRequired of SchemaType [aheckmann]
+ * Fix SchemaType#required(false) filter [aheckmann]
+ * More backwards compatibility [aheckmann]
+ * More tests [aheckmann]
+
+1.1.5 / 2011-03-14
+==================
+
+ * Added support for `uri, db, fn` and `uri, fn` signatures for replica sets.
+ * Improved/extended replica set tests.
+
+1.1.4 / 2011-03-09
+==================
+
+ * Fixed; running an empty Query doesn't throw. [aheckmann]
+ * Changed; Promise#addBack returns promise. [aheckmann]
+ * Added streaming cursor support. [aheckmann]
+ * Changed; Query#update defaults to use$SetOnSave now. [brian]
+ * Added more docs.
+
+1.1.3 / 2011-03-04
+==================
+
+ * Added Promise#resolve [aheckmann]
+ * Fixed backward compatibility with nulls [aheckmann]
+ * Changed; Query#{run,exec} return promises [aheckmann]
+
+1.1.2 / 2011-03-03
+==================
+
+ * Restored Query#exec and added notion of default operation [brian]
+ * Fixed ValidatorError messages [brian]
+
+1.1.1 / 2011-03-01
+==================
+
+ * Added SchemaType String `lowercase`, `uppercase`, `trim`.
+ * Public exports (`Model`, `Document`) and tests.
+ * Added ObjectId casting support for `Document`s.
+
+1.1.0 / 2011-02-25
+==================
+
+ * Added support for replica sets.
+
+1.0.16 / 2011-02-18
+===================
+
+ * Added $nin as another whitelisted $conditional for SchemaArray [brian]
+ * Changed #with to #where [brian]
+ * Added ability to use $in conditional with Array types [brian]
+
+1.0.15 / 2011-02-18
+===================
+
+ * Added `id` virtual getter for documents to easily access the hexString of
+ the `_id`.
+
+1.0.14 / 2011-02-17
+===================
+
+ * Fix for arrays within subdocuments [brian]
+
+1.0.13 / 2011-02-16
+===================
+
+ * Fixed embedded documents saving.
+
+1.0.12 / 2011-02-14
+===================
+
+ * Minor refactorings [brian]
+
+1.0.11 / 2011-02-14
+===================
+
+ * Query refactor and $ne, $slice, $or, $size, $elemMatch, $nin, $exists support [brian]
+ * Named scopes sugar [brian]
+
+1.0.10 / 2011-02-11
+===================
+
+ * Updated node-mongodb-native driver [thanks John Allen]
+
+1.0.9 / 2011-02-09
+==================
+
+ * Fixed single member arrays as defaults [brian]
+
+1.0.8 / 2011-02-09
+==================
+
+ * Fixed for collection-level buffering of commands [gitfy]
+ * Fixed `Document#toJSON` [dalejefferson]
+ * Fixed `Connection` authentication [robrighter]
+ * Fixed clash of accessors in getters/setters [eirikurn]
+ * Improved `Model#save` promise handling
+
+1.0.7 / 2011-02-05
+==================
+
+ * Fixed memory leak warnings for test suite on 0.3
+ * Fixed querying documents that have an array that contain at least one
+ specified member. [brian]
+ * Fixed default value for Array types (fixes GH-210). [brian]
+ * Fixed example code.
+
+1.0.6 / 2011-02-03
+==================
+
+ * Fixed `post` middleware
+ * Fixed; it's now possible to instantiate a model even when one of the paths maps
+ to an undefined value [brian]
+
+1.0.5 / 2011-02-02
+==================
+
+ * Fixed; combo $push and $pushAll auto-converts into a $pushAll [brian]
+ * Fixed; combo $pull and $pullAll auto-converts to a single $pullAll [brian]
+ * Fixed; $pullAll now removes said members from array before save (so it acts just
+ like pushAll) [brian]
+ * Fixed; multiple $pulls and $pushes become a single $pullAll and $pushAll.
+ Moreover, $pull now modifies the array before save to reflect the immediate
+ change [brian]
+ * Added tests for nested shortcut getters [brian]
+ * Added tests that show that Schemas with nested Arrays don't apply defaults
+ [brian]
+
+1.0.4 / 2011-02-02
+==================
+
+ * Added MongooseNumber#toString
+ * Added MongooseNumber unit tests
+
+1.0.3 / 2011-02-02
+==================
+
+ * Make sure safe mode works with Model#save
+ * Changed Schema options: safe mode is now the default
+ * Updated node-mongodb-native to HEAD
+
+1.0.2 / 2011-02-02
+==================
+
+ * Added a Model.create shortcut for creating documents. [brian]
+ * Fixed; we can now instantiate models with hashes that map to at least one
+ null value. [brian]
+ * Fixed Schema with more than 2 nested levels. [brian]
+
+1.0.1 / 2011-02-02
+==================
+
+ * Improved `MongooseNumber`, works almost like the native except for `typeof`
+ not being `'number'`.
diff --git a/node_modules/mongoose/LICENSE.md b/node_modules/mongoose/LICENSE.md
new file mode 100644
index 0000000..14cdf56
--- /dev/null
+++ b/node_modules/mongoose/LICENSE.md
@@ -0,0 +1,21 @@
+# MIT License
+
+Copyright (c) 2010 LearnBoost <dev@learnboost.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/mongoose/README.md b/node_modules/mongoose/README.md
new file mode 100644
index 0000000..0da1d48
--- /dev/null
+++ b/node_modules/mongoose/README.md
@@ -0,0 +1,371 @@
+# Mongoose
+
+Mongoose is a [MongoDB](https://www.mongodb.org/) object modeling tool designed to work in an asynchronous environment. Mongoose supports both promises and callbacks.
+
+[![Slack Status](http://slack.mongoosejs.io/badge.svg)](http://slack.mongoosejs.io)
+[![Build Status](https://api.travis-ci.org/Automattic/mongoose.svg?branch=master)](https://travis-ci.org/Automattic/mongoose)
+[![NPM version](https://badge.fury.io/js/mongoose.svg)](http://badge.fury.io/js/mongoose)
+
+[![npm](https://nodei.co/npm/mongoose.png)](https://www.npmjs.com/package/mongoose)
+
+## Documentation
+
+The official documentation website is [mongoosejs.com](http://mongoosejs.com/).
+
+[Mongoose 5.0.0](https://github.com/Automattic/mongoose/blob/master/History.md#500--2018-01-17) was released on January 17, 2018. You can find more details on [backwards breaking changes in 5.0.0 on our docs site](https://mongoosejs.com/docs/migrating_to_5.html).
+
+## Support
+
+ - [Stack Overflow](http://stackoverflow.com/questions/tagged/mongoose)
+ - [Bug Reports](https://github.com/Automattic/mongoose/issues/)
+ - [Mongoose Slack Channel](http://slack.mongoosejs.io/)
+ - [Help Forum](http://groups.google.com/group/mongoose-orm)
+ - [MongoDB Support](https://docs.mongodb.org/manual/support/)
+
+## Plugins
+
+Check out the [plugins search site](http://plugins.mongoosejs.io/) to see hundreds of related modules from the community. Next, learn how to write your own plugin from the [docs](http://mongoosejs.com/docs/plugins.html) or [this blog post](http://thecodebarbarian.com/2015/03/06/guide-to-mongoose-plugins).
+
+## Contributors
+
+Pull requests are always welcome! Please base pull requests against the `master`
+branch and follow the [contributing guide](https://github.com/Automattic/mongoose/blob/master/CONTRIBUTING.md).
+
+If your pull requests makes documentation changes, please do **not**
+modify any `.html` files. The `.html` files are compiled code, so please make
+your changes in `docs/*.pug`, `lib/*.js`, or `test/docs/*.js`.
+
+View all 400+ [contributors](https://github.com/Automattic/mongoose/graphs/contributors).
+
+## Installation
+
+First install [Node.js](http://nodejs.org/) and [MongoDB](https://www.mongodb.org/downloads). Then:
+
+```sh
+$ npm install mongoose
+```
+
+## Importing
+
+```javascript
+// Using Node.js `require()`
+const mongoose = require('mongoose');
+
+// Using ES6 imports
+import mongoose from 'mongoose';
+```
+
+## Mongoose for Enterprise
+
+Available as part of the Tidelift Subscription
+
+The maintainers of mongoose and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-mongoose?utm_source=npm-mongoose&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
+
+## Overview
+
+### Connecting to MongoDB
+
+First, we need to define a connection. If your app uses only one database, you should use `mongoose.connect`. If you need to create additional connections, use `mongoose.createConnection`.
+
+Both `connect` and `createConnection` take a `mongodb://` URI, or the parameters `host, database, port, options`.
+
+```js
+await mongoose.connect('mongodb://localhost/my_database', {
+ useNewUrlParser: true,
+ useUnifiedTopology: true,
+ useFindAndModify: false,
+ useCreateIndex: true
+});
+```
+
+Once connected, the `open` event is fired on the `Connection` instance. If you're using `mongoose.connect`, the `Connection` is `mongoose.connection`. Otherwise, `mongoose.createConnection` return value is a `Connection`.
+
+**Note:** _If the local connection fails then try using 127.0.0.1 instead of localhost. Sometimes issues may arise when the local hostname has been changed._
+
+**Important!** Mongoose buffers all the commands until it's connected to the database. This means that you don't have to wait until it connects to MongoDB in order to define models, run queries, etc.
+
+### Defining a Model
+
+Models are defined through the `Schema` interface.
+
+```js
+const Schema = mongoose.Schema;
+const ObjectId = Schema.ObjectId;
+
+const BlogPost = new Schema({
+ author: ObjectId,
+ title: String,
+ body: String,
+  date: Date
+});
+```
+
+Aside from defining the structure of your documents and the types of data you're storing, a Schema handles the definition of:
+
+* [Validators](http://mongoosejs.com/docs/validation.html) (async and sync)
+* [Defaults](http://mongoosejs.com/docs/api.html#schematype_SchemaType-default)
+* [Getters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-get)
+* [Setters](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set)
+* [Indexes](http://mongoosejs.com/docs/guide.html#indexes)
+* [Middleware](http://mongoosejs.com/docs/middleware.html)
+* [Methods](http://mongoosejs.com/docs/guide.html#methods) definition
+* [Statics](http://mongoosejs.com/docs/guide.html#statics) definition
+* [Plugins](http://mongoosejs.com/docs/plugins.html)
+* [pseudo-JOINs](http://mongoosejs.com/docs/populate.html)
+
+The following example shows some of these features:
+
+```js
+const Comment = new Schema({
+ name: { type: String, default: 'hahaha' },
+ age: { type: Number, min: 18, index: true },
+ bio: { type: String, match: /[a-z]/ },
+ date: { type: Date, default: Date.now },
+ buff: Buffer
+});
+
+// a setter
+Comment.path('name').set(function (v) {
+ return capitalize(v);
+});
+
+// middleware
+Comment.pre('save', function (next) {
+ notify(this.get('email'));
+ next();
+});
+```
+
+Take a look at the example in [`examples/schema/schema.js`](https://github.com/Automattic/mongoose/blob/master/examples/schema/schema.js) for an end-to-end example of a typical setup.
+
+### Accessing a Model
+
+Once we define a model through `mongoose.model('ModelName', mySchema)`, we can access it through the same function
+
+```js
+const MyModel = mongoose.model('ModelName');
+```
+
+Or just do it all at once
+
+```js
+const MyModel = mongoose.model('ModelName', mySchema);
+```
+
+The first argument is the _singular_ name of the collection your model is for. **Mongoose automatically looks for the _plural_ version of your model name.** For example, if you use
+
+```js
+const MyModel = mongoose.model('Ticket', mySchema);
+```
+
+Then Mongoose will create the model for your __tickets__ collection, not your __ticket__ collection.
+
+Once we have our model, we can then instantiate it, and save it:
+
+```js
+const instance = new MyModel();
+instance.my.key = 'hello';
+instance.save(function (err) {
+ //
+});
+```
+
+Or we can find documents from the same collection
+
+```js
+MyModel.find({}, function (err, docs) {
+ // docs.forEach
+});
+```
+
+You can also `findOne`, `findById`, `update`, etc.
+
+```js
+const instance = await MyModel.findOne({ ... });
+console.log(instance.my.key); // 'hello'
+```
+
+For more details check out [the docs](http://mongoosejs.com/docs/queries.html).
+
+**Important!** If you opened a separate connection using `mongoose.createConnection()` but attempt to access the model through `mongoose.model('ModelName')` it will not work as expected since it is not hooked up to an active db connection. In this case access your model through the connection you created:
+
+```js
+const conn = mongoose.createConnection('your connection string');
+const MyModel = conn.model('ModelName', schema);
+const m = new MyModel;
+m.save(); // works
+```
+
+vs
+
+```js
+const conn = mongoose.createConnection('your connection string');
+const MyModel = mongoose.model('ModelName', schema);
+const m = new MyModel;
+m.save(); // does not work b/c the default connection object was never connected
+```
+
+### Embedded Documents
+
+In the first example snippet, we defined a key in the Schema that looks like:
+
+```
+comments: [Comment]
+```
+
+Where `Comment` is a `Schema` we created. This means that creating embedded documents is as simple as:
+
+```js
+// retrieve my model
+const BlogPost = mongoose.model('BlogPost');
+
+// create a blog post
+const post = new BlogPost();
+
+// create a comment
+post.comments.push({ title: 'My comment' });
+
+post.save(function (err) {
+ if (!err) console.log('Success!');
+});
+```
+
+The same goes for removing them:
+
+```js
+BlogPost.findById(myId, function (err, post) {
+ if (!err) {
+ post.comments[0].remove();
+ post.save(function (err) {
+ // do something
+ });
+ }
+});
+```
+
+Embedded documents enjoy all the same features as your models. Defaults, validators, middleware. Whenever an error occurs, it's bubbled to the `save()` error callback, so error handling is a snap!
+
+
+### Middleware
+
+See the [docs](http://mongoosejs.com/docs/middleware.html) page.
+
+#### Intercepting and mutating method arguments
+
+You can intercept method arguments via middleware.
+
+For example, this would allow you to broadcast changes about your Documents every time someone `set`s a path in your Document to a new value:
+
+```js
+schema.pre('set', function (next, path, val, typel) {
+ // `this` is the current Document
+ this.emit('set', path, val);
+
+ // Pass control to the next pre
+ next();
+});
+```
+
+Moreover, you can mutate the incoming `method` arguments so that subsequent middleware see different values for those arguments. To do so, just pass the new values to `next`:
+
+```js
+.pre(method, function firstPre (next, methodArg1, methodArg2) {
+ // Mutate methodArg1
+ next("altered-" + methodArg1.toString(), methodArg2);
+});
+
+// pre declaration is chainable
+.pre(method, function secondPre (next, methodArg1, methodArg2) {
+ console.log(methodArg1);
+ // => 'altered-originalValOfMethodArg1'
+
+ console.log(methodArg2);
+ // => 'originalValOfMethodArg2'
+
+ // Passing no arguments to `next` automatically passes along the current argument values
+ // i.e., the following `next()` is equivalent to `next(methodArg1, methodArg2)`
+ // and also equivalent to, with the example method arg
+ // values, `next('altered-originalValOfMethodArg1', 'originalValOfMethodArg2')`
+ next();
+});
+```
+
+#### Schema gotcha
+
+`type`, when used in a schema has special meaning within Mongoose. If your schema requires using `type` as a nested property you must use object notation:
+
+```js
+new Schema({
+ broken: { type: Boolean },
+ asset: {
+ name: String,
+ type: String // uh oh, it broke. asset will be interpreted as String
+ }
+});
+
+new Schema({
+ works: { type: Boolean },
+ asset: {
+ name: String,
+ type: { type: String } // works. asset is an object with a type property
+ }
+});
+```
+
+### Driver Access
+
+Mongoose is built on top of the [official MongoDB Node.js driver](https://github.com/mongodb/node-mongodb-native). Each mongoose model keeps a reference to a [native MongoDB driver collection](http://mongodb.github.io/node-mongodb-native/2.1/api/Collection.html). The collection object can be accessed using `YourModel.collection`. However, using the collection object directly bypasses all mongoose features, including hooks, validation, etc. The one
+notable exception that `YourModel.collection` still buffers
+commands. As such, `YourModel.collection.find()` will **not**
+return a cursor.
+
+## API Docs
+
+Find the API docs [here](http://mongoosejs.com/docs/api.html), generated using [dox](https://github.com/tj/dox)
+and [acquit](https://github.com/vkarpov15/acquit).
+
+## Related Projects
+
+#### MongoDB Runners
+
+- [run-rs](https://www.npmjs.com/package/run-rs)
+- [mongodb-memory-server](https://www.npmjs.com/package/mongodb-memory-server)
+- [mongodb-topology-manager](https://www.npmjs.com/package/mongodb-topology-manager)
+
+#### Unofficial CLIs
+
+- [mongoosejs-cli](https://www.npmjs.com/package/mongoosejs-cli)
+
+#### Data Seeding
+
+- [dookie](https://www.npmjs.com/package/dookie)
+- [seedgoose](https://www.npmjs.com/package/seedgoose)
+- [mongoose-data-seed](https://www.npmjs.com/package/mongoose-data-seed)
+
+#### Express Session Stores
+
+- [connect-mongodb-session](https://www.npmjs.com/package/connect-mongodb-session)
+- [connect-mongo](https://www.npmjs.com/package/connect-mongo)
+
+## License
+
+Copyright (c) 2010 LearnBoost &lt;dev@learnboost.com&gt;
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/node_modules/mongoose/SECURITY.md b/node_modules/mongoose/SECURITY.md
new file mode 100644
index 0000000..41b89d8
--- /dev/null
+++ b/node_modules/mongoose/SECURITY.md
@@ -0,0 +1 @@
+Please follow the instructions on [Tidelift's security page](https://tidelift.com/docs/security) to report a security issue.
diff --git a/node_modules/mongoose/browser.js b/node_modules/mongoose/browser.js
new file mode 100644
index 0000000..4cf8228
--- /dev/null
+++ b/node_modules/mongoose/browser.js
@@ -0,0 +1,8 @@
+/**
+ * Export lib/mongoose
+ *
+ */
+
+'use strict';
+
+module.exports = require('./lib/browser');
diff --git a/node_modules/mongoose/build-browser.js b/node_modules/mongoose/build-browser.js
new file mode 100644
index 0000000..6f4aa16
--- /dev/null
+++ b/node_modules/mongoose/build-browser.js
@@ -0,0 +1,18 @@
+'use strict';
+
+const config = require('./webpack.config.js');
+const webpack = require('webpack');
+
+const compiler = webpack(config);
+
+console.log('Starting browser build...');
+compiler.run((err, stats) => {
+ if (err) {
+ console.err(stats.toString());
+ console.err('Browser build unsuccessful.');
+ process.exit(1);
+ }
+ console.log(stats.toString());
+ console.log('Browser build successful.');
+ process.exit(0);
+});
diff --git a/node_modules/mongoose/dist/browser.umd.js b/node_modules/mongoose/dist/browser.umd.js
new file mode 100644
index 0000000..ba4ae13
--- /dev/null
+++ b/node_modules/mongoose/dist/browser.umd.js
@@ -0,0 +1,1591 @@
+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.mongoose=e():t.mongoose=e()}("undefined"!=typeof self?self:this,(function(){return function(t){var e={};function r(n){if(e[n])return e[n].exports;var o=e[n]={i:n,l:!1,exports:{}};return t[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}return r.m=t,r.c=e,r.d=function(t,e,n){r.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(t,e){if(1&e&&(t=r(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var o in t)r.d(n,o,function(e){return t[e]}.bind(null,o));return n},r.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(e,"a",e),e},r.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},r.p="",r(r.s=93)}([function(t,e,r){"use strict";e.arrayAtomicsSymbol=Symbol("mongoose#Array#_atomics"),e.arrayParentSymbol=Symbol("mongoose#Array#_parent"),e.arrayPathSymbol=Symbol("mongoose#Array#_path"),e.arraySchemaSymbol=Symbol("mongoose#Array#_schema"),e.documentArrayParent=Symbol("mongoose:documentArrayParent"),e.documentIsSelected=Symbol("mongoose#Document#isSelected"),e.documentIsModified=Symbol("mongoose#Document#isModified"),e.documentModifiedPaths=Symbol("mongoose#Document#modifiedPaths"),e.documentSchemaSymbol=Symbol("mongoose#Document#schema"),e.getSymbol=Symbol("mongoose#Document#get"),e.modelSymbol=Symbol("mongoose#Model"),e.objectIdSymbol=Symbol("mongoose#ObjectId"),e.populateModelSymbol=Symbol("mongoose.PopulateOptions#Model"),e.schemaTypeSymbol=Symbol("mongoose#schemaType"),e.sessionNewDocuments=Symbol("mongoose:ClientSession#newDocuments"),e.scopeSymbol=Symbol("mongoose#Document#scope"),e.validatorErrorSymbol=Symbol("mongoose:validatorError")},function(t,e,r){"use strict";(function(t){
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh <http://feross.org>
+ * @license MIT
+ */
+var n=r(95),o=r(96),i=r(97);function s(){return u.TYPED_ARRAY_SUPPORT?2147483647:1073741823}function a(t,e){if(s()<e)throw new RangeError("Invalid typed array length");return u.TYPED_ARRAY_SUPPORT?(t=new Uint8Array(e)).__proto__=u.prototype:(null===t&&(t=new u(e)),t.length=e),t}function u(t,e,r){if(!(u.TYPED_ARRAY_SUPPORT||this instanceof u))return new u(t,e,r);if("number"==typeof t){if("string"==typeof e)throw new Error("If encoding is specified then the first argument must be a string");return f(this,t)}return c(this,t,e,r)}function c(t,e,r,n){if("number"==typeof e)throw new TypeError('"value" argument must not be a number');return"undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer?function(t,e,r,n){if(e.byteLength,r<0||e.byteLength<r)throw new RangeError("'offset' is out of bounds");if(e.byteLength<r+(n||0))throw new RangeError("'length' is out of bounds");e=void 0===r&&void 0===n?new Uint8Array(e):void 0===n?new Uint8Array(e,r):new Uint8Array(e,r,n);u.TYPED_ARRAY_SUPPORT?(t=e).__proto__=u.prototype:t=p(t,e);return t}(t,e,r,n):"string"==typeof e?function(t,e,r){"string"==typeof r&&""!==r||(r="utf8");if(!u.isEncoding(r))throw new TypeError('"encoding" must be a valid string encoding');var n=0|y(e,r),o=(t=a(t,n)).write(e,r);o!==n&&(t=t.slice(0,o));return t}(t,e,r):function(t,e){if(u.isBuffer(e)){var r=0|h(e.length);return 0===(t=a(t,r)).length||e.copy(t,0,0,r),t}if(e){if("undefined"!=typeof ArrayBuffer&&e.buffer instanceof ArrayBuffer||"length"in e)return"number"!=typeof e.length||(n=e.length)!=n?a(t,0):p(t,e);if("Buffer"===e.type&&i(e.data))return p(t,e.data)}var n;throw new TypeError("First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.")}(t,e)}function l(t){if("number"!=typeof t)throw new TypeError('"size" argument must be a number');if(t<0)throw new RangeError('"size" argument must not be negative')}function f(t,e){if(l(e),t=a(t,e<0?0:0|h(e)),!u.TYPED_ARRAY_SUPPORT)for(var r=0;r<e;++r)t[r]=0;return t}function p(t,e){var r=e.length<0?0:0|h(e.length);t=a(t,r);for(var n=0;n<r;n+=1)t[n]=255&e[n];return t}function h(t){if(t>=s())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+s().toString(16)+" bytes");return 0|t}function y(t,e){if(u.isBuffer(t))return t.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(t)||t instanceof ArrayBuffer))return t.byteLength;"string"!=typeof t&&(t=""+t);var r=t.length;if(0===r)return 0;for(var n=!1;;)switch(e){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return L(t).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return U(t).length;default:if(n)return L(t).length;e=(""+e).toLowerCase(),n=!0}}function d(t,e,r){var n=!1;if((void 0===e||e<0)&&(e=0),e>this.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(e>>>=0))return"";for(t||(t="utf8");;)switch(t){case"hex":return P(this,e,r);case"utf8":case"utf-8":return E(this,e,r);case"ascii":return $(this,e,r);case"latin1":case"binary":return x(this,e,r);case"base64":return j(this,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return N(this,e,r);default:if(n)throw new TypeError("Unknown encoding: "+t);t=(t+"").toLowerCase(),n=!0}}function m(t,e,r){var n=t[e];t[e]=t[r],t[r]=n}function _(t,e,r,n,o){if(0===t.length)return-1;if("string"==typeof r?(n=r,r=0):r>2147483647?r=2147483647:r<-2147483648&&(r=-2147483648),r=+r,isNaN(r)&&(r=o?0:t.length-1),r<0&&(r=t.length+r),r>=t.length){if(o)return-1;r=t.length-1}else if(r<0){if(!o)return-1;r=0}if("string"==typeof e&&(e=u.from(e,n)),u.isBuffer(e))return 0===e.length?-1:v(t,e,r,n,o);if("number"==typeof e)return e&=255,u.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?o?Uint8Array.prototype.indexOf.call(t,e,r):Uint8Array.prototype.lastIndexOf.call(t,e,r):v(t,[e],r,n,o);throw new TypeError("val must be string, number or Buffer")}function v(t,e,r,n,o){var i,s=1,a=t.length,u=e.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(t.length<2||e.length<2)return-1;s=2,a/=2,u/=2,r/=2}function c(t,e){return 1===s?t[e]:t.readUInt16BE(e*s)}if(o){var l=-1;for(i=r;i<a;i++)if(c(t,i)===c(e,-1===l?0:i-l)){if(-1===l&&(l=i),i-l+1===u)return l*s}else-1!==l&&(i-=i-l),l=-1}else for(r+u>a&&(r=a-u),i=r;i>=0;i--){for(var f=!0,p=0;p<u;p++)if(c(t,i+p)!==c(e,p)){f=!1;break}if(f)return i}return-1}function g(t,e,r,n){r=Number(r)||0;var o=t.length-r;n?(n=Number(n))>o&&(n=o):n=o;var i=e.length;if(i%2!=0)throw new TypeError("Invalid hex string");n>i/2&&(n=i/2);for(var s=0;s<n;++s){var a=parseInt(e.substr(2*s,2),16);if(isNaN(a))return s;t[r+s]=a}return s}function b(t,e,r,n){return V(L(e,t.length-r),t,r,n)}function w(t,e,r,n){return V(function(t){for(var e=[],r=0;r<t.length;++r)e.push(255&t.charCodeAt(r));return e}(e),t,r,n)}function O(t,e,r,n){return w(t,e,r,n)}function S(t,e,r,n){return V(U(e),t,r,n)}function A(t,e,r,n){return V(function(t,e){for(var r,n,o,i=[],s=0;s<t.length&&!((e-=2)<0);++s)r=t.charCodeAt(s),n=r>>8,o=r%256,i.push(o),i.push(n);return i}(e,t.length-r),t,r,n)}function j(t,e,r){return 0===e&&r===t.length?n.fromByteArray(t):n.fromByteArray(t.slice(e,r))}function E(t,e,r){r=Math.min(t.length,r);for(var n=[],o=e;o<r;){var i,s,a,u,c=t[o],l=null,f=c>239?4:c>223?3:c>191?2:1;if(o+f<=r)switch(f){case 1:c<128&&(l=c);break;case 2:128==(192&(i=t[o+1]))&&(u=(31&c)<<6|63&i)>127&&(l=u);break;case 3:i=t[o+1],s=t[o+2],128==(192&i)&&128==(192&s)&&(u=(15&c)<<12|(63&i)<<6|63&s)>2047&&(u<55296||u>57343)&&(l=u);break;case 4:i=t[o+1],s=t[o+2],a=t[o+3],128==(192&i)&&128==(192&s)&&128==(192&a)&&(u=(15&c)<<18|(63&i)<<12|(63&s)<<6|63&a)>65535&&u<1114112&&(l=u)}null===l?(l=65533,f=1):l>65535&&(l-=65536,n.push(l>>>10&1023|55296),l=56320|1023&l),n.push(l),o+=f}return function(t){var e=t.length;if(e<=4096)return String.fromCharCode.apply(String,t);var r="",n=0;for(;n<e;)r+=String.fromCharCode.apply(String,t.slice(n,n+=4096));return r}(n)}e.Buffer=u,e.SlowBuffer=function(t){+t!=t&&(t=0);return u.alloc(+t)},e.INSPECT_MAX_BYTES=50,u.TYPED_ARRAY_SUPPORT=void 0!==t.TYPED_ARRAY_SUPPORT?t.TYPED_ARRAY_SUPPORT:function(){try{var t=new Uint8Array(1);return t.__proto__={__proto__:Uint8Array.prototype,foo:function(){return 42}},42===t.foo()&&"function"==typeof t.subarray&&0===t.subarray(1,1).byteLength}catch(t){return!1}}(),e.kMaxLength=s(),u.poolSize=8192,u._augment=function(t){return t.__proto__=u.prototype,t},u.from=function(t,e,r){return c(null,t,e,r)},u.TYPED_ARRAY_SUPPORT&&(u.prototype.__proto__=Uint8Array.prototype,u.__proto__=Uint8Array,"undefined"!=typeof Symbol&&Symbol.species&&u[Symbol.species]===u&&Object.defineProperty(u,Symbol.species,{value:null,configurable:!0})),u.alloc=function(t,e,r){return function(t,e,r,n){return l(e),e<=0?a(t,e):void 0!==r?"string"==typeof n?a(t,e).fill(r,n):a(t,e).fill(r):a(t,e)}(null,t,e,r)},u.allocUnsafe=function(t){return f(null,t)},u.allocUnsafeSlow=function(t){return f(null,t)},u.isBuffer=function(t){return!(null==t||!t._isBuffer)},u.compare=function(t,e){if(!u.isBuffer(t)||!u.isBuffer(e))throw new TypeError("Arguments must be Buffers");if(t===e)return 0;for(var r=t.length,n=e.length,o=0,i=Math.min(r,n);o<i;++o)if(t[o]!==e[o]){r=t[o],n=e[o];break}return r<n?-1:n<r?1:0},u.isEncoding=function(t){switch(String(t).toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"latin1":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return!0;default:return!1}},u.concat=function(t,e){if(!i(t))throw new TypeError('"list" argument must be an Array of Buffers');if(0===t.length)return u.alloc(0);var r;if(void 0===e)for(e=0,r=0;r<t.length;++r)e+=t[r].length;var n=u.allocUnsafe(e),o=0;for(r=0;r<t.length;++r){var s=t[r];if(!u.isBuffer(s))throw new TypeError('"list" argument must be an Array of Buffers');s.copy(n,o),o+=s.length}return n},u.byteLength=y,u.prototype._isBuffer=!0,u.prototype.swap16=function(){var t=this.length;if(t%2!=0)throw new RangeError("Buffer size must be a multiple of 16-bits");for(var e=0;e<t;e+=2)m(this,e,e+1);return this},u.prototype.swap32=function(){var t=this.length;if(t%4!=0)throw new RangeError("Buffer size must be a multiple of 32-bits");for(var e=0;e<t;e+=4)m(this,e,e+3),m(this,e+1,e+2);return this},u.prototype.swap64=function(){var t=this.length;if(t%8!=0)throw new RangeError("Buffer size must be a multiple of 64-bits");for(var e=0;e<t;e+=8)m(this,e,e+7),m(this,e+1,e+6),m(this,e+2,e+5),m(this,e+3,e+4);return this},u.prototype.toString=function(){var t=0|this.length;return 0===t?"":0===arguments.length?E(this,0,t):d.apply(this,arguments)},u.prototype.equals=function(t){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");return this===t||0===u.compare(this,t)},u.prototype.inspect=function(){var t="",r=e.INSPECT_MAX_BYTES;return this.length>0&&(t=this.toString("hex",0,r).match(/.{2}/g).join(" "),this.length>r&&(t+=" ... ")),"<Buffer "+t+">"},u.prototype.compare=function(t,e,r,n,o){if(!u.isBuffer(t))throw new TypeError("Argument must be a Buffer");if(void 0===e&&(e=0),void 0===r&&(r=t?t.length:0),void 0===n&&(n=0),void 0===o&&(o=this.length),e<0||r>t.length||n<0||o>this.length)throw new RangeError("out of range index");if(n>=o&&e>=r)return 0;if(n>=o)return-1;if(e>=r)return 1;if(this===t)return 0;for(var i=(o>>>=0)-(n>>>=0),s=(r>>>=0)-(e>>>=0),a=Math.min(i,s),c=this.slice(n,o),l=t.slice(e,r),f=0;f<a;++f)if(c[f]!==l[f]){i=c[f],s=l[f];break}return i<s?-1:s<i?1:0},u.prototype.includes=function(t,e,r){return-1!==this.indexOf(t,e,r)},u.prototype.indexOf=function(t,e,r){return _(this,t,e,r,!0)},u.prototype.lastIndexOf=function(t,e,r){return _(this,t,e,r,!1)},u.prototype.write=function(t,e,r,n){if(void 0===e)n="utf8",r=this.length,e=0;else if(void 0===r&&"string"==typeof e)n=e,r=this.length,e=0;else{if(!isFinite(e))throw new Error("Buffer.write(string, encoding, offset[, length]) is no longer supported");e|=0,isFinite(r)?(r|=0,void 0===n&&(n="utf8")):(n=r,r=void 0)}var o=this.length-e;if((void 0===r||r>o)&&(r=o),t.length>0&&(r<0||e<0)||e>this.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var i=!1;;)switch(n){case"hex":return g(this,t,e,r);case"utf8":case"utf-8":return b(this,t,e,r);case"ascii":return w(this,t,e,r);case"latin1":case"binary":return O(this,t,e,r);case"base64":return S(this,t,e,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return A(this,t,e,r);default:if(i)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),i=!0}},u.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};function $(t,e,r){var n="";r=Math.min(t.length,r);for(var o=e;o<r;++o)n+=String.fromCharCode(127&t[o]);return n}function x(t,e,r){var n="";r=Math.min(t.length,r);for(var o=e;o<r;++o)n+=String.fromCharCode(t[o]);return n}function P(t,e,r){var n=t.length;(!e||e<0)&&(e=0),(!r||r<0||r>n)&&(r=n);for(var o="",i=e;i<r;++i)o+=F(t[i]);return o}function N(t,e,r){for(var n=t.slice(e,r),o="",i=0;i<n.length;i+=2)o+=String.fromCharCode(n[i]+256*n[i+1]);return o}function T(t,e,r){if(t%1!=0||t<0)throw new RangeError("offset is not uint");if(t+e>r)throw new RangeError("Trying to access beyond buffer length")}function k(t,e,r,n,o,i){if(!u.isBuffer(t))throw new TypeError('"buffer" argument must be a Buffer instance');if(e>o||e<i)throw new RangeError('"value" argument is out of bounds');if(r+n>t.length)throw new RangeError("Index out of range")}function C(t,e,r,n){e<0&&(e=65535+e+1);for(var o=0,i=Math.min(t.length-r,2);o<i;++o)t[r+o]=(e&255<<8*(n?o:1-o))>>>8*(n?o:1-o)}function D(t,e,r,n){e<0&&(e=4294967295+e+1);for(var o=0,i=Math.min(t.length-r,4);o<i;++o)t[r+o]=e>>>8*(n?o:3-o)&255}function R(t,e,r,n,o,i){if(r+n>t.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function B(t,e,r,n,i){return i||R(t,0,r,4),o.write(t,e,r,n,23,4),r+4}function M(t,e,r,n,i){return i||R(t,0,r,8),o.write(t,e,r,n,52,8),r+8}u.prototype.slice=function(t,e){var r,n=this.length;if((t=~~t)<0?(t+=n)<0&&(t=0):t>n&&(t=n),(e=void 0===e?n:~~e)<0?(e+=n)<0&&(e=0):e>n&&(e=n),e<t&&(e=t),u.TYPED_ARRAY_SUPPORT)(r=this.subarray(t,e)).__proto__=u.prototype;else{var o=e-t;r=new u(o,void 0);for(var i=0;i<o;++i)r[i]=this[i+t]}return r},u.prototype.readUIntLE=function(t,e,r){t|=0,e|=0,r||T(t,e,this.length);for(var n=this[t],o=1,i=0;++i<e&&(o*=256);)n+=this[t+i]*o;return n},u.prototype.readUIntBE=function(t,e,r){t|=0,e|=0,r||T(t,e,this.length);for(var n=this[t+--e],o=1;e>0&&(o*=256);)n+=this[t+--e]*o;return n},u.prototype.readUInt8=function(t,e){return e||T(t,1,this.length),this[t]},u.prototype.readUInt16LE=function(t,e){return e||T(t,2,this.length),this[t]|this[t+1]<<8},u.prototype.readUInt16BE=function(t,e){return e||T(t,2,this.length),this[t]<<8|this[t+1]},u.prototype.readUInt32LE=function(t,e){return e||T(t,4,this.length),(this[t]|this[t+1]<<8|this[t+2]<<16)+16777216*this[t+3]},u.prototype.readUInt32BE=function(t,e){return e||T(t,4,this.length),16777216*this[t]+(this[t+1]<<16|this[t+2]<<8|this[t+3])},u.prototype.readIntLE=function(t,e,r){t|=0,e|=0,r||T(t,e,this.length);for(var n=this[t],o=1,i=0;++i<e&&(o*=256);)n+=this[t+i]*o;return n>=(o*=128)&&(n-=Math.pow(2,8*e)),n},u.prototype.readIntBE=function(t,e,r){t|=0,e|=0,r||T(t,e,this.length);for(var n=e,o=1,i=this[t+--n];n>0&&(o*=256);)i+=this[t+--n]*o;return i>=(o*=128)&&(i-=Math.pow(2,8*e)),i},u.prototype.readInt8=function(t,e){return e||T(t,1,this.length),128&this[t]?-1*(255-this[t]+1):this[t]},u.prototype.readInt16LE=function(t,e){e||T(t,2,this.length);var r=this[t]|this[t+1]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt16BE=function(t,e){e||T(t,2,this.length);var r=this[t+1]|this[t]<<8;return 32768&r?4294901760|r:r},u.prototype.readInt32LE=function(t,e){return e||T(t,4,this.length),this[t]|this[t+1]<<8|this[t+2]<<16|this[t+3]<<24},u.prototype.readInt32BE=function(t,e){return e||T(t,4,this.length),this[t]<<24|this[t+1]<<16|this[t+2]<<8|this[t+3]},u.prototype.readFloatLE=function(t,e){return e||T(t,4,this.length),o.read(this,t,!0,23,4)},u.prototype.readFloatBE=function(t,e){return e||T(t,4,this.length),o.read(this,t,!1,23,4)},u.prototype.readDoubleLE=function(t,e){return e||T(t,8,this.length),o.read(this,t,!0,52,8)},u.prototype.readDoubleBE=function(t,e){return e||T(t,8,this.length),o.read(this,t,!1,52,8)},u.prototype.writeUIntLE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||k(this,t,e,r,Math.pow(2,8*r)-1,0);var o=1,i=0;for(this[e]=255&t;++i<r&&(o*=256);)this[e+i]=t/o&255;return e+r},u.prototype.writeUIntBE=function(t,e,r,n){(t=+t,e|=0,r|=0,n)||k(this,t,e,r,Math.pow(2,8*r)-1,0);var o=r-1,i=1;for(this[e+o]=255&t;--o>=0&&(i*=256);)this[e+o]=t/i&255;return e+r},u.prototype.writeUInt8=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,1,255,0),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),this[e]=255&t,e+1},u.prototype.writeUInt16LE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):C(this,t,e,!0),e+2},u.prototype.writeUInt16BE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,2,65535,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):C(this,t,e,!1),e+2},u.prototype.writeUInt32LE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e+3]=t>>>24,this[e+2]=t>>>16,this[e+1]=t>>>8,this[e]=255&t):D(this,t,e,!0),e+4},u.prototype.writeUInt32BE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,4,4294967295,0),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):D(this,t,e,!1),e+4},u.prototype.writeIntLE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);k(this,t,e,r,o-1,-o)}var i=0,s=1,a=0;for(this[e]=255&t;++i<r&&(s*=256);)t<0&&0===a&&0!==this[e+i-1]&&(a=1),this[e+i]=(t/s>>0)-a&255;return e+r},u.prototype.writeIntBE=function(t,e,r,n){if(t=+t,e|=0,!n){var o=Math.pow(2,8*r-1);k(this,t,e,r,o-1,-o)}var i=r-1,s=1,a=0;for(this[e+i]=255&t;--i>=0&&(s*=256);)t<0&&0===a&&0!==this[e+i+1]&&(a=1),this[e+i]=(t/s>>0)-a&255;return e+r},u.prototype.writeInt8=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,1,127,-128),u.TYPED_ARRAY_SUPPORT||(t=Math.floor(t)),t<0&&(t=255+t+1),this[e]=255&t,e+1},u.prototype.writeInt16LE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8):C(this,t,e,!0),e+2},u.prototype.writeInt16BE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,2,32767,-32768),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>8,this[e+1]=255&t):C(this,t,e,!1),e+2},u.prototype.writeInt32LE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,4,2147483647,-2147483648),u.TYPED_ARRAY_SUPPORT?(this[e]=255&t,this[e+1]=t>>>8,this[e+2]=t>>>16,this[e+3]=t>>>24):D(this,t,e,!0),e+4},u.prototype.writeInt32BE=function(t,e,r){return t=+t,e|=0,r||k(this,t,e,4,2147483647,-2147483648),t<0&&(t=4294967295+t+1),u.TYPED_ARRAY_SUPPORT?(this[e]=t>>>24,this[e+1]=t>>>16,this[e+2]=t>>>8,this[e+3]=255&t):D(this,t,e,!1),e+4},u.prototype.writeFloatLE=function(t,e,r){return B(this,t,e,!0,r)},u.prototype.writeFloatBE=function(t,e,r){return B(this,t,e,!1,r)},u.prototype.writeDoubleLE=function(t,e,r){return M(this,t,e,!0,r)},u.prototype.writeDoubleBE=function(t,e,r){return M(this,t,e,!1,r)},u.prototype.copy=function(t,e,r,n){if(r||(r=0),n||0===n||(n=this.length),e>=t.length&&(e=t.length),e||(e=0),n>0&&n<r&&(n=r),n===r)return 0;if(0===t.length||0===this.length)return 0;if(e<0)throw new RangeError("targetStart out of bounds");if(r<0||r>=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),t.length-e<n-r&&(n=t.length-e+r);var o,i=n-r;if(this===t&&r<e&&e<n)for(o=i-1;o>=0;--o)t[o+e]=this[o+r];else if(i<1e3||!u.TYPED_ARRAY_SUPPORT)for(o=0;o<i;++o)t[o+e]=this[o+r];else Uint8Array.prototype.set.call(t,this.subarray(r,r+i),e);return i},u.prototype.fill=function(t,e,r,n){if("string"==typeof t){if("string"==typeof e?(n=e,e=0,r=this.length):"string"==typeof r&&(n=r,r=this.length),1===t.length){var o=t.charCodeAt(0);o<256&&(t=o)}if(void 0!==n&&"string"!=typeof n)throw new TypeError("encoding must be a string");if("string"==typeof n&&!u.isEncoding(n))throw new TypeError("Unknown encoding: "+n)}else"number"==typeof t&&(t&=255);if(e<0||this.length<e||this.length<r)throw new RangeError("Out of range index");if(r<=e)return this;var i;if(e>>>=0,r=void 0===r?this.length:r>>>0,t||(t=0),"number"==typeof t)for(i=e;i<r;++i)this[i]=t;else{var s=u.isBuffer(t)?t:L(new u(t,n).toString()),a=s.length;for(i=0;i<r-e;++i)this[i+e]=s[i%a]}return this};var I=/[^+\/0-9A-Za-z-_]/g;function F(t){return t<16?"0"+t.toString(16):t.toString(16)}function L(t,e){var r;e=e||1/0;for(var n=t.length,o=null,i=[],s=0;s<n;++s){if((r=t.charCodeAt(s))>55295&&r<57344){if(!o){if(r>56319){(e-=3)>-1&&i.push(239,191,189);continue}if(s+1===n){(e-=3)>-1&&i.push(239,191,189);continue}o=r;continue}if(r<56320){(e-=3)>-1&&i.push(239,191,189),o=r;continue}r=65536+(o-55296<<10|r-56320)}else o&&(e-=3)>-1&&i.push(239,191,189);if(o=null,r<128){if((e-=1)<0)break;i.push(r)}else if(r<2048){if((e-=2)<0)break;i.push(r>>6|192,63&r|128)}else if(r<65536){if((e-=3)<0)break;i.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((e-=4)<0)break;i.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return i}function U(t){return n.toByteArray(function(t){if((t=function(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}(t).replace(I,"")).length<2)return"";for(;t.length%4!=0;)t+="=";return t}(t))}function V(t,e,r,n){for(var o=0;o<n&&!(o+r>=e.length||o>=t.length);++o)e[o+r]=t[o];return o}}).call(this,r(11))},function(t,e,r){"use strict";(function(t){
+/*!
+ * Module dependencies.
+ */
+function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var s,a=r(111),u=r(46),c=r(62),l=r(63).Buffer,f=r(20),p=r(13),h=r(113),y=r(28),d=r(21),m=r(66),_=r(65),v=r(29),g=r(24),b=r(47);function w(t){if(Array.isArray(t.populate)){var r=[];t.populate.forEach((function(t){if(/[\s]/.test(t.path)){var n=Object.assign({},t);n.path.split(" ").forEach((function(t){n.path=t,r.push(e.populate(n)[0])}))}else r.push(e.populate(t)[0])})),t.populate=e.populate(r)}else null!=t.populate&&"object"===i(t.populate)&&(t.populate=e.populate(t.populate));var o=[],s=t.path.split(" ");null!=t.options&&(t.options=e.clone(t.options));var a,u=n(s);try{for(u.s();!(a=u.n()).done;){var c=a.value;o.push(new h(Object.assign({},t,{path:c})))}}catch(t){u.e(t)}finally{u.f()}return o}
+/*!
+ * Return the value of `obj` at the given `path`.
+ *
+ * @param {String} path
+ * @param {Object} obj
+ */e.specialProperties=b,
+/*!
+ * Produces a collection name from model `name`. By default, just returns
+ * the model name
+ *
+ * @param {String} name a model name
+ * @param {Function} pluralize function that pluralizes the collection name
+ * @return {String} a collection name
+ * @api private
+ */
+e.toCollectionName=function(t,e){return"system.profile"===t||"system.indexes"===t?t:"function"==typeof e?e(t):t},
+/*!
+ * Determines if `a` and `b` are deep equal.
+ *
+ * Modified from node/lib/assert.js
+ *
+ * @param {any} a a value to compare to `b`
+ * @param {any} b a value to compare to `a`
+ * @return {Boolean}
+ * @api private
+ */
+e.deepEqual=function t(r,n){if(r===n)return!0;if(r instanceof Date&&n instanceof Date)return r.getTime()===n.getTime();if(m(r,"ObjectID")&&m(n,"ObjectID")||m(r,"Decimal128")&&m(n,"Decimal128"))return r.toString()===n.toString();if(r instanceof RegExp&&n instanceof RegExp)return r.source===n.source&&r.ignoreCase===n.ignoreCase&&r.multiline===n.multiline&&r.global===n.global;if("object"!==i(r)&&"object"!==i(n))return r===n;if(null===r||null===n||void 0===r||void 0===n)return!1;if(r.prototype!==n.prototype)return!1;if(r instanceof Number&&n instanceof Number)return r.valueOf()===n.valueOf();if(l.isBuffer(r))return e.buffer.areEqual(r,n);var o,s,a,u;v(r)&&(r=r.toObject()),v(n)&&(n=n.toObject());try{o=Object.keys(r),s=Object.keys(n)}catch(t){return!1}if(o.length!==s.length)return!1;for(o.sort(),s.sort(),u=o.length-1;u>=0;u--)if(o[u]!==s[u])return!1;for(u=o.length-1;u>=0;u--)if(!t(r[a=o[u]],n[a]))return!1;return!0},
+/*!
+ * Get the last element of an array
+ */
+e.last=function(t){if(t.length>0)return t[t.length-1]},e.clone=y,
+/*!
+ * ignore
+ */
+e.promiseOrCallback=g,
+/*!
+ * ignore
+ */
+e.omit=function(t,e){if(null==e)return Object.assign({},t);Array.isArray(e)||(e=[e]);var r,o=Object.assign({},t),i=n(e);try{for(i.s();!(r=i.n()).done;){delete o[r.value]}}catch(t){i.e(t)}finally{i.f()}return o},
+/*!
+ * Shallow copies defaults into options.
+ *
+ * @param {Object} defaults
+ * @param {Object} options
+ * @return {Object} the merged object
+ * @api private
+ */
+e.options=function(t,e){var r,n=Object.keys(t),o=n.length;for(e=e||{};o--;)(r=n[o])in e||(e[r]=t[r]);return e},
+/*!
+ * Generates a random string
+ *
+ * @api private
+ */
+e.random=function(){return Math.random().toString().substr(3)},
+/*!
+ * Merges `from` into `to` without overwriting existing properties.
+ *
+ * @param {Object} to
+ * @param {Object} from
+ * @api private
+ */
+e.merge=function t(r,n,o,i){o=o||{};var s,a=Object.keys(n),u=0,c=a.length;i=i||"";for(var l=o.omitNested||{};u<c;)if(s=a[u++],!(o.omit&&o.omit[s]||l[i]||b.has(s)))if(null==r[s])r[s]=n[s];else if(e.isObject(n[s])){if(e.isObject(r[s])||(r[s]={}),null!=n[s]){if(o.isDiscriminatorSchemaMerge&&n[s].$isSingleNested&&r[s].$isMongooseDocumentArray||n[s].$isMongooseDocumentArray&&r[s].$isSingleNested)continue;if(n[s].instanceOfSchema){r[s].instanceOfSchema?r[s].add(n[s].clone()):r[s]=n[s].clone();continue}if(n[s]instanceof p){r[s]=new p(n[s]);continue}}t(r[s],n[s],o,i?i+"."+s:s)}else o.overwrite&&(r[s]=n[s])},
+/*!
+ * Applies toObject recursively.
+ *
+ * @param {Document|Array|Object} obj
+ * @return {Object}
+ * @api private
+ */
+e.toObject=function t(o){var i;if(s||(s=r(6)),null==o)return o;if(o instanceof s)return o.toObject();if(Array.isArray(o)){i=[];var a,u=n(o);try{for(u.s();!(a=u.n()).done;){var c=a.value;i.push(t(c))}}catch(t){u.e(t)}finally{u.f()}return i}if(e.isPOJO(o)){for(var l in i={},o)b.has(l)||(i[l]=t(o[l]));return i}return o},e.isObject=d,
+/*!
+ * Determines if `arg` is a plain old JavaScript object (POJO). Specifically,
+ * `arg` must be an object but not an instance of any special class, like String,
+ * ObjectId, etc.
+ *
+ * `Object.getPrototypeOf()` is part of ES5: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
+ *
+ * @param {Object|Array|String|Function|RegExp|any} arg
+ * @api private
+ * @return {Boolean}
+ */
+e.isPOJO=function(t){if(null==t||"object"!==i(t))return!1;var e=Object.getPrototypeOf(t);return!e||"Object"===e.constructor.name},
+/*!
+ * Determines if `obj` is a built-in object like an array, date, boolean,
+ * etc.
+ */
+e.isNativeObject=function(t){return Array.isArray(t)||t instanceof Date||t instanceof Boolean||t instanceof Number||t instanceof String},
+/*!
+ * Determines if `val` is an object that has no own keys
+ */
+e.isEmptyObject=function(t){return null!=t&&"object"===i(t)&&0===Object.keys(t).length},
+/*!
+ * Search if `obj` or any POJOs nested underneath `obj` has a property named
+ * `key`
+ */
+e.hasKey=function(t,r){for(var n=0,o=Object.keys(t);n<o.length;n++){var i=o[n];if(i===r)return!0;if(e.isPOJO(t[i])&&e.hasKey(t[i],r))return!0}return!1},
+/*!
+ * A faster Array.prototype.slice.call(arguments) alternative
+ * @api private
+ */
+e.args=c,
+/*!
+ * process.nextTick helper.
+ *
+ * Wraps `callback` in a try/catch + nextTick.
+ *
+ * node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.
+ *
+ * @param {Function} callback
+ * @api private
+ */
+e.tick=function(e){if("function"==typeof e)return function(){try{e.apply(this,arguments)}catch(e){t.nextTick((function(){throw e}))}}},
+/*!
+ * Returns true if `v` is an object that can be serialized as a primitive in
+ * MongoDB
+ */
+e.isMongooseType=function(t){return t instanceof p||t instanceof f||t instanceof l},e.isMongooseObject=v,
+/*!
+ * Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB.
+ *
+ * @param {Object} object
+ * @api private
+ */
+e.expires=function(t){var e;t&&"Object"===t.constructor.name&&("expires"in t&&(e="string"!=typeof t.expires?t.expires:Math.round(a(t.expires)/1e3),t.expireAfterSeconds=e,delete t.expires))},
+/*!
+ * populate helper
+ */
+e.populate=function(t,r,n,o,s,a,u,c){var l=null;if(1===arguments.length){if(t instanceof h)return[t];if(Array.isArray(t)){var f=p(t);return f.map((function(t){return e.populate(t)[0]}))}l=e.isObject(t)?Object.assign({},t):{path:t}}else l="object"===i(n)?{path:t,select:r,match:n,options:o}:{path:t,select:r,model:n,match:o,options:s,populate:a,justOne:u,count:c};if("string"!=typeof l.path)throw new TypeError("utils.populate: invalid path. Expected string. Got typeof `"+i(t)+"`");return w(l);function p(t){var e=[];return t.forEach((function(t){/[\s]/.test(t.path)?t.path.split(" ").forEach((function(r){var n=Object.assign({},t);n.path=r,e.push(n)})):e.push(t)})),e}},e.getValue=function(t,e,r){return u.get(t,e,"_doc",r)},
+/*!
+ * Sets the value of `obj` at the given `path`.
+ *
+ * @param {String} path
+ * @param {Anything} val
+ * @param {Object} obj
+ */
+e.setValue=function(t,e,r,n,o){u.set(t,e,r,"_doc",n,o)},
+/*!
+ * Returns an array of values from object `o`.
+ *
+ * @param {Object} o
+ * @return {Array}
+ * @private
+ */
+e.object={},e.object.vals=function(t){for(var e=Object.keys(t),r=e.length,n=[];r--;)n.push(t[e[r]]);return n},
+/*!
+ * @see exports.options
+ */
+e.object.shallowCopy=e.options;
+/*!
+ * Safer helper for hasOwnProperty checks
+ *
+ * @param {Object} obj
+ * @param {String} prop
+ */
+var O=Object.prototype.hasOwnProperty;e.object.hasOwnProperty=function(t,e){return O.call(t,e)},
+/*!
+ * Determine if `val` is null or undefined
+ *
+ * @return {Boolean}
+ */
+e.isNullOrUndefined=function(t){return null==t},
+/*!
+ * ignore
+ */
+e.array={},
+/*!
+ * Flattens an array.
+ *
+ * [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]
+ *
+ * @param {Array} arr
+ * @param {Function} [filter] If passed, will be invoked with each item in the array. If `filter` returns a falsy value, the item will not be included in the results.
+ * @return {Array}
+ * @private
+ */
+e.array.flatten=function t(e,r,n){return n||(n=[]),e.forEach((function(e){Array.isArray(e)?t(e,r,n):r&&!r(e)||n.push(e)})),n};
+/*!
+ * ignore
+ */
+var S=Object.prototype.hasOwnProperty;e.hasUserDefinedProperty=function(t,r){if(null==t)return!1;if(Array.isArray(r)){var o,s=n(r);try{for(s.s();!(o=s.n()).done;){var a=o.value;if(e.hasUserDefinedProperty(t,a))return!0}}catch(t){s.e(t)}finally{s.f()}return!1}if(S.call(t,r))return!0;if("object"===i(t)&&r in t){var u=t[r];return u!==Object.prototype[r]&&u!==Array.prototype[r]}return!1};
+/*!
+ * ignore
+ */
+var A=Math.pow(2,32)-1;e.isArrayIndex=function(t){return"number"==typeof t?t>=0&&t<=A:"string"==typeof t&&(!!/^\d+$/.test(t)&&((t=+t)>=0&&t<=A))},
+/*!
+ * Removes duplicate values from an array
+ *
+ * [1, 2, 3, 3, 5] => [1, 2, 3, 5]
+ * [ ObjectId("550988ba0c19d57f697dc45e"), ObjectId("550988ba0c19d57f697dc45e") ]
+ * => [ObjectId("550988ba0c19d57f697dc45e")]
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @private
+ */
+e.array.unique=function(t){var e,r={},o={},i=[],s=n(t);try{for(s.s();!(e=s.n()).done;){var a=e.value;if("number"==typeof a||"string"==typeof a||null==a){if(r[a])continue;i.push(a),r[a]=!0}else if(a instanceof p){if(o[a.toString()])continue;i.push(a),o[a.toString()]=!0}else i.push(a)}}catch(t){s.e(t)}finally{s.f()}return i},
+/*!
+ * Determines if two buffers are equal.
+ *
+ * @param {Buffer} a
+ * @param {Object} b
+ */
+e.buffer={},e.buffer.areEqual=function(t,e){if(!l.isBuffer(t))return!1;if(!l.isBuffer(e))return!1;if(t.length!==e.length)return!1;for(var r=0,n=t.length;r<n;++r)if(t[r]!==e[r])return!1;return!0},e.getFunctionName=_,
+/*!
+ * Decorate buffers
+ */
+e.decorate=function(t,e){for(var r in e)b.has(r)||(t[r]=e[r])},e.mergeClone=function(t,r){v(r)&&(r=r.toObject({transform:!1,virtuals:!1,depopulate:!0,getters:!1,flattenDecimals:!1}));for(var n,o=Object.keys(r),i=o.length,s=0;s<i;)if(n=o[s++],!b.has(n))if(void 0===t[n])t[n]=e.clone(r[n],{transform:!1,virtuals:!1,depopulate:!0,getters:!1,flattenDecimals:!1});else{var a=r[n];if(null==a||!a.valueOf||a instanceof Date||(a=a.valueOf()),e.isObject(a)){var u=a;v(a)&&!a.isMongooseBuffer&&(u=u.toObject({transform:!1,virtuals:!1,depopulate:!0,getters:!1,flattenDecimals:!1})),a.isMongooseBuffer&&(u=l.from(u)),e.mergeClone(t[n],u)}else t[n]=e.clone(a,{flattenDecimals:!1})}},e.each=function(t,e){var r,o=n(t);try{for(o.s();!(r=o.n()).done;){e(r.value)}}catch(t){o.e(t)}finally{o.f()}},
+/*!
+ * ignore
+ */
+e.getOption=function(t){var e,r=Array.prototype.slice.call(arguments,1),o=n(r);try{for(o.s();!(e=o.n()).done;){var i=e.value;if(null!=i[t])return i[t]}}catch(t){o.e(t)}finally{o.f()}return null},
+/*!
+ * ignore
+ */
+e.noop=function(){}}).call(this,r(8))},function(t,e,r){"use strict";
+/*!
+ * Simplified lodash.get to work around the annoying null quirk. See:
+ * https://github.com/lodash/lodash/issues/3659
+ */function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function i(t,e){return null==t?t:t instanceof Map?t.get(e):t[e]}t.exports=function(t,e,r){var o,s=e.split("."),a=e,u=t,c=n(s);try{for(c.s();!(o=c.n()).done;){var l=o.value;if(null==u)return r;if(null!=u[a])return u[a];u=i(u,l),a=a.substr(l.length+1)}}catch(t){c.e(t)}finally{c.f()}return null==u?r:u}},function(t,e,r){(function(t){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=Object.getOwnPropertyDescriptors||function(t){for(var e=Object.keys(t),r={},n=0;n<e.length;n++)r[e[n]]=Object.getOwnPropertyDescriptor(t,e[n]);return r},i=/%[sdj%]/g;e.format=function(t){if(!v(t)){for(var e=[],r=0;r<arguments.length;r++)e.push(u(arguments[r]));return e.join(" ")}r=1;for(var n=arguments,o=n.length,s=String(t).replace(i,(function(t){if("%%"===t)return"%";if(r>=o)return t;switch(t){case"%s":return String(n[r++]);case"%d":return Number(n[r++]);case"%j":try{return JSON.stringify(n[r++])}catch(t){return"[Circular]"}default:return t}})),a=n[r];r<o;a=n[++r])m(a)||!w(a)?s+=" "+a:s+=" "+u(a);return s},e.deprecate=function(r,n){if(void 0!==t&&!0===t.noDeprecation)return r;if(void 0===t)return function(){return e.deprecate(r,n).apply(this,arguments)};var o=!1;return function(){if(!o){if(t.throwDeprecation)throw new Error(n);t.traceDeprecation?console.trace(n):console.error(n),o=!0}return r.apply(this,arguments)}};var s,a={};function u(t,r){var n={seen:[],stylize:l};return arguments.length>=3&&(n.depth=arguments[2]),arguments.length>=4&&(n.colors=arguments[3]),d(r)?n.showHidden=r:r&&e._extend(n,r),g(n.showHidden)&&(n.showHidden=!1),g(n.depth)&&(n.depth=2),g(n.colors)&&(n.colors=!1),g(n.customInspect)&&(n.customInspect=!0),n.colors&&(n.stylize=c),f(n,t,n.depth)}function c(t,e){var r=u.styles[e];return r?"["+u.colors[r][0]+"m"+t+"["+u.colors[r][1]+"m":t}function l(t,e){return t}function f(t,r,n){if(t.customInspect&&r&&A(r.inspect)&&r.inspect!==e.inspect&&(!r.constructor||r.constructor.prototype!==r)){var o=r.inspect(n,t);return v(o)||(o=f(t,o,n)),o}var i=function(t,e){if(g(e))return t.stylize("undefined","undefined");if(v(e)){var r="'"+JSON.stringify(e).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return t.stylize(r,"string")}if(_(e))return t.stylize(""+e,"number");if(d(e))return t.stylize(""+e,"boolean");if(m(e))return t.stylize("null","null")}(t,r);if(i)return i;var s=Object.keys(r),a=function(t){var e={};return t.forEach((function(t,r){e[t]=!0})),e}(s);if(t.showHidden&&(s=Object.getOwnPropertyNames(r)),S(r)&&(s.indexOf("message")>=0||s.indexOf("description")>=0))return p(r);if(0===s.length){if(A(r)){var u=r.name?": "+r.name:"";return t.stylize("[Function"+u+"]","special")}if(b(r))return t.stylize(RegExp.prototype.toString.call(r),"regexp");if(O(r))return t.stylize(Date.prototype.toString.call(r),"date");if(S(r))return p(r)}var c,l="",w=!1,j=["{","}"];(y(r)&&(w=!0,j=["[","]"]),A(r))&&(l=" [Function"+(r.name?": "+r.name:"")+"]");return b(r)&&(l=" "+RegExp.prototype.toString.call(r)),O(r)&&(l=" "+Date.prototype.toUTCString.call(r)),S(r)&&(l=" "+p(r)),0!==s.length||w&&0!=r.length?n<0?b(r)?t.stylize(RegExp.prototype.toString.call(r),"regexp"):t.stylize("[Object]","special"):(t.seen.push(r),c=w?function(t,e,r,n,o){for(var i=[],s=0,a=e.length;s<a;++s)P(e,String(s))?i.push(h(t,e,r,n,String(s),!0)):i.push("");return o.forEach((function(o){o.match(/^\d+$/)||i.push(h(t,e,r,n,o,!0))})),i}(t,r,n,a,s):s.map((function(e){return h(t,r,n,a,e,w)})),t.seen.pop(),function(t,e,r){if(t.reduce((function(t,e){return e.indexOf("\n")>=0&&0,t+e.replace(/\u001b\[\d\d?m/g,"").length+1}),0)>60)return r[0]+(""===e?"":e+"\n ")+" "+t.join(",\n ")+" "+r[1];return r[0]+e+" "+t.join(", ")+" "+r[1]}(c,l,j)):j[0]+l+j[1]}function p(t){return"["+Error.prototype.toString.call(t)+"]"}function h(t,e,r,n,o,i){var s,a,u;if((u=Object.getOwnPropertyDescriptor(e,o)||{value:e[o]}).get?a=u.set?t.stylize("[Getter/Setter]","special"):t.stylize("[Getter]","special"):u.set&&(a=t.stylize("[Setter]","special")),P(n,o)||(s="["+o+"]"),a||(t.seen.indexOf(u.value)<0?(a=m(r)?f(t,u.value,null):f(t,u.value,r-1)).indexOf("\n")>-1&&(a=i?a.split("\n").map((function(t){return" "+t})).join("\n").substr(2):"\n"+a.split("\n").map((function(t){return" "+t})).join("\n")):a=t.stylize("[Circular]","special")),g(s)){if(i&&o.match(/^\d+$/))return a;(s=JSON.stringify(""+o)).match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(s=s.substr(1,s.length-2),s=t.stylize(s,"name")):(s=s.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),s=t.stylize(s,"string"))}return s+": "+a}function y(t){return Array.isArray(t)}function d(t){return"boolean"==typeof t}function m(t){return null===t}function _(t){return"number"==typeof t}function v(t){return"string"==typeof t}function g(t){return void 0===t}function b(t){return w(t)&&"[object RegExp]"===j(t)}function w(t){return"object"===n(t)&&null!==t}function O(t){return w(t)&&"[object Date]"===j(t)}function S(t){return w(t)&&("[object Error]"===j(t)||t instanceof Error)}function A(t){return"function"==typeof t}function j(t){return Object.prototype.toString.call(t)}function E(t){return t<10?"0"+t.toString(10):t.toString(10)}e.debuglog=function(r){if(g(s)&&(s=t.env.NODE_DEBUG||""),r=r.toUpperCase(),!a[r])if(new RegExp("\\b"+r+"\\b","i").test(s)){var n=t.pid;a[r]=function(){var t=e.format.apply(e,arguments);console.error("%s %d: %s",r,n,t)}}else a[r]=function(){};return a[r]},e.inspect=u,u.colors={bold:[1,22],italic:[3,23],underline:[4,24],inverse:[7,27],white:[37,39],grey:[90,39],black:[30,39],blue:[34,39],cyan:[36,39],green:[32,39],magenta:[35,39],red:[31,39],yellow:[33,39]},u.styles={special:"cyan",number:"yellow",boolean:"yellow",undefined:"grey",null:"bold",string:"green",date:"magenta",regexp:"red"},e.isArray=y,e.isBoolean=d,e.isNull=m,e.isNullOrUndefined=function(t){return null==t},e.isNumber=_,e.isString=v,e.isSymbol=function(t){return"symbol"===n(t)},e.isUndefined=g,e.isRegExp=b,e.isObject=w,e.isDate=O,e.isError=S,e.isFunction=A,e.isPrimitive=function(t){return null===t||"boolean"==typeof t||"number"==typeof t||"string"==typeof t||"symbol"===n(t)||void 0===t},e.isBuffer=r(100);var $=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function x(){var t=new Date,e=[E(t.getHours()),E(t.getMinutes()),E(t.getSeconds())].join(":");return[t.getDate(),$[t.getMonth()],e].join(" ")}function P(t,e){return Object.prototype.hasOwnProperty.call(t,e)}e.log=function(){console.log("%s - %s",x(),e.format.apply(e,arguments))},e.inherits=r(101),e._extend=function(t,e){if(!e||!w(e))return t;for(var r=Object.keys(e),n=r.length;n--;)t[r[n]]=e[r[n]];return t};var N="undefined"!=typeof Symbol?Symbol("util.promisify.custom"):void 0;function T(t,e){if(!t){var r=new Error("Promise was rejected with a falsy value");r.reason=t,t=r}return e(t)}e.promisify=function(t){if("function"!=typeof t)throw new TypeError('The "original" argument must be of type Function');if(N&&t[N]){var e;if("function"!=typeof(e=t[N]))throw new TypeError('The "util.promisify.custom" argument must be of type Function');return Object.defineProperty(e,N,{value:e,enumerable:!1,writable:!1,configurable:!0}),e}function e(){for(var e,r,n=new Promise((function(t,n){e=t,r=n})),o=[],i=0;i<arguments.length;i++)o.push(arguments[i]);o.push((function(t,n){t?r(t):e(n)}));try{t.apply(this,o)}catch(t){r(t)}return n}return Object.setPrototypeOf(e,Object.getPrototypeOf(t)),N&&Object.defineProperty(e,N,{value:e,enumerable:!1,writable:!1,configurable:!0}),Object.defineProperties(e,o(t))},e.promisify.custom=N,e.callbackify=function(e){if("function"!=typeof e)throw new TypeError('The "original" argument must be of type Function');function r(){for(var r=[],n=0;n<arguments.length;n++)r.push(arguments[n]);var o=r.pop();if("function"!=typeof o)throw new TypeError("The last argument must be of type Function");var i=this,s=function(){return o.apply(i,arguments)};e.apply(this,r).then((function(e){t.nextTick(s,null,e)}),(function(e){t.nextTick(T,e,s)}))}return Object.setPrototypeOf(r,Object.getPrototypeOf(e)),Object.defineProperties(r,o(e)),r}}).call(this,r(8))},function(t,e,r){"use strict";var n=r(14);
+/*!
+ * Module exports.
+ */t.exports=n,n.messages=r(126),n.Messages=n.messages,n.DocumentNotFoundError=r(127),n.CastError=r(12),n.ValidationError=r(31),n.ValidatorError=r(71),n.VersionError=r(128),n.ParallelSaveError=r(129),n.OverwriteModelError=r(130),n.MissingSchemaError=r(131),n.DivergentArrayError=r(132),n.StrictModeError=r(32)},function(t,e,r){"use strict";(function(e,n){
+/*!
+ * Module dependencies.
+ */
+function o(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function i(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return s(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return s(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,i=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw i}}}}function s(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var u,c,l,f=r(19).EventEmitter,p=r(109),h=r(5),y=r(25),d=r(73),m=r(134),_=r(135),v=r(52),g=r(32),b=r(31),w=r(71),O=r(53),S=r(24),A=r(84),j=r(57).compile,E=r(57).defineKey,$=r(171).flatten,x=r(3),P=r(172),N=r(88),T=r(173),k=r(58),C=r(174),D=r(4).inspect,R=r(17).internalToObjectOptions,B=r(46),M=r(175),I=r(2),F=r(177),L=I.clone,U=I.deepEqual,V=I.isMongooseObject,q=Symbol("mongoose.Array#atomicsBackup"),W=r(0).arrayAtomicsSymbol,H=r(0).documentArrayParent,Y=r(0).documentIsSelected,K=r(0).documentIsModified,z=r(0).documentModifiedPaths,Q=r(0).documentSchemaSymbol,J=r(0).getSymbol,G=r(0).populateModelSymbol,X=r(0).scopeSymbol,Z=I.specialProperties;function tt(t,e,r,n){var o=this;"object"===a(r)&&null!=r&&(r=(n=r).skipId),n=Object.assign({},n);var s=x(n,"defaults",!0);if(n.defaults=s,null==this.schema){var u=I.isObject(e)&&!e.instanceOfSchema?new v(e):e;this.$__setSchema(u),e=r,r=n,n=arguments[4]||{}}if(this.$__=new p,this.$__.emitter=new f,this.isNew=!("isNew"in n)||n.isNew,this.errors=void 0,this.$__.$options=n||{},this.$locals={},this.$op=null,null!=t&&"object"!==a(t))throw new m(t,"obj","Document");var c=this.schema;"boolean"==typeof e||"throw"===e?(this.$__.strictMode=e,e=void 0):(this.$__.strictMode=c.options.strict,this.$__.selected=e);var l,h=c.requiredPaths(!0),y=i(h);try{for(y.s();!(l=y.n()).done;){var d=l.value;this.$__.activePaths.require(d)}}catch(t){y.e(t)}finally{y.f()}this.$__.emitter.setMaxListeners(0);var _=null;I.isPOJO(e)&&(_=C(e));var g=!1===_&&e?rt(e):{};if(null==this._doc&&(this.$__buildDoc(t,e,r,_,g,!1),s&&nt(this,e,r,_,g,!0,{isNew:this.isNew})),t&&(this.$__original_set?this.$__original_set(t,void 0,!0):this.$set(t,void 0,!0),t instanceof tt&&(this.isNew=t.isNew)),n.willInit&&s?f.prototype.once.call(this,"init",(function(){nt(o,e,r,_,g,!1,n.skipDefaults,o.isNew)})):s&&nt(this,e,r,_,g,!1,n.skipDefaults,this.isNew),this.$__._id=this._id,!this.$__.strictMode&&t){var b=this,w=Object.keys(this._doc);w.forEach((function(t){t in c.tree||E(t,null,b)}))}at(this)}
+/*!
+ * Document exposes the NodeJS event emitter API, so you can use
+ * `on`, `once`, etc.
+ */for(var et in I.each(["on","once","emit","listeners","removeListener","setMaxListeners","removeAllListeners","addListener"],(function(t){tt.prototype[t]=function(){return this.$__.emitter[t].apply(this.$__.emitter,arguments)}})),tt.prototype.constructor=tt,f.prototype)tt[et]=f.prototype[et];
+/*!
+ * ignore
+ */
+function rt(t){for(var e={},r=0,n=Object.keys(t);r<n.length;r++){var o,s=[],a=i(n[r].split("."));try{for(a.s();!(o=a.n()).done;){var u=o.value;s.push(u),e[s.join(".")]=1}}catch(t){a.e(t)}finally{a.f()}}return e}
+/*!
+ * ignore
+ */function nt(t,e,r,n,o,i,s){for(var a=Object.keys(t.schema.paths),u=a.length,c=0;c<u;++c){var l=void 0,f="",p=a[c];if("_id"!==p||!r)for(var h=t.schema.paths[p],y=-1===p.indexOf(".")?[p]:p.split("."),d=y.length,m=!1,_=t._doc,v=0;v<d&&null!=_;++v){var g=y[v];if(f+=(f.length?".":"")+g,!0===n){if(f in e)break}else if(!1===n&&e&&!m)if(f in e)m=!0;else if(!o[f])break;if(v===d-1){if(void 0!==_[g])break;if("function"==typeof h.defaultValue){if(!h.defaultValue.$runBeforeSetters&&i)break;if(h.defaultValue.$runBeforeSetters&&!i)break}else if(!i)continue;if(s&&s[f])break;if(e&&null!==n){if(!0===n){if(p in e)continue;try{l=h.getDefault(t,!1)}catch(e){t.invalidate(p,e);break}void 0!==l&&(_[g]=l,t.$__.activePaths.default(p))}else if(m){try{l=h.getDefault(t,!1)}catch(e){t.invalidate(p,e);break}void 0!==l&&(_[g]=l,t.$__.activePaths.default(p))}}else{try{l=h.getDefault(t,!1)}catch(e){t.invalidate(p,e);break}void 0!==l&&(_[g]=l,t.$__.activePaths.default(p))}}else _=_[g]}}}function ot(t){if(null==t)return!0;if("object"!==a(t)||Array.isArray(t))return!1;for(var e=0,r=Object.keys(t);e<r.length;e++){if(!ot(t[r[e]]))return!1}return!0}
+/*!
+ * ignore
+ */
+function it(t){var e={};!
+/*!
+ * ignore
+ */
+function(t){Object.keys(t.$__.activePaths.states.require).forEach((function(e){var r=t.schema.path(e);null!=r&&"function"==typeof r.originalRequiredValue&&(t.$__.cachedRequired[e]=r.originalRequiredValue.call(t,t))}))}(t);var r=new Set(Object.keys(t.$__.activePaths.states.require).filter((function(e){return!(!t.isSelected(e)&&!t.isModified(e))&&(!(e in t.$__.cachedRequired)||t.$__.cachedRequired[e])})));function n(t){r.add(t)}Object.keys(t.$__.activePaths.states.init).forEach(n),Object.keys(t.$__.activePaths.states.modify).forEach(n),Object.keys(t.$__.activePaths.states.default).forEach(n);var o,s=t.$__getAllSubdocs(),a=t.modifiedPaths(),u=i(s);try{for(u.s();!(o=u.n()).done;){var c=o.value;if(c.$basePath){var l,f=i(r);try{for(f.s();!(l=f.n()).done;){var p=l.value;(null===p||p.startsWith(c.$basePath+"."))&&r.delete(p)}}catch(t){f.e(t)}finally{f.f()}!t.isModified(c.$basePath,a)||t.isDirectModified(c.$basePath)||t.$isDefault(c.$basePath)||(r.add(c.$basePath),e[c.$basePath]=!0)}}}catch(t){u.e(t)}finally{u.f()}var h,y=i(r);try{for(y.s();!(h=y.n()).done;){var d=h.value,m=t.schema.path(d);if(m&&m.$isMongooseArray&&(!m.$isMongooseDocumentArray||x(m,"schemaOptions.required")))_(t.$__getValue(d),r,d)}}catch(t){y.e(t)}finally{y.f()}function _(t,e,r){if(null!=t)for(var n=t.length,o=0;o<n;++o)Array.isArray(t[o])?_(t[o],e,r+"."+o):e.add(r+"."+o)}var v,g={skipArrays:!0},b=i(r);try{for(b.s();!(v=b.n()).done;){var w=v.value;if(t.schema.nested[w]){var O=t.$__getValue(w);V(O)&&(O=O.toObject({transform:!1}));var S=$(O,w,g,t.schema);Object.keys(S).forEach(n)}}}catch(t){b.e(t)}finally{b.f()}var A,j=i(r);try{for(j.s();!(A=j.n()).done;){var E=A.value;if(t.schema.singleNestedPaths.hasOwnProperty(E))r.delete(E);else{var P=t.schema.path(E);if(P&&P.$isSchemaMap){var N=t.$__getValue(E);if(null!=N){var T,k=i(N.keys());try{for(k.s();!(T=k.n()).done;){var C=T.value;r.add(E+"."+C)}}catch(t){k.e(t)}finally{k.f()}}}}}}catch(t){j.e(t)}finally{j.f()}return[r=Array.from(r),e]}
+/*!
+ * ignore
+ */
+/*!
+ * ignore
+ */
+function st(t,e){var r,n=new Set(e),o=new Map([]),s=i(e);try{for(s.s();!(r=s.n()).done;){var a=r.value;if(-1!==a.indexOf("."))for(var u=a.split("."),c=u[0],l=1;l<u.length;++l)o.set(c,a),c=c+"."+u[l]}}catch(t){s.e(t)}finally{s.f()}var f,p=[],h=i(t);try{for(h.s();!(f=h.n()).done;){var y=f.value;n.has(y)?p.push(y):o.has(y)&&p.push(o.get(y))}}catch(t){h.e(t)}finally{h.f()}return p}
+/*!
+ * Runs queued functions
+ */
+function at(t){var e=t.schema&&t.schema.callQueue;if(e.length){var r,n=i(e);try{for(n.s();!(r=n.n()).done;){var o=r.value;"pre"!==o[0]&&"post"!==o[0]&&"on"!==o[0]&&t[o[0]].apply(t,o[1])}}catch(t){n.e(t)}finally{n.f()}}}
+/*!
+ * ignore
+ */
+/*!
+ * Applies virtuals properties to `json`.
+ */
+function ut(t,e,r,n){var o,i,s,a=t.schema,u=Object.keys(a.virtuals),c=u.length,l=c,f=t._doc,p=x(n,"aliases",!0);if(!f)return e;for(r=r||{},c=0;c<l;++c)if(o=u[c],p||!a.aliases.hasOwnProperty(o)){if(i=o,null!=r.path){if(!o.startsWith(r.path+"."))continue;i=o.substr(r.path.length+1)}var h=i.split(".");if(void 0!==(s=L(t.get(o),r))){var y=h.length;f=e;for(var d=0;d<y-1;++d)f[h[d]]=f[h[d]]||{},f=f[h[d]];f[h[y-1]]=s}}return e}
+/*!
+ * Applies virtuals properties to `json`.
+ *
+ * @param {Document} self
+ * @param {Object} json
+ * @return {Object} `json`
+ */function ct(t,e){if(F(e))throw new Error("`transform` function must be synchronous, but the transform on path `"+t+"` returned a promise.")}
+/*!
+ * ignore
+ */tt.prototype.schema,Object.defineProperty(tt.prototype,"$locals",{configurable:!1,enumerable:!1,writable:!0}),tt.prototype.isNew,tt.prototype.id,tt.prototype.errors,tt.prototype.$op,tt.prototype.$__buildDoc=function(t,e,r,n,o){for(var i={},s=Object.keys(this.schema.paths).filter((function(t){return!t.includes("$*")})),a=s.length,u=0;u<a;++u){var c=s[u];if("_id"===c){if(r)continue;if(t&&"_id"in t)continue}for(var l=c.split("."),f=l.length,p=f-1,h="",y=i,d=!1,m=0;m<f;++m){var _=l[m];if(h+=(h.length?".":"")+_,!0===n){if(h in e)break}else if(!1===n&&e&&!d)if(h in e)d=!0;else if(!o[h])break;m<p&&(y=y[_]||(y[_]={}))}}this._doc=i},
+/*!
+ * Converts to POJO when you use the document for querying
+ */
+tt.prototype.toBSON=function(){return this.toObject(R)},tt.prototype.init=function(t,e,r){return"function"==typeof e&&(r=e,e=null),this.$__init(t,e),r&&r(null,this),this},
+/*!
+ * ignore
+ */
+tt.prototype.$__init=function(t,e){if(this.isNew=!1,this.$init=!0,e=e||{},null!=t._id&&e.populated&&e.populated.length){var r,n=String(t._id),o=i(e.populated);try{for(o.s();!(r=o.n()).done;){var s=r.value;if(s.isVirtual?this.populated(s.path,I.getValue(s.path,t),s):this.populated(s.path,s._docs[n],s),null!=s._childDocs){var a,u=i(s._childDocs);try{for(u.s();!(a=u.n()).done;){var c=a.value;null!=c&&null!=c.$__&&(c.$__.parent=this)}}catch(t){u.e(t)}finally{u.f()}}}}catch(t){o.e(t)}finally{o.f()}}
+/*!
+ * Init helper.
+ *
+ * @param {Object} self document instance
+ * @param {Object} obj raw mongodb doc
+ * @param {Object} doc object we are initializing
+ * @api private
+ */
+return function t(e,r,n,o,i){i=i||"";var s,a,u,c=Object.keys(r),l=c.length,f=0;for(;f<l;)p(f++);function p(l){if(u=c[l],a=i+u,s=e.schema.path(a),!e.schema.$isRootDiscriminator||e.isSelected(a))if(!s&&I.isPOJO(r[u]))n[u]||(n[u]={}),t(e,r[u],n[u],o,a+".");else if(s){if(null===r[u])n[u]=s._castNullish(null);else if(void 0!==r[u]){var f=(r[u].$__||{}).wasPopulated||null;if(s&&!f)try{n[u]=s.cast(r[u],e,!0)}catch(t){e.invalidate(t.path,new w({path:t.path,message:t.message,type:"cast",value:t.value,reason:t}))}else n[u]=r[u]}e.isModified(a)||e.$__.activePaths.init(a)}else n[u]=r[u]}}(this,t,this._doc,e),
+/*!
+ * If populating a path within a document array, make sure each
+ * subdoc within the array knows its subpaths are populated.
+ *
+ * ####Example:
+ * const doc = await Article.findOne().populate('comments.author');
+ * doc.comments[0].populated('author'); // Should be set
+ */
+function(t,e){if(null==t._id||null==e||0===e.length)return;var r,n=String(t._id),o=i(e);try{for(o.s();!(r=o.n()).done;){var s=r.value;if(!s.isVirtual)for(var a=s.path.split("."),u=0;u<a.length-1;++u){var c=a.slice(0,u+1).join("."),l=a.slice(u+1).join("."),f=t.get(c);if(null!=f&&f.isMongooseDocumentArray){for(var p=0;p<f.length;++p)f[p].populated(l,null==s._docs[n]?[]:s._docs[n][p],s);break}}}}catch(t){o.e(t)}finally{o.f()}}(this,e.populated),this.emit("init",this),this.constructor.emit("init",this),this.$__._id=this._id,this},tt.prototype.update=function(){var t=I.args(arguments);t.unshift({_id:this._id});var e=this.constructor.update.apply(this.constructor,t);return null!=this.$session()&&("session"in e.options||(e.options.session=this.$session())),e},tt.prototype.updateOne=function(t,e,r){var n=this,o=this.constructor.updateOne({_id:this._id},t,e);return o._pre((function(t){n.constructor._middleware.execPre("updateOne",n,[n],t)})),o._post((function(t){n.constructor._middleware.execPost("updateOne",n,[n],{},t)})),null!=this.$session()&&("session"in o.options||(o.options.session=this.$session())),null!=r?o.exec(r):o},tt.prototype.replaceOne=function(){var t=I.args(arguments);return t.unshift({_id:this._id}),this.constructor.replaceOne.apply(this.constructor,t)},tt.prototype.$session=function(t){if(0===arguments.length)return this.$__.session;if(this.$__.session=t,!this.ownerDocument){var e,r=this.$__getAllSubdocs(),n=i(r);try{for(n.s();!(e=n.n()).done;){var o=e.value;o.$session(t)}}catch(t){n.e(t)}finally{n.f()}}return t},tt.prototype.overwrite=function(t){for(var e=0,r=Array.from(new Set(Object.keys(this._doc).concat(Object.keys(t))));e<r.length;e++){var n=r[e];"_id"!==n&&(this.schema.options.versionKey&&n===this.schema.options.versionKey||this.schema.options.discriminatorKey&&n===this.schema.options.discriminatorKey||this.$set(n,t[n]))}return this},tt.prototype.$set=function(t,e,r,n){var s=this;I.isPOJO(r)&&(n=r,r=void 0);var u,c,l,f,p=(n=n||{}).merge,m=r&&!0!==r,_=!0===r,v=0,b="strict"in n?n.strict:this.$__.strictMode;if(m&&((this.$__.adhocPaths||(this.$__.adhocPaths={}))[t]=this.schema.interpretAsType(t,r,this.schema.options)),"string"!=typeof t){if(t instanceof tt&&(t=t.$__isNested?t.toObject():t._doc),null!=t){f=e?e+".":"";var w=(u=Object.keys(t)).length,O=x(n,"_skipMinimizeTopLevel",!1);if(0===w&&O)return delete n._skipMinimizeTopLevel,e&&this.$set(e,{}),this;for(;v<w;)j.call(this,v++);return this}var S=t;t=e,e=S}else this.$__.$setCalled.add(t);function j(e){l=u[e];var o=f+l;if(c=this.schema.pathType(o),!0!==r||f||null==t[l]||"nested"!==c||null==this._doc[l]||0!==Object.keys(this._doc[l]).length||(delete this._doc[l],n=Object.assign({},n,{_skipMinimizeTopLevel:!0})),"object"!==a(t[l])||I.isNativeObject(t[l])||I.isMongooseType(t[l])||null==t[l]||"virtual"===c||"real"===c||"adhocOrUndefined"===c||this.$__path(o)instanceof y||this.schema.paths[o]&&this.schema.paths[o].options&&this.schema.paths[o].options.ref)if(b){if(_&&void 0===t[l]&&void 0!==this.get(o))return;if("adhocOrUndefined"===c&&(c=P(this,o,{typeOnly:!0})),"real"===c||"virtual"===c){var i=t[l];this.schema.paths[o]&&this.schema.paths[o].$isSingleNested&&t[l]instanceof tt&&(i=i.toObject({virtuals:!1,transform:!1})),this.$set(f+l,i,_,n)}else if("nested"===c&&t[l]instanceof tt)this.$set(f+l,t[l].toObject({transform:!1}),_,n);else if("throw"===b)throw"nested"===c?new d(l,t[l]):new g(l)}else void 0!==t[l]&&this.$set(f+l,t[l],_,n);else this.$__.$setCalled.add(f+l),this.$set(t[l],f+l,_,n)}var E,$=this.schema.pathType(t);if("adhocOrUndefined"===$&&($=P(this,t,{typeOnly:!0})),e=N(e),"nested"===$&&e){if("object"===a(e)&&null!=e){if(p)return this.$set(e,t,_);this.$__setValue(t,null),A(this,t);var T=Object.keys(e);this.$__setValue(t,{});for(var k=0,C=T;k<C.length;k++){var D=C[k];this.$set(t+"."+D,e[D],_)}return this.markModified(t),A(this,t,{skipDocArrays:!0}),this}return this.invalidate(t,new h.CastError("Object",e,t)),this}var R=-1===t.indexOf(".")?[t]:t.split(".");if("string"==typeof this.schema.aliases[R[0]]&&(R[0]=this.schema.aliases[R[0]]),"adhocOrUndefined"===$&&b){var M;for(v=0;v<R.length;++v){var F=R.slice(0,v+1).join(".");if(v+1<R.length&&"virtual"===this.schema.pathType(F))return B.set(t,e,this),this;if(null!=(E=this.schema.path(F))&&E instanceof y){M=!0;break}}if(null==E&&(E=P(this,t)),!M&&!E){if("throw"===b)throw new g(t);return this}}else{if("virtual"===$)return(E=this.schema.virtualpath(t)).applySetters(e,this),this;E=this.$__path(t)}var L,U=this._doc,V="";for(v=0;v<R.length-1;++v)U=U[R[v]],V+=(V.length>0?".":"")+R[v],U||(this.$set(V,{}),this.isSelected(V)||this.unmarkModified(V),U=this.$__getValue(V));if(R.length<=1)L=t;else{for(v=0;v<R.length;++v){var q=R.slice(0,v+1).join(".");if(null===this.get(q,null,{getters:!1})){L=q;break}}L||(L=t)}var W=null!=s.$__.$options.priorDoc?s.$__.$options.priorDoc.$__getValue(t):_?void 0:s.$__getValue(t);if(!E)return this.$__set(L,t,_,R,E,e,W),this;if((E.$isSingleNested||E.$isMongooseArray)&&
+/*!
+ * ignore
+ */
+function(t,e){if(!t.$__.validationError)return;for(var r=Object.keys(t.$__.validationError.errors),n=0,o=r;n<o.length;n++){var i=o[n];i.startsWith(e+".")&&delete t.$__.validationError.errors[i]}0===Object.keys(t.$__.validationError.errors).length&&(t.$__.validationError=null)}
+/*!
+ * ignore
+ */(this,t),E.$isSingleNested&&null!=e&&p){e instanceof tt&&(e=e.toObject({virtuals:!1,transform:!1}));for(var H=0,Y=Object.keys(e);H<Y.length;H++){var K=Y[H];this.$set(t+"."+K,e[K],_,n)}return this}var z=!0;try{var Q,J=function(){if(null==E.options)return!1;if(!(e instanceof tt))return!1;var t=e.constructor,r=E.options.ref;if(null!=r&&(r===t.modelName||r===t.baseModelName))return!0;var n=E.options.refPath;if(null==n)return!1;var o=e.get(n);return o===t.modelName||o===t.baseModelName}(),X=!1;if(J&&e instanceof tt&&(this.populated(t,e._id,o({},G,e.constructor)),X=!0),E.options&&Array.isArray(E.options[this.schema.options.typeKey])&&E.options[this.schema.options.typeKey].length&&E.options[this.schema.options.typeKey][0].ref&&
+/*!
+ * ignore
+ */
+function(t,e){if(!Array.isArray(t))return!1;if(0===t.length)return!1;var r,n=i(t);try{for(n.s();!(r=n.n()).done;){var o=r.value;if(!(o instanceof tt))return!1;if(null==o.constructor.modelName)return!1;if(o.constructor.modelName!=e&&o.constructor.baseModelName!=e)return!1}}catch(t){n.e(t)}finally{n.f()}return!0}(e,E.options[this.schema.options.typeKey][0].ref)&&(this.ownerDocument?(Q=o({},G,e[0].constructor),this.ownerDocument().populated(this.$__fullPath(t),e.map((function(t){return t._id})),Q)):(Q=o({},G,e[0].constructor),this.populated(t,e.map((function(t){return t._id})),Q)),X=!0),null==this.schema.singleNestedPaths[t]&&(e=E.applySetters(e,this,!1,W)),E.$isMongooseDocumentArray&&Array.isArray(e)&&e.length>0&&null!=e[0]&&null!=e[0].$__&&null!=e[0].$__.populated){for(var Z=Object.keys(e[0].$__.populated),et=function(){var r=nt[rt];s.populated(t+"."+r,e.map((function(t){return t.populated(r)})),e[0].$__.populated[r].options)},rt=0,nt=Z;rt<nt.length;rt++)et();X=!0}if(!X&&this.$__.populated){if(Array.isArray(e)&&this.$__.populated[t])for(var ot=0;ot<e.length;++ot)e[ot]instanceof tt&&(e[ot]=e[ot]._id);delete this.$__.populated[t]}E.$isSingleNested&&null!=e&&function(t,e,r){var n=e.schema;if(null==n)return;for(var o=0,i=Object.keys(n.paths);o<i.length;o++){var s=i[o],a=n.paths[s];if(null!=a.$immutableSetter){var u=null==r?void 0:r.$__getValue(s);a.$immutableSetter.call(t,u)}}}(e,E,W),this.$markValid(t)}catch(r){r instanceof h.StrictModeError&&r.isImmutableError?this.invalidate(t,r):r instanceof h.CastError?(this.invalidate(r.path,r),r.$originalErrorPath&&this.invalidate(t,new h.CastError(E.instance,e,t,r.$originalErrorPath))):this.invalidate(t,new h.CastError(E.instance,e,t,r)),z=!1}return z&&this.$__set(L,t,_,R,E,e,W),E.$isSingleNested&&(this.isDirectModified(t)||null==e)&&A(this,t),this},tt.prototype.set=tt.prototype.$set,tt.prototype.$__shouldModify=function(t,e,r,n,o,i,s){return!!this.isNew||null==this.schema.singleNestedPaths[e]&&(void 0===i&&!this.isSelected(e)||(void 0!==i||!(e in this.$__.activePaths.states.default))&&(!(this.populated(e)&&i instanceof tt&&U(i._id,s))&&(!U(i,s||I.getValue(e,this))||!(r||null==i||!(e in this.$__.activePaths.states.default)||!U(i,o.getDefault(this,r))))))},tt.prototype.$__set=function(t,e,n,o,i,s,a){l=l||r(26);var u=this.$__shouldModify(t,e,n,o,i,s,a),f=this;u&&(this.markModified(t),c||(c=r(82)),s&&s.isMongooseArray&&(s._registerAtomic("$set",s),s.isMongooseDocumentArray&&s.forEach((function(t){t&&t.__parentArray&&(t.__parentArray=s)})),this.$__.activePaths.forEach((function(t){t.startsWith(e+".")&&f.$__.activePaths.ignore(t)}))));for(var p=this._doc,h=0,y=o.length,d="";h<y;h++){var m=h+1===y;if(d+=d?"."+o[h]:o[h],Z.has(o[h]))return;m?p instanceof Map?p.set(o[h],s):p[o[h]]=s:(I.isPOJO(p[o[h]])||p[o[h]]&&p[o[h]]instanceof l||p[o[h]]&&p[o[h]].$isSingleNested||p[o[h]]&&Array.isArray(p[o[h]])||(p[o[h]]=p[o[h]]||{}),p=p[o[h]])}},tt.prototype.$__getValue=function(t){return I.getValue(t,this._doc)},tt.prototype.$__setValue=function(t,e){return I.setValue(t,e,this._doc),this},tt.prototype.get=function(t,e,r){var n;r=r||{},e&&(n=this.schema.interpretAsType(t,e,this.schema.options));var o=this.$__path(t);if(null==o&&(o=this.schema.virtualpath(t)),o instanceof y){var i=this.schema.virtualpath(t);null!=i&&(o=i)}var s=t.split("."),a=this._doc;if(o instanceof O){if(0===o.getters.length)return;return o.applyGetters(null,this)}"string"==typeof this.schema.aliases[s[0]]&&(s[0]=this.schema.aliases[s[0]]);for(var u=0,c=s.length;u<c;u++)a&&a._doc&&(a=a._doc),a=null==a?void 0:a instanceof Map?a.get(s[u],{getters:!1}):u===c-1?I.getValue(s[u],a):a[s[u]];if(n&&(a=n.cast(a)),null!=o&&!1!==r.getters)a=o.applyGetters(a,this);else if(this.schema.nested[t]&&r.virtuals)return ut(this,I.clone(a)||{},{path:t});return a},
+/*!
+ * ignore
+ */
+tt.prototype[J]=tt.prototype.get,tt.prototype.$__path=function(t){var e=this.$__.adhocPaths,r=e&&e.hasOwnProperty(t)?e[t]:null;return r||this.schema.path(t)},tt.prototype.markModified=function(t,e){this.$__.activePaths.modify(t),null==e||this.ownerDocument||(this.$__.pathsToScopes[t]=e)},tt.prototype.unmarkModified=function(t){this.$__.activePaths.init(t),delete this.$__.pathsToScopes[t]},tt.prototype.$ignore=function(t){this.$__.activePaths.ignore(t)},tt.prototype.directModifiedPaths=function(){return Object.keys(this.$__.activePaths.states.modify)},tt.prototype.$isEmpty=function(t){var e={minimize:!0,virtuals:!1,getters:!1,transform:!1};if(arguments.length>0){var r=this.get(t);return null==r||"object"===a(r)&&(I.isPOJO(r)?ot(r):0===Object.keys(r.toObject(e)).length)}return 0===Object.keys(this.toObject(e)).length},tt.prototype.modifiedPaths=function(t){t=t||{};var e=Object.keys(this.$__.activePaths.states.modify),r=this;return e.reduce((function(e,n){var o=n.split(".");if(e=e.concat(o.reduce((function(t,e,r){return t.concat(o.slice(0,r).concat(e).join("."))}),[]).filter((function(t){return-1===e.indexOf(t)}))),!t.includeChildren)return e;var s=r.get(n);if(null!=s&&"object"===a(s))if(s._doc&&(s=s._doc),Array.isArray(s)){for(var u=s.length,c=0;c<u;++c)if(-1===e.indexOf(n+"."+c)&&(e.push(n+"."+c),null!=s[c]&&s[c].$__)){var l,f=i(s[c].modifiedPaths());try{for(f.s();!(l=f.n()).done;){var p=l.value;e.push(n+"."+c+"."+p)}}catch(t){f.e(t)}finally{f.f()}}}else Object.keys(s).filter((function(t){return-1===e.indexOf(n+"."+t)})).forEach((function(t){e.push(n+"."+t)}));return e}),[])},tt.prototype[z]=tt.prototype.modifiedPaths,tt.prototype.isModified=function(t,e){if(t){Array.isArray(t)||(t=t.split(" "));var r=e||this[z](),n=Object.keys(this.$__.activePaths.states.modify);return t.some((function(t){return!!~r.indexOf(t)}))||t.some((function(t){return n.some((function(e){return e===t||t.startsWith(e+".")}))}))}return this.$__.activePaths.some("modify")},tt.prototype[K]=tt.prototype.isModified,tt.prototype.$isDefault=function(t){return t in this.$__.activePaths.states.default},tt.prototype.$isDeleted=function(t){return 0===arguments.length?!!this.$__.isDeleted:(this.$__.isDeleted=!!t,this)},tt.prototype.isDirectModified=function(t){return t in this.$__.activePaths.states.modify},tt.prototype.isInit=function(t){return t in this.$__.activePaths.states.init},tt.prototype.isSelected=function(t){if(this.$__.selected){if("_id"===t)return 0!==this.$__.selected._id;var e,r=Object.keys(this.$__.selected),n=r.length,o=null;if(1===n&&"_id"===r[0])return 0===this.$__.selected._id;for(;n--;)if("_id"!==(e=r[n])&&k(this.$__.selected[e])){o=!!this.$__.selected[e];break}if(null===o)return!0;if(t in this.$__.selected)return o;n=r.length;for(var i=t+".";n--;)if("_id"!==(e=r[n])){if(e.startsWith(i))return o||e!==i;if(i.startsWith(e+"."))return o}return!o}return!0},tt.prototype[Y]=tt.prototype.isSelected,tt.prototype.isDirectSelected=function(t){if(this.$__.selected){if("_id"===t)return 0!==this.$__.selected._id;var e,r=Object.keys(this.$__.selected),n=r.length,o=null;if(1===n&&"_id"===r[0])return 0===this.$__.selected._id;for(;n--;)if("_id"!==(e=r[n])&&k(this.$__.selected[e])){o=!!this.$__.selected[e];break}return null===o||(t in this.$__.selected?o:!o)}return!0},tt.prototype.validate=function(t,e,r){var n,o=this;return this.$op="validate",null!=this.ownerDocument||(this.$__.validating?n=new _(this,{parentStack:e&&e.parentStack,conflictStack:this.$__.validating.stack}):this.$__.validating=new _(this,{parentStack:e&&e.parentStack})),"function"==typeof t?(r=t,e=null,t=null):"function"==typeof e&&(r=e,e=t,t=null),S(r,(function(r){if(null!=n)return r(n);o.$__validate(t,e,(function(t){o.$op=null,r(t)}))}),this.constructor.events)},tt.prototype.$__validate=function(t,r,n){var o=this;"function"==typeof t?(n=t,r=null,t=null):"function"==typeof r&&(n=r,r=null);var i,s=r&&"object"===a(r)&&"validateModifiedOnly"in r;i=s?!!r.validateModifiedOnly:this.schema.options.validateModifiedOnly;var u=this,c=function(){var t=o.$__.validationError;if(o.$__.validationError=void 0,i&&null!=t){for(var e=0,r=Object.keys(t.errors);e<r.length;e++){var n=r[e];o.isModified(n)||delete t.errors[n]}0===Object.keys(t.errors).length&&(t=void 0)}if(o.$__.cachedRequired={},o.emit("validate",u),o.constructor.emit("validate",u),o.$__.validating=null,t){for(var s in t.errors)!o[H]&&t.errors[s]instanceof h.CastError&&o.invalidate(s,t.errors[s]);return t}},l=it(this),f=i?l[0].filter((function(t){return o.isModified(t)})):l[0],p=l[1];if(Array.isArray(t)&&(f=st(f,t)),0===f.length)return e.nextTick((function(){var t=c();if(t)return u.schema.s.hooks.execPost("validate:error",u,[u],{error:t},(function(t){n(t)}));n(null,u)}));for(var y={},d=0,m=function(){var t=c();if(t)return u.schema.s.hooks.execPost("validate:error",u,[u],{error:t},(function(t){n(t)}));n(null,u)},_=function(t){null==t||y[t]||(y[t]=!0,d++,e.nextTick((function(){var e=u.schema.path(t);if(!e)return--d||m();if(u.$isValid(t)){var r,n=u.$__getValue(t);null==n&&(r=u.populated(t))&&(n=r);var o=t in u.$__.pathsToScopes?u.$__.pathsToScopes[t]:u,i={skipSchemaValidators:p[t],path:t};e.doValidate(n,(function(r){if(r&&(!e.$isMongooseDocumentArray||r.$isArrayValidatorError)){if(e.$isSingleNested&&r instanceof b&&!1===e.schema.options.storeSubdocValidationError)return--d||m();u.invalidate(t,r,void 0,!0)}--d||m()}),o,i)}else--d||m()})))},v=f.length,g=0;g<v;++g)_(f[g])},tt.prototype.validateSync=function(t,e){var r,n=this,o=this;r=e&&"object"===a(e)&&"validateModifiedOnly"in e?!!e.validateModifiedOnly:this.schema.options.validateModifiedOnly,"string"==typeof t&&(t=t.split(" "));var i=it(this),s=r?i[0].filter((function(t){return n.isModified(t)})):i[0],u=i[1];Array.isArray(t)&&(s=st(s,t));var c={};s.forEach((function(t){if(!c[t]){c[t]=!0;var e=o.schema.path(t);if(e&&o.$isValid(t)){var r=o.$__getValue(t),n=e.doValidateSync(r,o,{skipSchemaValidators:u[t],path:t});if(n&&(!e.$isMongooseDocumentArray||n.$isArrayValidatorError)){if(e.$isSingleNested&&n instanceof b&&!1===e.schema.options.storeSubdocValidationError)return;o.invalidate(t,n,void 0,!0)}}}}));var l=o.$__.validationError;if(o.$__.validationError=void 0,o.emit("validate",o),o.constructor.emit("validate",o),l)for(var f in l.errors)l.errors[f]instanceof h.CastError&&o.invalidate(f,l.errors[f]);return l},tt.prototype.invalidate=function(t,e,r,n){if(this.$__.validationError||(this.$__.validationError=new b(this)),!this.$__.validationError.errors[t])return e&&"string"!=typeof e||(e=new w({path:t,message:e,type:n||"user defined",value:r})),this.$__.validationError===e||this.$__.validationError.addError(t,e),this.$__.validationError},tt.prototype.$markValid=function(t){this.$__.validationError&&this.$__.validationError.errors[t]&&(delete this.$__.validationError.errors[t],0===Object.keys(this.$__.validationError.errors).length&&(this.$__.validationError=null))},tt.prototype.$isValid=function(t){return!this.$__.validationError||!this.$__.validationError.errors[t]},tt.prototype.$__reset=function(){var t=this;return u||(u=r(18)),this.$__.activePaths.map("init","modify",(function(e){return t.$__getValue(e)})).filter((function(t){return t&&t instanceof Array&&t.isMongooseDocumentArray&&t.length})).forEach((function(e){for(var r=e.length;r--;){var n=e[r];n&&n.$__reset()}t.$__.activePaths.init(e.$path()),e[q]=e[W],e[W]={}})),this.$__.activePaths.map("init","modify",(function(e){return t.$__getValue(e)})).filter((function(t){return t&&t.$isSingleNested})).forEach((function(e){e.$__reset(),t.$__.activePaths.init(e.$basePath)})),this.$__dirty().forEach((function(t){var e=t.value;e&&e[W]&&(e[q]=e[W],e[W]={})})),this.$__.backup={},this.$__.backup.activePaths={modify:Object.assign({},this.$__.activePaths.states.modify),default:Object.assign({},this.$__.activePaths.states.default)},this.$__.backup.validationError=this.$__.validationError,this.$__.backup.errors=this.errors,this.$__.activePaths.clear("modify"),this.$__.activePaths.clear("default"),this.$__.validationError=void 0,this.errors=void 0,t=this,this.schema.requiredPaths().forEach((function(e){t.$__.activePaths.require(e)})),this},
+/*!
+ * ignore
+ */
+tt.prototype.$__undoReset=function(){if(null!=this.$__.backup&&null!=this.$__.backup.activePaths){this.$__.activePaths.states.modify=this.$__.backup.activePaths.modify,this.$__.activePaths.states.default=this.$__.backup.activePaths.default,this.$__.validationError=this.$__.backup.validationError,this.errors=this.$__.backup.errors;var t,e=i(this.$__dirty());try{for(e.s();!(t=e.n()).done;){var r=t.value.value;r&&r[W]&&r[q]&&(r[W]=r[q])}}catch(t){e.e(t)}finally{e.f()}var n,o=i(this.$__getAllSubdocs());try{for(o.s();!(n=o.n()).done;){n.value.$__undoReset()}}catch(t){o.e(t)}finally{o.f()}}},tt.prototype.$__dirty=function(){var t=this,e=this.$__.activePaths.map("modify",(function(e){return{path:e,value:t.$__getValue(e),schema:t.$__path(e)}}));(e=e.concat(this.$__.activePaths.map("default",(function(e){if("_id"!==e&&null!=t.$__getValue(e))return{path:e,value:t.$__getValue(e),schema:t.$__path(e)}})))).sort((function(t,e){return t.path<e.path?-1:t.path>e.path?1:0}));var r,n,o=[];return e.forEach((function(t){t&&(null==r||0!==t.path.indexOf(r)?(r=t.path+".",o.push(t),n=t):null!=n&&null!=n.value&&null!=n.value[W]&&n.value.hasAtomics()&&(n.value[W]={},n.value[W].$set=n.value))})),n=r=null,o},tt.prototype.$__setSchema=function(t){t.plugin(T,{deduplicate:!0}),j(t.tree,this,void 0,t.options);for(var e=0,r=Object.keys(t.virtuals);e<r.length;e++){var n=r[e];t.virtuals[n]._applyDefaultGetters()}this.schema=t,this[Q]=t},tt.prototype.$__getArrayPathsToValidate=function(){return u||(u=r(18)),this.$__.activePaths.map("init","modify",function(t){return this.$__getValue(t)}.bind(this)).filter((function(t){return t&&t instanceof Array&&t.isMongooseDocumentArray&&t.length})).reduce((function(t,e){return t.concat(e)}),[]).filter((function(t){return t}))},tt.prototype.$__getAllSubdocs=function(){u||(u=r(18)),l=l||r(26);var t=this;return Object.keys(this._doc).reduce((function(e,r){return function t(e,r,n){var o=e;return n&&(o=e instanceof tt&&e[Q].paths[n]?e._doc[n]:e[n]),o instanceof l?r.push(o):o instanceof Map?r=Array.from(o.keys()).reduce((function(e,r){return t(o.get(r),e,null)}),r):o&&o.$isSingleNested?(r=Object.keys(o._doc).reduce((function(e,r){return t(o._doc,e,r)}),r)).push(o):o&&o.isMongooseDocumentArray?o.forEach((function(e){e&&e._doc&&(r=Object.keys(e._doc).reduce((function(r,n){return t(e._doc,r,n)}),r),e instanceof l&&r.push(e))})):o instanceof tt&&o.$__isNested&&(r=Object.keys(o).reduce((function(e,r){return t(o,e,r)}),r)),r}(t,e,r)}),[])},tt.prototype.$__handleReject=function(t){this.listeners("error").length?this.emit("error",t):this.constructor.listeners&&this.constructor.listeners("error").length&&this.constructor.emit("error",t)},tt.prototype.$toObject=function(t,e){var r,o={transform:!0,flattenDecimals:!0},i=e?"toJSON":"toObject",s=x(this,"constructor.base.options."+i,{}),a=x(this,"schema.options",{});o=I.options(o,L(s)),o=I.options(o,L(a[i]||{})),(t=I.isPOJO(t)?L(t):{})._calledWithOptions=t._calledWithOptions||L(t),"flattenMaps"in t||(t.flattenMaps=o.flattenMaps),r=null!=t._calledWithOptions.minimize?t.minimize:null!=o.minimize?o.minimize:a.minimize;var u=Object.assign(I.clone(t),{_isNested:!0,json:e,minimize:r});if(I.hasUserDefinedProperty(t,"getters")&&(u.getters=t.getters),I.hasUserDefinedProperty(t,"virtuals")&&(u.virtuals=t.virtuals),(t.depopulate||x(t,"_parentOptions.depopulate",!1))&&t._isNested&&this.$__.wasPopulated)return L(this._id,u);(t=I.options(o,t))._isNested=!0,t.json=e,t.minimize=r,u._parentOptions=t,u._skipSingleNestedGetters=!0;var c=Object.assign({},u);c._skipSingleNestedGetters=!1;var l=t.transform,f=L(this._doc,u)||{};t.getters&&(!function(t,e,r){var n,o,i=t.schema,s=Object.keys(i.paths),a=s.length,u=t._doc;if(!u)return e;for(;a--;){var c=(n=s[a]).split("."),l=c.length,f=l-1,p=e,h=void 0;if(u=t._doc,t.isSelected(n))for(var y=0;y<l;++y){if(h=c[y],o=u[h],y===f){var d=t.get(n);p[h]=L(d,r)}else{if(null==o){h in u&&(p[h]=o);break}p=p[h]||(p[h]={})}u=o}}}
+/*!
+ * Applies schema type transforms to `json`.
+ *
+ * @param {Document} self
+ * @param {Object} json
+ * @return {Object} `json`
+ */(this,f,c),t.minimize&&(f=
+/*!
+ * Minimizes an object, removing undefined values and empty objects
+ *
+ * @param {Object} object to minimize
+ * @return {Object}
+ */
+function t(e){var r,o,i,s=Object.keys(e),a=s.length;for(;a--;)o=s[a],i=e[o],I.isObject(i)&&!n.isBuffer(i)&&(e[o]=t(i)),void 0!==e[o]?r=!0:delete e[o];return r?e:void 0}(f)||{})),(t.virtuals||t.getters&&!1!==t.virtuals)&&ut(this,f,c,t),!1===t.versionKey&&this.schema.options.versionKey&&delete f[this.schema.options.versionKey];var p=t.transform;if(p&&function(t,e){var r=t.schema,n=Object.keys(r.paths||{});if(!t._doc)return e;for(var o=0,i=n;o<i.length;o++){var s=i[o],a=r.paths[s];if("function"==typeof a.options.transform){var u=t.get(s),c=a.options.transform.call(t,u);ct(s,c),e[s]=c}else if(null!=a.$embeddedSchemaType&&"function"==typeof a.$embeddedSchemaType.options.transform){for(var l=[].concat(t.get(s)),f=a.$embeddedSchemaType.options.transform,p=0;p<l.length;++p){var h=f.call(t,l[p]);l[p]=h,ct(s,h)}e[s]=l}}}(this,f),t.useProjection&&function(t,e){var r=t.schema,n=Object.keys(r.paths||{});if(!t._doc)return e;var o=t.$__.selected;void 0===o&&(o={},M.applyPaths(o,r));if(null==o||0===Object.keys(o).length)return e;for(var i=0,s=n;i<s.length;i++){var a=s[i];null==o[a]||o[a]||delete e[a]}}(this,f),!0===p||a.toObject&&p){var h=t.json?a.toJSON:a.toObject;h&&(p="function"==typeof t.transform?t.transform:h.transform)}else t.transform=l;if("function"==typeof p){var y=p(this,f,t);void 0!==y&&(f=y)}return f},tt.prototype.toObject=function(t){return this.$toObject(t)},tt.prototype.toJSON=function(t){return this.$toObject(t,!0)},tt.prototype.parent=function(){return this.$__.parent},tt.prototype.inspect=function(t){var e;I.isPOJO(t)&&((e=t).minimize=!1);var r=this.toObject(e);return null==r?"MongooseDocument { "+r+" }":r},D.custom&&(
+/*!
+ * Avoid Node deprecation warning DEP0079
+ */
+tt.prototype[D.custom]=tt.prototype.inspect),tt.prototype.toString=function(){var t=this.inspect();return"string"==typeof t?t:D(t)},tt.prototype.equals=function(t){if(!t)return!1;var e=this.$__getValue("_id"),r=null!=t.$__?t.$__getValue("_id"):t;return e||r?e&&e.equals?e.equals(r):e===r:U(this,t)},tt.prototype.populate=function(){if(0===arguments.length)return this;var t,e=this.$__.populate||(this.$__.populate={}),r=I.args(arguments);if("function"==typeof r[r.length-1]&&(t=r.pop()),r.length){var n,o=I.populate.apply(null,r),s=i(o);try{for(s.s();!(n=s.n()).done;){var a=n.value;e[a.path]=a}}catch(t){s.e(t)}finally{s.f()}}if(t){var u=I.object.vals(e);this.$__.populate=void 0;var c=this.constructor;if(this.$__isNested){c=this.$__[X].constructor;var l=this.$__.nestedPath;u.forEach((function(t){t.path=l+"."+t.path}))}if(null!=this.$session()){var f=this.$session();u.forEach((function(t){null!=t.options?"session"in t.options||(t.options.session=f):t.options={session:f}}))}c.populate(this,u,t)}return this},tt.prototype.execPopulate=function(t){var e=this,r=null!=t&&"function"!=typeof t;return r?this.populate.apply(this,arguments).execPopulate():S(t,(function(t){e.populate(t)}),this.constructor.events)},tt.prototype.populated=function(t,e,r){if(null==e){if(!this.$__.populated)return;var n=this.$__.populated[t];return n?n.value:void 0}if(!0===e){if(!this.$__.populated)return;return this.$__.populated[t]}this.$__.populated||(this.$__.populated={}),this.$__.populated[t]={value:e,options:r};for(var o=t.split("."),i=0;i<o.length-1;++i){var s=o.slice(0,i+1).join("."),a=this.get(s);if(null!=a&&null!=a.$__&&this.populated(s)){var u=o.slice(i+1).join(".");a.populated(u,e,r);break}}return e},tt.prototype.depopulate=function(t){var e;"string"==typeof t&&(t=t.split(" "));var r=this.$$populatedVirtuals?Object.keys(this.$$populatedVirtuals):[],n=x(this,"$__.populated",{});if(0===arguments.length){var o,s=i(r);try{for(s.s();!(o=s.n()).done;){var a=o.value;delete this.$$populatedVirtuals[a],delete this._doc[a],delete n[a]}}catch(t){s.e(t)}finally{s.f()}for(var u=Object.keys(n),c=0,l=u;c<l.length;c++){var f=l[c];(e=this.populated(f))&&(delete n[f],this.$set(f,e))}return this}var p,h=i(t);try{for(h.s();!(p=h.n()).done;){var y=p.value;e=this.populated(y),delete n[y],-1!==r.indexOf(y)?(delete this.$$populatedVirtuals[y],delete this._doc[y]):e&&this.$set(y,e)}}catch(t){h.e(t)}finally{h.f()}return this},tt.prototype.$__fullPath=function(t){return t||""},tt.prototype.getChanges=function(){var t=this.$__delta();return t?t[1]:{}},
+/*!
+ * Module exports.
+ */
+tt.ValidationError=b,t.exports=tt}).call(this,r(8),r(1).Buffer)},function(t,e,r){"use strict";(function(n){
+/*!
+ * Module dependencies.
+ */
+function o(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function s(t){return(s="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var a=r(5),u=r(9),c=r(48),l=r(72),f=r(3),p=r(133),h=r(50),y=r(0).schemaTypeSymbol,d=r(4),m=r(2),_=r(0).validatorErrorSymbol,v=r(0).documentIsSelected,g=r(0).documentIsModified,b=a.CastError,w=a.ValidatorError;function O(t,e,r){this[y]=!0,this.path=t,this.instance=r,this.validators=[],this.getters=this.constructor.hasOwnProperty("getters")?this.constructor.getters.slice():[],this.setters=[],e=e||{};for(var n=this.constructor.defaultOptions||{},o=0,i=Object.keys(n);o<i.length;o++){var a=i[o];n.hasOwnProperty(a)&&!e.hasOwnProperty(a)&&(e[a]=n[a])}null==e.select&&delete e.select;var c=this.OptionsConstructor||u;this.options=new c(e),this._index=null,m.hasUserDefinedProperty(this.options,"immutable")&&(this.$immutable=this.options.immutable,p(this));for(var l=0,f=Object.keys(this.options);l<f.length;l++){var h=f[l];if("cast"!==h&&(m.hasUserDefinedProperty(this.options,h)&&"function"==typeof this[h])){if("index"===h&&this._index){if(!1===e.index){var d=this._index;if("object"===s(d)&&null!=d){if(d.unique)throw new Error('Path "'+this.path+'" may not have `index` set to false and `unique` set to true');if(d.sparse)throw new Error('Path "'+this.path+'" may not have `index` set to false and `sparse` set to true')}this._index=!1}continue}var _=e[h];if("default"===h){this.default(_);continue}var v=Array.isArray(_)?_:[_];this[h].apply(this,v)}}Object.defineProperty(this,"$$context",{enumerable:!1,configurable:!1,writable:!0,value:null})}
+/*!
+ * ignore
+ */O.prototype.OptionsConstructor=u,O.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){return t}),this._cast=t),this._cast},O.set=function(t,e){this.hasOwnProperty("defaultOptions")||(this.defaultOptions=Object.assign({},this.defaultOptions)),this.defaultOptions[t]=e},O.get=function(t){this.getters=this.hasOwnProperty("getters")?this.getters:[],this.getters.push(t)},O.prototype.default=function(t){if(1===arguments.length){if(void 0===t)return void(this.defaultValue=void 0);if(null!=t&&t.instanceOfSchema)throw new a("Cannot set default value of path `"+this.path+"` to a mongoose Schema instance.");return this.defaultValue=t,this.defaultValue}return arguments.length>1&&(this.defaultValue=m.args(arguments)),this.defaultValue},O.prototype.index=function(t){return this._index=t,m.expires(this._index),this},O.prototype.unique=function(t){if(!1===this._index){if(!t)return;throw new Error('Path "'+this.path+'" may not have `index` set to false and `unique` set to true')}return null==this._index||!0===this._index?this._index={}:"string"==typeof this._index&&(this._index={type:this._index}),this._index.unique=t,this},O.prototype.text=function(t){if(!1===this._index){if(!t)return;throw new Error('Path "'+this.path+'" may not have `index` set to false and `text` set to true')}return null===this._index||void 0===this._index||"boolean"==typeof this._index?this._index={}:"string"==typeof this._index&&(this._index={type:this._index}),this._index.text=t,this},O.prototype.sparse=function(t){if(!1===this._index){if(!t)return;throw new Error('Path "'+this.path+'" may not have `index` set to false and `sparse` set to true')}return null==this._index||"boolean"==typeof this._index?this._index={}:"string"==typeof this._index&&(this._index={type:this._index}),this._index.sparse=t,this},O.prototype.immutable=function(t){return this.$immutable=t,p(this),this},O.prototype.transform=function(t){return this.options.transform=t,this},O.prototype.set=function(t){if("function"!=typeof t)throw new TypeError("A setter must be a function.");return this.setters.push(t),this},O.prototype.get=function(t){if("function"!=typeof t)throw new TypeError("A getter must be a function.");return this.getters.push(t),this},O.prototype.validate=function(t,e,r){var n,o,i,u;if("function"==typeof t||t&&"RegExp"===m.getFunctionName(t.constructor))return"function"==typeof e?(n={validator:t,message:e}).type=r||"user defined":e instanceof Object&&!r?((n=m.clone(e)).message||(n.message=n.msg),n.validator=t,n.type=n.type||"user defined"):(null==e&&(e=a.messages.general.default),r||(r="user defined"),n={message:e,type:r,validator:t}),n.isAsync&&S(),this.validators.push(n),this;for(o=0,i=arguments.length;o<i;o++){if(u=arguments[o],!m.isPOJO(u)){var c="Invalid validator. Received ("+s(u)+") "+u+". See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate";throw new Error(c)}this.validate(u.validator,u)}return this};
+/*!
+ * ignore
+ */
+var S=d.deprecate((function(){}),"Mongoose: the `isAsync` option for custom validators is deprecated. Make your async validators return a promise instead: https://mongoosejs.com/docs/validation.html#async-custom-validators");
+/*!
+ * ignore
+ */
+function A(t){return this.castForQuery(t)}
+/*!
+ * ignore
+ */
+/*!
+ * Just like handleArray, except also allows `[]` because surprisingly
+ * `$in: [1, []]` works fine
+ */
+function j(t){var e=this;return Array.isArray(t)?t.map((function(t){return Array.isArray(t)&&0===t.length?t:e.castForQuery(t)})):[this.castForQuery(t)]}
+/*!
+ * ignore
+ */O.prototype.required=function(t,e){var r={};if(arguments.length>0&&null==t)return this.validators=this.validators.filter((function(t){return t.validator!==this.requiredValidator}),this),this.isRequired=!1,delete this.originalRequiredValue,this;if("object"===s(t)&&(e=(r=t).message||e,t=t.isRequired),!1===t)return this.validators=this.validators.filter((function(t){return t.validator!==this.requiredValidator}),this),this.isRequired=!1,delete this.originalRequiredValue,this;var n=this;this.isRequired=!0,this.requiredValidator=function(e){var r=f(this,"$__.cachedRequired");if(null!=r&&!this[v](n.path)&&!this[g](n.path))return!0;if(null!=r&&n.path in r){var o=!r[n.path]||n.checkRequired(e,this);return delete r[n.path],o}return"function"==typeof t&&!t.apply(this)||n.checkRequired(e,this)},this.originalRequiredValue=t,"string"==typeof t&&(e=t,t=void 0);var o=e||a.messages.general.required;return this.validators.unshift(Object.assign({},r,{validator:this.requiredValidator,message:o,type:"required"})),this},O.prototype.ref=function(t){return this.options.ref=t,this},O.prototype.getDefault=function(t,e){var r="function"==typeof this.defaultValue?this.defaultValue.call(t):this.defaultValue;if(null!=r){"object"!==s(r)||this.options&&this.options.shared||(r=m.clone(r));var n=this.applySetters(r,t,e);return n&&n.$isSingleNested&&(n.$parent=t),n}return r},
+/*!
+ * Applies setters without casting
+ *
+ * @api private
+ */
+O.prototype._applySetters=function(t,e,r,n){var i,s=t,u=this.setters,c=this.caster,l=o(m.clone(u).reverse());try{for(l.s();!(i=l.n()).done;){s=i.value.call(e,s,this)}}catch(t){l.e(t)}finally{l.f()}if(Array.isArray(s)&&c&&c.setters){for(var f=[],p=0;p<s.length;++p){var h=s[p];try{f.push(c.applySetters(h,e,r,n))}catch(t){throw t instanceof a.CastError&&(t.$originalErrorPath=t.path,t.path=t.path+"."+p),t}}s=f}return s},
+/*!
+ * ignore
+ */
+O.prototype._castNullish=function(t){return t},O.prototype.applySetters=function(t,e,r,n,o){var i=this._applySetters(t,e,r,n,o);return null==i?this._castNullish(i):i=this.cast(i,e,r,n,o)},O.prototype.applyGetters=function(t,e){var r=t,n=this.getters,o=n.length;if(0===o)return r;for(var i=0;i<o;++i)r=n[i].call(e,r,this);return r},O.prototype.select=function(t){return this.selected=!!t,this},O.prototype.doValidate=function(t,e,r,n){var o=!1,i=this.path,a=this.validators.filter((function(t){return null!=t&&"object"===s(t)})),u=a.length;if(!u)return e(null);var c=this;function l(t,r){if(!o)if(void 0===t||t)--u<=0&&h((function(){e(null)}));else{var n=r.ErrorConstructor||w;(o=new n(r))[_]=!0,h((function(){e(o)}))}}a.forEach((function(e){if(!o){var s,a=e.validator,u=m.clone(e);if(u.path=n&&n.path?n.path:i,u.value=t,a instanceof RegExp)l(a.test(t),u);else if("function"==typeof a)if(void 0!==t||a===c.requiredValidator)if(u.isAsync)!
+/*!
+ * Handle async validators
+ */
+function(t,e,r,n,o){var i=!1,s=t.call(e,r,(function(t,e){i||(i=!0,e&&(n.message=e),o(t,n))}));"boolean"==typeof s?(i=!0,o(s,n)):s&&"function"==typeof s.then&&s.then((function(t){i||(i=!0,o(t,n))}),(function(t){i||(i=!0,n.reason=t,n.message=t.message,o(!1,n))}))}(a,r,t,u,l);else{try{s=u.propsParameter?a.call(r,t,u):a.call(r,t)}catch(t){s=!1,u.reason=t,t.message&&(u.message=t.message)}null!=s&&"function"==typeof s.then?s.then((function(t){l(t,u)}),(function(t){u.reason=t,u.message=t.message,l(s=!1,u)})):l(s,u)}else l(!0,u)}}))},O.prototype.doValidateSync=function(t,e,r){var n=this.path;if(!this.validators.length)return null;var o=this.validators;if(void 0===t){if(!(this.validators.length>0&&"required"===this.validators[0].type))return null;o=[this.validators[0]]}var i=null;return o.forEach((function(o){if(!i&&null!=o&&"object"===s(o)){var u,c=o.validator,l=m.clone(o);if(l.path=r&&r.path?r.path:n,l.value=t,!c.isAsync)if(c instanceof RegExp)a(c.test(t),l);else if("function"==typeof c){try{u=l.propsParameter?c.call(e,t,l):c.call(e,t)}catch(t){u=!1,l.reason=t}null!=u&&"function"==typeof u.then||a(u,l)}}})),i;function a(t,e){if(!i&&void 0!==t&&!t){var r=e.ErrorConstructor||w;(i=new r(e))[_]=!0}}},O._isRef=function(t,e,r,o){var i=o&&t.options&&(t.options.ref||t.options.refPath);if(!i&&r&&null!=r.$__){var s=r.$__fullPath(t.path);i=(r.ownerDocument?r.ownerDocument():r).populated(s)||r.populated(t.path)}if(i){if(null==e)return!0;if(!n.isBuffer(e)&&"Binary"!==e._bsontype&&m.isObject(e))return!0}return!1},O.prototype.$conditionalHandlers={$all:function(t){var e=this;return Array.isArray(t)?t.map((function(t){return e.castForQuery(t)})):[this.castForQuery(t)]},$eq:A,$in:j,$ne:A,$nin:j,$exists:c,$type:l},
+/*!
+ * Wraps `castForQuery` to handle context
+ */
+O.prototype.castForQueryWrapper=function(t){if(this.$$context=t.context,"$conditional"in t){var e=this.castForQuery(t.$conditional,t.val);return this.$$context=null,e}if(t.$skipQueryCastForUpdate||t.$applySetters){var r=this._castForQuery(t.val);return this.$$context=null,r}var n=this.castForQuery(t.val);return this.$$context=null,n},O.prototype.castForQuery=function(t,e){var r;if(2===arguments.length){if(!(r=this.$conditionalHandlers[t]))throw new Error("Can't use "+t);return r.call(this,e)}return e=t,this._castForQuery(e)},
+/*!
+ * Internal switch for runSetters
+ *
+ * @api private
+ */
+O.prototype._castForQuery=function(t){return this.applySetters(t,this.$$context)},O.checkRequired=function(t){return arguments.length>0&&(this._checkRequired=t),this._checkRequired},O.prototype.checkRequired=function(t){return null!=t},
+/*!
+ * ignore
+ */
+O.prototype.clone=function(){var t=Object.assign({},this.options),e=new this.constructor(this.path,t,this.instance);return e.validators=this.validators.slice(),void 0!==this.requiredValidator&&(e.requiredValidator=this.requiredValidator),void 0!==this.defaultValue&&(e.defaultValue=this.defaultValue),void 0!==this.$immutable&&void 0===this.options.immutable&&(e.$immutable=this.$immutable,p(e)),void 0!==this._index&&(e._index=this._index),void 0!==this.selected&&(e.selected=this.selected),void 0!==this.isRequired&&(e.isRequired=this.isRequired),void 0!==this.originalRequiredValue&&(e.originalRequiredValue=this.originalRequiredValue),e.getters=this.getters.slice(),e.setters=this.setters.slice(),e},
+/*!
+ * Module exports.
+ */
+t.exports=e=O,e.CastError=b,e.ValidatorError=w}).call(this,r(1).Buffer)},function(t,e){var r,n,o=t.exports={};function i(){throw new Error("setTimeout has not been defined")}function s(){throw new Error("clearTimeout has not been defined")}function a(t){if(r===setTimeout)return setTimeout(t,0);if((r===i||!r)&&setTimeout)return r=setTimeout,setTimeout(t,0);try{return r(t,0)}catch(e){try{return r.call(null,t,0)}catch(e){return r.call(this,t,0)}}}!function(){try{r="function"==typeof setTimeout?setTimeout:i}catch(t){r=i}try{n="function"==typeof clearTimeout?clearTimeout:s}catch(t){n=s}}();var u,c=[],l=!1,f=-1;function p(){l&&u&&(l=!1,u.length?c=u.concat(c):f=-1,c.length&&h())}function h(){if(!l){var t=a(p);l=!0;for(var e=c.length;e;){for(u=c,c=[];++f<e;)u&&u[f].run();f=-1,e=c.length}u=null,l=!1,function(t){if(n===clearTimeout)return clearTimeout(t);if((n===s||!n)&&clearTimeout)return n=clearTimeout,clearTimeout(t);try{n(t)}catch(e){try{return n.call(null,t)}catch(e){return n.call(this,t)}}}(t)}}function y(t,e){this.fun=t,this.array=e}function d(){}o.nextTick=function(t){var e=new Array(arguments.length-1);if(arguments.length>1)for(var r=1;r<arguments.length;r++)e[r-1]=arguments[r];c.push(new y(t,e)),1!==c.length||l||a(h)},y.prototype.run=function(){this.fun.apply(null,this.array)},o.title="browser",o.browser=!0,o.env={},o.argv=[],o.version="",o.versions={},o.on=d,o.addListener=d,o.once=d,o.off=d,o.removeListener=d,o.removeAllListeners=d,o.emit=d,o.prependListener=d,o.prependOnceListener=d,o.listeners=function(t){return[]},o.binding=function(t){throw new Error("process.binding is not supported")},o.cwd=function(){return"/"},o.chdir=function(t){throw new Error("process.chdir is not supported")},o.umask=function(){return 0}},function(t,e,r){"use strict";var n=r(28),o=function t(e){if(function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),null==e)return this;Object.assign(this,n(e))},i=r(10);Object.defineProperty(o.prototype,"type",i),Object.defineProperty(o.prototype,"validate",i),Object.defineProperty(o.prototype,"cast",i),Object.defineProperty(o.prototype,"required",i),Object.defineProperty(o.prototype,"default",i),Object.defineProperty(o.prototype,"ref",i),Object.defineProperty(o.prototype,"select",i),Object.defineProperty(o.prototype,"index",i),Object.defineProperty(o.prototype,"unique",i),Object.defineProperty(o.prototype,"immutable",i),Object.defineProperty(o.prototype,"sparse",i),Object.defineProperty(o.prototype,"text",i),Object.defineProperty(o.prototype,"transform",i),t.exports=o},function(t,e,r){"use strict";t.exports=Object.freeze({enumerable:!0,configurable:!0,writable:!0,value:void 0})},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(t){"object"===("undefined"==typeof window?"undefined":r(window))&&(n=window)}t.exports=n},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function s(t,e){return(s=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function a(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=c(t);if(e){var o=c(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return u(this,r)}}function u(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function c(t){return(c=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var l=r(14),f=r(3),p=r(4),h=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&s(t,e)}(l,t);var e,r,n,c=a(l);function l(t,e,r,n,i){var s;if(o(this,l),arguments.length>0){var a=y(e),f=d(i),p=m(null,t,a,r,f);(s=c.call(this,p)).init(t,e,r,n,i)}else s=c.call(this,m());return u(s)}
+/*!
+ * ignore
+ */return e=l,(r=[{key:"init",value:function(t,e,r,n,o){this.stringValue=y(e),this.messageFormat=d(o),this.kind=t,this.value=e,this.path=r,this.reason=n}
+/*!
+ * ignore
+ * @param {Readonly<CastError>} other
+ */},{key:"copy",value:function(t){this.messageFormat=t.messageFormat,this.stringValue=t.stringValue,this.kind=t.kind,this.value=t.value,this.path=t.path,this.reason=t.reason,this.message=t.message}
+/*!
+ * ignore
+ */},{key:"setModel",value:function(t){this.model=t,this.message=m(t,this.kind,this.stringValue,this.path,this.messageFormat)}}])&&i(e.prototype,r),n&&i(e,n),l}(l);function y(t){var e=p.inspect(t);return(e=e.replace(/^'|'$/g,'"')).startsWith('"')||(e='"'+e+'"'),e}function d(t){var e=f(t,"options.cast",null);if("string"==typeof e)return e}
+/*!
+ * ignore
+ */function m(t,e,r,n,o){if(null!=o){var i=o.replace("{KIND}",e).replace("{VALUE}",r).replace("{PATH}",n);return null!=t&&(i=i.replace("{MODEL}",t.modelName)),i}var s="Cast to "+e+" failed for value "+r+' at path "'+n+'"';return null!=t&&(s+=' for model "'+t.modelName+'"'),s}
+/*!
+ * exports
+ */Object.defineProperty(h.prototype,"name",{value:"CastError"}),t.exports=h},function(t,e,r){"use strict";var n=r(15).get().ObjectId,o=r(0).objectIdSymbol;
+/*!
+ * Getter for convenience with populate, see gh-6115
+ */
+Object.defineProperty(n.prototype,"_id",{enumerable:!1,configurable:!0,get:function(){return this}}),n.prototype[o]=!0,t.exports=n},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function s(t){var e="function"==typeof Map?new Map:void 0;return(s=function(t){if(null===t||(r=t,-1===Function.toString.call(r).indexOf("[native code]")))return t;var r;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return a(t,arguments,l(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),c(n,t)})(t)}function a(t,e,r){return(a=u()?Reflect.construct:function(t,e,r){var n=[null];n.push.apply(n,e);var o=new(Function.bind.apply(t,n));return r&&c(o,r.prototype),o}).apply(null,arguments)}function u(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function c(t,e){return(c=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function l(t){return(l=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var f=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&c(t,e)}(s,t);var e,r,n=(e=s,r=u(),function(){var t,n=l(e);if(r){var o=l(this).constructor;t=Reflect.construct(n,arguments,o)}else t=n.apply(this,arguments);return i(this,t)});function s(){return o(this,s),n.apply(this,arguments)}return s}(s(Error));Object.defineProperty(f.prototype,"name",{value:"MongooseError"}),t.exports=f},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */var n=null;t.exports.get=function(){return n},t.exports.set=function(t){n=t}},function(t,e,r){"use strict";(function(e){function r(t,r){return new e(t,r)}t.exports={normalizedFunctionString:function(t){return t.toString().replace(/function *\(/,"function (")},allocBuffer:"function"==typeof e.alloc?function(){return e.alloc.apply(e,arguments)}:r,toBuffer:"function"==typeof e.from?function(){return e.from.apply(e,arguments)}:r}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */e.internalToObjectOptions={transform:!1,virtuals:!1,getters:!1,_skipDepopulateTopLevel:!0,depopulate:!0,flattenDecimals:!1}},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module dependencies.
+ */
+function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function s(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function u(t,e,r){return(u="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,r){var n=function(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=p(t)););return t}(t,e);if(n){var o=Object.getOwnPropertyDescriptor(n,e);return o.get?o.get.call(r):o.value}})(t,e,r||t)}function c(t,e){return(c=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function l(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=p(t);if(e){var o=p(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return f(this,r)}}function f(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function p(t){return(p=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var h=r(83),y=r(6),d=r(13),m=r(86),_=r(34),v=r(17).internalToObjectOptions,g=r(4),b=r(2),w=r(0).arrayAtomicsSymbol,O=r(0).arrayParentSymbol,S=r(0).arrayPathSymbol,A=r(0).arraySchemaSymbol,j=r(0).documentArrayParent,E=Array.prototype.push,$=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&c(t,e)}(n,t);var r=l(n);function n(){return s(this,n),r.apply(this,arguments)}return function(t,e,r){e&&a(t.prototype,e),r&&a(t,r)}(n,[{key:"toBSON",
+/*!
+ * ignore
+ */
+value:function(){return this.toObject(v)}
+/*!
+ * ignore
+ */},{key:"map",value:function(){var t=u(p(n.prototype),"map",this).apply(this,arguments);return t[A]=null,t[S]=null,t[O]=null,t}},{key:"_cast",value:function(t,r){if(null==this[A])return t;var n=this[A].casterConstructor;if((n.$isMongooseDocumentArray?t&&t.isMongooseDocumentArray:t instanceof n)||t&&t.constructor&&t.constructor.baseCasterConstructor===n)return t[j]&&t.__parentArray||(t[j]=this[O],t.__parentArray=this),t.$setIndex(r),t;if(null==t)return null;if((e.isBuffer(t)||t instanceof d||!b.isObject(t))&&(t={_id:t}),t&&n.discriminators&&n.schema&&n.schema.options&&n.schema.options.discriminatorKey)if("string"==typeof t[n.schema.options.discriminatorKey]&&n.discriminators[t[n.schema.options.discriminatorKey]])n=n.discriminators[t[n.schema.options.discriminatorKey]];else{var o=_(n,t[n.schema.options.discriminatorKey]);o&&(n=o)}return n.$isMongooseDocumentArray?n.cast(t,this,void 0,void 0,r):new n(t,this,void 0,void 0,r)}},{key:"id",value:function(t){var e,r,n;try{e=m(t).toString()}catch(t){e=null}var i,s=o(this);try{for(s.s();!(i=s.n()).done;){var a=i.value;if(a&&null!=(n=a.get("_id")))if(n instanceof y){if(r||(r=String(t)),r==n._id)return a}else if(t instanceof d||n instanceof d){if(e==n)return a}else if(t==n||b.deepEqual(t,n))return a}}catch(t){s.e(t)}finally{s.f()}return null}},{key:"toObject",value:function(t){return[].concat(this.map((function(e){return null==e?null:"function"!=typeof e.toObject?e:e.toObject(t)})))}},{key:"slice",value:function(){var t=u(p(n.prototype),"slice",this).apply(this,arguments);return t[O]=this[O],t[S]=this[S],t}},{key:"push",value:function(){var t=u(p(n.prototype),"push",this).apply(this,arguments);return x(this),t}},{key:"pull",value:function(){var t=u(p(n.prototype),"pull",this).apply(this,arguments);return x(this),t}},{key:"shift",value:function(){var t=u(p(n.prototype),"shift",this).apply(this,arguments);return x(this),t}},{key:"splice",value:function(){var t=u(p(n.prototype),"splice",this).apply(this,arguments);return x(this),t}},{key:"inspect",value:function(){return this.toObject()}},{key:"create",value:function(t){var e=this[A].casterConstructor;if(t&&e.discriminators&&e.schema&&e.schema.options&&e.schema.options.discriminatorKey)if("string"==typeof t[e.schema.options.discriminatorKey]&&e.discriminators[t[e.schema.options.discriminatorKey]])e=e.discriminators[t[e.schema.options.discriminatorKey]];else{var r=_(e,t[e.schema.options.discriminatorKey]);r&&(e=r)}return new e(t,this)}
+/*!
+ * ignore
+ */},{key:"notify",value:function(t){var e=this;return function r(n,o){for(var i=(o=o||e).length;i--;)if(null!=o[i]){switch(t){case"save":n=e[i]}o[i].isMongooseArray?r(n,o[i]):o[i]&&o[i].emit(t,n)}}}},{key:"isMongooseDocumentArray",get:function(){return!0}}]),n}(h);
+/*!
+ * If this is a document array, each element may contain single
+ * populated paths, so we need to modify the top-level document's
+ * populated cache. See gh-8247, gh-8265.
+ */
+function x(t){var e=t[O];if(e&&null!=e.$__.populated){var r,n=o(Object.keys(e.$__.populated).filter((function(e){return e.startsWith(t[S]+".")})));try{var i=function(){var n=r.value,o=n.slice((t[S]+".").length);if(!Array.isArray(e.$__.populated[n].value))return"continue";e.$__.populated[n].value=t.map((function(t){return t.populated(o)}))};for(n.s();!(r=n.n()).done;)i()}catch(t){n.e(t)}finally{n.f()}}}g.inspect.custom&&($.prototype[g.inspect.custom]=$.prototype.inspect),
+/*!
+ * Module exports.
+ */
+t.exports=function(t,e,r){var n=new $;if(n[w]={},n[A]=void 0,Array.isArray(t)&&(t instanceof $&&t[S]===e&&t[O]===r&&(n[w]=Object.assign({},t[w])),t.forEach((function(t){E.call(n,t)}))),n[S]=e,r&&r instanceof y)for(n[O]=r,n[A]=r.schema.path(e);null!=n&&null!=n[A]&&n[A].$isMongooseArray&&!n[A].$isMongooseDocumentArray;)n[A]=n[A].casterConstructor;return n}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o,i="object"===("undefined"==typeof Reflect?"undefined":n(Reflect))?Reflect:null,s=i&&"function"==typeof i.apply?i.apply:function(t,e,r){return Function.prototype.apply.call(t,e,r)};o=i&&"function"==typeof i.ownKeys?i.ownKeys:Object.getOwnPropertySymbols?function(t){return Object.getOwnPropertyNames(t).concat(Object.getOwnPropertySymbols(t))}:function(t){return Object.getOwnPropertyNames(t)};var a=Number.isNaN||function(t){return t!=t};function u(){u.init.call(this)}t.exports=u,t.exports.once=function(t,e){return new Promise((function(r,n){function o(){void 0!==i&&t.removeListener("error",i),r([].slice.call(arguments))}var i;"error"!==e&&(i=function(r){t.removeListener(e,o),n(r)},t.once("error",i)),t.once(e,o)}))},u.EventEmitter=u,u.prototype._events=void 0,u.prototype._eventsCount=0,u.prototype._maxListeners=void 0;var c=10;function l(t){if("function"!=typeof t)throw new TypeError('The "listener" argument must be of type Function. Received type '+n(t))}function f(t){return void 0===t._maxListeners?u.defaultMaxListeners:t._maxListeners}function p(t,e,r,n){var o,i,s,a;if(l(r),void 0===(i=t._events)?(i=t._events=Object.create(null),t._eventsCount=0):(void 0!==i.newListener&&(t.emit("newListener",e,r.listener?r.listener:r),i=t._events),s=i[e]),void 0===s)s=i[e]=r,++t._eventsCount;else if("function"==typeof s?s=i[e]=n?[r,s]:[s,r]:n?s.unshift(r):s.push(r),(o=f(t))>0&&s.length>o&&!s.warned){s.warned=!0;var u=new Error("Possible EventEmitter memory leak detected. "+s.length+" "+String(e)+" listeners added. Use emitter.setMaxListeners() to increase limit");u.name="MaxListenersExceededWarning",u.emitter=t,u.type=e,u.count=s.length,a=u,console&&console.warn&&console.warn(a)}return t}function h(){if(!this.fired)return this.target.removeListener(this.type,this.wrapFn),this.fired=!0,0===arguments.length?this.listener.call(this.target):this.listener.apply(this.target,arguments)}function y(t,e,r){var n={fired:!1,wrapFn:void 0,target:t,type:e,listener:r},o=h.bind(n);return o.listener=r,n.wrapFn=o,o}function d(t,e,r){var n=t._events;if(void 0===n)return[];var o=n[e];return void 0===o?[]:"function"==typeof o?r?[o.listener||o]:[o]:r?function(t){for(var e=new Array(t.length),r=0;r<e.length;++r)e[r]=t[r].listener||t[r];return e}(o):_(o,o.length)}function m(t){var e=this._events;if(void 0!==e){var r=e[t];if("function"==typeof r)return 1;if(void 0!==r)return r.length}return 0}function _(t,e){for(var r=new Array(e),n=0;n<e;++n)r[n]=t[n];return r}Object.defineProperty(u,"defaultMaxListeners",{enumerable:!0,get:function(){return c},set:function(t){if("number"!=typeof t||t<0||a(t))throw new RangeError('The value of "defaultMaxListeners" is out of range. It must be a non-negative number. Received '+t+".");c=t}}),u.init=function(){void 0!==this._events&&this._events!==Object.getPrototypeOf(this)._events||(this._events=Object.create(null),this._eventsCount=0),this._maxListeners=this._maxListeners||void 0},u.prototype.setMaxListeners=function(t){if("number"!=typeof t||t<0||a(t))throw new RangeError('The value of "n" is out of range. It must be a non-negative number. Received '+t+".");return this._maxListeners=t,this},u.prototype.getMaxListeners=function(){return f(this)},u.prototype.emit=function(t){for(var e=[],r=1;r<arguments.length;r++)e.push(arguments[r]);var n="error"===t,o=this._events;if(void 0!==o)n=n&&void 0===o.error;else if(!n)return!1;if(n){var i;if(e.length>0&&(i=e[0]),i instanceof Error)throw i;var a=new Error("Unhandled error."+(i?" ("+i.message+")":""));throw a.context=i,a}var u=o[t];if(void 0===u)return!1;if("function"==typeof u)s(u,this,e);else{var c=u.length,l=_(u,c);for(r=0;r<c;++r)s(l[r],this,e)}return!0},u.prototype.addListener=function(t,e){return p(this,t,e,!1)},u.prototype.on=u.prototype.addListener,u.prototype.prependListener=function(t,e){return p(this,t,e,!0)},u.prototype.once=function(t,e){return l(e),this.on(t,y(this,t,e)),this},u.prototype.prependOnceListener=function(t,e){return l(e),this.prependListener(t,y(this,t,e)),this},u.prototype.removeListener=function(t,e){var r,n,o,i,s;if(l(e),void 0===(n=this._events))return this;if(void 0===(r=n[t]))return this;if(r===e||r.listener===e)0==--this._eventsCount?this._events=Object.create(null):(delete n[t],n.removeListener&&this.emit("removeListener",t,r.listener||e));else if("function"!=typeof r){for(o=-1,i=r.length-1;i>=0;i--)if(r[i]===e||r[i].listener===e){s=r[i].listener,o=i;break}if(o<0)return this;0===o?r.shift():function(t,e){for(;e+1<t.length;e++)t[e]=t[e+1];t.pop()}(r,o),1===r.length&&(n[t]=r[0]),void 0!==n.removeListener&&this.emit("removeListener",t,s||e)}return this},u.prototype.off=u.prototype.removeListener,u.prototype.removeAllListeners=function(t){var e,r,n;if(void 0===(r=this._events))return this;if(void 0===r.removeListener)return 0===arguments.length?(this._events=Object.create(null),this._eventsCount=0):void 0!==r[t]&&(0==--this._eventsCount?this._events=Object.create(null):delete r[t]),this;if(0===arguments.length){var o,i=Object.keys(r);for(n=0;n<i.length;++n)"removeListener"!==(o=i[n])&&this.removeAllListeners(o);return this.removeAllListeners("removeListener"),this._events=Object.create(null),this._eventsCount=0,this}if("function"==typeof(e=r[t]))this.removeListener(t,e);else if(void 0!==e)for(n=e.length-1;n>=0;n--)this.removeListener(t,e[n]);return this},u.prototype.listeners=function(t){return d(this,t,!0)},u.prototype.rawListeners=function(t){return d(this,t,!1)},u.listenerCount=function(t,e){return"function"==typeof t.listenerCount?t.listenerCount(e):m.call(t,e)},u.prototype.listenerCount=m,u.prototype.eventNames=function(){return this._eventsCount>0?o(this._events):[]}},function(t,e,r){"use strict";t.exports=r(15).get().Decimal128},function(t,e,r){"use strict";(function(e){
+/*!
+ * Determines if `arg` is an object.
+ *
+ * @param {Object|Array|String|Function|RegExp|any} arg
+ * @api private
+ * @return {Boolean}
+ */
+t.exports=function(t){return!!e.isBuffer(t)||"[object Object]"===Object.prototype.toString.call(t)}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(114);
+/*!
+ * The buffer module from node.js, for the browser.
+ *
+ * @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
+ * @license MIT
+ */function i(t,e){if(t===e)return 0;for(var r=t.length,n=e.length,o=0,i=Math.min(r,n);o<i;++o)if(t[o]!==e[o]){r=t[o],n=e[o];break}return r<n?-1:n<r?1:0}function s(t){return e.Buffer&&"function"==typeof e.Buffer.isBuffer?e.Buffer.isBuffer(t):!(null==t||!t._isBuffer)}var a=r(4),u=Object.prototype.hasOwnProperty,c=Array.prototype.slice,l="foo"===function(){}.name;function f(t){return Object.prototype.toString.call(t)}function p(t){return!s(t)&&("function"==typeof e.ArrayBuffer&&("function"==typeof ArrayBuffer.isView?ArrayBuffer.isView(t):!!t&&(t instanceof DataView||!!(t.buffer&&t.buffer instanceof ArrayBuffer))))}var h=t.exports=g,y=/\s*function\s+([^\(\s]*)\s*/;function d(t){if(a.isFunction(t)){if(l)return t.name;var e=t.toString().match(y);return e&&e[1]}}function m(t,e){return"string"==typeof t?t.length<e?t:t.slice(0,e):t}function _(t){if(l||!a.isFunction(t))return a.inspect(t);var e=d(t);return"[Function"+(e?": "+e:"")+"]"}function v(t,e,r,n,o){throw new h.AssertionError({message:r,actual:t,expected:e,operator:n,stackStartFunction:o})}function g(t,e){t||v(t,!0,e,"==",h.ok)}function b(t,e,r,o){if(t===e)return!0;if(s(t)&&s(e))return 0===i(t,e);if(a.isDate(t)&&a.isDate(e))return t.getTime()===e.getTime();if(a.isRegExp(t)&&a.isRegExp(e))return t.source===e.source&&t.global===e.global&&t.multiline===e.multiline&&t.lastIndex===e.lastIndex&&t.ignoreCase===e.ignoreCase;if(null!==t&&"object"===n(t)||null!==e&&"object"===n(e)){if(p(t)&&p(e)&&f(t)===f(e)&&!(t instanceof Float32Array||t instanceof Float64Array))return 0===i(new Uint8Array(t.buffer),new Uint8Array(e.buffer));if(s(t)!==s(e))return!1;var u=(o=o||{actual:[],expected:[]}).actual.indexOf(t);return-1!==u&&u===o.expected.indexOf(e)||(o.actual.push(t),o.expected.push(e),function(t,e,r,n){if(null==t||null==e)return!1;if(a.isPrimitive(t)||a.isPrimitive(e))return t===e;if(r&&Object.getPrototypeOf(t)!==Object.getPrototypeOf(e))return!1;var o=w(t),i=w(e);if(o&&!i||!o&&i)return!1;if(o)return t=c.call(t),e=c.call(e),b(t,e,r);var s,u,l=A(t),f=A(e);if(l.length!==f.length)return!1;for(l.sort(),f.sort(),u=l.length-1;u>=0;u--)if(l[u]!==f[u])return!1;for(u=l.length-1;u>=0;u--)if(s=l[u],!b(t[s],e[s],r,n))return!1;return!0}(t,e,r,o))}return r?t===e:t==e}function w(t){return"[object Arguments]"==Object.prototype.toString.call(t)}function O(t,e){if(!t||!e)return!1;if("[object RegExp]"==Object.prototype.toString.call(e))return e.test(t);try{if(t instanceof e)return!0}catch(t){}return!Error.isPrototypeOf(e)&&!0===e.call({},t)}function S(t,e,r,n){var o;if("function"!=typeof e)throw new TypeError('"block" argument must be a function');"string"==typeof r&&(n=r,r=null),o=function(t){var e;try{t()}catch(t){e=t}return e}(e),n=(r&&r.name?" ("+r.name+").":".")+(n?" "+n:"."),t&&!o&&v(o,r,"Missing expected exception"+n);var i="string"==typeof n,s=!t&&o&&!r;if((!t&&a.isError(o)&&i&&O(o,r)||s)&&v(o,r,"Got unwanted exception"+n),t&&o&&r&&!O(o,r)||!t&&o)throw o}h.AssertionError=function(t){this.name="AssertionError",this.actual=t.actual,this.expected=t.expected,this.operator=t.operator,t.message?(this.message=t.message,this.generatedMessage=!1):(this.message=function(t){return m(_(t.actual),128)+" "+t.operator+" "+m(_(t.expected),128)}(this),this.generatedMessage=!0);var e=t.stackStartFunction||v;if(Error.captureStackTrace)Error.captureStackTrace(this,e);else{var r=new Error;if(r.stack){var n=r.stack,o=d(e),i=n.indexOf("\n"+o);if(i>=0){var s=n.indexOf("\n",i+1);n=n.substring(s+1)}this.stack=n}}},a.inherits(h.AssertionError,Error),h.fail=v,h.ok=g,h.equal=function(t,e,r){t!=e&&v(t,e,r,"==",h.equal)},h.notEqual=function(t,e,r){t==e&&v(t,e,r,"!=",h.notEqual)},h.deepEqual=function(t,e,r){b(t,e,!1)||v(t,e,r,"deepEqual",h.deepEqual)},h.deepStrictEqual=function(t,e,r){b(t,e,!0)||v(t,e,r,"deepStrictEqual",h.deepStrictEqual)},h.notDeepEqual=function(t,e,r){b(t,e,!1)&&v(t,e,r,"notDeepEqual",h.notDeepEqual)},h.notDeepStrictEqual=function t(e,r,n){b(e,r,!0)&&v(e,r,n,"notDeepStrictEqual",t)},h.strictEqual=function(t,e,r){t!==e&&v(t,e,r,"===",h.strictEqual)},h.notStrictEqual=function(t,e,r){t===e&&v(t,e,r,"!==",h.notStrictEqual)},h.throws=function(t,e,r){S(!0,t,e,r)},h.doesNotThrow=function(t,e,r){S(!1,t,e,r)},h.ifError=function(t){if(t)throw t},h.strict=o((function t(e,r){e||v(e,!0,r,"==",t)}),h,{equal:h.strictEqual,deepEqual:h.deepStrictEqual,notEqual:h.notStrictEqual,notDeepEqual:h.notDeepStrictEqual}),h.strict.strict=h.strict;var A=Object.keys||function(t){var e=[];for(var r in t)u.call(t,r)&&e.push(r);return e}}).call(this,r(11))},function(t,e){function r(t,e){if(!(this instanceof r))return new r(t,e);this._bsontype="Long",this.low_=0|t,this.high_=0|e}r.prototype.toInt=function(){return this.low_},r.prototype.toNumber=function(){return this.high_*r.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()},r.prototype.toJSON=function(){return this.toString()},r.prototype.toString=function(t){var e=t||10;if(e<2||36<e)throw Error("radix out of range: "+e);if(this.isZero())return"0";if(this.isNegative()){if(this.equals(r.MIN_VALUE)){var n=r.fromNumber(e),o=this.div(n),i=o.multiply(n).subtract(this);return o.toString(e)+i.toInt().toString(e)}return"-"+this.negate().toString(e)}var s=r.fromNumber(Math.pow(e,6));i=this;for(var a="";!i.isZero();){var u=i.div(s),c=i.subtract(u.multiply(s)).toInt().toString(e);if((i=u).isZero())return c+a;for(;c.length<6;)c="0"+c;a=""+c+a}},r.prototype.getHighBits=function(){return this.high_},r.prototype.getLowBits=function(){return this.low_},r.prototype.getLowBitsUnsigned=function(){return this.low_>=0?this.low_:r.TWO_PWR_32_DBL_+this.low_},r.prototype.getNumBitsAbs=function(){if(this.isNegative())return this.equals(r.MIN_VALUE)?64:this.negate().getNumBitsAbs();for(var t=0!==this.high_?this.high_:this.low_,e=31;e>0&&0==(t&1<<e);e--);return 0!==this.high_?e+33:e+1},r.prototype.isZero=function(){return 0===this.high_&&0===this.low_},r.prototype.isNegative=function(){return this.high_<0},r.prototype.isOdd=function(){return 1==(1&this.low_)},r.prototype.equals=function(t){return this.high_===t.high_&&this.low_===t.low_},r.prototype.notEquals=function(t){return this.high_!==t.high_||this.low_!==t.low_},r.prototype.lessThan=function(t){return this.compare(t)<0},r.prototype.lessThanOrEqual=function(t){return this.compare(t)<=0},r.prototype.greaterThan=function(t){return this.compare(t)>0},r.prototype.greaterThanOrEqual=function(t){return this.compare(t)>=0},r.prototype.compare=function(t){if(this.equals(t))return 0;var e=this.isNegative(),r=t.isNegative();return e&&!r?-1:!e&&r?1:this.subtract(t).isNegative()?-1:1},r.prototype.negate=function(){return this.equals(r.MIN_VALUE)?r.MIN_VALUE:this.not().add(r.ONE)},r.prototype.add=function(t){var e=this.high_>>>16,n=65535&this.high_,o=this.low_>>>16,i=65535&this.low_,s=t.high_>>>16,a=65535&t.high_,u=t.low_>>>16,c=0,l=0,f=0,p=0;return f+=(p+=i+(65535&t.low_))>>>16,p&=65535,l+=(f+=o+u)>>>16,f&=65535,c+=(l+=n+a)>>>16,l&=65535,c+=e+s,c&=65535,r.fromBits(f<<16|p,c<<16|l)},r.prototype.subtract=function(t){return this.add(t.negate())},r.prototype.multiply=function(t){if(this.isZero())return r.ZERO;if(t.isZero())return r.ZERO;if(this.equals(r.MIN_VALUE))return t.isOdd()?r.MIN_VALUE:r.ZERO;if(t.equals(r.MIN_VALUE))return this.isOdd()?r.MIN_VALUE:r.ZERO;if(this.isNegative())return t.isNegative()?this.negate().multiply(t.negate()):this.negate().multiply(t).negate();if(t.isNegative())return this.multiply(t.negate()).negate();if(this.lessThan(r.TWO_PWR_24_)&&t.lessThan(r.TWO_PWR_24_))return r.fromNumber(this.toNumber()*t.toNumber());var e=this.high_>>>16,n=65535&this.high_,o=this.low_>>>16,i=65535&this.low_,s=t.high_>>>16,a=65535&t.high_,u=t.low_>>>16,c=65535&t.low_,l=0,f=0,p=0,h=0;return p+=(h+=i*c)>>>16,h&=65535,f+=(p+=o*c)>>>16,p&=65535,f+=(p+=i*u)>>>16,p&=65535,l+=(f+=n*c)>>>16,f&=65535,l+=(f+=o*u)>>>16,f&=65535,l+=(f+=i*a)>>>16,f&=65535,l+=e*c+n*u+o*a+i*s,l&=65535,r.fromBits(p<<16|h,l<<16|f)},r.prototype.div=function(t){if(t.isZero())throw Error("division by zero");if(this.isZero())return r.ZERO;if(this.equals(r.MIN_VALUE)){if(t.equals(r.ONE)||t.equals(r.NEG_ONE))return r.MIN_VALUE;if(t.equals(r.MIN_VALUE))return r.ONE;var e=this.shiftRight(1).div(t).shiftLeft(1);if(e.equals(r.ZERO))return t.isNegative()?r.ONE:r.NEG_ONE;var n=this.subtract(t.multiply(e));return e.add(n.div(t))}if(t.equals(r.MIN_VALUE))return r.ZERO;if(this.isNegative())return t.isNegative()?this.negate().div(t.negate()):this.negate().div(t).negate();if(t.isNegative())return this.div(t.negate()).negate();var o=r.ZERO;for(n=this;n.greaterThanOrEqual(t);){e=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var i=Math.ceil(Math.log(e)/Math.LN2),s=i<=48?1:Math.pow(2,i-48),a=r.fromNumber(e),u=a.multiply(t);u.isNegative()||u.greaterThan(n);)e-=s,u=(a=r.fromNumber(e)).multiply(t);a.isZero()&&(a=r.ONE),o=o.add(a),n=n.subtract(u)}return o},r.prototype.modulo=function(t){return this.subtract(this.div(t).multiply(t))},r.prototype.not=function(){return r.fromBits(~this.low_,~this.high_)},r.prototype.and=function(t){return r.fromBits(this.low_&t.low_,this.high_&t.high_)},r.prototype.or=function(t){return r.fromBits(this.low_|t.low_,this.high_|t.high_)},r.prototype.xor=function(t){return r.fromBits(this.low_^t.low_,this.high_^t.high_)},r.prototype.shiftLeft=function(t){if(0===(t&=63))return this;var e=this.low_;if(t<32){var n=this.high_;return r.fromBits(e<<t,n<<t|e>>>32-t)}return r.fromBits(0,e<<t-32)},r.prototype.shiftRight=function(t){if(0===(t&=63))return this;var e=this.high_;if(t<32){var n=this.low_;return r.fromBits(n>>>t|e<<32-t,e>>t)}return r.fromBits(e>>t-32,e>=0?0:-1)},r.prototype.shiftRightUnsigned=function(t){if(0===(t&=63))return this;var e=this.high_;if(t<32){var n=this.low_;return r.fromBits(n>>>t|e<<32-t,e>>>t)}return 32===t?r.fromBits(e,0):r.fromBits(e>>>t-32,0)},r.fromInt=function(t){if(-128<=t&&t<128){var e=r.INT_CACHE_[t];if(e)return e}var n=new r(0|t,t<0?-1:0);return-128<=t&&t<128&&(r.INT_CACHE_[t]=n),n},r.fromNumber=function(t){return isNaN(t)||!isFinite(t)?r.ZERO:t<=-r.TWO_PWR_63_DBL_?r.MIN_VALUE:t+1>=r.TWO_PWR_63_DBL_?r.MAX_VALUE:t<0?r.fromNumber(-t).negate():new r(t%r.TWO_PWR_32_DBL_|0,t/r.TWO_PWR_32_DBL_|0)},r.fromBits=function(t,e){return new r(t,e)},r.fromString=function(t,e){if(0===t.length)throw Error("number format error: empty string");var n=e||10;if(n<2||36<n)throw Error("radix out of range: "+n);if("-"===t.charAt(0))return r.fromString(t.substring(1),n).negate();if(t.indexOf("-")>=0)throw Error('number format error: interior "-" character: '+t);for(var o=r.fromNumber(Math.pow(n,8)),i=r.ZERO,s=0;s<t.length;s+=8){var a=Math.min(8,t.length-s),u=parseInt(t.substring(s,s+a),n);if(a<8){var c=r.fromNumber(Math.pow(n,a));i=i.multiply(c).add(r.fromNumber(u))}else i=(i=i.multiply(o)).add(r.fromNumber(u))}return i},r.INT_CACHE_={},r.TWO_PWR_16_DBL_=65536,r.TWO_PWR_24_DBL_=1<<24,r.TWO_PWR_32_DBL_=r.TWO_PWR_16_DBL_*r.TWO_PWR_16_DBL_,r.TWO_PWR_31_DBL_=r.TWO_PWR_32_DBL_/2,r.TWO_PWR_48_DBL_=r.TWO_PWR_32_DBL_*r.TWO_PWR_16_DBL_,r.TWO_PWR_64_DBL_=r.TWO_PWR_32_DBL_*r.TWO_PWR_32_DBL_,r.TWO_PWR_63_DBL_=r.TWO_PWR_64_DBL_/2,r.ZERO=r.fromInt(0),r.ONE=r.fromInt(1),r.NEG_ONE=r.fromInt(-1),r.MAX_VALUE=r.fromBits(-1,2147483647),r.MIN_VALUE=r.fromBits(0,-2147483648),r.TWO_PWR_24_=r.fromInt(1<<24),t.exports=r,t.exports.Long=r},function(t,e,r){"use strict";(function(e){var n=r(67),o=Symbol.for("mongoose:emitted");t.exports=function(t,r,i){return"function"==typeof t?r((function(r){if(null==r)t.apply(this,arguments);else{null!=i&&i.listeners("error").length>0&&!r[o]&&(r[o]=!0,i.emit("error",r));try{t(r)}catch(r){return e.nextTick((function(){throw r}))}}})):new(n.get())((function(t,e){r((function(r,n){return null!=r?(null!=i&&i.listeners("error").length>0&&!r[o]&&(r[o]=!0,i.emit("error",r)),e(r)):arguments.length>2?t(Array.prototype.slice.call(arguments,1)):void t(n)}))}))}}).call(this,r(8))},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(7),o=r(51),i=r(21);function s(t,e){if(e&&e.default){var r=e.default;Array.isArray(r)&&0===r.length?e.default=Array:!e.shared&&i(r)&&0===Object.keys(r).length&&(e.default=function(){return{}})}n.call(this,t,e,"Mixed"),this[o.schemaMixedSymbol]=!0}s.schemaName="Mixed",s.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+s.prototype=Object.create(n.prototype),s.prototype.constructor=s,s.get=n.get,s.set=n.set,s.prototype.cast=function(t){return t},s.prototype.castForQuery=function(t,e){return 2===arguments.length?e:t},
+/*!
+ * Module exports.
+ */
+t.exports=s},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(61)(),o=r(19).EventEmitter,i=r(31),s=r(50),a=r(17).internalToObjectOptions,u=r(3),c=r(24),l=r(4),f=r(0).documentArrayParent,p=r(0).validatorErrorSymbol;function h(t,e,r,o,i){null!=e&&e.isMongooseDocumentArray?(this.__parentArray=e,this[f]=e.$parent()):(this.__parentArray=void 0,this[f]=void 0),this.$setIndex(i),this.$isDocumentArrayElement=!0,n.call(this,t,o,r);var s=this;this.on("isNew",(function(t){s.isNew=t})),s.on("save",(function(){s.constructor.emit("save",s)}))}
+/*!
+ * Inherit from Document
+ */for(var y in h.prototype=Object.create(n.prototype),h.prototype.constructor=h,o.prototype)h[y]=o.prototype[y];h.prototype.toBSON=function(){return this.toObject(a)},
+/*!
+ * ignore
+ */
+h.prototype.$setIndex=function(t){if(this.__index=t,null!=u(this,"$__.validationError",null))for(var e=0,r=Object.keys(this.$__.validationError.errors);e<r.length;e++){var n=r[e];this.invalidate(n,this.$__.validationError.errors[n])}},h.prototype.markModified=function(t){if(this.$__.activePaths.modify(t),this.__parentArray){var e=this.__parentArray.$path()+".0."+t;this.isNew&&this.ownerDocument().isSelected(e)?this.__parentArray._markModified():this.__parentArray._markModified(this,t)}},
+/*!
+ * ignore
+ */
+h.prototype.populate=function(){throw new Error('Mongoose does not support calling populate() on nested docs. Instead of `doc.arr[0].populate("path")`, use `doc.populate("arr.0.path")`')},h.prototype.save=function(t,e){var r=this;return"function"==typeof t&&(e=t,t={}),(t=t||{}).suppressWarning||console.warn("mongoose: calling `save()` on a subdoc does **not** save the document to MongoDB, it only runs save middleware. Use `subdoc.save({ suppressWarning: true })` to hide this warning if you're sure this behavior is right for your app."),c(e,(function(t){r.$__save(t)}))},h.prototype.$__save=function(t){var e=this;return s((function(){return t(null,e)}))},
+/*!
+ * no-op for hooks
+ */
+h.prototype.$__remove=function(t){return t(null,this)},h.prototype.remove=function(t,e){if("function"!=typeof t||e||(e=t,t=void 0),!this.__parentArray||t&&t.noop)return e&&e(null),this;var r;if(!this.willRemove){if(!(r=this._doc._id))throw new Error("For your own good, Mongoose does not know how to remove an EmbeddedDocument that has no _id");this.__parentArray.pull({_id:r}),this.willRemove=!0,
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+function(t){var e=t.ownerDocument();function r(){e.removeListener("save",r),e.removeListener("remove",r),t.emit("remove",t),t.constructor.emit("remove",t),e=t=null}e.on("save",r),e.on("remove",r)}(this)}return e&&e(null),this},h.prototype.update=function(){throw new Error("The #update method is not available on EmbeddedDocuments")},h.prototype.inspect=function(){return this.toObject({transform:!1,virtuals:!1,flattenDecimals:!1})},l.inspect.custom&&(
+/*!
+ * Avoid Node deprecation warning DEP0079
+ */
+h.prototype[l.inspect.custom]=h.prototype.inspect),h.prototype.invalidate=function(t,e,r){if(n.prototype.invalidate.call(this,t,e,r),!this[f]||null==this.__index){if(e[p]||e instanceof i)return this.ownerDocument().$__.validationError;throw e}var o=this.__index,s=[this.__parentArray.$path(),o,t].join(".");return this[f].invalidate(s,e,r),this.ownerDocument().$__.validationError},h.prototype.$markValid=function(t){if(this[f]){var e=this.__index;if(void 0!==e){var r=[this.__parentArray.$path(),e,t].join(".");this[f].$markValid(r)}}},
+/*!
+ * ignore
+ */
+h.prototype.$ignore=function(t){if(n.prototype.$ignore.call(this,t),this[f]){var e=this.__index;if(void 0!==e){var r=[this.__parentArray.$path(),e,t].join(".");this[f].$ignore(r)}}},h.prototype.$isValid=function(t){return void 0===this.__index||!this[f]||(!this[f].$__.validationError||!this[f].$__.validationError.errors[this.$__fullPath(t)])},h.prototype.ownerDocument=function(){if(this.$__.ownerDocument)return this.$__.ownerDocument;var t=this[f];if(!t)return this;for(;t[f]||t.$parent;)t=t[f]||t.$parent;return this.$__.ownerDocument=t,this.$__.ownerDocument},h.prototype.$__fullPath=function(t){if(!this.$__.fullPath){var e=this;if(!e[f])return t;for(var r=[];e[f]||e.$parent;)e[f]?r.unshift(e.__parentArray.$path()):r.unshift(e.$basePath),e=e[f]||e.$parent;this.$__.fullPath=r.join("."),this.$__.ownerDocument||(this.$__.ownerDocument=e)}return t?this.$__.fullPath+"."+t:this.$__.fullPath},h.prototype.parent=function(){return this[f]},h.prototype.parentArray=function(){return this.__parentArray},
+/*!
+ * Module exports.
+ */
+t.exports=h},function(t,e,r){(function(e){if(void 0!==e)var n=r(1).Buffer;var o=r(16);function i(t,e){if(!(this instanceof i))return new i(t,e);if(!(null==t||"string"==typeof t||n.isBuffer(t)||t instanceof Uint8Array||Array.isArray(t)))throw new Error("only String, Buffer, Uint8Array or Array accepted");if(this._bsontype="Binary",t instanceof Number?(this.sub_type=t,this.position=0):(this.sub_type=null==e?s:e,this.position=0),null==t||t instanceof Number)void 0!==n?this.buffer=o.allocBuffer(i.BUFFER_SIZE):"undefined"!=typeof Uint8Array?this.buffer=new Uint8Array(new ArrayBuffer(i.BUFFER_SIZE)):this.buffer=new Array(i.BUFFER_SIZE),this.position=0;else{if("string"==typeof t)if(void 0!==n)this.buffer=o.toBuffer(t);else{if("undefined"==typeof Uint8Array&&"[object Array]"!==Object.prototype.toString.call(t))throw new Error("only String, Buffer, Uint8Array or Array accepted");this.buffer=a(t)}else this.buffer=t;this.position=t.length}}i.prototype.put=function(t){if(null!=t.length&&"number"!=typeof t&&1!==t.length)throw new Error("only accepts single character String, Uint8Array or Array");if("number"!=typeof t&&t<0||t>255)throw new Error("only accepts number in a valid unsigned byte range 0-255");var e=null;if(e="string"==typeof t?t.charCodeAt(0):null!=t.length?t[0]:t,this.buffer.length>this.position)this.buffer[this.position++]=e;else if(void 0!==n&&n.isBuffer(this.buffer)){var r=o.allocBuffer(i.BUFFER_SIZE+this.buffer.length);this.buffer.copy(r,0,0,this.buffer.length),this.buffer=r,this.buffer[this.position++]=e}else{r=null,r="[object Uint8Array]"===Object.prototype.toString.call(this.buffer)?new Uint8Array(new ArrayBuffer(i.BUFFER_SIZE+this.buffer.length)):new Array(i.BUFFER_SIZE+this.buffer.length);for(var s=0;s<this.buffer.length;s++)r[s]=this.buffer[s];this.buffer=r,this.buffer[this.position++]=e}},i.prototype.write=function(t,e){if(e="number"==typeof e?e:this.position,this.buffer.length<e+t.length){var r=null;if(void 0!==n&&n.isBuffer(this.buffer))r=o.allocBuffer(this.buffer.length+t.length),this.buffer.copy(r,0,0,this.buffer.length);else if("[object Uint8Array]"===Object.prototype.toString.call(this.buffer)){r=new Uint8Array(new ArrayBuffer(this.buffer.length+t.length));for(var i=0;i<this.position;i++)r[i]=this.buffer[i]}this.buffer=r}if(void 0!==n&&n.isBuffer(t)&&n.isBuffer(this.buffer))t.copy(this.buffer,e,0,t.length),this.position=e+t.length>this.position?e+t.length:this.position;else if(void 0!==n&&"string"==typeof t&&n.isBuffer(this.buffer))this.buffer.write(t,e,"binary"),this.position=e+t.length>this.position?e+t.length:this.position;else if("[object Uint8Array]"===Object.prototype.toString.call(t)||"[object Array]"===Object.prototype.toString.call(t)&&"string"!=typeof t){for(i=0;i<t.length;i++)this.buffer[e++]=t[i];this.position=e>this.position?e:this.position}else if("string"==typeof t){for(i=0;i<t.length;i++)this.buffer[e++]=t.charCodeAt(i);this.position=e>this.position?e:this.position}},i.prototype.read=function(t,e){if(e=e&&e>0?e:this.position,this.buffer.slice)return this.buffer.slice(t,t+e);for(var r="undefined"!=typeof Uint8Array?new Uint8Array(new ArrayBuffer(e)):new Array(e),n=0;n<e;n++)r[n]=this.buffer[t++];return r},i.prototype.value=function(t){if((t=null!=t&&t)&&void 0!==n&&n.isBuffer(this.buffer)&&this.buffer.length===this.position)return this.buffer;if(void 0!==n&&n.isBuffer(this.buffer))return t?this.buffer.slice(0,this.position):this.buffer.toString("binary",0,this.position);if(t){if(null!=this.buffer.slice)return this.buffer.slice(0,this.position);for(var e="[object Uint8Array]"===Object.prototype.toString.call(this.buffer)?new Uint8Array(new ArrayBuffer(this.position)):new Array(this.position),r=0;r<this.position;r++)e[r]=this.buffer[r];return e}return u(this.buffer,0,this.position)},i.prototype.length=function(){return this.position},i.prototype.toJSON=function(){return null!=this.buffer?this.buffer.toString("base64"):""},i.prototype.toString=function(t){return null!=this.buffer?this.buffer.slice(0,this.position).toString(t):""};var s=0,a=function(t){for(var e="undefined"!=typeof Uint8Array?new Uint8Array(new ArrayBuffer(t.length)):new Array(t.length),r=0;r<t.length;r++)e[r]=t.charCodeAt(r);return e},u=function(t,e,r){for(var n="",o=e;o<r;o++)n+=String.fromCharCode(t[o]);return n};i.BUFFER_SIZE=256,i.SUBTYPE_DEFAULT=0,i.SUBTYPE_FUNCTION=1,i.SUBTYPE_BYTE_ARRAY=2,i.SUBTYPE_UUID_OLD=3,i.SUBTYPE_UUID=4,i.SUBTYPE_MD5=5,i.SUBTYPE_USER_DEFINED=128,t.exports=i,t.exports.Binary=i}).call(this,r(11))},function(t,e,r){"use strict";function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i=r(64),s=r(20),a=r(13),u=r(47),c=r(29),l=r(65),f=r(66),p=r(21),h=r(0),y=r(2);
+/*!
+ * Object clone with Mongoose natives support.
+ *
+ * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
+ *
+ * Functions are never cloned.
+ *
+ * @param {Object} obj the object to clone
+ * @param {Object} options
+ * @param {Boolean} isArrayChild true if cloning immediately underneath an array. Special case for minimize.
+ * @return {Object} the cloned object
+ * @api private
+ */
+function d(t,e,r){if(null==t)return t;if(Array.isArray(t))return function(t,e){var r,o=[],i=n(t);try{for(i.s();!(r=i.n()).done;){var s=r.value;o.push(d(s,e,!0))}}catch(t){i.e(t)}finally{i.f()}return o}(t,e);if(c(t))return e&&e._skipSingleNestedGetters&&t.$isSingleNested&&(e=Object.assign({},e,{getters:!1})),y.isPOJO(t)&&null!=t.$__&&null!=t._doc?t._doc:e&&e.json&&"function"==typeof t.toJSON?t.toJSON(e):t.toObject(e);if(t.constructor)switch(l(t.constructor)){case"Object":return m(t,e,r);case"Date":return new t.constructor(+t);case"RegExp":return i(t)}return t instanceof a?new a(t.id):f(t,"Decimal128")?e&&e.flattenDecimals?t.toJSON():s.fromString(t.toString()):!t.constructor&&p(t)?m(t,e,r):t[h.schemaTypeSymbol]?t.clone():e&&e.bson&&"function"==typeof t.toBSON?t:null!=t.valueOf?t.valueOf():m(t,e,r)}
+/*!
+ * ignore
+ */
+function m(t,e,r){var n,o=e&&e.minimize,i={};for(var s in t)if(!u.has(s)){var a=d(t[s],e);o&&void 0===a||(!1===o&&void 0===a?delete i[s]:(n||(n=!0),i[s]=a))}return o&&!r?n&&i:i}t.exports=d},function(t,e,r){"use strict";
+/*!
+ * Returns if `v` is a mongoose object that has a `toObject()` method we can use.
+ *
+ * This is for compatibility with libs like Date.js which do foolish things to Natives.
+ *
+ * @param {any} v
+ * @api private
+ */t.exports=function(t){return null!=t&&(null!=t.$__||t.isMongooseArray||t.isMongooseBuffer||t.$isMongooseMap)}},function(t,e,r){"use strict";var n=["find","findOne","update","updateMany","updateOne","replaceOne","remove","count","distinct","findAndModify","aggregate","findStream","deleteOne","deleteMany"];function o(){}for(var i=0,s=n.length;i<s;++i){var a=n[i];o.prototype[a]=u(a)}function u(t){return function(){throw new Error("collection."+t+" not implemented")}}t.exports=o,o.methods=n},function(t,e,r){"use strict";
+/*!
+ * Module requirements
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=r(14),l=r(4),f=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(u,t);var e,r,n,a=s(u);function u(t){var e,r;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,u),r=t&&"model"===t.constructor.name?t.constructor.modelName+" validation failed":"Validation failed",(e=a.call(this,r)).errors={},e._message=r,t&&(t.errors=e.errors),e}return e=u,(r=[{key:"toString",value:function(){return this.name+": "+p(this)}
+/*!
+ * inspect helper
+ */},{key:"inspect",value:function(){return Object.assign(new Error(this.message),this)}
+/*!
+ * add message
+ */},{key:"addError",value:function(t,e){this.errors[t]=e,this.message=this._message+": "+p(this)}}])&&o(e.prototype,r),n&&o(e,n),u}(c);
+/*!
+ * ignore
+ */
+function p(t){for(var e,r=Object.keys(t.errors||{}),n=r.length,o=[],i=0;i<n;++i)e=r[i],t!==t.errors[e]&&o.push(e+": "+t.errors[e].message);return o.join(", ")}
+/*!
+ * Module exports
+ */l.inspect.custom&&(
+/*!
+ * Avoid Node deprecation warning DEP0079
+ */
+f.prototype[l.inspect.custom]=f.prototype.inspect)
+/*!
+ * Helper for JSON.stringify
+ */,Object.defineProperty(f.prototype,"toJSON",{enumerable:!1,writable:!1,configurable:!0,value:function(){return Object.assign({},this,{message:this.message})}}),Object.defineProperty(f.prototype,"name",{value:"ValidationError"}),t.exports=f},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t,n,o){var i;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r),n=n||"Field `"+t+"` is not in schema and strict mode is set to throw.",(i=e.call(this,n)).isImmutableError=!!o,i.path=t,i}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"StrictModeError"}),t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module requirements.
+ */var n=r(78);
+/*!
+ * @ignore
+ */
+/*!
+ * @ignore
+ */
+function o(t){return n.cast()(t)}e.castToNumber=o,e.castArraysOfNumbers=function t(e,r){e.forEach((function(n,i){Array.isArray(n)?t(n,r):e[i]=o.call(r,n)}))}},function(t,e,r){"use strict";
+/*!
+* returns discriminator by discriminatorMapping.value
+*
+* @param {Model} model
+* @param {string} value
+*/t.exports=function(t,e){var r=null;if(!t.discriminators)return r;for(var n in t.discriminators){var o=t.discriminators[n];if(o.schema&&o.schema.discriminatorMapping&&o.schema.discriminatorMapping.value==e){r=o;break}}return r}},function(t,e,r){"use strict";var n=r(59),o=r(23),i=r(36),s=r(37),a=r(38),u=r(39),c=r(40),l=r(60),f=r(41),p=r(42),h=r(43),y=r(44),d=r(45),m=r(27),_=r(102),v=r(103),g=r(105),b=r(16),w=b.allocBuffer(17825792),O=function(){};O.prototype.serialize=function(t,e){var r="boolean"==typeof(e=e||{}).checkKeys&&e.checkKeys,n="boolean"==typeof e.serializeFunctions&&e.serializeFunctions,o="boolean"!=typeof e.ignoreUndefined||e.ignoreUndefined,i="number"==typeof e.minInternalBufferSize?e.minInternalBufferSize:17825792;w.length<i&&(w=b.allocBuffer(i));var s=v(w,t,r,0,0,n,o,[]),a=b.allocBuffer(s);return w.copy(a,0,0,a.length),a},O.prototype.serializeWithBufferAndIndex=function(t,e,r){var n="boolean"==typeof(r=r||{}).checkKeys&&r.checkKeys,o="boolean"==typeof r.serializeFunctions&&r.serializeFunctions,i="boolean"!=typeof r.ignoreUndefined||r.ignoreUndefined,s="number"==typeof r.index?r.index:0;return v(e,t,n,s||0,0,o,i)-1},O.prototype.deserialize=function(t,e){return _(t,e)},O.prototype.calculateObjectSize=function(t,e){var r="boolean"==typeof(e=e||{}).serializeFunctions&&e.serializeFunctions,n="boolean"!=typeof e.ignoreUndefined||e.ignoreUndefined;return g(t,r,n)},O.prototype.deserializeStream=function(t,e,r,n,o,i){i=null!=i?i:{};for(var s=e,a=0;a<r;a++){var u=t[s]|t[s+1]<<8|t[s+2]<<16|t[s+3]<<24;i.index=s,n[o+a]=this.deserialize(t,i),s+=u}return s},O.BSON_INT32_MAX=2147483647,O.BSON_INT32_MIN=-2147483648,O.BSON_INT64_MAX=Math.pow(2,63)-1,O.BSON_INT64_MIN=-Math.pow(2,63),O.JS_INT_MAX=9007199254740992,O.JS_INT_MIN=-9007199254740992,O.BSON_DATA_NUMBER=1,O.BSON_DATA_STRING=2,O.BSON_DATA_OBJECT=3,O.BSON_DATA_ARRAY=4,O.BSON_DATA_BINARY=5,O.BSON_DATA_OID=7,O.BSON_DATA_BOOLEAN=8,O.BSON_DATA_DATE=9,O.BSON_DATA_NULL=10,O.BSON_DATA_REGEXP=11,O.BSON_DATA_CODE=13,O.BSON_DATA_SYMBOL=14,O.BSON_DATA_CODE_W_SCOPE=15,O.BSON_DATA_INT=16,O.BSON_DATA_TIMESTAMP=17,O.BSON_DATA_LONG=18,O.BSON_DATA_MIN_KEY=255,O.BSON_DATA_MAX_KEY=127,O.BSON_BINARY_SUBTYPE_DEFAULT=0,O.BSON_BINARY_SUBTYPE_FUNCTION=1,O.BSON_BINARY_SUBTYPE_BYTE_ARRAY=2,O.BSON_BINARY_SUBTYPE_UUID=3,O.BSON_BINARY_SUBTYPE_MD5=4,O.BSON_BINARY_SUBTYPE_USER_DEFINED=128,t.exports=O,t.exports.Code=f,t.exports.Map=n,t.exports.Symbol=c,t.exports.BSON=O,t.exports.DBRef=d,t.exports.Binary=m,t.exports.ObjectID=a,t.exports.Long=o,t.exports.Timestamp=s,t.exports.Double=i,t.exports.Int32=l,t.exports.MinKey=h,t.exports.MaxKey=y,t.exports.BSONRegExp=u,t.exports.Decimal128=p},function(t,e){function r(t){if(!(this instanceof r))return new r(t);this._bsontype="Double",this.value=t}r.prototype.valueOf=function(){return this.value},r.prototype.toJSON=function(){return this.value},t.exports=r,t.exports.Double=r},function(t,e){function r(t,e){if(!(this instanceof r))return new r(t,e);this._bsontype="Timestamp",this.low_=0|t,this.high_=0|e}r.prototype.toInt=function(){return this.low_},r.prototype.toNumber=function(){return this.high_*r.TWO_PWR_32_DBL_+this.getLowBitsUnsigned()},r.prototype.toJSON=function(){return this.toString()},r.prototype.toString=function(t){var e=t||10;if(e<2||36<e)throw Error("radix out of range: "+e);if(this.isZero())return"0";if(this.isNegative()){if(this.equals(r.MIN_VALUE)){var n=r.fromNumber(e),o=this.div(n),i=o.multiply(n).subtract(this);return o.toString(e)+i.toInt().toString(e)}return"-"+this.negate().toString(e)}var s=r.fromNumber(Math.pow(e,6));i=this;for(var a="";!i.isZero();){var u=i.div(s),c=i.subtract(u.multiply(s)).toInt().toString(e);if((i=u).isZero())return c+a;for(;c.length<6;)c="0"+c;a=""+c+a}},r.prototype.getHighBits=function(){return this.high_},r.prototype.getLowBits=function(){return this.low_},r.prototype.getLowBitsUnsigned=function(){return this.low_>=0?this.low_:r.TWO_PWR_32_DBL_+this.low_},r.prototype.getNumBitsAbs=function(){if(this.isNegative())return this.equals(r.MIN_VALUE)?64:this.negate().getNumBitsAbs();for(var t=0!==this.high_?this.high_:this.low_,e=31;e>0&&0==(t&1<<e);e--);return 0!==this.high_?e+33:e+1},r.prototype.isZero=function(){return 0===this.high_&&0===this.low_},r.prototype.isNegative=function(){return this.high_<0},r.prototype.isOdd=function(){return 1==(1&this.low_)},r.prototype.equals=function(t){return this.high_===t.high_&&this.low_===t.low_},r.prototype.notEquals=function(t){return this.high_!==t.high_||this.low_!==t.low_},r.prototype.lessThan=function(t){return this.compare(t)<0},r.prototype.lessThanOrEqual=function(t){return this.compare(t)<=0},r.prototype.greaterThan=function(t){return this.compare(t)>0},r.prototype.greaterThanOrEqual=function(t){return this.compare(t)>=0},r.prototype.compare=function(t){if(this.equals(t))return 0;var e=this.isNegative(),r=t.isNegative();return e&&!r?-1:!e&&r?1:this.subtract(t).isNegative()?-1:1},r.prototype.negate=function(){return this.equals(r.MIN_VALUE)?r.MIN_VALUE:this.not().add(r.ONE)},r.prototype.add=function(t){var e=this.high_>>>16,n=65535&this.high_,o=this.low_>>>16,i=65535&this.low_,s=t.high_>>>16,a=65535&t.high_,u=t.low_>>>16,c=0,l=0,f=0,p=0;return f+=(p+=i+(65535&t.low_))>>>16,p&=65535,l+=(f+=o+u)>>>16,f&=65535,c+=(l+=n+a)>>>16,l&=65535,c+=e+s,c&=65535,r.fromBits(f<<16|p,c<<16|l)},r.prototype.subtract=function(t){return this.add(t.negate())},r.prototype.multiply=function(t){if(this.isZero())return r.ZERO;if(t.isZero())return r.ZERO;if(this.equals(r.MIN_VALUE))return t.isOdd()?r.MIN_VALUE:r.ZERO;if(t.equals(r.MIN_VALUE))return this.isOdd()?r.MIN_VALUE:r.ZERO;if(this.isNegative())return t.isNegative()?this.negate().multiply(t.negate()):this.negate().multiply(t).negate();if(t.isNegative())return this.multiply(t.negate()).negate();if(this.lessThan(r.TWO_PWR_24_)&&t.lessThan(r.TWO_PWR_24_))return r.fromNumber(this.toNumber()*t.toNumber());var e=this.high_>>>16,n=65535&this.high_,o=this.low_>>>16,i=65535&this.low_,s=t.high_>>>16,a=65535&t.high_,u=t.low_>>>16,c=65535&t.low_,l=0,f=0,p=0,h=0;return p+=(h+=i*c)>>>16,h&=65535,f+=(p+=o*c)>>>16,p&=65535,f+=(p+=i*u)>>>16,p&=65535,l+=(f+=n*c)>>>16,f&=65535,l+=(f+=o*u)>>>16,f&=65535,l+=(f+=i*a)>>>16,f&=65535,l+=e*c+n*u+o*a+i*s,l&=65535,r.fromBits(p<<16|h,l<<16|f)},r.prototype.div=function(t){if(t.isZero())throw Error("division by zero");if(this.isZero())return r.ZERO;if(this.equals(r.MIN_VALUE)){if(t.equals(r.ONE)||t.equals(r.NEG_ONE))return r.MIN_VALUE;if(t.equals(r.MIN_VALUE))return r.ONE;var e=this.shiftRight(1).div(t).shiftLeft(1);if(e.equals(r.ZERO))return t.isNegative()?r.ONE:r.NEG_ONE;var n=this.subtract(t.multiply(e));return e.add(n.div(t))}if(t.equals(r.MIN_VALUE))return r.ZERO;if(this.isNegative())return t.isNegative()?this.negate().div(t.negate()):this.negate().div(t).negate();if(t.isNegative())return this.div(t.negate()).negate();var o=r.ZERO;for(n=this;n.greaterThanOrEqual(t);){e=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var i=Math.ceil(Math.log(e)/Math.LN2),s=i<=48?1:Math.pow(2,i-48),a=r.fromNumber(e),u=a.multiply(t);u.isNegative()||u.greaterThan(n);)e-=s,u=(a=r.fromNumber(e)).multiply(t);a.isZero()&&(a=r.ONE),o=o.add(a),n=n.subtract(u)}return o},r.prototype.modulo=function(t){return this.subtract(this.div(t).multiply(t))},r.prototype.not=function(){return r.fromBits(~this.low_,~this.high_)},r.prototype.and=function(t){return r.fromBits(this.low_&t.low_,this.high_&t.high_)},r.prototype.or=function(t){return r.fromBits(this.low_|t.low_,this.high_|t.high_)},r.prototype.xor=function(t){return r.fromBits(this.low_^t.low_,this.high_^t.high_)},r.prototype.shiftLeft=function(t){if(0===(t&=63))return this;var e=this.low_;if(t<32){var n=this.high_;return r.fromBits(e<<t,n<<t|e>>>32-t)}return r.fromBits(0,e<<t-32)},r.prototype.shiftRight=function(t){if(0===(t&=63))return this;var e=this.high_;if(t<32){var n=this.low_;return r.fromBits(n>>>t|e<<32-t,e>>t)}return r.fromBits(e>>t-32,e>=0?0:-1)},r.prototype.shiftRightUnsigned=function(t){if(0===(t&=63))return this;var e=this.high_;if(t<32){var n=this.low_;return r.fromBits(n>>>t|e<<32-t,e>>>t)}return 32===t?r.fromBits(e,0):r.fromBits(e>>>t-32,0)},r.fromInt=function(t){if(-128<=t&&t<128){var e=r.INT_CACHE_[t];if(e)return e}var n=new r(0|t,t<0?-1:0);return-128<=t&&t<128&&(r.INT_CACHE_[t]=n),n},r.fromNumber=function(t){return isNaN(t)||!isFinite(t)?r.ZERO:t<=-r.TWO_PWR_63_DBL_?r.MIN_VALUE:t+1>=r.TWO_PWR_63_DBL_?r.MAX_VALUE:t<0?r.fromNumber(-t).negate():new r(t%r.TWO_PWR_32_DBL_|0,t/r.TWO_PWR_32_DBL_|0)},r.fromBits=function(t,e){return new r(t,e)},r.fromString=function(t,e){if(0===t.length)throw Error("number format error: empty string");var n=e||10;if(n<2||36<n)throw Error("radix out of range: "+n);if("-"===t.charAt(0))return r.fromString(t.substring(1),n).negate();if(t.indexOf("-")>=0)throw Error('number format error: interior "-" character: '+t);for(var o=r.fromNumber(Math.pow(n,8)),i=r.ZERO,s=0;s<t.length;s+=8){var a=Math.min(8,t.length-s),u=parseInt(t.substring(s,s+a),n);if(a<8){var c=r.fromNumber(Math.pow(n,a));i=i.multiply(c).add(r.fromNumber(u))}else i=(i=i.multiply(o)).add(r.fromNumber(u))}return i},r.INT_CACHE_={},r.TWO_PWR_16_DBL_=65536,r.TWO_PWR_24_DBL_=1<<24,r.TWO_PWR_32_DBL_=r.TWO_PWR_16_DBL_*r.TWO_PWR_16_DBL_,r.TWO_PWR_31_DBL_=r.TWO_PWR_32_DBL_/2,r.TWO_PWR_48_DBL_=r.TWO_PWR_32_DBL_*r.TWO_PWR_16_DBL_,r.TWO_PWR_64_DBL_=r.TWO_PWR_32_DBL_*r.TWO_PWR_32_DBL_,r.TWO_PWR_63_DBL_=r.TWO_PWR_64_DBL_/2,r.ZERO=r.fromInt(0),r.ONE=r.fromInt(1),r.NEG_ONE=r.fromInt(-1),r.MAX_VALUE=r.fromBits(-1,2147483647),r.MIN_VALUE=r.fromBits(0,-2147483648),r.TWO_PWR_24_=r.fromInt(1<<24),t.exports=r,t.exports.Timestamp=r},function(t,e,r){(function(e,n){var o="inspect",i=r(16),s=parseInt(16777215*Math.random(),10),a=new RegExp("^[0-9a-fA-F]{24}$");try{if(e&&e.from){var u=!0;o=r(4).inspect.custom||"inspect"}}catch(t){u=!1}for(var c=function t(e){if(e instanceof t)return e;if(!(this instanceof t))return new t(e);if(this._bsontype="ObjectID",null==e||"number"==typeof e)return this.id=this.generate(e),void(t.cacheHexString&&(this.__id=this.toString("hex")));var r=t.isValid(e);if(!r&&null!=e)throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");if(r&&"string"==typeof e&&24===e.length&&u)return new t(i.toBuffer(e,"hex"));if(r&&"string"==typeof e&&24===e.length)return t.createFromHexString(e);if(null==e||12!==e.length){if(null!=e&&"function"==typeof e.toHexString)return e;throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters")}this.id=e,t.cacheHexString&&(this.__id=this.toString("hex"))},l=[],f=0;f<256;f++)l[f]=(f<=15?"0":"")+f.toString(16);c.prototype.toHexString=function(){if(c.cacheHexString&&this.__id)return this.__id;var t="";if(!this.id||!this.id.length)throw new Error("invalid ObjectId, ObjectId.id must be either a string or a Buffer, but is ["+JSON.stringify(this.id)+"]");if(this.id instanceof h)return t=y(this.id),c.cacheHexString&&(this.__id=t),t;for(var e=0;e<this.id.length;e++)t+=l[this.id.charCodeAt(e)];return c.cacheHexString&&(this.__id=t),t},c.prototype.get_inc=function(){return c.index=(c.index+1)%16777215},c.prototype.getInc=function(){return this.get_inc()},c.prototype.generate=function(t){"number"!=typeof t&&(t=~~(Date.now()/1e3));var e=(void 0===n||1===n.pid?Math.floor(1e5*Math.random()):n.pid)%65535,r=this.get_inc(),o=i.allocBuffer(12);return o[3]=255&t,o[2]=t>>8&255,o[1]=t>>16&255,o[0]=t>>24&255,o[6]=255&s,o[5]=s>>8&255,o[4]=s>>16&255,o[8]=255&e,o[7]=e>>8&255,o[11]=255&r,o[10]=r>>8&255,o[9]=r>>16&255,o},c.prototype.toString=function(t){return this.id&&this.id.copy?this.id.toString("string"==typeof t?t:"hex"):this.toHexString()},c.prototype[o]=c.prototype.toString,c.prototype.toJSON=function(){return this.toHexString()},c.prototype.equals=function(t){return t instanceof c?this.toString()===t.toString():"string"==typeof t&&c.isValid(t)&&12===t.length&&this.id instanceof h?t===this.id.toString("binary"):"string"==typeof t&&c.isValid(t)&&24===t.length?t.toLowerCase()===this.toHexString():"string"==typeof t&&c.isValid(t)&&12===t.length?t===this.id:!(null==t||!(t instanceof c||t.toHexString))&&t.toHexString()===this.toHexString()},c.prototype.getTimestamp=function(){var t=new Date,e=this.id[3]|this.id[2]<<8|this.id[1]<<16|this.id[0]<<24;return t.setTime(1e3*Math.floor(e)),t},c.index=~~(16777215*Math.random()),c.createPk=function(){return new c},c.createFromTime=function(t){var e=i.toBuffer([0,0,0,0,0,0,0,0,0,0,0,0]);return e[3]=255&t,e[2]=t>>8&255,e[1]=t>>16&255,e[0]=t>>24&255,new c(e)};var p=[];for(f=0;f<10;)p[48+f]=f++;for(;f<16;)p[55+f]=p[87+f]=f++;var h=e,y=function(t){return t.toString("hex")};c.createFromHexString=function(t){if(void 0===t||null!=t&&24!==t.length)throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters");if(u)return new c(i.toBuffer(t,"hex"));for(var e=new h(12),r=0,n=0;n<24;)e[r++]=p[t.charCodeAt(n++)]<<4|p[t.charCodeAt(n++)];return new c(e)},c.isValid=function(t){return null!=t&&("number"==typeof t||("string"==typeof t?12===t.length||24===t.length&&a.test(t):t instanceof c||(t instanceof h||"function"==typeof t.toHexString&&(t.id instanceof h||"string"==typeof t.id)&&(12===t.id.length||24===t.id.length&&a.test(t.id)))))},Object.defineProperty(c.prototype,"generationTime",{enumerable:!0,get:function(){return this.id[3]|this.id[2]<<8|this.id[1]<<16|this.id[0]<<24},set:function(t){this.id[3]=255&t,this.id[2]=t>>8&255,this.id[1]=t>>16&255,this.id[0]=t>>24&255}}),t.exports=c,t.exports.ObjectID=c,t.exports.ObjectId=c}).call(this,r(1).Buffer,r(8))},function(t,e){function r(t,e){if(!(this instanceof r))return new r;this._bsontype="BSONRegExp",this.pattern=t||"",this.options=e||"";for(var n=0;n<this.options.length;n++)if("i"!==this.options[n]&&"m"!==this.options[n]&&"x"!==this.options[n]&&"l"!==this.options[n]&&"s"!==this.options[n]&&"u"!==this.options[n])throw new Error("the regular expression options ["+this.options[n]+"] is not supported")}t.exports=r,t.exports.BSONRegExp=r},function(t,e,r){(function(e){var n=e&&r(4).inspect.custom||"inspect";function o(t){if(!(this instanceof o))return new o(t);this._bsontype="Symbol",this.value=t}o.prototype.valueOf=function(){return this.value},o.prototype.toString=function(){return this.value},o.prototype[n]=function(){return this.value},o.prototype.toJSON=function(){return this.value},t.exports=o,t.exports.Symbol=o}).call(this,r(1).Buffer)},function(t,e){var r=function t(e,r){if(!(this instanceof t))return new t(e,r);this._bsontype="Code",this.code=e,this.scope=r};r.prototype.toJSON=function(){return{scope:this.scope,code:this.code}},t.exports=r,t.exports.Code=r},function(t,e,r){"use strict";var n=r(23),o=/^(\+|-)?(\d+|(\d*\.\d*))?(E|e)?([-+])?(\d+)?$/,i=/^(\+|-)?(Infinity|inf)$/i,s=/^(\+|-)?NaN$/i,a=6176,u=[124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].reverse(),c=[248,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].reverse(),l=[120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0].reverse(),f=/^([-+])?(\d+)?$/,p=r(16),h=function(t){return!isNaN(parseInt(t,10))},y=function(t){var e=n.fromNumber(1e9),r=n.fromNumber(0),o=0;if(!(t.parts[0]||t.parts[1]||t.parts[2]||t.parts[3]))return{quotient:t,rem:r};for(o=0;o<=3;o++)r=(r=r.shiftLeft(32)).add(new n(t.parts[o],0)),t.parts[o]=r.div(e).low_,r=r.modulo(e);return{quotient:t,rem:r}},d=function(t){this._bsontype="Decimal128",this.bytes=t};d.fromString=function(t){var e,r=!1,y=!1,m=!1,_=0,v=0,g=0,b=0,w=0,O=[0],S=0,A=0,j=0,E=0,$=0,x=0,P=[0,0],N=[0,0],T=0;if((t=t.trim()).length>=7e3)throw new Error(t+" not a valid Decimal128 string");var k=t.match(o),C=t.match(i),D=t.match(s);if(!k&&!C&&!D||0===t.length)throw new Error(t+" not a valid Decimal128 string");if(k&&k[4]&&void 0===k[2])throw new Error(t+" not a valid Decimal128 string");if("+"!==t[T]&&"-"!==t[T]||(r="-"===t[T++]),!h(t[T])&&"."!==t[T]){if("i"===t[T]||"I"===t[T])return new d(p.toBuffer(r?c:l));if("N"===t[T])return new d(p.toBuffer(u))}for(;h(t[T])||"."===t[T];)if("."!==t[T])S<34&&("0"!==t[T]||m)&&(m||(w=v),m=!0,O[A++]=parseInt(t[T],10),S+=1),m&&(g+=1),y&&(b+=1),v+=1,T+=1;else{if(y)return new d(p.toBuffer(u));y=!0,T+=1}if(y&&!v)throw new Error(t+" not a valid Decimal128 string");if("e"===t[T]||"E"===t[T]){var R=t.substr(++T).match(f);if(!R||!R[2])return new d(p.toBuffer(u));$=parseInt(R[0],10),T+=R[0].length}if(t[T])return new d(p.toBuffer(u));if(j=0,S){if(E=S-1,_=g,0!==$&&1!==_)for(;"0"===t[w+_-1];)_-=1}else j=0,E=0,O[0]=0,g=1,S=1,_=0;for($<=b&&b-$>16384?$=-6176:$-=b;$>6111;){if((E+=1)-j>34){var B=O.join("");if(B.match(/^0+$/)){$=6111;break}return new d(p.toBuffer(r?c:l))}$-=1}for(;$<-6176||S<g;){if(0===E){$=-6176,_=0;break}if(S<g?g-=1:E-=1,!($<6111)){if((B=O.join("")).match(/^0+$/)){$=6111;break}return new d(p.toBuffer(r?c:l))}$+=1}if(E-j+1<_&&"0"!==t[_]){var M=v;y&&-6176===$&&(w+=1,M+=1);var I=parseInt(t[w+E+1],10),F=0;if(I>=5&&(F=1,5===I))for(F=O[E]%2==1,x=w+E+2;x<M;x++)if(parseInt(t[x],10)){F=1;break}if(F)for(var L=E;L>=0&&++O[L]>9;L--)if(O[L]=0,0===L){if(!($<6111))return new d(p.toBuffer(r?c:l));$+=1,O[L]=1}}if(P=n.fromNumber(0),N=n.fromNumber(0),0===_)P=n.fromNumber(0),N=n.fromNumber(0);else if(E-j<17)for(L=j,N=n.fromNumber(O[L++]),P=new n(0,0);L<=E;L++)N=(N=N.multiply(n.fromNumber(10))).add(n.fromNumber(O[L]));else{for(L=j,P=n.fromNumber(O[L++]);L<=E-17;L++)P=(P=P.multiply(n.fromNumber(10))).add(n.fromNumber(O[L]));for(N=n.fromNumber(O[L++]);L<=E;L++)N=(N=N.multiply(n.fromNumber(10))).add(n.fromNumber(O[L]))}var U,V,q,W,H=function(t,e){if(!t&&!e)return{high:n.fromNumber(0),low:n.fromNumber(0)};var r=t.shiftRightUnsigned(32),o=new n(t.getLowBits(),0),i=e.shiftRightUnsigned(32),s=new n(e.getLowBits(),0),a=r.multiply(i),u=r.multiply(s),c=o.multiply(i),l=o.multiply(s);return a=a.add(u.shiftRightUnsigned(32)),u=new n(u.getLowBits(),0).add(c).add(l.shiftRightUnsigned(32)),{high:a=a.add(u.shiftRightUnsigned(32)),low:l=u.shiftLeft(32).add(new n(l.getLowBits(),0))}}(P,n.fromString("100000000000000000"));H.low=H.low.add(N),U=H.low,V=N,q=U.high_>>>0,W=V.high_>>>0,(q<W||q===W&&U.low_>>>0<V.low_>>>0)&&(H.high=H.high.add(n.fromNumber(1))),e=$+a;var Y={low:n.fromNumber(0),high:n.fromNumber(0)};H.high.shiftRightUnsigned(49).and(n.fromNumber(1)).equals(n.fromNumber)?(Y.high=Y.high.or(n.fromNumber(3).shiftLeft(61)),Y.high=Y.high.or(n.fromNumber(e).and(n.fromNumber(16383).shiftLeft(47))),Y.high=Y.high.or(H.high.and(n.fromNumber(0x7fffffffffff)))):(Y.high=Y.high.or(n.fromNumber(16383&e).shiftLeft(49)),Y.high=Y.high.or(H.high.and(n.fromNumber(562949953421311)))),Y.low=H.low,r&&(Y.high=Y.high.or(n.fromString("9223372036854775808")));var K=p.allocBuffer(16);return T=0,K[T++]=255&Y.low.low_,K[T++]=Y.low.low_>>8&255,K[T++]=Y.low.low_>>16&255,K[T++]=Y.low.low_>>24&255,K[T++]=255&Y.low.high_,K[T++]=Y.low.high_>>8&255,K[T++]=Y.low.high_>>16&255,K[T++]=Y.low.high_>>24&255,K[T++]=255&Y.high.low_,K[T++]=Y.high.low_>>8&255,K[T++]=Y.high.low_>>16&255,K[T++]=Y.high.low_>>24&255,K[T++]=255&Y.high.high_,K[T++]=Y.high.high_>>8&255,K[T++]=Y.high.high_>>16&255,K[T++]=Y.high.high_>>24&255,new d(K)};a=6176,d.prototype.toString=function(){for(var t,e,r,o,i,s,u=0,c=new Array(36),l=0;l<c.length;l++)c[l]=0;var f,p,h,d,m,_=0,v=!1,g={parts:new Array(4)},b=[];_=0;var w=this.bytes;if(o=w[_++]|w[_++]<<8|w[_++]<<16|w[_++]<<24,r=w[_++]|w[_++]<<8|w[_++]<<16|w[_++]<<24,e=w[_++]|w[_++]<<8|w[_++]<<16|w[_++]<<24,t=w[_++]|w[_++]<<8|w[_++]<<16|w[_++]<<24,_=0,{low:new n(o,r),high:new n(e,t)}.high.lessThan(n.ZERO)&&b.push("-"),(i=t>>26&31)>>3==3){if(30===i)return b.join("")+"Infinity";if(31===i)return"NaN";s=t>>15&16383,h=8+(t>>14&1)}else h=t>>14&7,s=t>>17&16383;if(f=s-a,g.parts[0]=(16383&t)+((15&h)<<14),g.parts[1]=e,g.parts[2]=r,g.parts[3]=o,0===g.parts[0]&&0===g.parts[1]&&0===g.parts[2]&&0===g.parts[3])v=!0;else for(m=3;m>=0;m--){var O=0,S=y(g);if(g=S.quotient,O=S.rem.low_)for(d=8;d>=0;d--)c[9*m+d]=O%10,O=Math.floor(O/10)}if(v)u=1,c[_]=0;else for(u=36,l=0;!c[_];)l++,u-=1,_+=1;if((p=u-1+f)>=34||p<=-7||f>0){for(b.push(c[_++]),(u-=1)&&b.push("."),l=0;l<u;l++)b.push(c[_++]);b.push("E"),p>0?b.push("+"+p):b.push(p)}else if(f>=0)for(l=0;l<u;l++)b.push(c[_++]);else{var A=u+f;if(A>0)for(l=0;l<A;l++)b.push(c[_++]);else b.push("0");for(b.push(".");A++<0;)b.push("0");for(l=0;l<u-Math.max(A-1,0);l++)b.push(c[_++])}return b.join("")},d.prototype.toJSON=function(){return{$numberDecimal:this.toString()}},t.exports=d,t.exports.Decimal128=d},function(t,e){function r(){if(!(this instanceof r))return new r;this._bsontype="MinKey"}t.exports=r,t.exports.MinKey=r},function(t,e){function r(){if(!(this instanceof r))return new r;this._bsontype="MaxKey"}t.exports=r,t.exports.MaxKey=r},function(t,e){function r(t,e,n){if(!(this instanceof r))return new r(t,e,n);this._bsontype="DBRef",this.namespace=t,this.oid=e,this.db=n}r.prototype.toJSON=function(){return{$ref:this.namespace,$id:this.oid,$db:null==this.db?"":this.db}},t.exports=r,t.exports.DBRef=r},function(t,e,r){t.exports=r(112)},function(t,e,r){"use strict";t.exports=new Set(["__proto__","constructor","prototype"])},function(t,e,r){"use strict";var n=r(49);
+/*!
+ * ignore
+ */t.exports=function(t){var e=null!=this?this.path:null;return n(t,e)}},function(t,e,r){"use strict";var n=r(12);
+/*!
+ * Given a value, cast it to a boolean, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {Boolean|null|undefined}
+ * @throws {CastError} if `value` is not one of the allowed values
+ * @api private
+ */t.exports=function(e,r){if(t.exports.convertToTrue.has(e))return!0;if(t.exports.convertToFalse.has(e))return!1;if(null==e)return e;throw new n("boolean",e,r)},t.exports.convertToTrue=new Set([!0,"true",1,"1","yes"]),t.exports.convertToFalse=new Set([!1,"false",0,"0","no"])},function(t,e,r){"use strict";(function(e){
+/*!
+ * Centralize this so we can more easily work around issues with people
+ * stubbing out `process.nextTick()` in tests using sinon:
+ * https://github.com/sinonjs/lolex#automatically-incrementing-mocked-time
+ * See gh-6074
+ */
+t.exports=function(t){return e.nextTick(t)}}).call(this,r(8))},function(t,e,r){"use strict";e.schemaMixedSymbol=Symbol.for("mongoose:schema_mixed"),e.builtInMiddleware=Symbol.for("mongoose:built-in-middleware")},function(t,e,r){"use strict";(function(n){
+/*!
+ * Module dependencies.
+ */
+function o(t,e,r){return e in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function s(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return a(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return a(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return s=t.done,t},e:function(t){u=!0,i=t},f:function(){try{s||null==r.return||r.return()}finally{if(u)throw i}}}}function a(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var u,c=r(19).EventEmitter,l=r(136),f=r(14),p=r(7),h=r(9),y=r(137),d=r(53),m=r(74),_=r(0).arrayParentSymbol,v=r(3),g=r(138),b=r(139),w=r(46),O=r(15).get().ReadPreference,S=r(140),A=r(4),j=r(2),E=r(144),$=r(145).middlewareFunctions,x=r(76).middlewareFunctions,P=$.concat(x).reduce((function(t,e){return t.add(e)}),new Set),N=0;function T(t,e){if(!(this instanceof T))return new T(t,e);if(this.obj=t,this.paths={},this.aliases={},this.subpaths={},this.virtuals={},this.singleNestedPaths={},this.nested={},this.inherits={},this.callQueue=[],this._indexes=[],this.methods={},this.methodOptions={},this.statics={},this.tree={},this.query={},this.childSchemas=[],this.plugins=[],this.$id=++N,this.s={hooks:new l},this.options=this.defaultOptions(e),Array.isArray(t)){var r,n=s(t);try{for(n.s();!(r=n.n()).done;){var o=r.value;this.add(o)}}catch(t){n.e(t)}finally{n.f()}}else t&&this.add(t);var i=t&&t._id&&j.isObject(t._id);!this.paths._id&&!this.options.noId&&this.options._id&&!i&&m(this),this.setupTimestamp(this.options.timestamps)}
+/*!
+ * Create virtual properties with alias field
+ */
+/*!
+ * Inherit from EventEmitter.
+ */
+T.prototype=Object.create(c.prototype),T.prototype.constructor=T,T.prototype.instanceOfSchema=!0,
+/*!
+ * ignore
+ */
+Object.defineProperty(T.prototype,"$schemaType",{configurable:!1,enumerable:!1,writable:!0}),Object.defineProperty(T.prototype,"childSchemas",{configurable:!1,enumerable:!0,writable:!0}),T.prototype.obj,T.prototype.paths,T.prototype.tree,T.prototype.clone=function(){var t=this,e=new(null==this.base?T:this.base.Schema)({},this._userProvidedOptions);return e.base=this.base,e.obj=this.obj,e.options=j.clone(this.options),e.callQueue=this.callQueue.map((function(t){return t})),e.methods=j.clone(this.methods),e.methodOptions=j.clone(this.methodOptions),e.statics=j.clone(this.statics),e.query=j.clone(this.query),e.plugins=Array.prototype.slice.call(this.plugins),e._indexes=j.clone(this._indexes),e.s.hooks=this.s.hooks.clone(),e.tree=j.clone(this.tree),e.paths=j.clone(this.paths),e.nested=j.clone(this.nested),e.subpaths=j.clone(this.subpaths),e.singleNestedPaths=j.clone(this.singleNestedPaths),e.childSchemas=
+/*!
+ * ignore
+ */
+function(t){for(var e=[],r=0,n=Object.keys(t.paths);r<n.length;r++){var o=n[r],i=t.paths[o];(i.$isMongooseDocumentArray||i.$isSingleNested)&&e.push({schema:i.schema,model:i.caster})}return e}
+/*!
+ * ignore
+ */(e),e.virtuals=j.clone(this.virtuals),e.$globalPluginsApplied=this.$globalPluginsApplied,e.$isRootDiscriminator=this.$isRootDiscriminator,e.$implicitlyCreated=this.$implicitlyCreated,null!=this.discriminatorMapping&&(e.discriminatorMapping=Object.assign({},this.discriminatorMapping)),null!=this.discriminators&&(e.discriminators=Object.assign({},this.discriminators)),e.aliases=Object.assign({},this.aliases),e.on("init",(function(e){return t.emit("init",e)})),e},T.prototype.pick=function(t,e){var r=new T({},e||this.options);if(!Array.isArray(t))throw new f('Schema#pick() only accepts an array argument, got "'+i(t)+'"');var n,a=s(t);try{for(a.s();!(n=a.n()).done;){var u=n.value;if(this.nested[u])r.add(o({},u,v(this.tree,u)));else{var c=this.path(u);if(null==c)throw new f("Path `"+u+"` is not in the schema");r.add(o({},u,c))}}}catch(t){a.e(t)}finally{a.f()}return r},T.prototype.defaultOptions=function(t){t&&!1===t.safe&&(t.safe={w:0}),t&&t.safe&&0===t.safe.w&&(t.versionKey=!1),this._userProvidedOptions=null==t?{}:j.clone(t);var e=v(this,"base.options",{});if((t=j.options({strict:!("strict"in e)||e.strict,strictQuery:"strictQuery"in e&&e.strictQuery,bufferCommands:!0,capped:!1,versionKey:"__v",optimisticConcurrency:!1,discriminatorKey:"__t",minimize:!0,autoIndex:null,shardKey:null,read:null,validateBeforeSave:!0,noId:!1,_id:!0,noVirtualId:!1,id:!0,typeKey:"type",typePojoToMixed:!("typePojoToMixed"in e)||e.typePojoToMixed},j.clone(t))).read&&(t.read=O(t.read)),t.optimisticConcurrency&&!t.versionKey)throw new f("Must set `versionKey` if using `optimisticConcurrency`");return t},T.prototype.add=function(t,e){if(t instanceof T||null!=t&&t.instanceOfSchema)return b(this,t),this;!1===t._id&&null==e&&(this.options._id=!1),e=e||"";for(var r=0,n=Object.keys(t);r<n.length;r++){var i=n[r],a=e+i;if(null==t[i])throw new TypeError("Invalid value for schema path `"+a+'`, got value "'+t[i]+'"');if("_id"!==i||!1!==t[i])if(t[i]instanceof d||"VirtualType"===v(t[i],"constructor.name",null))this.virtual(t[i]);else{if(Array.isArray(t[i])&&1===t[i].length&&null==t[i][0])throw new TypeError("Invalid value for schema Array path `"+a+'`, got value "'+t[i][0]+'"');if(j.isPOJO(t[i])||t[i]instanceof h)if(Object.keys(t[i]).length<1)e&&(this.nested[e.substr(0,e.length-1)]=!0),this.path(a,t[i]);else if(!t[i][this.options.typeKey]||"type"===this.options.typeKey&&t[i].type.type)this.nested[a]=!0,this.add(t[i],a+".");else if(!this.options.typePojoToMixed&&j.isPOJO(t[i][this.options.typeKey])){e&&(this.nested[e.substr(0,e.length-1)]=!0);var u=new T(t[i][this.options.typeKey],{typePojoToMixed:!1}),c=Object.assign({},t[i],o({},this.options.typeKey,u));this.path(e+i,c)}else e&&(this.nested[e.substr(0,e.length-1)]=!0),this.path(e+i,t[i]);else e&&(this.nested[e.substr(0,e.length-1)]=!0),this.path(e+i,t[i])}}return function(t,e){var r,n=s(e=e||Object.keys(t.paths));try{for(n.s();!(r=n.n()).done;){var o=r.value,i=v(t.paths[o],"options");if(null!=i){var a=t.paths[o].path,u=i.alias;if(u){if("string"!=typeof u)throw new Error("Invalid value for alias option on "+a+", got "+u);t.aliases[u]=a,t.virtual(u).get(function(t){return function(){return"function"==typeof this.get?this.get(t):this[t]}}(a)).set(function(t){return function(e){return this.$set(t,e)}}(a))}}}}catch(t){n.e(t)}finally{n.f()}}(this,Object.keys(t).map((function(t){return e?e+t:t}))),this},T.reserved=Object.create(null),T.prototype.reserved=T.reserved;var k=T.reserved;k.prototype=k.emit=k.listeners=k.on=k.removeListener=k.collection=k.errors=k.get=k.init=k.isModified=k.isNew=k.populated=k.remove=k.save=k.schema=k.toObject=k.validate=1;
+/*!
+ * Document keys to print warnings for
+ */
+var C={};
+/*!
+ * ignore
+ */
+function D(t){return/\.\d+/.test(t)?t.replace(/\.\d+\./g,".$.").replace(/\.\d+$/,".$"):t}
+/*!
+ * ignore
+ */function R(t,e){for(var r=0,n=Object.keys(t.paths);r<n.length;r++){var o=n[r];if(o.includes(".$*"))if(new RegExp("^"+o.replace(/\.\$\*/g,"\\.[^.]+")+"$").test(e))return t.paths[o]}return null}
+/*!
+ * ignore. Deprecated re: #6405
+ */
+function B(t,e){var r=e.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);if(r.length<2)return t.paths.hasOwnProperty(r[0])?t.paths[r[0]]:"adhocOrUndefined";var n=t.path(r[0]),o=!1;if(!n)return"adhocOrUndefined";for(var i=r.length-1,s=1;s<r.length;++s){o=!1;var a=r[s];if(s===i&&n&&!/\D/.test(a)){n=n.$isMongooseDocumentArray?n.$embeddedSchemaType:n instanceof u.Array?n.caster:void 0;break}if(/\D/.test(a)){if(!n||!n.schema){n=void 0;break}o="nested"===n.schema.pathType(a),n=n.schema.path(a)}else n instanceof u.Array&&s!==i&&(n=n.caster)}return t.subpaths[e]=n,n?"real":o?"nested":"adhocOrUndefined"}
+/*!
+ * ignore
+ */C.increment="`increment` should not be used as a schema path name unless you have disabled versioning.",T.prototype.path=function(t,e){var r=D(t);if(void 0===e){var n=function(t,e,r){if(t.paths.hasOwnProperty(e))return t.paths[e];if(t.subpaths.hasOwnProperty(r))return t.subpaths[r];if(t.singleNestedPaths.hasOwnProperty(r)&&"object"===i(t.singleNestedPaths[r]))return t.singleNestedPaths[r];return null}(this,t,r);if(null!=n)return n;var o=R(this,t);return null!=o?o:null!=(n=this.hasMixedParent(r))?n:/\.\d+\.?.*$/.test(t)?function(t,e){return B(t,e),t.subpaths[e]}(this,t):void 0}var a=t.split(".")[0];if(k[a])throw new Error("`"+a+"` may not be used as a schema pathname");C[t]&&console.log("WARN: "+C[t]),"object"===i(e)&&j.hasUserDefinedProperty(e,"ref")&&E(e.ref,t);var u,c=t.split(/\./),l=c.pop(),f=this.tree,h="",y=s(c);try{for(y.s();!(u=y.n()).done;){var d=u.value;if(h=h+=(h.length>0?".":"")+d,f[d]||(this.nested[h]=!0,f[d]={}),"object"!==i(f[d])){var m="Cannot set nested path `"+t+"`. Parent path `"+h+"` already set to type "+f[d].name+".";throw new Error(m)}f=f[d]}}catch(t){y.e(t)}finally{y.f()}f[l]=j.clone(e),this.paths[t]=this.interpretAsType(t,e,this.options);var _=this.paths[t];if(_.$isSchemaMap){var v=t+".$*",g={type:{}};if(j.hasUserDefinedProperty(e,"of"))g=j.isPOJO(e.of)&&Object.keys(e.of).length>0&&!j.hasUserDefinedProperty(e.of,this.options.typeKey)?new T(e.of):e.of;this.paths[v]=this.interpretAsType(v,g,this.options),_.$__schemaType=this.paths[v]}if(_.$isSingleNested){for(var b in _.schema.paths)this.singleNestedPaths[t+"."+b]=_.schema.paths[b];for(var w in _.schema.singleNestedPaths)this.singleNestedPaths[t+"."+w]=_.schema.singleNestedPaths[w];for(var O in _.schema.subpaths)this.singleNestedPaths[t+"."+O]=_.schema.subpaths[O];for(var S in _.schema.nested)this.singleNestedPaths[t+"."+S]="nested";Object.defineProperty(_.schema,"base",{configurable:!0,enumerable:!1,writable:!1,value:this.base}),_.caster.base=this.base,this.childSchemas.push({schema:_.schema,model:_.caster})}else _.$isMongooseDocumentArray&&(Object.defineProperty(_.schema,"base",{configurable:!0,enumerable:!1,writable:!1,value:this.base}),_.casterConstructor.base=this.base,this.childSchemas.push({schema:_.schema,model:_.casterConstructor}));if(_.$isMongooseArray&&_.caster instanceof p){for(var A=t,$=_,x=[];$.$isMongooseArray;)A+=".$",$.$isMongooseDocumentArray?($.$embeddedSchemaType._arrayPath=A,$=$.$embeddedSchemaType.clone()):($.caster._arrayPath=A,$=$.caster.clone()),$.path=A,x.push($);for(var P=0,N=x;P<N.length;P++){var M=N[P];this.subpaths[M.path]=M}}if(_.$isMongooseDocumentArray){for(var I=0,F=Object.keys(_.schema.paths);I<F.length;I++){var L=F[I];this.subpaths[t+"."+L]=_.schema.paths[L],_.schema.paths[L].$isUnderneathDocArray=!0}for(var U=0,V=Object.keys(_.schema.subpaths);U<V.length;U++){var q=V[U];this.subpaths[t+"."+q]=_.schema.subpaths[q],_.schema.subpaths[q].$isUnderneathDocArray=!0}for(var W=0,H=Object.keys(_.schema.singleNestedPaths);W<H.length;W++){var Y=H[W];"object"===i(_.schema.singleNestedPaths[r])&&(this.subpaths[t+"."+Y]=_.schema.singleNestedPaths[Y],_.schema.singleNestedPaths[Y].$isUnderneathDocArray=!0)}}return this},Object.defineProperty(T.prototype,"base",{configurable:!0,enumerable:!1,writable:!0,value:null}),T.prototype.interpretAsType=function(t,e,r){if(e instanceof p){var o=e.clone();return o.path=t,o}var s=null!=this.base?this.base.Schema.Types:T.Types;if(!(j.isPOJO(e)||e instanceof h)&&"Object"!==j.getFunctionName(e.constructor)){var a=e;(e={})[r.typeKey]=a}var u,c=!e[r.typeKey]||"type"===r.typeKey&&e.type.type?{}:e[r.typeKey];if(j.isPOJO(c)||"mixed"===c)return new s.Mixed(t,e);if(Array.isArray(c)||c===Array||"array"===c||c===s.Array){var l=c===Array||"array"===c?e.cast:c[0];if(l&&l.instanceOfSchema)return new s.DocumentArray(t,l,e);if(l&&l[r.typeKey]&&l[r.typeKey].instanceOfSchema)return new s.DocumentArray(t,l[r.typeKey],e,l);if(Array.isArray(l))return new s.Array(t,this.interpretAsType(t,l,r),e);if("string"==typeof l)l=s[l.charAt(0).toUpperCase()+l.substring(1)];else if(l&&(!l[r.typeKey]||"type"===r.typeKey&&l.type.type)&&j.isPOJO(l)){if(Object.keys(l).length){var f={minimize:r.minimize};r.typeKey&&(f.typeKey=r.typeKey),r.hasOwnProperty("strict")&&(f.strict=r.strict),r.hasOwnProperty("typePojoToMixed")&&(f.typePojoToMixed=r.typePojoToMixed),this._userProvidedOptions.hasOwnProperty("_id")?f._id=this._userProvidedOptions._id:T.Types.DocumentArray.defaultOptions&&null!=T.Types.DocumentArray.defaultOptions._id&&(f._id=T.Types.DocumentArray.defaultOptions._id);var y=new T(l,f);return y.$implicitlyCreated=!0,new s.DocumentArray(t,y,e)}return new s.Array(t,s.Mixed,e)}if(l&&(u="string"==typeof(c=!l[r.typeKey]||"type"===r.typeKey&&l.type.type?l:l[r.typeKey])?c:c.schemaName||j.getFunctionName(c),!s.hasOwnProperty(u)))throw new TypeError("Invalid schema configuration: "+"`".concat(u,"` is not a valid type within the array `").concat(t,"`.")+"See http://bit.ly/mongoose-schematypes for a list of valid schema types.");return new s.Array(t,l||s.Mixed,e,r)}if(c&&c.instanceOfSchema)return new s.Embedded(c,t,e);if((u=n.isBuffer(c)?"Buffer":"function"==typeof c||"object"===i(c)?c.schemaName||j.getFunctionName(c):null==c?""+c:c.toString())&&(u=u.charAt(0).toUpperCase()+u.substring(1)),"ObjectID"===u&&(u="ObjectId"),null==s[u])throw new TypeError("Invalid schema configuration: `".concat(u,"` is not ")+"a valid type at path `".concat(t,"`. See ")+"http://bit.ly/mongoose-schematypes for a list of valid schema types.");return new s[u](t,e)},T.prototype.eachPath=function(t){for(var e=Object.keys(this.paths),r=e.length,n=0;n<r;++n)t(e[n],this.paths[e[n]]);return this},T.prototype.requiredPaths=function(t){if(this._requiredpaths&&!t)return this._requiredpaths;for(var e=Object.keys(this.paths),r=e.length,n=[];r--;){var o=e[r];this.paths[o].isRequired&&n.push(o)}return this._requiredpaths=n,this._requiredpaths},T.prototype.indexedPaths=function(){return this._indexedpaths||(this._indexedpaths=this.indexes()),this._indexedpaths},T.prototype.pathType=function(t){var e=D(t);if(this.paths.hasOwnProperty(t))return"real";if(this.virtuals.hasOwnProperty(t))return"virtual";if(this.nested.hasOwnProperty(t))return"nested";if(this.subpaths.hasOwnProperty(e)||this.subpaths.hasOwnProperty(t))return"real";var r=this.singleNestedPaths.hasOwnProperty(e)||this.singleNestedPaths.hasOwnProperty(t);return r?"nested"===r?"nested":"real":null!=R(this,t)?"real":/\.\d+\.|\.\d+$/.test(t)?B(this,t):"adhocOrUndefined"},T.prototype.hasMixedParent=function(t){var e=t.split(/\./g);t="";for(var r=0;r<e.length;++r)if((t=r>0?t+"."+e[r]:e[r])in this.paths&&this.paths[t]instanceof u.Mixed)return this.paths[t];return null},T.prototype.setupTimestamp=function(t){return S(this,t)},T.prototype.queue=function(t,e){return this.callQueue.push([t,e]),this},T.prototype.pre=function(t){if(t instanceof RegExp){var e,r=Array.prototype.slice.call(arguments,1),n=s(P);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.test(o)&&this.pre.apply(this,[o].concat(r))}}catch(t){n.e(t)}finally{n.f()}return this}if(Array.isArray(t)){var i,a=Array.prototype.slice.call(arguments,1),u=s(t);try{for(u.s();!(i=u.n()).done;){var c=i.value;this.pre.apply(this,[c].concat(a))}}catch(t){u.e(t)}finally{u.f()}return this}return this.s.hooks.pre.apply(this.s.hooks,arguments),this},T.prototype.post=function(t){if(t instanceof RegExp){var e,r=Array.prototype.slice.call(arguments,1),n=s(P);try{for(n.s();!(e=n.n()).done;){var o=e.value;t.test(o)&&this.post.apply(this,[o].concat(r))}}catch(t){n.e(t)}finally{n.f()}return this}if(Array.isArray(t)){var i,a=Array.prototype.slice.call(arguments,1),u=s(t);try{for(u.s();!(i=u.n()).done;){var c=i.value;this.post.apply(this,[c].concat(a))}}catch(t){u.e(t)}finally{u.f()}return this}return this.s.hooks.post.apply(this.s.hooks,arguments),this},T.prototype.plugin=function(t,e){if("function"!=typeof t)throw new Error('First param to `schema.plugin()` must be a function, got "'+i(t)+'"');if(e&&e.deduplicate){var r,n=s(this.plugins);try{for(n.s();!(r=n.n()).done;){if(r.value.fn===t)return this}}catch(t){n.e(t)}finally{n.f()}}return this.plugins.push({fn:t,opts:e}),t(this,e),this},T.prototype.method=function(t,e,r){if("string"!=typeof t)for(var n in t)this.methods[n]=t[n],this.methodOptions[n]=j.clone(r);else this.methods[t]=e,this.methodOptions[t]=j.clone(r);return this},T.prototype.static=function(t,e){if("string"!=typeof t)for(var r in t)this.statics[r]=t[r];else this.statics[t]=e;return this},T.prototype.index=function(t,e){return t||(t={}),e||(e={}),e.expires&&j.expires(e),this._indexes.push([t,e]),this},T.prototype.set=function(t,e,r){if(1===arguments.length)return this.options[t];switch(t){case"read":this.options[t]=O(e,r),this._userProvidedOptions[t]=this.options[t];break;case"safe":M(this.options,e),this._userProvidedOptions[t]=this.options[t];break;case"timestamps":this.setupTimestamp(e),this.options[t]=e,this._userProvidedOptions[t]=this.options[t];break;case"_id":this.options[t]=e,this._userProvidedOptions[t]=this.options[t],e&&!this.paths._id?m(this):!e&&null!=this.paths._id&&this.paths._id.auto&&this.remove("_id");break;default:this.options[t]=e,this._userProvidedOptions[t]=this.options[t]}return this};
+/*!
+ * ignore
+ */
+var M=A.deprecate((function(t,e){t.safe=!1===e?{w:0}:e}),"Mongoose: The `safe` option for schemas is deprecated. Use the `writeConcern` option instead: http://bit.ly/mongoose-write-concern");T.prototype.get=function(t){return this.options[t]};var I="2d 2dsphere hashed text".split(" ");
+/*!
+ * ignore
+ */
+function F(t,e){var r,n=e.split("."),o=n.pop(),i=t.tree,a=s(n);try{for(a.s();!(r=a.n()).done;){i=i[r.value]}}catch(t){a.e(t)}finally{a.f()}delete i[o]}
+/*!
+ * ignore
+ */
+function L(t){return t.startsWith("$[")&&t.endsWith("]")}
+/*!
+ * Module exports.
+ */Object.defineProperty(T,"indexTypes",{get:function(){return I},set:function(){throw new Error("Cannot overwrite Schema.indexTypes")}}),T.prototype.indexes=function(){return g(this)},T.prototype.virtual=function(t,e){var r=this;if(t instanceof d||null!=t&&"VirtualType"===t.constructor.name)return this.virtual(t.path,t.options);if(e=new y(e),j.hasUserDefinedProperty(e,["ref","refPath"])){if(null==e.localField)throw new Error("Reference virtuals require `localField` option");if(null==e.foreignField)throw new Error("Reference virtuals require `foreignField` option");this.pre("init",(function(r){if(w.has(t,r)){var n=w.get(t,r);this.$$populatedVirtuals||(this.$$populatedVirtuals={}),e.justOne||e.count?this.$$populatedVirtuals[t]=Array.isArray(n)?n[0]:n:this.$$populatedVirtuals[t]=Array.isArray(n)?n:null==n?[]:[n],w.unset(t,r)}}));var n=this.virtual(t);return n.options=e,n.get((function(e){return this.$$populatedVirtuals&&this.$$populatedVirtuals.hasOwnProperty(t)?this.$$populatedVirtuals[t]:null!=e?e:void 0})).set((function(r){this.$$populatedVirtuals||(this.$$populatedVirtuals={}),e.justOne||e.count?(this.$$populatedVirtuals[t]=Array.isArray(r)?r[0]:r,"object"!==i(this.$$populatedVirtuals[t])&&(this.$$populatedVirtuals[t]=e.count?r:null)):(this.$$populatedVirtuals[t]=Array.isArray(r)?r:null==r?[]:[r],this.$$populatedVirtuals[t]=this.$$populatedVirtuals[t].filter((function(t){return t&&"object"===i(t)})))}))}var o=this.virtuals,s=t.split(".");if("real"===this.pathType(t))throw new Error('Virtual path "'+t+'" conflicts with a real path in the schema');o[t]=s.reduce((function(r,n,o){return r[n]||(r[n]=o===s.length-1?new d(e,t):{}),r[n]}),this.tree);for(var a=s[0],u=0;u<s.length-1;++u){if(null!=this.paths[a]&&this.paths[a].$isMongooseDocumentArray)if("break"===function(){var t=s.slice(u+1).join(".");return r.paths[a].schema.virtual(t).get((function(e,r,n){var o=n.__parentArray[_],i=a+"."+n.__index+"."+t;return o.get(i)})),"break"}())break;a+="."+s[u+1]}return o[t]},T.prototype.virtualpath=function(t){return this.virtuals.hasOwnProperty(t)?this.virtuals[t]:null},T.prototype.remove=function(t){return"string"==typeof t&&(t=[t]),Array.isArray(t)&&t.forEach((function(t){if(null!=this.path(t)||this.nested[t]){if(this.nested[t]){var e,r=s(Object.keys(this.paths).concat(Object.keys(this.nested)));try{for(r.s();!(e=r.n()).done;){var n=e.value;n.startsWith(t+".")&&(delete this.paths[n],delete this.nested[n],F(this,n))}}catch(t){r.e(t)}finally{r.f()}return delete this.nested[t],void F(this,t)}delete this.paths[t],F(this,t)}}),this),this},T.prototype.loadClass=function(t,e){return t===Object.prototype||t===Function.prototype||t.prototype.hasOwnProperty("$isMongooseModelPrototype")||(this.loadClass(Object.getPrototypeOf(t)),e||Object.getOwnPropertyNames(t).forEach((function(e){if(!e.match(/^(length|name|prototype)$/)){var r=Object.getOwnPropertyDescriptor(t,e);"function"==typeof r.value&&this.static(e,r.value)}}),this),Object.getOwnPropertyNames(t.prototype).forEach((function(r){if(!r.match(/^(constructor)$/)){var n=Object.getOwnPropertyDescriptor(t.prototype,r);e||"function"==typeof n.value&&this.method(r,n.value),"function"==typeof n.get&&this.virtual(r).get(n.get),"function"==typeof n.set&&this.virtual(r).set(n.set)}}),this)),this},
+/*!
+ * ignore
+ */
+T.prototype._getSchema=function(t){var e=this.path(t),r=[];if(e)return e.$fullPath=t,e;for(var n=t.split("."),o=0;o<n.length;++o)("$"===n[o]||L(n[o]))&&(n[o]="0");return function t(e,n){for(var o,i,s=e.length+1;s--;)if(i=e.slice(0,s).join("."),o=n.path(i)){if(r.push(i),o.caster){if(o.caster instanceof u.Mixed)return o.caster.$fullPath=r.join("."),o.caster;if(s!==e.length&&o.schema){var a=void 0;return"$"===e[s]||L(e[s])?s+1===e.length?o:((a=t(e.slice(s+1),o.schema))&&(a.$isUnderneathDocArray=a.$isUnderneathDocArray||!o.schema.$isSingleNested),a):((a=t(e.slice(s),o.schema))&&(a.$isUnderneathDocArray=a.$isUnderneathDocArray||!o.schema.$isSingleNested),a)}}else if(o.$isSchemaMap){return s+1>=e.length?o.$__schemaType:t(e.slice(s+1),o.$__schemaType.schema)}return o.$fullPath=r.join("."),o}}(n,this)},
+/*!
+ * ignore
+ */
+T.prototype._getPathType=function(t){if(this.path(t))return"real";return function t(e,r){for(var n,o,i=e.length+1;i--;){if(o=e.slice(0,i).join("."),n=r.path(o))return n.caster?n.caster instanceof u.Mixed?{schema:n,pathType:"mixed"}:i!==e.length&&n.schema?"$"===e[i]||L(e[i])?i===e.length-1?{schema:n,pathType:"nested"}:t(e.slice(i+1),n.schema):t(e.slice(i),n.schema):{schema:n,pathType:n.$isSingleNested?"nested":"array"}:{schema:n,pathType:"real"};if(i===e.length&&r.nested[o])return{schema:r,pathType:"nested"}}return{schema:n||r,pathType:"undefined"}}(t.split("."),this)},t.exports=e=T,T.Types=u=r(54),
+/*!
+ * ignore
+ */
+e.ObjectId=u.ObjectId}).call(this,r(1).Buffer)},function(t,e,r){"use strict";function n(t,e){this.path=e,this.getters=[],this.setters=[],this.options=Object.assign({},t)}n.prototype._applyDefaultGetters=function(){if(!(this.getters.length>0||this.setters.length>0)){var t="$"+this.path;this.getters.push((function(){return this[t]})),this.setters.push((function(e){this[t]=e}))}},
+/*!
+ * ignore
+ */
+n.prototype.clone=function(){var t=new n(this.options,this.path);return t.getters=[].concat(this.getters),t.setters=[].concat(this.setters),t},n.prototype.get=function(t){return this.getters.push(t),this},n.prototype.set=function(t){return this.setters.push(t),this},n.prototype.applyGetters=function(t,e){for(var r=t,n=this.getters.length-1;n>=0;n--)r=this.getters[n].call(e,r,this,e);return r},n.prototype.applySetters=function(t,e){for(var r=t,n=this.setters.length-1;n>=0;n--)r=this.setters[n].call(e,r,this,e);return r},
+/*!
+ * exports
+ */
+t.exports=n},function(t,e,r){"use strict";
+/*!
+ * Module exports.
+ */e.String=r(146),e.Number=r(78),e.Boolean=r(150),e.DocumentArray=r(151),e.Embedded=r(158),e.Array=r(55),e.Buffer=r(160),e.Date=r(162),e.ObjectId=r(165),e.Mixed=r(25),e.Decimal128=e.Decimal=r(167),e.Map=r(169),e.Oid=e.ObjectId,e.Object=e.Mixed,e.Bool=e.Boolean,e.ObjectID=e.ObjectId},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i,s,a=r(48),u=r(72),c=r(14),l=r(152),f=r(7),p=f.CastError,h=r(25),y=r(153),d=r(154),m=r(3),_=r(80),v=r(4),g=r(2),b=r(33).castToNumber,w=r(81),O=r(34),S=Symbol("mongoose#isNestedArray");function A(t,e,n,o){s||(s=r(56).Embedded);var i,a,u="type";if(o&&o.typeKey&&(u=o.typeKey),this.schemaOptions=o,e){var c={};g.isPOJO(e)&&(e[u]?(delete(c=g.clone(e))[u],e=e[u]):e=h),e===Object&&(e=h);var l="string"==typeof e?e:g.getFunctionName(e),p=r(54),y=p.hasOwnProperty(l)?p[l]:e;this.casterConstructor=y,this.casterConstructor instanceof A&&(this.casterConstructor[S]=!0),"function"!=typeof y||y.$isArraySubdocument||y.$isSchemaMap?this.caster=y:this.caster=new y(null,c),this.$embeddedSchemaType=this.caster,this.caster instanceof s||(this.caster.path=t)}if(this.$isMongooseArray=!0,f.call(this,t,n,"Array"),null!=this.defaultValue&&(i=this.defaultValue,a="function"==typeof i),!("defaultValue"in this)||void 0!==this.defaultValue){var d=function(){var t=[];return a?t=i.call(this):null!=i&&(t=t.concat(i)),t};d.$runBeforeSetters=!a,this.default(d)}}A.schemaName="Array",A.options={castNonArrays:!0},A.defaultOptions={},A.set=f.set,
+/*!
+ * Inherits from SchemaType.
+ */
+A.prototype=Object.create(f.prototype),A.prototype.constructor=A,A.prototype.OptionsConstructor=l,
+/*!
+ * ignore
+ */
+A._checkRequired=f.prototype.checkRequired,A.checkRequired=f.checkRequired,A.prototype.checkRequired=function(t,e){return f._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():A.checkRequired())(t)},A.prototype.enum=function(){for(var t=this;;){var e=m(t,"caster.instance");if("Array"!==e){if("String"!==e&&"Number"!==e)throw new Error("`enum` can only be set on an array of strings or numbers , not "+e);break}t=t.caster}return t.caster.enum.apply(t.caster,arguments),this},A.prototype.applyGetters=function(t,e){return this.caster.options&&this.caster.options.ref?t:f.prototype.applyGetters.call(this,t,e)},A.prototype._applySetters=function(t,e,r,n){if(this.casterConstructor instanceof A&&A.options.castNonArrays&&!this[S]){for(var o=0,i=this;null!=i&&i instanceof A&&!i.$isMongooseDocumentArray;)++o,i=i.casterConstructor;if(null!=t&&t.length>0){var s=y(t);if(s.min===s.max&&s.max<o&&s.containsNonArrayItem)for(var a=s.max;a<o;++a)t=[t]}}return f.prototype._applySetters.call(this,t,e,r,n)},A.prototype.cast=function(t,e,n,o,s){var a,u;if(i||(i=r(56).Array),Array.isArray(t)){if(!t.length&&e){var l=e.schema.indexedPaths(),f=this.path;for(a=0,u=l.length;a<u;++a){var y=l[a][0][f];if("2dsphere"===y||"2d"===y)return}var d=this.path.endsWith(".coordinates")?this.path.substr(0,this.path.lastIndexOf(".")):null;if(null!=d)for(a=0,u=l.length;a<u;++a){if("2dsphere"===l[a][0][d])return}}if(t&&t.isMongooseArray?t&&t.isMongooseArray&&(t=new i(t,this._arrayPath||this.path,e)):t=new i(t,this._arrayPath||this.path,e),null!=e&&null!=e.$__&&e.populated(this.path))return t;if(this.caster&&this.casterConstructor!==h)try{for(a=0,u=t.length;a<u;a++){if("Number"===this.caster.instance&&void 0===t[a])throw new c("Mongoose number arrays disallow storing undefined");var m={};null!=s&&null!=s.arrayPath?m.arrayPath=s.arrayPath+"."+a:null!=this.caster._arrayPath&&(m.arrayPath=this.caster._arrayPath.slice(0,-2)+"."+a),t[a]=this.caster.cast(t[a],e,n,void 0,m)}}catch(e){throw new p("["+e.kind+"]",v.inspect(t),this.path,e,this)}return t}if(n||A.options.castNonArrays)return e&&n&&e.markModified(this.path),this.cast([t],e,n);throw new p("Array",v.inspect(t),this.path,null,this)},
+/*!
+ * Ignore
+ */
+A.prototype.discriminator=function(t,e){for(var r=this;r.$isMongooseArray&&!r.$isMongooseDocumentArray;)if(null==(r=r.casterConstructor)||"function"==typeof r)throw new c("You can only add an embedded discriminator on a document array, "+this.path+" is a plain array");return r.discriminator(t,e)},
+/*!
+ * ignore
+ */
+A.prototype.clone=function(){var t=Object.assign({},this.options),e=new this.constructor(this.path,this.caster,t,this.schemaOptions);return e.validators=this.validators.slice(),void 0!==this.requiredValidator&&(e.requiredValidator=this.requiredValidator),e},A.prototype.castForQuery=function(t,e){var r,n,o=this;if(2===arguments.length){if(!(r=this.$conditionalHandlers[t]))throw new Error("Can't use "+t+" with Array.");n=r.call(this,e)}else{n=t;var i=this.casterConstructor;if(n&&i.discriminators&&i.schema&&i.schema.options&&i.schema.options.discriminatorKey)if("string"==typeof n[i.schema.options.discriminatorKey]&&i.discriminators[n[i.schema.options.discriminatorKey]])i=i.discriminators[n[i.schema.options.discriminatorKey]];else{var s=O(i,n[i.schema.options.discriminatorKey]);s&&(i=s)}var a=this.casterConstructor.prototype,u=a&&(a.castForQuery||a.cast);!u&&i.castForQuery&&(u=i.castForQuery);var c=this.caster;Array.isArray(n)?(this.setters.reverse().forEach((function(t){n=t.call(o,n,o)})),n=n.map((function(t){return g.isObject(t)&&t.$elemMatch?t:u?t=u.call(c,t):null!=t?t=new i(t):t}))):u?n=u.call(c,n):null!=n&&(n=new i(n))}return n};var j=A.prototype.$conditionalHandlers={};function E(t){return function(e){if(!Array.isArray(e))throw new TypeError("conditional "+t+" requires an array");var r,o=[],i=n(e);try{for(i.s();!(r=i.n()).done;){var s=r.value;o.push(d(this.casterConstructor.schema,s))}}catch(t){i.e(t)}finally{i.f()}return o}}j.$all=function(t){return Array.isArray(t)||(t=[t]),t=t.map((function(t){if(g.isObject(t)){var e={};return e[this.path]=t,d(this.casterConstructor.schema,e)[this.path]}return t}),this),this.castForQuery(t)},j.$options=String,j.$elemMatch=function(t){for(var e=Object.keys(t),r=e.length,n=0;n<r;++n){var o=e[n],i=t[o];_(o)&&null!=i&&(t[o]=this.castForQuery(o,i))}var s=m(this,"casterConstructor.schema.options.discriminatorKey"),a=m(this,"casterConstructor.schema.discriminators",{});return null!=s&&null!=t[s]&&null!=a[t[s]]?d(a[t[s]],t):d(this.casterConstructor.schema,t)},j.$geoIntersects=w.cast$geoIntersects,j.$or=E("$or"),j.$and=E("$and"),j.$nor=E("$nor"),j.$near=j.$nearSphere=w.cast$near,j.$within=j.$geoWithin=w.cast$within,j.$size=j.$minDistance=j.$maxDistance=b,j.$exists=a,j.$type=u,j.$eq=j.$gt=j.$gte=j.$lt=j.$lte=j.$ne=j.$regex=A.prototype.castForQuery,j.$nin=f.prototype.$conditionalHandlers.$nin,j.$in=f.prototype.$conditionalHandlers.$in,
+/*!
+ * Module exports.
+ */
+t.exports=A},function(t,e,r){"use strict";
+/*!
+ * Module exports.
+ */e.Array=r(82),e.Buffer=r(85),e.Document=e.Embedded=r(26),e.DocumentArray=r(18),e.Decimal128=r(20),e.ObjectId=r(13),e.Map=r(87),e.Subdocument=r(89)},function(t,e,r){"use strict";var n,o=r(0).documentSchemaSymbol,i=r(3),s=r(17).internalToObjectOptions,a=r(2),u=r(0).getSymbol,c=r(0).scopeSymbol;
+/*!
+ * Compiles schemas.
+ */
+function l(t,e,o,i){n=n||r(6);for(var s,u,c=Object.keys(t),l=c.length,p=0;p<l;++p){s=t[u=c[p]],f(u,a.isPOJO(s)&&Object.keys(s).length&&(!s[i.typeKey]||"type"===i.typeKey&&s.type.type)?s:null,e,o,c,i)}}
+/*!
+ * Defines the accessor named prop on the incoming prototype.
+ */function f(t,e,f,p,h,y){n=n||r(6);var d=(p?p+".":"")+t;p=p||"",e?Object.defineProperty(f,t,{enumerable:!0,configurable:!0,get:function(){var t,r,s=this;if(this.$__.getters||(this.$__.getters={}),!this.$__.getters[d]){var u=Object.create(n.prototype,(t=this,r={},Object.getOwnPropertyNames(t).forEach((function(e){r[e]=Object.getOwnPropertyDescriptor(t,e),r[e].get?delete r[e]:r[e].enumerable=-1===["isNew","$__","errors","_doc","$locals","$op","__parentArray","__index","$isDocumentArrayElement"].indexOf(e)})),r));p||(u.$__[c]=this),u.$__.nestedPath=d,Object.defineProperty(u,"schema",{enumerable:!1,configurable:!0,writable:!1,value:f.schema}),Object.defineProperty(u,o,{enumerable:!1,configurable:!0,writable:!1,value:f.schema}),Object.defineProperty(u,"toObject",{enumerable:!1,configurable:!0,writable:!1,value:function(){return a.clone(s.get(d,null,{virtuals:i(this,"schema.options.toObject.virtuals",null)}))}}),Object.defineProperty(u,"$__get",{enumerable:!1,configurable:!0,writable:!1,value:function(){return s.get(d,null,{virtuals:i(this,"schema.options.toObject.virtuals",null)})}}),Object.defineProperty(u,"toJSON",{enumerable:!1,configurable:!0,writable:!1,value:function(){return s.get(d,null,{virtuals:i(s,"schema.options.toJSON.virtuals",null)})}}),Object.defineProperty(u,"$__isNested",{enumerable:!1,configurable:!0,writable:!1,value:!0});var h=Object.freeze({minimize:!0,virtuals:!1,getters:!1,transform:!1});Object.defineProperty(u,"$isEmpty",{enumerable:!1,configurable:!0,writable:!1,value:function(){return 0===Object.keys(this.get(d,null,h)||{}).length}}),Object.defineProperty(u,"$__parent",{enumerable:!1,configurable:!0,writable:!1,value:this}),l(e,u,d,y),this.$__.getters[d]=u}return this.$__.getters[d]},set:function(t){null!=t&&t.$__isNested?t=t.$__get():t instanceof n&&!t.$__isNested&&(t=t.toObject(s)),(this.$__[c]||this).$set(d,t)}}):Object.defineProperty(f,t,{enumerable:!0,configurable:!0,get:function(){return this[u].call(this.$__[c]||this,d)},set:function(t){this.$set.call(this.$__[c]||this,d,t)}})}
+/*!
+ * exports
+ */
+e.compile=l,e.defineKey=f},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports=function(t){return null==t||("object"!==n(t)||!("$meta"in t)&&!("$slice"in t))}},function(t,e,r){"use strict";(function(e){if(void 0!==e.Map)t.exports=e.Map,t.exports.Map=e.Map;else{var r=function(t){this._keys=[],this._values={};for(var e=0;e<t.length;e++)if(null!=t[e]){var r=t[e],n=r[0],o=r[1];this._keys.push(n),this._values[n]={v:o,i:this._keys.length-1}}};r.prototype.clear=function(){this._keys=[],this._values={}},r.prototype.delete=function(t){var e=this._values[t];return null!=e&&(delete this._values[t],this._keys.splice(e.i,1),!0)},r.prototype.entries=function(){var t=this,e=0;return{next:function(){var r=t._keys[e++];return{value:void 0!==r?[r,t._values[r].v]:void 0,done:void 0===r}}}},r.prototype.forEach=function(t,e){e=e||this;for(var r=0;r<this._keys.length;r++){var n=this._keys[r];t.call(e,this._values[n].v,n,e)}},r.prototype.get=function(t){return this._values[t]?this._values[t].v:void 0},r.prototype.has=function(t){return null!=this._values[t]},r.prototype.keys=function(){var t=this,e=0;return{next:function(){var r=t._keys[e++];return{value:void 0!==r?r:void 0,done:void 0===r}}}},r.prototype.set=function(t,e){return this._values[t]?(this._values[t].v=e,this):(this._keys.push(t),this._values[t]={v:e,i:this._keys.length-1},this)},r.prototype.values=function(){var t=this,e=0;return{next:function(){var r=t._keys[e++];return{value:void 0!==r?t._values[r].v:void 0,done:void 0===r}}}},Object.defineProperty(r.prototype,"size",{enumerable:!0,get:function(){return this._keys.length}}),t.exports=r,t.exports.Map=r}}).call(this,r(11))},function(t,e){var r=function t(e){if(!(this instanceof t))return new t(e);this._bsontype="Int32",this.value=e};r.prototype.valueOf=function(){return this.value},r.prototype.toJSON=function(){return this.value},t.exports=r,t.exports.Int32=r},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(6),o=r(178),i=!1;t.exports=function(){return i?o:n},
+/*!
+ * ignore
+ */
+t.exports.setBrowser=function(t){i=t}},function(t,e){t.exports=function(t,e,r){var n=[],o=t.length;if(0===o)return n;var i=e<0?Math.max(0,e+o):e||0;for(void 0!==r&&(o=r<0?r+o:r);o-- >i;)n[o-i]=t[o];return n}},function(t,e,r){
+/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
+var n=r(1),o=n.Buffer;function i(t,e){for(var r in t)e[r]=t[r]}function s(t,e,r){return o(t,e,r)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?t.exports=n:(i(n,e),e.Buffer=s),s.prototype=Object.create(o.prototype),i(o,s),s.from=function(t,e,r){if("number"==typeof t)throw new TypeError("Argument must not be a number");return o(t,e,r)},s.alloc=function(t,e,r){if("number"!=typeof t)throw new TypeError("Argument must be a number");var n=o(t);return void 0!==e?"string"==typeof r?n.fill(e,r):n.fill(e):n.fill(0),n},s.allocUnsafe=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return o(t)},s.allocUnsafeSlow=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return n.SlowBuffer(t)}},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n=Object.prototype.toString;t.exports=function(t){if("object"!=r(e=t)||"[object RegExp]"!=n.call(e))throw new TypeError("Not a RegExp");var e,o=[];t.global&&o.push("g"),t.multiline&&o.push("m"),t.ignoreCase&&o.push("i"),t.dotAll&&o.push("s"),t.unicode&&o.push("u"),t.sticky&&o.push("y");var i=new RegExp(t.source,o.join(""));return"number"==typeof t.lastIndex&&(i.lastIndex=t.lastIndex),i}},function(t,e,r){"use strict";t.exports=function(t){return t.name?t.name:(t.toString().trim().match(/^function\s*([^\s(]+)/)||[])[1]}},function(t,e,r){"use strict";var n=r(3);
+/*!
+ * Get the bson type, if it exists
+ */t.exports=function(t,e){return n(t,"_bsontype",void 0)===e}},function(t,e,r){"use strict";(function(e){
+/*!
+ * ignore
+ */
+var n=r(22),o=r(115),i={_promise:null,get:function(){return i._promise},set:function(t){n.ok("function"==typeof t,"mongoose.Promise must be a function, got ".concat(t)),i._promise=t,o.Promise=t}};
+/*!
+ * Use native promises by default
+ */
+i.set(e.Promise),t.exports=i}).call(this,r(11))},function(t,e,r){"use strict";(function(t,n){
+/*!
+ * Module dependencies.
+ */
+function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var i=r(117).Buffer,s=r(64),a=e.clone=function t(r,n){if(null==r)return r;if(Array.isArray(r))return e.cloneArray(r,n);if(r.constructor){if(/ObjectI[dD]$/.test(r.constructor.name))return"function"==typeof r.clone?r.clone():new r.constructor(r.id);if("ReadPreference"===r.constructor.name)return new r.constructor(r.mode,t(r.tags,n));if("Binary"==r._bsontype&&r.buffer&&r.value)return"function"==typeof r.clone?r.clone():new r.constructor(r.value(!0),r.sub_type);if("Date"===r.constructor.name||"Function"===r.constructor.name)return new r.constructor(+r);if("RegExp"===r.constructor.name)return s(r);if("Buffer"===r.constructor.name)return e.cloneBuffer(r)}return c(r)?e.cloneObject(r,n):r.valueOf?r.valueOf():void 0};
+/*!
+ * ignore
+ */
+e.cloneObject=function(t,e){var r,n,o,i=e&&e.minimize,s={};for(o in t)n=a(t[o],e),i&&void 0===n||(r||(r=!0),s[o]=n);return i?r&&s:s},e.cloneArray=function(t,e){for(var r=[],n=0,o=t.length;n<o;n++)r.push(a(t[n],e));return r},e.tick=function(t){if("function"==typeof t)return function(){var e=arguments;l((function(){t.apply(this,e)}))}},e.merge=function t(r,n){for(var o,i=Object.keys(n),s=i.length;s--;)void 0===r[o=i[s]]?r[o]=n[o]:e.isObject(n[o])?t(r[o],n[o]):r[o]=n[o]},e.mergeClone=function t(r,n){for(var o,i=Object.keys(n),s=i.length;s--;)void 0===r[o=i[s]]?r[o]=a(n[o]):e.isObject(n[o])?t(r[o],n[o]):r[o]=a(n[o])},e.readPref=function(t){switch(t){case"p":t="primary";break;case"pp":t="primaryPreferred";break;case"s":t="secondary";break;case"sp":t="secondaryPreferred";break;case"n":t="nearest"}return t},e.readConcern=function(t){if("string"==typeof t){switch(t){case"l":t="local";break;case"a":t="available";break;case"m":t="majority";break;case"lz":t="linearizable";break;case"s":t="snapshot"}t={level:t}}return t};var u=Object.prototype.toString;e.toString=function(t){return u.call(t)};var c=e.isObject=function(t){return"[object Object]"==e.toString(t)};e.isArray=function(t){return Array.isArray(t)||"object"==o(t)&&"[object Array]"==e.toString(t)},e.keys=Object.keys||function(t){var e=[];for(var r in t)t.hasOwnProperty(r)&&e.push(r);return e},e.create="function"==typeof Object.create?Object.create:function(t){if(arguments.length>1)throw new Error("Adding properties is not supported");function e(){}return e.prototype=t,new e},e.inherits=function(t,r){t.prototype=e.create(r.prototype),t.prototype.constructor=t};var l=e.soon="function"==typeof t?t:n.nextTick;e.cloneBuffer=function(t){var e=i.alloc(t.length);return t.copy(e,0,0,t.length),e},e.isArgumentsObject=function(t){return"[object Arguments]"===Object.prototype.toString.call(t)}}).call(this,r(69).setImmediate,r(8))},function(t,e,r){(function(t){var n=void 0!==t&&t||"undefined"!=typeof self&&self||window,o=Function.prototype.apply;function i(t,e){this._id=t,this._clearFn=e}e.setTimeout=function(){return new i(o.call(setTimeout,n,arguments),clearTimeout)},e.setInterval=function(){return new i(o.call(setInterval,n,arguments),clearInterval)},e.clearTimeout=e.clearInterval=function(t){t&&t.close()},i.prototype.unref=i.prototype.ref=function(){},i.prototype.close=function(){this._clearFn.call(n,this._id)},e.enroll=function(t,e){clearTimeout(t._idleTimeoutId),t._idleTimeout=e},e.unenroll=function(t){clearTimeout(t._idleTimeoutId),t._idleTimeout=-1},e._unrefActive=e.active=function(t){clearTimeout(t._idleTimeoutId);var e=t._idleTimeout;e>=0&&(t._idleTimeoutId=setTimeout((function(){t._onTimeout&&t._onTimeout()}),e))},r(116),e.setImmediate="undefined"!=typeof self&&self.setImmediate||void 0!==t&&t.setImmediate||this&&this.setImmediate,e.clearImmediate="undefined"!=typeof self&&self.clearImmediate||void 0!==t&&t.clearImmediate||this&&this.clearImmediate}).call(this,r(11))},function(t,e,r){"use strict";(function(t,r,n,o){function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}e.isNode=void 0!==t&&"object"==i(r)&&"object"==(void 0===n?"undefined":i(n))&&"function"==typeof o&&t.argv,e.isMongo=!e.isNode&&"function"==typeof printjson&&"function"==typeof ObjectId&&"function"==typeof rs&&"function"==typeof sh,e.isBrowser=!e.isNode&&!e.isMongo&&"undefined"!=typeof window,e.type=e.isNode?"node":e.isMongo?"mongo":e.isBrowser?"browser":"unknown"}).call(this,r(8),r(122)(t),r(11),r(1).Buffer)},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=r(5),l=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(u,t);var e,r,n,a=s(u);function u(t){var e;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,u);var r=t.message;r||(r=c.messages.general.default);var n=f(r,t);return e=a.call(this,n),t=Object.assign({},t,{message:n}),e.properties=t,e.kind=t.type,e.path=t.path,e.value=t.value,e.reason=t.reason,e}
+/*!
+ * toString helper
+ * TODO remove? This defaults to `${this.name}: ${this.message}`
+ */return e=u,(r=[{key:"toString",value:function(){return this.message}
+/*!
+ * Ensure `name` and `message` show up in toJSON output re: gh-9296
+ */},{key:"toJSON",value:function(){return Object.assign({name:this.name,message:this.message},this)}}])&&o(e.prototype,r),n&&o(e,n),u}(c);
+/*!
+ * Formats error messages
+ */
+function f(t,e){if("function"==typeof t)return t(e);for(var r=0,n=Object.keys(e);r<n.length;r++){var o=n[r];"message"!==o&&(t=t.replace("{"+o.toUpperCase()+"}",e[o]))}return t}
+/*!
+ * exports
+ */Object.defineProperty(l.prototype,"name",{value:"ValidatorError"}),
+/*!
+ * The object used to define this validator. Not enumerable to hide
+ * it from `require('util').inspect()` output re: gh-3925
+ */
+Object.defineProperty(l.prototype,"properties",{enumerable:!1,writable:!0,value:null}),l.prototype.formatMessage=f,t.exports=l},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */t.exports=function(t){if("number"!=typeof t&&"string"!=typeof t)throw new Error("$type parameter must be number or string");return t}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t,n){var o;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);var i=Array.isArray(n)?"array":"primitive value";return(o=e.call(this,"Tried to set nested object field `"+t+"` to ".concat(i," `")+n+"` and strict mode is set to throw.")).path=t,o}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"ObjectExpectedError"}),t.exports=u},function(t,e,r){"use strict";t.exports=function(t){var e={_id:{auto:!0}};e._id[t.options.typeKey]="ObjectId",t.add(e)}},function(t,e,r){"use strict";t.exports=
+/*!
+ * ignore
+ */
+function(t,e){if(null==t)return null;if("boolean"==typeof t)return e;if("boolean"==typeof t[e])return t[e]?e:null;if(!(e in t))return e;return t[e]}},function(t,e,r){"use strict";var n=r(51),o=r(24);
+/*!
+ * Register hooks for this model
+ *
+ * @param {Model} model
+ * @param {Schema} schema
+ */
+function i(t,e,r){var s={useErrorHandlers:!0,numCallbackParams:1,nullResultByDefault:!0,contextParameter:!0},a=(r=r||{}).decorateDoc?t:t.prototype;t.$appliedHooks=!0;for(var u=0,c=Object.keys(e.paths);u<c.length;u++){var l=c[u],f=e.paths[l],p=null;if(f.$isSingleNested)p=f.caster;else{if(!f.$isMongooseDocumentArray)continue;p=f.Constructor}if(!p.$appliedHooks&&(i(p,f.schema,r),null!=p.discriminators))for(var h=0,y=Object.keys(p.discriminators);h<y.length;h++){var d=y[h];i(p.discriminators[d],p.discriminators[d].schema,r)}}var m=e.s.hooks.filter((function(t){return"updateOne"===t.name||"deleteOne"===t.name?!!t.document:"remove"!==t.name&&"init"!==t.name||(null==t.document||!!t.document)})).filter((function(t){return!e.methods[t.name]||!t.fn[n.builtInMiddleware]}));t._middleware=m,a.$__originalValidate=a.$__originalValidate||a.$__validate;for(var _=0,v=["save","validate","remove","deleteOne"];_<v.length;_++){var g=v[_],b="validate"===g?"$__originalValidate":"$__".concat(g),w=m.createWrapper(g,a[b],null,s);a["$__".concat(g)]=w}a.$__init=m.createWrapperSync("init",a.$__init,null,s);for(var O=Object.keys(e.methods),S=Object.assign({},s,{checkForPromise:!0}),A=function(){var e=E[j];if(!m.hasHooks(e))return"continue";var r=a[e];a[e]=function(){var r=this,n=Array.prototype.slice.call(arguments),i=n.slice(-1).pop(),s="function"==typeof i?n.slice(0,n.length-1):n;return o(i,(function(t){return r["$__".concat(e)].apply(r,s.concat([t]))}),t.events)},a["$__".concat(e)]=m.createWrapper(e,r,null,S)},j=0,E=O;j<E.length;j++)A()}
+/*!
+ * ignore
+ */
+t.exports=i,
+/*!
+ * ignore
+ */
+i.middlewareFunctions=["deleteOne","save","validate","remove","updateOne","init"]},function(t,e,r){"use strict";var n=r(12);
+/*!
+ * Given a value, cast it to a string, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {string|null|undefined}
+ * @throws {CastError}
+ * @api private
+ */t.exports=function(t,e){if(null==t)return t;if(t._id&&"string"==typeof t._id)return t._id;if(t.toString&&t.toString!==Object.prototype.toString&&!Array.isArray(t))return t.toString();throw new n("string",t,e)}},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module requirements.
+ */
+var n,o=r(5),i=r(148),s=r(7),a=r(149),u=r(79),c=r(2),l=r(0).populateModelSymbol,f=s.CastError;function p(t,e){s.call(this,t,e,"Number")}
+/*!
+ * ignore
+ */
+function h(t){return this.cast(t)}p.get=s.get,p.set=s.set,
+/*!
+ * ignore
+ */
+p._cast=a,p.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if("number"!=typeof t)throw new Error;return t}),this._cast=t),this._cast},p.schemaName="Number",p.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+p.prototype=Object.create(s.prototype),p.prototype.constructor=p,p.prototype.OptionsConstructor=i,
+/*!
+ * ignore
+ */
+p._checkRequired=function(t){return"number"==typeof t||t instanceof Number},p.checkRequired=s.checkRequired,p.prototype.checkRequired=function(t,e){return s._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():p.checkRequired())(t)},p.prototype.min=function(t,e){if(this.minValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.minValidator}),this)),null!=t){var r=e||o.messages.Number.min;r=r.replace(/{MIN}/,t),this.validators.push({validator:this.minValidator=function(e){return null==e||e>=t},message:r,type:"min",min:t})}return this},p.prototype.max=function(t,e){if(this.maxValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.maxValidator}),this)),null!=t){var r=e||o.messages.Number.max;r=r.replace(/{MAX}/,t),this.validators.push({validator:this.maxValidator=function(e){return null==e||e<=t},message:r,type:"max",max:t})}return this},p.prototype.enum=function(t,e){return this.enumValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.enumValidator}),this)),Array.isArray(t)||(t=Array.prototype.slice.call(arguments),e=o.messages.Number.enum),e=null==e?o.messages.Number.enum:e,this.enumValidator=function(e){return null==e||-1!==t.indexOf(e)},this.validators.push({validator:this.enumValidator,message:e,type:"enum",enumValues:t}),this},p.prototype.cast=function(t,o,i){if(s._isRef(this,t,o,i)){if(null==t)return t;if(n||(n=r(6)),t instanceof n)return t.$__.wasPopulated=!0,t;if("number"==typeof t)return t;if(e.isBuffer(t)||!c.isObject(t))throw new f("Number",t,this.path,null,this);var a=o.$__fullPath(this.path),u=new((o.ownerDocument?o.ownerDocument():o).populated(a,!0).options[l])(t);return u.$__.wasPopulated=!0,u}var h=t&&void 0!==t._id?t._id:t,y="function"==typeof this.constructor.cast?this.constructor.cast():p.cast();try{return y(h)}catch(t){throw new f("Number",h,this.path,t,this)}},p.prototype.$conditionalHandlers=c.options(s.prototype.$conditionalHandlers,{$bitsAllClear:u,$bitsAnyClear:u,$bitsAllSet:u,$bitsAnySet:u,$gt:h,$gte:h,$lt:h,$lte:h,$mod:function(t){var e=this;return Array.isArray(t)?t.map((function(t){return e.cast(t)})):[this.cast(t)]}}),p.prototype.castForQuery=function(t,e){var r;if(2===arguments.length){if(!(r=this.$conditionalHandlers[t]))throw new f("number",e,this.path,null,this);return r.call(this,e)}return e=this._castForQuery(t)},
+/*!
+ * Module exports.
+ */
+t.exports=p}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module requirements.
+ */
+var n=r(12);
+/*!
+ * ignore
+ */
+/*!
+ * ignore
+ */
+function o(t,e){var r=Number(e);if(isNaN(r))throw new n("number",e,t);return r}t.exports=function(t){var r=this;return Array.isArray(t)?t.map((function(t){return o(r.path,t)})):e.isBuffer(t)?t:o(r.path,t)}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";var n=new Set(["$ref","$id","$db"]);t.exports=function(t){return t.startsWith("$")&&!n.has(t)}},function(t,e,r){"use strict";
+/*!
+ * Module requirements.
+ */var n=r(33).castArraysOfNumbers,o=r(33).castToNumber;function i(t,e){switch(t.$geometry.type){case"Polygon":case"LineString":case"Point":n(t.$geometry.coordinates,e)}return s(e,t),t}function s(t,e){e.$maxDistance&&(e.$maxDistance=o.call(t,e.$maxDistance)),e.$minDistance&&(e.$minDistance=o.call(t,e.$minDistance))}
+/*!
+ * ignore
+ */
+e.cast$geoIntersects=function(t){if(!t.$geometry)return;return i(t,this),t},e.cast$near=function(t){var e=r(55);if(Array.isArray(t))return n(t,this),t;if(s(this,t),t&&t.$geometry)return i(t,this);if(!Array.isArray(t))throw new TypeError("$near must be either an array or an object with a $geometry property");return e.prototype.castForQuery.call(this,t)},e.cast$within=function(t){var e=this;if(s(this,t),t.$box||t.$polygon){var r=t.$box?"$box":"$polygon";t[r].forEach((function(t){if(!Array.isArray(t))throw new TypeError("Invalid $within $box argument. Expected an array, received "+t);t.forEach((function(r,n){t[n]=o.call(e,r)}))}))}else if(t.$center||t.$centerSphere){var n=t.$center?"$center":"$centerSphere";t[n].forEach((function(r,i){Array.isArray(r)?r.forEach((function(t,n){r[n]=o.call(e,t)})):t[n][i]=o.call(e,r)}))}else t.$geometry&&i(t,this);return t}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(83),o=r(6),i=r(0).arrayAtomicsSymbol,s=r(0).arrayParentSymbol,a=r(0).arrayPathSymbol,u=r(0).arraySchemaSymbol,c=Array.prototype.push;
+/*!
+ * Module exports.
+ */
+t.exports=function(t,e,r){var l=new n;if(l[i]={},Array.isArray(t)){for(var f=t.length,p=0;p<f;++p)c.call(l,t[p]);l[i]=t[i]||{}}return l[a]=e,l[u]=void 0,r&&r instanceof o&&(l[s]=r,l[u]=r.schema.path(e)),l}},function(t,e,r){"use strict";(function(e){function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function s(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function a(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function u(t,e,r){return(u="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,r){var n=function(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=y(t)););return t}(t,e);if(n){var o=Object.getOwnPropertyDescriptor(n,e);return o.get?o.get.call(r):o.value}})(t,e,r||t)}function c(t,e){return!e||"object"!==i(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function l(t){var e="function"==typeof Map?new Map:void 0;return(l=function(t){if(null===t||(r=t,-1===Function.toString.call(r).indexOf("[native code]")))return t;var r;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return f(t,arguments,y(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),h(n,t)})(t)}function f(t,e,r){return(f=p()?Reflect.construct:function(t,e,r){var n=[null];n.push.apply(n,e);var o=new(Function.bind.apply(t,n));return r&&h(o,r.prototype),o}).apply(null,arguments)}function p(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function h(t,e){return(h=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function y(t){return(y=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var d=r(6),m=r(26),_=r(14),v=r(13),g=r(84),b=r(3),w=r(17).internalToObjectOptions,O=r(2),S=r(4),A=r(0).arrayAtomicsSymbol,j=r(0).arrayParentSymbol,E=r(0).arrayPathSymbol,$=r(0).arraySchemaSymbol,x=r(0).populateModelSymbol,P=Symbol("mongoose#Array#sliced"),N=Array.prototype.push,T=Symbol("mongoose#MongooseCoreArray#validators"),k=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&h(t,e)}(S,t);var r,n,o,i,l,f=(r=S,n=p(),function(){var t,e=y(r);if(n){var o=y(this).constructor;t=Reflect.construct(e,arguments,o)}else t=e.apply(this,arguments);return c(this,t)});function S(){return s(this,S),f.apply(this,arguments)}return o=S,(i=[{key:"$__getAtomics",value:function(){var t=[],e=Object.keys(this[A]),r=e.length,n=Object.assign({},w,{_isNested:!0});if(0===r)return t[0]=["$set",this.toObject(n)],t;for(;r--;){var o=e[r],i=this[A][o];O.isMongooseObject(i)?i=i.toObject(n):Array.isArray(i)?i=this.toObject.call(i,n):null!=i&&Array.isArray(i.$each)?i.$each=this.toObject.call(i.$each,n):null!=i&&"function"==typeof i.valueOf&&(i=i.valueOf()),"$addToSet"===o&&(i={$each:i}),t.push([o,i])}return t}
+/*!
+ * ignore
+ */},{key:"$atomics",value:function(){return this[A]}
+/*!
+ * ignore
+ */},{key:"$parent",value:function(){return this[j]}
+/*!
+ * ignore
+ */},{key:"$path",value:function(){return this[E]}},{key:"$shift",value:function(){if(this._registerAtomic("$pop",-1),this._markModified(),!this._shifted)return this._shifted=!0,[].shift.call(this)}},{key:"$pop",value:function(){if(this._registerAtomic("$pop",1),this._markModified(),!this._popped)return this._popped=!0,[].pop.call(this)}
+/*!
+ * ignore
+ */},{key:"$schema",value:function(){return this[$]}},{key:"_cast",value:function(t){var r,n=!1;return this[j]&&(n=this[j].populated(this[E],!0)),n&&null!=t?(r=n.options[x],(e.isBuffer(t)||t instanceof v||!O.isObject(t))&&(t={_id:t}),t.schema&&t.schema.discriminatorMapping&&void 0!==t.schema.discriminatorMapping.key||(t=new r(t)),this[$].caster.applySetters(t,this[j],!0)):this[$].caster.applySetters(t,this[j],!1)}},{key:"_mapCast",value:function(t,e){return this._cast(t,this.length+e)}},{key:"_markModified",value:function(t,e){var r,n=this[j];if(n){if(r=this[E],arguments.length&&(r=null!=e?r+"."+this.indexOf(t)+"."+e:r+"."+t),null!=r&&r.endsWith(".$"))return this;n.markModified(r,arguments.length>0?t:n)}return this}},{key:"_registerAtomic",value:function(t,e){if(!this[P]){if("$set"===t)return this[A]={$set:e},g(this[j],this[E]),this._markModified(),this;var r,n=this[A];if("$pop"===t&&!("$pop"in n)){var o=this;this[j].once("save",(function(){o._popped=o._shifted=null}))}if(this[A].$set||Object.keys(n).length&&!(t in n))return this[A]={$set:this},this;if("$pullAll"===t||"$addToSet"===t)n[t]||(n[t]=[]),n[t]=n[t].concat(e);else if("$pullDocs"===t){var i=n.$pull||(n.$pull={});e[0]instanceof m?(r=i.$or||(i.$or=[]),Array.prototype.push.apply(r,e.map((function(t){return t.toObject({transform:!1,virtuals:!1})})))):(r=i._id||(i._id={$in:[]})).$in=r.$in.concat(e)}else"$push"===t?(n.$push=n.$push||{$each:[]},null!=e&&O.hasUserDefinedProperty(e,"$each")?n.$push=e:n.$push.$each=n.$push.$each.concat(e)):n[t]=e;return this}}},{key:"addToSet",value:function(){C(this,arguments);var t=[].map.call(arguments,this._mapCast,this);t=this[$].applySetters(t,this[j]);var e=[],r="";return t[0]instanceof m?r="doc":t[0]instanceof Date&&(r="date"),t.forEach((function(t){var n,o=+t;switch(r){case"doc":n=this.some((function(e){return e.equals(t)}));break;case"date":n=this.some((function(t){return+t===o}));break;default:n=~this.indexOf(t)}n||([].push.call(this,t),this._registerAtomic("$addToSet",t),this._markModified(),[].push.call(e,t))}),this),e}},{key:"hasAtomics",value:function(){return O.isPOJO(this[A])?Object.keys(this[A]).length:0}},{key:"includes",value:function(t,e){return-1!==this.indexOf(t,e)}},{key:"indexOf",value:function(t,e){t instanceof v&&(t=t.toString()),e=null==e?0:e;for(var r=this.length,n=e;n<r;++n)if(t==this[n])return n;return-1}},{key:"inspect",value:function(){return JSON.stringify(this)}},{key:"nonAtomicPush",value:function(){var t=[].map.call(arguments,this._mapCast,this),e=[].push.apply(this,t);return this._registerAtomic("$set",this),this._markModified(),e}},{key:"pop",value:function(){var t=[].pop.call(this);return this._registerAtomic("$set",this),this._markModified(),t}},{key:"pull",value:function(){for(var t,e=[].map.call(arguments,this._cast,this),r=this[j].get(this[E]),n=r.length;n--;)if((t=r[n])instanceof d){var o=e.some((function(e){return t.equals(e)}));o&&[].splice.call(r,n,1)}else~r.indexOf.call(e,t)&&[].splice.call(r,n,1);return e[0]instanceof m?this._registerAtomic("$pullDocs",e.map((function(t){return t.$__getValue("_id")||t}))):this._registerAtomic("$pullAll",e),this._markModified(),g(this[j],this[E])>0&&this._registerAtomic("$set",this),this}},{key:"push",value:function(){var t=arguments,e=t,r=null!=t[0]&&O.hasUserDefinedProperty(t[0],"$each");if(r&&(e=t[0],t=t[0].$each),null==this[$])return N.apply(this,t);C(this,t);var n,o=this[j];t=[].map.call(t,this._mapCast,this),t=this[$].applySetters(t,o,void 0,void 0,{skipDocumentArrayCast:!0});var i=this[A];if(r){if(e.$each=t,b(i,"$push.$each.length",0)>0&&i.$push.$position!=i.$position)throw new _("Cannot call `Array#push()` multiple times with different `$position`");null!=e.$position?([].splice.apply(this,[e.$position,0].concat(t)),n=this.length):n=[].push.apply(this,t)}else{if(b(i,"$push.$each.length",0)>0&&null!=i.$push.$position)throw new _("Cannot call `Array#push()` multiple times with different `$position`");e=t,n=[].push.apply(this,t)}return this._registerAtomic("$push",e),this._markModified(),n}},{key:"remove",value:function(){return this.pull.apply(this,arguments)}},{key:"set",value:function(t,e){var r=this._cast(e,t);return this[t]=r,this._markModified(t),this}},{key:"shift",value:function(){var t=[].shift.call(this);return this._registerAtomic("$set",this),this._markModified(),t}},{key:"sort",value:function(){var t=[].sort.apply(this,arguments);return this._registerAtomic("$set",this),t}},{key:"splice",value:function(){var t;if(C(this,Array.prototype.slice.call(arguments,2)),arguments.length){var e;if(null==this[$])e=arguments;else{e=[];for(var r=0;r<arguments.length;++r)e[r]=r<2?arguments[r]:this._cast(arguments[r],arguments[0]+(r-2))}t=[].splice.apply(this,e),this._registerAtomic("$set",this)}return t}
+/*!
+ * ignore
+ */},{key:"slice",value:function(){var t=u(y(S.prototype),"slice",this).apply(this,arguments);return t[j]=this[j],t[$]=this[$],t[A]=this[A],t[P]=!0,t}
+/*!
+ * ignore
+ */},{key:"toBSON",value:function(){return this.toObject(w)}},{key:"toObject",value:function(t){return t&&t.depopulate?((t=O.clone(t))._isNested=!0,this.map((function(e){return e instanceof d?e.toObject(t):e}))):this.slice()}},{key:"unshift",value:function(){var t;return C(this,arguments),null==this[$]?t=arguments:(t=[].map.call(arguments,this._cast,this),t=this[$].applySetters(t,this[j])),[].unshift.apply(this,t),this._registerAtomic("$set",this),this._markModified(),this.length}},{key:"isMongooseArray",get:function(){return!0}},{key:"validators",get:function(){return this[T]},set:function(t){this[T]=t}}])&&a(o.prototype,i),l&&a(o,l),S}(l(Array));
+/*!
+ * ignore
+ */
+function C(t,e){var r,o,i,s=null==t?null:b(t[$],"caster.options.ref",null);0===t.length&&e.length>0&&
+/*!
+ * ignore
+ */
+function(t,e){if(!e)return!1;var r,o=n(t);try{for(o.s();!(r=o.n()).done;){var i=r.value;if(null==i)return!1;var s=i.constructor;if(!(i instanceof d)||s.modelName!==e&&s.baseModelName!==e)return!1}}catch(t){o.e(t)}finally{o.f()}return!0}(e,s)&&t[j].populated(t[E],[],(r={},o=x,i=e[0].constructor,o in r?Object.defineProperty(r,o,{value:i,enumerable:!0,configurable:!0,writable:!0}):r[o]=i,r))}S.inspect.custom&&(k.prototype[S.inspect.custom]=k.prototype.inspect),t.exports=k}).call(this,r(1).Buffer)},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */t.exports=function(t,e,r){var n=(r=r||{}).skipDocArrays,o=0;if(!t)return o;for(var i=0,s=Object.keys(t.$__.activePaths.states.modify);i<s.length;i++){var a=s[i];if(n){var u=t.schema.path(a);if(u&&u.$isMongooseDocumentArray)continue}a.startsWith(e+".")&&(delete t.$__.activePaths.states.modify[a],++o)}return o}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(15).get().Binary,o=r(2),i=r(63).Buffer;function s(t,e,r){var n,a,c,l,f,p=arguments.length;return n=0===p||null==arguments[0]?0:t,Array.isArray(e)?(c=e[0],l=e[1]):a=e,f="number"==typeof n||n instanceof Number?i.alloc(n):i.from(n,a,r),o.decorate(f,s.mixin),f.isMongooseBuffer=!0,f[s.pathSymbol]=c,f[u]=l,f._subtype=0,f}var a=Symbol.for("mongoose#Buffer#_path"),u=Symbol.for("mongoose#Buffer#_parent");s.pathSymbol=a,
+/*!
+ * Inherit from Buffer.
+ */
+s.mixin={_subtype:void 0,_markModified:function(){var t=this[u];return t&&t.markModified(this[s.pathSymbol]),this},write:function(){var t=i.prototype.write.apply(this,arguments);return t>0&&this._markModified(),t},copy:function(t){var e=i.prototype.copy.apply(this,arguments);return t&&t.isMongooseBuffer&&t._markModified(),e}},
+/*!
+ * Compile other Buffer methods marking this buffer as modified.
+ */
+"writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 writeFloat writeDouble fill utf8Write binaryWrite asciiWrite set writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE writeInt16LE writeInt16BE writeInt32LE writeInt32BE writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE".split(" ").forEach((function(t){i.prototype[t]&&(s.mixin[t]=function(){var e=i.prototype[t].apply(this,arguments);return this._markModified(),e})})),s.mixin.toObject=function(t){var e="number"==typeof t?t:this._subtype||0;return new n(i.from(this),e)},s.mixin.toBSON=function(){return new n(this,this._subtype||0)},s.mixin.equals=function(t){if(!i.isBuffer(t))return!1;if(this.length!==t.length)return!1;for(var e=0;e<this.length;++e)if(this[e]!==t[e])return!1;return!0},s.mixin.subtype=function(t){if("number"!=typeof t)throw new TypeError("Invalid subtype. Expected a number");this._subtype!==t&&this._markModified(),this._subtype=t},
+/*!
+ * Module exports.
+ */
+s.Binary=n,t.exports=s},function(t,e,r){"use strict";var n=r(15).get().ObjectId,o=r(22);t.exports=function(t){if(null==t)return t;if(t instanceof n)return t;if(t._id){if(t._id instanceof n)return t._id;if(t._id.toString instanceof Function)return new n(t._id.toString())}if(t.toString instanceof Function)return new n(t.toString());o.ok(!1)}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function s(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function a(t,e,r){return(a="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,r){var n=function(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=h(t)););return t}(t,e);if(n){var o=Object.getOwnPropertyDescriptor(n,e);return o.get?o.get.call(r):o.value}})(t,e,r||t)}function u(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function c(t){var e="function"==typeof Map?new Map:void 0;return(c=function(t){if(null===t||(r=t,-1===Function.toString.call(r).indexOf("[native code]")))return t;var r;if("function"!=typeof t)throw new TypeError("Super expression must either be null or a function");if(void 0!==e){if(e.has(t))return e.get(t);e.set(t,n)}function n(){return l(t,arguments,h(this).constructor)}return n.prototype=Object.create(t.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),p(n,t)})(t)}function l(t,e,r){return(l=f()?Reflect.construct:function(t,e,r){var n=[null];n.push.apply(n,e);var o=new(Function.bind.apply(t,n));return r&&p(o,r.prototype),o}).apply(null,arguments)}function f(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}function p(t,e){return(p=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function h(t){return(h=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var y=r(25),d=r(2).deepEqual,m=r(3),_=r(88),v=r(4),g=r(47),b=r(0).populateModelSymbol,w=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&p(t,e)}(v,t);var e,r,n,i,c,l=(e=v,r=f(),function(){var t,n=h(e);if(r){var o=h(this).constructor;t=Reflect.construct(n,arguments,o)}else t=n.apply(this,arguments);return u(this,t)});function v(t,e,r,n){var o;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,v),null!=t&&"Object"===t.constructor.name&&(t=Object.keys(t).reduce((function(e,r){return e.concat([[r,t[r]]])}),[])),(o=l.call(this,t)).$__parent=null!=r&&null!=r.$__?r:null,o.$__path=e,o.$__schemaType=null==n?new y(e):n,o.$__runDeferred(),o}return n=v,(i=[{key:"$init",value:function(t,e){O(t),a(h(v.prototype),"set",this).call(this,t,e),null!=e&&e.$isSingleNested&&(e.$basePath=this.$__path+"."+t)}},{key:"$__set",value:function(t,e){a(h(v.prototype),"set",this).call(this,t,e)}},{key:"get",value:function(t,e){return!1===(e=e||{}).getters?a(h(v.prototype),"get",this).call(this,t):this.$__schemaType.applyGetters(a(h(v.prototype),"get",this).call(this,t),this.$__parent)}},{key:"set",value:function(t,e){if(O(t),e=_(e),null==this.$__schemaType)return this.$__deferred=this.$__deferred||[],void this.$__deferred.push({key:t,value:e});var r=this.$__path+"."+t,n=null!=this.$__parent&&this.$__parent.$__?this.$__parent.populated(r)||this.$__parent.populated(this.$__path):null,o=this.get(t);if(null!=n)null==e.$__&&(e=new n.options[b](e)),e.$__.wasPopulated=!0;else try{e=this.$__schemaType.applySetters(e,this.$__parent,!1,this.get(t))}catch(t){if(null!=this.$__parent&&null!=this.$__parent.$__)return void this.$__parent.invalidate(r,t);throw t}a(h(v.prototype),"set",this).call(this,t,e),null!=e&&e.$isSingleNested&&(e.$basePath=this.$__path+"."+t);var i=this.$__parent;null==i||null==i.$__||d(e,o)||i.markModified(this.$__path+"."+t)}},{key:"clear",value:function(){a(h(v.prototype),"clear",this).call(this);var t=this.$__parent;null!=t&&t.markModified(this.$__path)}},{key:"delete",value:function(t){this.set(t,void 0),a(h(v.prototype),"delete",this).call(this,t)}},{key:"toBSON",value:function(){return new Map(this)}},{key:"toObject",value:function(t){if(m(t,"flattenMaps")){var e,r={},n=o(this.keys());try{for(n.s();!(e=n.n()).done;){var i=e.value;r[i]=this.get(i)}}catch(t){n.e(t)}finally{n.f()}return r}return new Map(this)}},{key:"toJSON",value:function(){var t,e={},r=o(this.keys());try{for(r.s();!(t=r.n()).done;){var n=t.value;e[n]=this.get(n)}}catch(t){r.e(t)}finally{r.f()}return e}},{key:"inspect",value:function(){return new Map(this)}},{key:"$__runDeferred",value:function(){if(this.$__deferred){var t,e=o(this.$__deferred);try{for(e.s();!(t=e.n()).done;){var r=t.value;this.set(r.key,r.value)}}catch(t){e.e(t)}finally{e.f()}this.$__deferred=null}}}])&&s(n.prototype,i),c&&s(n,c),v}(c(Map));
+/*!
+ * Since maps are stored as objects under the hood, keys must be strings
+ * and can't contain any invalid characters
+ */
+function O(t){var e=n(t);if("string"!==e)throw new TypeError("Mongoose maps only support string keys, got ".concat(e));if(t.startsWith("$"))throw new Error('Mongoose maps do not support keys that start with "$", got "'.concat(t,'"'));if(t.includes("."))throw new Error('Mongoose maps do not support keys that contain ".", got "'.concat(t,'"'));if(g.has(t))throw new Error('Mongoose maps do not support reserved key name "'.concat(t,'"'))}v.inspect.custom&&Object.defineProperty(w.prototype,v.inspect.custom,{enumerable:!1,writable:!1,configurable:!1,value:w.prototype.inspect}),Object.defineProperty(w.prototype,"$__set",{enumerable:!1,writable:!0,configurable:!1}),Object.defineProperty(w.prototype,"$__parent",{enumerable:!1,writable:!0,configurable:!1}),Object.defineProperty(w.prototype,"$__path",{enumerable:!1,writable:!0,configurable:!1}),Object.defineProperty(w.prototype,"$__schemaType",{enumerable:!1,writable:!0,configurable:!1}),Object.defineProperty(w.prototype,"$isMongooseMap",{enumerable:!1,writable:!1,configurable:!1,value:!0}),Object.defineProperty(w.prototype,"$__deferredCalls",{enumerable:!1,writable:!1,configurable:!1,value:!0}),t.exports=w},function(t,e,r){"use strict";var n=r(2);t.exports=function(t){return n.isPOJO(t)&&null!=t.$__&&null!=t._doc?t._doc:t}},function(t,e,r){"use strict";function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i=r(6),s=r(50),a=r(17).internalToObjectOptions,u=r(24),c=r(0).documentArrayParent;function l(t,e,r,o,s){var a=this;this.$isSingleNested=!0;var u=null!=s&&s.priorDoc,c=null;if(u&&(this._doc=Object.assign({},s.priorDoc._doc),delete this._doc[this.schema.options.discriminatorKey],c=Object.keys(s.priorDoc._doc||{}).filter((function(t){return t!==a.schema.options.discriminatorKey}))),null!=r&&(s=Object.assign({},s,{isNew:r.isNew,defaults:r.$__.$options.defaults})),i.call(this,t,e,o,s),u){var l,f=n(c);try{for(f.s();!(l=f.n()).done;){var p=l.value;if(!this.$__.activePaths.states.modify[p]&&!this.$__.activePaths.states.default[p]&&!this.$__.$setCalled.has(p)){var h=this.schema.path(p),y=null==h?void 0:h.getDefault(this);void 0===y?delete this._doc[p]:(this._doc[p]=y,this.$__.activePaths.default(p))}}}catch(t){f.e(t)}finally{f.f()}delete s.priorDoc,delete this.$__.$options.priorDoc}}t.exports=l,l.prototype=Object.create(i.prototype),l.prototype.toBSON=function(){return this.toObject(a)},l.prototype.save=function(t,e){var r=this;return"function"==typeof t&&(e=t,t={}),(t=t||{}).suppressWarning||console.warn("mongoose: calling `save()` on a subdoc does **not** save the document to MongoDB, it only runs save middleware. Use `subdoc.save({ suppressWarning: true })` to hide this warning if you're sure this behavior is right for your app."),u(e,(function(t){r.$__save(t)}))},l.prototype.$__save=function(t){var e=this;return s((function(){return t(null,e)}))},l.prototype.$isValid=function(t){return this.$parent&&this.$basePath?this.$parent.$isValid([this.$basePath,t].join(".")):i.prototype.$isValid.call(this,t)},l.prototype.markModified=function(t){if(i.prototype.markModified.call(this,t),this.$parent&&this.$basePath){if(this.$parent.isDirectModified(this.$basePath))return;this.$parent.markModified([this.$basePath,t].join("."),this)}},l.prototype.isModified=function(t,e){var r=this;return this.$parent&&this.$basePath?Array.isArray(t)||"string"==typeof t?(t=(t=Array.isArray(t)?t:t.split(" ")).map((function(t){return[r.$basePath,t].join(".")})),this.$parent.isModified(t,e)):this.$parent.isModified(this.$basePath):i.prototype.isModified.call(this,t,e)},l.prototype.$markValid=function(t){i.prototype.$markValid.call(this,t),this.$parent&&this.$basePath&&this.$parent.$markValid([this.$basePath,t].join("."))},
+/*!
+ * ignore
+ */
+l.prototype.invalidate=function(t,e,r){if(e!==this.ownerDocument().$__.validationError&&i.prototype.invalidate.call(this,t,e,r),this.$parent&&this.$basePath)this.$parent.invalidate([this.$basePath,t].join("."),e,r);else if("cast"===e.kind||"CastError"===e.name)throw e;return this.ownerDocument().$__.validationError},
+/*!
+ * ignore
+ */
+l.prototype.$ignore=function(t){i.prototype.$ignore.call(this,t),this.$parent&&this.$basePath&&this.$parent.$ignore([this.$basePath,t].join("."))},l.prototype.ownerDocument=function(){if(this.$__.ownerDocument)return this.$__.ownerDocument;var t=this.$parent;if(!t)return this;for(;t.$parent||t[c];)t=t.$parent||t[c];return this.$__.ownerDocument=t,this.$__.ownerDocument},l.prototype.parent=function(){return this.$parent},
+/*!
+ * no-op for hooks
+ */
+l.prototype.$__remove=function(t){return t(null,this)},l.prototype.remove=function(t,e){"function"==typeof t&&(e=t,t=null),
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {Subdocument} sub
+ * @api private
+ */
+function(t){var e=t.ownerDocument();function r(){e.removeListener("save",r),e.removeListener("remove",r),t.emit("remove",t),t.constructor.emit("remove",t),e=t=null}e.on("save",r),e.on("remove",r)}(this),t&&t.noop||this.$parent.set(this.$basePath,null),"function"==typeof e&&e(null)},
+/*!
+ * ignore
+ */
+l.prototype.populate=function(){throw new Error('Mongoose does not support calling populate() on nested docs. Instead of `doc.nested.populate("path")`, use `doc.populate("nested.path")`')}},function(t,e,r){"use strict";function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i=r(25),s=r(57).defineKey,a=r(3),u=r(2),c={toJSON:!0,toObject:!0,_id:!0,id:!0};
+/*!
+ * ignore
+ */
+t.exports=function(t,e,r,o,l){if(!r||!r.instanceOfSchema)throw new Error("You must pass a valid discriminator Schema");if(t.schema.discriminatorMapping&&!t.schema.discriminatorMapping.isRoot)throw new Error('Discriminator "'+e+'" can only be a discriminator of the root model');if(l){var f=a(t.base,"options.applyPluginsToDiscriminators",!1);t.base._applyPlugins(r,{skipTopLevel:!f})}var p=t.schema.options.discriminatorKey,h=t.schema.path(p);if(null!=h)u.hasUserDefinedProperty(h.options,"select")||(h.options.select=!0),h.options.$skipDiscriminatorCheck=!0;else{var y={};y[p]={default:void 0,select:!0,$skipDiscriminatorCheck:!0},y[p][t.schema.options.typeKey]=String,t.schema.add(y),s(p,null,t.prototype,null,[p],t.schema.options)}if(r.path(p)&&!0!==r.path(p).options.$skipDiscriminatorCheck)throw new Error('Discriminator "'+e+'" cannot have field with name "'+p+'"');var d=e;if("string"==typeof o&&o.length&&(d=o),function(e,r){e._baseSchema=r,r.paths._id&&r.paths._id.options&&!r.paths._id.options.auto&&e.remove("_id");for(var o=[],s=0,a=Object.keys(r.paths);s<a.length;s++){var l=a[s];if(e.nested[l])o.push(l);else if(-1!==l.indexOf(".")){var f,y="",m=n(l.split(".").slice(0,-1));try{for(m.s();!(f=m.n()).done;){var _=f.value;y+=(y.length?".":"")+_,(e.paths[y]instanceof i||e.singleNestedPaths[y]instanceof i)&&o.push(l)}}catch(t){m.e(t)}finally{m.f()}}}u.merge(e,r,{isDiscriminatorSchemaMerge:!0,omit:{discriminators:!0,base:!0},omitNested:o.reduce((function(t,e){return t["tree."+e]=!0,t}),{})});for(var v=0,g=o;v<g.length;v++){var b=g[v];delete e.paths[b]}e.childSchemas.forEach((function(t){t.model.prototype.$__setSchema(t.schema)}));var w={};w[p]={default:d,select:!0,set:function(t){if(t===d)return d;throw new Error("Can't set discriminator key \""+p+'"')},$skipDiscriminatorCheck:!0},w[p][e.options.typeKey]=h?h.instance:String,e.add(w),e.discriminatorMapping={key:p,value:d,isRoot:!1},r.options.collection&&(e.options.collection=r.options.collection);var O=e.options.toJSON,S=e.options.toObject,A=e.options._id,j=e.options.id,E=Object.keys(e.options);e.options.discriminatorKey=r.options.discriminatorKey;for(var $=0,x=E;$<x.length;$++){var P=x[$];if(!c[P]){if("pluralization"===P&&1==e.options[P]&&null==r.options[P])continue;if(!u.deepEqual(e.options[P],r.options[P]))throw new Error("Can't customize discriminator option "+P+" (can only modify "+Object.keys(c).join(", ")+")")}}e.options=u.clone(r.options),O&&(e.options.toJSON=O),S&&(e.options.toObject=S),void 0!==A&&(e.options._id=A),e.options.id=j,e.s.hooks=t.schema.s.hooks.merge(e.s.hooks),e.plugins=Array.prototype.slice.call(r.plugins),e.callQueue=r.callQueue.concat(e.callQueue),delete e._requiredpaths}(r,t.schema),t.discriminators||(t.discriminators={}),t.schema.discriminatorMapping||(t.schema.discriminatorMapping={key:p,value:null,isRoot:!0}),t.schema.discriminators||(t.schema.discriminators={}),t.schema.discriminators[e]=r,t.discriminators[e])throw new Error('Discriminator with name "'+e+'" already exists');return r}},function(t,e,r){"use strict";var n=r(74);t.exports=function(t,e){return null==e||null==e._id||(t=t.clone(),e._id?t.paths._id||(n(t),t.options._id=!0):(t.remove("_id"),t.options._id=!1)),t}},function(t,e,r){"use strict";var n=r(34);
+/*!
+ * Find the correct constructor, taking into account discriminators
+ */t.exports=function(t,e){var r=t.schema.options.discriminatorKey;if(null!=e&&t.discriminators&&null!=e[r])if(t.discriminators[e[r]])t=t.discriminators[e[r]];else{var o=n(t,e[r]);o&&(t=o)}return t}},function(t,e,r){"use strict";t.exports=r(94)},function(t,e,r){"use strict";(function(n){function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==o(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}r(15).set(r(98));var c=r(61),l=r(67);c.setBrowser(!0),Object.defineProperty(e,"Promise",{get:function(){return l.get()},set:function(t){l.set(t)}}),e.PromiseProvider=l,e.Error=r(5),e.Schema=r(52),e.Types=r(56),e.VirtualType=r(53),e.SchemaType=r(7),e.utils=r(2),e.Document=c(),e.model=function(t,r){var n=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(n,t);var e=s(n);function n(t,o){return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),e.call(this,t,r,o)}return n}(e.Document);return n.modelName=t,n},
+/*!
+ * Module exports.
+ */
+"undefined"!=typeof window&&(window.mongoose=t.exports,window.Buffer=n)}).call(this,r(1).Buffer)},function(t,e,r){"use strict";e.byteLength=function(t){var e=c(t),r=e[0],n=e[1];return 3*(r+n)/4-n},e.toByteArray=function(t){var e,r,n=c(t),s=n[0],a=n[1],u=new i(function(t,e,r){return 3*(e+r)/4-r}(0,s,a)),l=0,f=a>0?s-4:s;for(r=0;r<f;r+=4)e=o[t.charCodeAt(r)]<<18|o[t.charCodeAt(r+1)]<<12|o[t.charCodeAt(r+2)]<<6|o[t.charCodeAt(r+3)],u[l++]=e>>16&255,u[l++]=e>>8&255,u[l++]=255&e;2===a&&(e=o[t.charCodeAt(r)]<<2|o[t.charCodeAt(r+1)]>>4,u[l++]=255&e);1===a&&(e=o[t.charCodeAt(r)]<<10|o[t.charCodeAt(r+1)]<<4|o[t.charCodeAt(r+2)]>>2,u[l++]=e>>8&255,u[l++]=255&e);return u},e.fromByteArray=function(t){for(var e,r=t.length,o=r%3,i=[],s=0,a=r-o;s<a;s+=16383)i.push(l(t,s,s+16383>a?a:s+16383));1===o?(e=t[r-1],i.push(n[e>>2]+n[e<<4&63]+"==")):2===o&&(e=(t[r-2]<<8)+t[r-1],i.push(n[e>>10]+n[e>>4&63]+n[e<<2&63]+"="));return i.join("")};for(var n=[],o=[],i="undefined"!=typeof Uint8Array?Uint8Array:Array,s="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",a=0,u=s.length;a<u;++a)n[a]=s[a],o[s.charCodeAt(a)]=a;function c(t){var e=t.length;if(e%4>0)throw new Error("Invalid string. Length must be a multiple of 4");var r=t.indexOf("=");return-1===r&&(r=e),[r,r===e?0:4-r%4]}function l(t,e,r){for(var o,i,s=[],a=e;a<r;a+=3)o=(t[a]<<16&16711680)+(t[a+1]<<8&65280)+(255&t[a+2]),s.push(n[(i=o)>>18&63]+n[i>>12&63]+n[i>>6&63]+n[63&i]);return s.join("")}o["-".charCodeAt(0)]=62,o["_".charCodeAt(0)]=63},function(t,e){
+/*! ieee754. BSD-3-Clause License. Feross Aboukhadijeh <https://feross.org/opensource> */
+e.read=function(t,e,r,n,o){var i,s,a=8*o-n-1,u=(1<<a)-1,c=u>>1,l=-7,f=r?o-1:0,p=r?-1:1,h=t[e+f];for(f+=p,i=h&(1<<-l)-1,h>>=-l,l+=a;l>0;i=256*i+t[e+f],f+=p,l-=8);for(s=i&(1<<-l)-1,i>>=-l,l+=n;l>0;s=256*s+t[e+f],f+=p,l-=8);if(0===i)i=1-c;else{if(i===u)return s?NaN:1/0*(h?-1:1);s+=Math.pow(2,n),i-=c}return(h?-1:1)*s*Math.pow(2,i-n)},e.write=function(t,e,r,n,o,i){var s,a,u,c=8*i-o-1,l=(1<<c)-1,f=l>>1,p=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,h=n?0:i-1,y=n?1:-1,d=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=l):(s=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-s))<1&&(s--,u*=2),(e+=s+f>=1?p/u:p*Math.pow(2,1-f))*u>=2&&(s++,u/=2),s+f>=l?(a=0,s=l):s+f>=1?(a=(e*u-1)*Math.pow(2,o),s+=f):(a=e*Math.pow(2,f-1)*Math.pow(2,o),s=0));o>=8;t[r+h]=255&a,h+=y,a/=256,o-=8);for(s=s<<o|a,c+=o;c>0;t[r+h]=255&s,h+=y,s/=256,c-=8);t[r+h-y]|=128*d}},function(t,e){var r={}.toString;t.exports=Array.isArray||function(t){return"[object Array]"==r.call(t)}},function(t,e,r){"use strict";
+/*!
+ * Module exports.
+ */e.Binary=r(99),e.Collection=function(){throw new Error("Cannot create a collection from browser library")},e.Decimal128=r(106),e.ObjectId=r(107),e.ReadPreference=r(108)},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(35).Binary;
+/*!
+ * Module exports.
+ */t.exports=n},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports=function(t){return t&&"object"===r(t)&&"function"==typeof t.copy&&"function"==typeof t.fill&&"function"==typeof t.readUInt8}},function(t,e){"function"==typeof Object.create?t.exports=function(t,e){t.super_=e,t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}})}:t.exports=function(t,e){t.super_=e;var r=function(){};r.prototype=e.prototype,t.prototype=new r,t.prototype.constructor=t}},function(module,exports,__webpack_require__){"use strict";var Long=__webpack_require__(23).Long,Double=__webpack_require__(36).Double,Timestamp=__webpack_require__(37).Timestamp,ObjectID=__webpack_require__(38).ObjectID,_Symbol=__webpack_require__(40).Symbol,Code=__webpack_require__(41).Code,MinKey=__webpack_require__(43).MinKey,MaxKey=__webpack_require__(44).MaxKey,Decimal128=__webpack_require__(42),Int32=__webpack_require__(60),DBRef=__webpack_require__(45).DBRef,BSONRegExp=__webpack_require__(39).BSONRegExp,Binary=__webpack_require__(27).Binary,utils=__webpack_require__(16),deserialize=function(t,e,r){var n=(e=null==e?{}:e)&&e.index?e.index:0,o=t[n]|t[n+1]<<8|t[n+2]<<16|t[n+3]<<24;if(o<5||t.length<o||o+n>t.length)throw new Error("corrupt bson message");if(0!==t[n+o-1])throw new Error("One object, sized correctly, with a spot for an EOO, but the EOO isn't 0x00");return deserializeObject(t,n,e,r)},deserializeObject=function t(e,r,n,o){var i=null!=n.evalFunctions&&n.evalFunctions,s=null!=n.cacheFunctions&&n.cacheFunctions,a=null!=n.cacheFunctionsCrc32&&n.cacheFunctionsCrc32;if(!a)var u=null;var c=null==n.fieldsAsRaw?null:n.fieldsAsRaw,l=null!=n.raw&&n.raw,f="boolean"==typeof n.bsonRegExp&&n.bsonRegExp,p=null!=n.promoteBuffers&&n.promoteBuffers,h=null==n.promoteLongs||n.promoteLongs,y=null==n.promoteValues||n.promoteValues,d=r;if(e.length<5)throw new Error("corrupt bson message < 5 bytes long");var m=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;if(m<5||m>e.length)throw new Error("corrupt bson message");for(var _=o?[]:{},v=0;;){var g=e[r++];if(0===g)break;for(var b=r;0!==e[b]&&b<e.length;)b++;if(b>=e.length)throw new Error("Bad BSON Document: illegal CString");var w=o?v++:e.toString("utf8",r,b);if(r=b+1,g===BSON.BSON_DATA_STRING){var O=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;if(O<=0||O>e.length-r||0!==e[r+O-1])throw new Error("bad string length in bson");_[w]=e.toString("utf8",r,r+O-1),r+=O}else if(g===BSON.BSON_DATA_OID){var S=utils.allocBuffer(12);e.copy(S,0,r,r+12),_[w]=new ObjectID(S),r+=12}else if(g===BSON.BSON_DATA_INT&&!1===y)_[w]=new Int32(e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24);else if(g===BSON.BSON_DATA_INT)_[w]=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;else if(g===BSON.BSON_DATA_NUMBER&&!1===y)_[w]=new Double(e.readDoubleLE(r)),r+=8;else if(g===BSON.BSON_DATA_NUMBER)_[w]=e.readDoubleLE(r),r+=8;else if(g===BSON.BSON_DATA_DATE){var A=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24,j=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;_[w]=new Date(new Long(A,j).toNumber())}else if(g===BSON.BSON_DATA_BOOLEAN){if(0!==e[r]&&1!==e[r])throw new Error("illegal boolean type value");_[w]=1===e[r++]}else if(g===BSON.BSON_DATA_OBJECT){var E=r,$=e[r]|e[r+1]<<8|e[r+2]<<16|e[r+3]<<24;if($<=0||$>e.length-r)throw new Error("bad embedded document length in bson");_[w]=l?e.slice(r,r+$):t(e,E,n,!1),r+=$}else if(g===BSON.BSON_DATA_ARRAY){E=r;var x=n,P=r+($=e[r]|e[r+1]<<8|e[r+2]<<16|e[r+3]<<24);if(c&&c[w]){for(var N in x={},n)x[N]=n[N];x.raw=!0}if(_[w]=t(e,E,x,!0),0!==e[(r+=$)-1])throw new Error("invalid array terminator byte");if(r!==P)throw new Error("corrupted array bson")}else if(g===BSON.BSON_DATA_UNDEFINED)_[w]=void 0;else if(g===BSON.BSON_DATA_NULL)_[w]=null;else if(g===BSON.BSON_DATA_LONG){A=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24,j=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;var T=new Long(A,j);_[w]=h&&!0===y&&T.lessThanOrEqual(JS_INT_MAX_LONG)&&T.greaterThanOrEqual(JS_INT_MIN_LONG)?T.toNumber():T}else if(g===BSON.BSON_DATA_DECIMAL128){var k=utils.allocBuffer(16);e.copy(k,0,r,r+16),r+=16;var C=new Decimal128(k);_[w]=C.toObject?C.toObject():C}else if(g===BSON.BSON_DATA_BINARY){var D=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24,R=D,B=e[r++];if(D<0)throw new Error("Negative binary type element size found");if(D>e.length)throw new Error("Binary type size larger than document size");if(null!=e.slice){if(B===Binary.SUBTYPE_BYTE_ARRAY){if((D=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<0)throw new Error("Negative binary type element size found for subtype 0x02");if(D>R-4)throw new Error("Binary type with subtype 0x02 contains to long binary size");if(D<R-4)throw new Error("Binary type with subtype 0x02 contains to short binary size")}_[w]=p&&y?e.slice(r,r+D):new Binary(e.slice(r,r+D),B)}else{var M="undefined"!=typeof Uint8Array?new Uint8Array(new ArrayBuffer(D)):new Array(D);if(B===Binary.SUBTYPE_BYTE_ARRAY){if((D=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<0)throw new Error("Negative binary type element size found for subtype 0x02");if(D>R-4)throw new Error("Binary type with subtype 0x02 contains to long binary size");if(D<R-4)throw new Error("Binary type with subtype 0x02 contains to short binary size")}for(b=0;b<D;b++)M[b]=e[r+b];_[w]=p&&y?M:new Binary(M,B)}r+=D}else if(g===BSON.BSON_DATA_REGEXP&&!1===f){for(b=r;0!==e[b]&&b<e.length;)b++;if(b>=e.length)throw new Error("Bad BSON Document: illegal CString");var I=e.toString("utf8",r,b);for(b=r=b+1;0!==e[b]&&b<e.length;)b++;if(b>=e.length)throw new Error("Bad BSON Document: illegal CString");var F=e.toString("utf8",r,b);r=b+1;var L=new Array(F.length);for(b=0;b<F.length;b++)switch(F[b]){case"m":L[b]="m";break;case"s":L[b]="g";break;case"i":L[b]="i"}_[w]=new RegExp(I,L.join(""))}else if(g===BSON.BSON_DATA_REGEXP&&!0===f){for(b=r;0!==e[b]&&b<e.length;)b++;if(b>=e.length)throw new Error("Bad BSON Document: illegal CString");for(I=e.toString("utf8",r,b),b=r=b+1;0!==e[b]&&b<e.length;)b++;if(b>=e.length)throw new Error("Bad BSON Document: illegal CString");F=e.toString("utf8",r,b),r=b+1,_[w]=new BSONRegExp(I,F)}else if(g===BSON.BSON_DATA_SYMBOL){if((O=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<=0||O>e.length-r||0!==e[r+O-1])throw new Error("bad string length in bson");_[w]=new _Symbol(e.toString("utf8",r,r+O-1)),r+=O}else if(g===BSON.BSON_DATA_TIMESTAMP)A=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24,j=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24,_[w]=new Timestamp(A,j);else if(g===BSON.BSON_DATA_MIN_KEY)_[w]=new MinKey;else if(g===BSON.BSON_DATA_MAX_KEY)_[w]=new MaxKey;else if(g===BSON.BSON_DATA_CODE){if((O=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<=0||O>e.length-r||0!==e[r+O-1])throw new Error("bad string length in bson");var U=e.toString("utf8",r,r+O-1);if(i)if(s){var V=a?u(U):U;_[w]=isolateEvalWithHash(functionCache,V,U,_)}else _[w]=isolateEval(U);else _[w]=new Code(U);r+=O}else if(g===BSON.BSON_DATA_CODE_W_SCOPE){var q=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24;if(q<13)throw new Error("code_w_scope total size shorter minimum expected length");if((O=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<=0||O>e.length-r||0!==e[r+O-1])throw new Error("bad string length in bson");U=e.toString("utf8",r,r+O-1),E=r+=O,$=e[r]|e[r+1]<<8|e[r+2]<<16|e[r+3]<<24;var W=t(e,E,n,!1);if(r+=$,q<8+$+O)throw new Error("code_w_scope total size is to short, truncating scope");if(q>8+$+O)throw new Error("code_w_scope total size is to long, clips outer document");i?(s?(V=a?u(U):U,_[w]=isolateEvalWithHash(functionCache,V,U,_)):_[w]=isolateEval(U),_[w].scope=W):_[w]=new Code(U,W)}else{if(g!==BSON.BSON_DATA_DBPOINTER)throw new Error("Detected unknown BSON type "+g.toString(16)+' for fieldname "'+w+'", are you using the latest BSON parser');if((O=e[r++]|e[r++]<<8|e[r++]<<16|e[r++]<<24)<=0||O>e.length-r||0!==e[r+O-1])throw new Error("bad string length in bson");var H=e.toString("utf8",r,r+O-1);r+=O;var Y=utils.allocBuffer(12);e.copy(Y,0,r,r+12),S=new ObjectID(Y),r+=12;var K=H.split("."),z=K.shift(),Q=K.join(".");_[w]=new DBRef(Q,S,z)}}if(m!==r-d){if(o)throw new Error("corrupt array bson");throw new Error("corrupt object bson")}return null!=_.$id&&(_=new DBRef(_.$ref,_.$id,_.$db)),_},isolateEvalWithHash=function isolateEvalWithHash(functionCache,hash,functionString,object){var value=null;return null==functionCache[hash]&&(eval("value = "+functionString),functionCache[hash]=value),functionCache[hash].bind(object)},isolateEval=function isolateEval(functionString){var value=null;return eval("value = "+functionString),value},BSON={},functionCache=BSON.functionCache={};BSON.BSON_DATA_NUMBER=1,BSON.BSON_DATA_STRING=2,BSON.BSON_DATA_OBJECT=3,BSON.BSON_DATA_ARRAY=4,BSON.BSON_DATA_BINARY=5,BSON.BSON_DATA_UNDEFINED=6,BSON.BSON_DATA_OID=7,BSON.BSON_DATA_BOOLEAN=8,BSON.BSON_DATA_DATE=9,BSON.BSON_DATA_NULL=10,BSON.BSON_DATA_REGEXP=11,BSON.BSON_DATA_DBPOINTER=12,BSON.BSON_DATA_CODE=13,BSON.BSON_DATA_SYMBOL=14,BSON.BSON_DATA_CODE_W_SCOPE=15,BSON.BSON_DATA_INT=16,BSON.BSON_DATA_TIMESTAMP=17,BSON.BSON_DATA_LONG=18,BSON.BSON_DATA_DECIMAL128=19,BSON.BSON_DATA_MIN_KEY=255,BSON.BSON_DATA_MAX_KEY=127,BSON.BSON_BINARY_SUBTYPE_DEFAULT=0,BSON.BSON_BINARY_SUBTYPE_FUNCTION=1,BSON.BSON_BINARY_SUBTYPE_BYTE_ARRAY=2,BSON.BSON_BINARY_SUBTYPE_UUID=3,BSON.BSON_BINARY_SUBTYPE_MD5=4,BSON.BSON_BINARY_SUBTYPE_USER_DEFINED=128,BSON.BSON_INT32_MAX=2147483647,BSON.BSON_INT32_MIN=-2147483648,BSON.BSON_INT64_MAX=Math.pow(2,63)-1,BSON.BSON_INT64_MIN=-Math.pow(2,63),BSON.JS_INT_MAX=9007199254740992,BSON.JS_INT_MIN=-9007199254740992;var JS_INT_MAX_LONG=Long.fromNumber(9007199254740992),JS_INT_MIN_LONG=Long.fromNumber(-9007199254740992);module.exports=deserialize},function(t,e,r){"use strict";(function(e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(104).writeIEEE754,i=r(23).Long,s=r(59),a=r(27).Binary,u=r(16).normalizedFunctionString,c=/\x00/,l=["$db","$ref","$id","$clusterTime"],f=function(t){return"object"===n(t)&&"[object Date]"===Object.prototype.toString.call(t)},p=function(t){return"[object RegExp]"===Object.prototype.toString.call(t)},h=function(t,e,r,n,o){t[n++]=D.BSON_DATA_STRING;var i=o?t.write(e,n,"ascii"):t.write(e,n,"utf8");t[(n=n+i+1)-1]=0;var s=t.write(r,n+4,"utf8");return t[n+3]=s+1>>24&255,t[n+2]=s+1>>16&255,t[n+1]=s+1>>8&255,t[n]=s+1&255,n=n+4+s,t[n++]=0,n},y=function(t,e,r,n,s){if(Math.floor(r)===r&&r>=D.JS_INT_MIN&&r<=D.JS_INT_MAX)if(r>=D.BSON_INT32_MIN&&r<=D.BSON_INT32_MAX){t[n++]=D.BSON_DATA_INT;var a=s?t.write(e,n,"ascii"):t.write(e,n,"utf8");n+=a,t[n++]=0,t[n++]=255&r,t[n++]=r>>8&255,t[n++]=r>>16&255,t[n++]=r>>24&255}else if(r>=D.JS_INT_MIN&&r<=D.JS_INT_MAX)t[n++]=D.BSON_DATA_NUMBER,n+=a=s?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,o(t,r,n,"little",52,8),n+=8;else{t[n++]=D.BSON_DATA_LONG,n+=a=s?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var u=i.fromNumber(r),c=u.getLowBits(),l=u.getHighBits();t[n++]=255&c,t[n++]=c>>8&255,t[n++]=c>>16&255,t[n++]=c>>24&255,t[n++]=255&l,t[n++]=l>>8&255,t[n++]=l>>16&255,t[n++]=l>>24&255}else t[n++]=D.BSON_DATA_NUMBER,n+=a=s?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,o(t,r,n,"little",52,8),n+=8;return n},d=function(t,e,r,n,o){return t[n++]=D.BSON_DATA_NULL,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,n},m=function(t,e,r,n,o){return t[n++]=D.BSON_DATA_BOOLEAN,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,t[n++]=r?1:0,n},_=function(t,e,r,n,o){t[n++]=D.BSON_DATA_DATE,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var s=i.fromNumber(r.getTime()),a=s.getLowBits(),u=s.getHighBits();return t[n++]=255&a,t[n++]=a>>8&255,t[n++]=a>>16&255,t[n++]=a>>24&255,t[n++]=255&u,t[n++]=u>>8&255,t[n++]=u>>16&255,t[n++]=u>>24&255,n},v=function(t,e,r,n,o){if(t[n++]=D.BSON_DATA_REGEXP,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,r.source&&null!=r.source.match(c))throw Error("value "+r.source+" must not contain null bytes");return n+=t.write(r.source,n,"utf8"),t[n++]=0,r.global&&(t[n++]=115),r.ignoreCase&&(t[n++]=105),r.multiline&&(t[n++]=109),t[n++]=0,n},g=function(t,e,r,n,o){if(t[n++]=D.BSON_DATA_REGEXP,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,null!=r.pattern.match(c))throw Error("pattern "+r.pattern+" must not contain null bytes");return n+=t.write(r.pattern,n,"utf8"),t[n++]=0,n+=t.write(r.options.split("").sort().join(""),n,"utf8"),t[n++]=0,n},b=function(t,e,r,n,o){return null===r?t[n++]=D.BSON_DATA_NULL:"MinKey"===r._bsontype?t[n++]=D.BSON_DATA_MIN_KEY:t[n++]=D.BSON_DATA_MAX_KEY,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,n},w=function(t,e,r,n,o){if(t[n++]=D.BSON_DATA_OID,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,"string"==typeof r.id)t.write(r.id,n,"binary");else{if(!r.id||!r.id.copy)throw new Error("object ["+JSON.stringify(r)+"] is not a valid ObjectId");r.id.copy(t,n,0,12)}return n+12},O=function(t,e,r,n,o){t[n++]=D.BSON_DATA_BINARY,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var i=r.length;return t[n++]=255&i,t[n++]=i>>8&255,t[n++]=i>>16&255,t[n++]=i>>24&255,t[n++]=D.BSON_BINARY_SUBTYPE_DEFAULT,r.copy(t,n,0,i),n+=i},S=function(t,e,r,n,o,i,s,a,u,c){for(var l=0;l<c.length;l++)if(c[l]===r)throw new Error("cyclic dependency detected");c.push(r),t[n++]=Array.isArray(r)?D.BSON_DATA_ARRAY:D.BSON_DATA_OBJECT,n+=u?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var f=C(t,r,o,n,i+1,s,a,c);return c.pop(),f},A=function(t,e,r,n,o){return t[n++]=D.BSON_DATA_DECIMAL128,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,r.bytes.copy(t,n,0,16),n+16},j=function(t,e,r,n,o){t[n++]="Long"===r._bsontype?D.BSON_DATA_LONG:D.BSON_DATA_TIMESTAMP,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var i=r.getLowBits(),s=r.getHighBits();return t[n++]=255&i,t[n++]=i>>8&255,t[n++]=i>>16&255,t[n++]=i>>24&255,t[n++]=255&s,t[n++]=s>>8&255,t[n++]=s>>16&255,t[n++]=s>>24&255,n},E=function(t,e,r,n,o){return t[n++]=D.BSON_DATA_INT,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,t[n++]=255&r,t[n++]=r>>8&255,t[n++]=r>>16&255,t[n++]=r>>24&255,n},$=function(t,e,r,n,i){return t[n++]=D.BSON_DATA_NUMBER,n+=i?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0,o(t,r,n,"little",52,8),n+=8},x=function(t,e,r,n,o,i,s){t[n++]=D.BSON_DATA_CODE,n+=s?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var a=u(r),c=t.write(a,n+4,"utf8")+1;return t[n]=255&c,t[n+1]=c>>8&255,t[n+2]=c>>16&255,t[n+3]=c>>24&255,n=n+4+c-1,t[n++]=0,n},P=function(t,e,r,o,i,s,a,u,c){if(r.scope&&"object"===n(r.scope)){t[o++]=D.BSON_DATA_CODE_W_SCOPE;var l=c?t.write(e,o,"ascii"):t.write(e,o,"utf8");o+=l,t[o++]=0;var f=o,p="string"==typeof r.code?r.code:r.code.toString();o+=4;var h=t.write(p,o+4,"utf8")+1;t[o]=255&h,t[o+1]=h>>8&255,t[o+2]=h>>16&255,t[o+3]=h>>24&255,t[o+4+h-1]=0,o=o+h+4;var y=C(t,r.scope,i,o,s+1,a,u);o=y-1;var d=y-f;t[f++]=255&d,t[f++]=d>>8&255,t[f++]=d>>16&255,t[f++]=d>>24&255,t[o++]=0}else{t[o++]=D.BSON_DATA_CODE,o+=l=c?t.write(e,o,"ascii"):t.write(e,o,"utf8"),t[o++]=0,p=r.code.toString();var m=t.write(p,o+4,"utf8")+1;t[o]=255&m,t[o+1]=m>>8&255,t[o+2]=m>>16&255,t[o+3]=m>>24&255,o=o+4+m-1,t[o++]=0}return o},N=function(t,e,r,n,o){t[n++]=D.BSON_DATA_BINARY,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var i=r.value(!0),s=r.position;return r.sub_type===a.SUBTYPE_BYTE_ARRAY&&(s+=4),t[n++]=255&s,t[n++]=s>>8&255,t[n++]=s>>16&255,t[n++]=s>>24&255,t[n++]=r.sub_type,r.sub_type===a.SUBTYPE_BYTE_ARRAY&&(s-=4,t[n++]=255&s,t[n++]=s>>8&255,t[n++]=s>>16&255,t[n++]=s>>24&255),i.copy(t,n,0,r.position),n+=r.position},T=function(t,e,r,n,o){t[n++]=D.BSON_DATA_SYMBOL,n+=o?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var i=t.write(r.value,n+4,"utf8")+1;return t[n]=255&i,t[n+1]=i>>8&255,t[n+2]=i>>16&255,t[n+3]=i>>24&255,n=n+4+i-1,t[n++]=0,n},k=function(t,e,r,n,o,i,s){t[n++]=D.BSON_DATA_OBJECT,n+=s?t.write(e,n,"ascii"):t.write(e,n,"utf8"),t[n++]=0;var a,u=n,c=(a=null!=r.db?C(t,{$ref:r.namespace,$id:r.oid,$db:r.db},!1,n,o+1,i):C(t,{$ref:r.namespace,$id:r.oid},!1,n,o+1,i))-u;return t[u++]=255&c,t[u++]=c>>8&255,t[u++]=c>>16&255,t[u++]=c>>24&255,a},C=function(t,r,o,i,a,u,C,D){i=i||0,(D=D||[]).push(r);var R=i+4;if(Array.isArray(r))for(var B=0;B<r.length;B++){var M=""+B,I=r[B];if(I&&I.toBSON){if("function"!=typeof I.toBSON)throw new Error("toBSON is not a function");I=I.toBSON()}var F=n(I);if("string"===F)R=h(t,M,I,R,!0);else if("number"===F)R=y(t,M,I,R,!0);else if("boolean"===F)R=m(t,M,I,R,!0);else if(I instanceof Date||f(I))R=_(t,M,I,R,!0);else if(void 0===I)R=d(t,M,0,R,!0);else if(null===I)R=d(t,M,0,R,!0);else if("ObjectID"===I._bsontype||"ObjectId"===I._bsontype)R=w(t,M,I,R,!0);else if(e.isBuffer(I))R=O(t,M,I,R,!0);else if(I instanceof RegExp||p(I))R=v(t,M,I,R,!0);else if("object"===F&&null==I._bsontype)R=S(t,M,I,R,o,a,u,C,!0,D);else if("object"===F&&"Decimal128"===I._bsontype)R=A(t,M,I,R,!0);else if("Long"===I._bsontype||"Timestamp"===I._bsontype)R=j(t,M,I,R,!0);else if("Double"===I._bsontype)R=$(t,M,I,R,!0);else if("function"==typeof I&&u)R=x(t,M,I,R,0,0,u);else if("Code"===I._bsontype)R=P(t,M,I,R,o,a,u,C,!0);else if("Binary"===I._bsontype)R=N(t,M,I,R,!0);else if("Symbol"===I._bsontype)R=T(t,M,I,R,!0);else if("DBRef"===I._bsontype)R=k(t,M,I,R,a,u,!0);else if("BSONRegExp"===I._bsontype)R=g(t,M,I,R,!0);else if("Int32"===I._bsontype)R=E(t,M,I,R,!0);else if("MinKey"===I._bsontype||"MaxKey"===I._bsontype)R=b(t,M,I,R,!0);else if(void 0!==I._bsontype)throw new TypeError("Unrecognized or invalid _bsontype: "+I._bsontype)}else if(r instanceof s)for(var L=r.entries(),U=!1;!U;){var V=L.next();if(!(U=V.done)){if(M=V.value[0],F=n(I=V.value[1]),"string"==typeof M&&-1===l.indexOf(M)){if(null!=M.match(c))throw Error("key "+M+" must not contain null bytes");if(o){if("$"===M[0])throw Error("key "+M+" must not start with '$'");if(~M.indexOf("."))throw Error("key "+M+" must not contain '.'")}}if("string"===F)R=h(t,M,I,R);else if("number"===F)R=y(t,M,I,R);else if("boolean"===F)R=m(t,M,I,R);else if(I instanceof Date||f(I))R=_(t,M,I,R);else if(null===I||void 0===I&&!1===C)R=d(t,M,0,R);else if("ObjectID"===I._bsontype||"ObjectId"===I._bsontype)R=w(t,M,I,R);else if(e.isBuffer(I))R=O(t,M,I,R);else if(I instanceof RegExp||p(I))R=v(t,M,I,R);else if("object"===F&&null==I._bsontype)R=S(t,M,I,R,o,a,u,C,!1,D);else if("object"===F&&"Decimal128"===I._bsontype)R=A(t,M,I,R);else if("Long"===I._bsontype||"Timestamp"===I._bsontype)R=j(t,M,I,R);else if("Double"===I._bsontype)R=$(t,M,I,R);else if("Code"===I._bsontype)R=P(t,M,I,R,o,a,u,C);else if("function"==typeof I&&u)R=x(t,M,I,R,0,0,u);else if("Binary"===I._bsontype)R=N(t,M,I,R);else if("Symbol"===I._bsontype)R=T(t,M,I,R);else if("DBRef"===I._bsontype)R=k(t,M,I,R,a,u);else if("BSONRegExp"===I._bsontype)R=g(t,M,I,R);else if("Int32"===I._bsontype)R=E(t,M,I,R);else if("MinKey"===I._bsontype||"MaxKey"===I._bsontype)R=b(t,M,I,R);else if(void 0!==I._bsontype)throw new TypeError("Unrecognized or invalid _bsontype: "+I._bsontype)}}else{if(r.toBSON){if("function"!=typeof r.toBSON)throw new Error("toBSON is not a function");if(null!=(r=r.toBSON())&&"object"!==n(r))throw new Error("toBSON function did not return an object")}for(M in r){if((I=r[M])&&I.toBSON){if("function"!=typeof I.toBSON)throw new Error("toBSON is not a function");I=I.toBSON()}if(F=n(I),"string"==typeof M&&-1===l.indexOf(M)){if(null!=M.match(c))throw Error("key "+M+" must not contain null bytes");if(o){if("$"===M[0])throw Error("key "+M+" must not start with '$'");if(~M.indexOf("."))throw Error("key "+M+" must not contain '.'")}}if("string"===F)R=h(t,M,I,R);else if("number"===F)R=y(t,M,I,R);else if("boolean"===F)R=m(t,M,I,R);else if(I instanceof Date||f(I))R=_(t,M,I,R);else if(void 0===I)!1===C&&(R=d(t,M,0,R));else if(null===I)R=d(t,M,0,R);else if("ObjectID"===I._bsontype||"ObjectId"===I._bsontype)R=w(t,M,I,R);else if(e.isBuffer(I))R=O(t,M,I,R);else if(I instanceof RegExp||p(I))R=v(t,M,I,R);else if("object"===F&&null==I._bsontype)R=S(t,M,I,R,o,a,u,C,!1,D);else if("object"===F&&"Decimal128"===I._bsontype)R=A(t,M,I,R);else if("Long"===I._bsontype||"Timestamp"===I._bsontype)R=j(t,M,I,R);else if("Double"===I._bsontype)R=$(t,M,I,R);else if("Code"===I._bsontype)R=P(t,M,I,R,o,a,u,C);else if("function"==typeof I&&u)R=x(t,M,I,R,0,0,u);else if("Binary"===I._bsontype)R=N(t,M,I,R);else if("Symbol"===I._bsontype)R=T(t,M,I,R);else if("DBRef"===I._bsontype)R=k(t,M,I,R,a,u);else if("BSONRegExp"===I._bsontype)R=g(t,M,I,R);else if("Int32"===I._bsontype)R=E(t,M,I,R);else if("MinKey"===I._bsontype||"MaxKey"===I._bsontype)R=b(t,M,I,R);else if(void 0!==I._bsontype)throw new TypeError("Unrecognized or invalid _bsontype: "+I._bsontype)}}D.pop(),t[R++]=0;var q=R-i;return t[i++]=255&q,t[i++]=q>>8&255,t[i++]=q>>16&255,t[i++]=q>>24&255,R},D={BSON_DATA_NUMBER:1,BSON_DATA_STRING:2,BSON_DATA_OBJECT:3,BSON_DATA_ARRAY:4,BSON_DATA_BINARY:5,BSON_DATA_UNDEFINED:6,BSON_DATA_OID:7,BSON_DATA_BOOLEAN:8,BSON_DATA_DATE:9,BSON_DATA_NULL:10,BSON_DATA_REGEXP:11,BSON_DATA_CODE:13,BSON_DATA_SYMBOL:14,BSON_DATA_CODE_W_SCOPE:15,BSON_DATA_INT:16,BSON_DATA_TIMESTAMP:17,BSON_DATA_LONG:18,BSON_DATA_DECIMAL128:19,BSON_DATA_MIN_KEY:255,BSON_DATA_MAX_KEY:127,BSON_BINARY_SUBTYPE_DEFAULT:0,BSON_BINARY_SUBTYPE_FUNCTION:1,BSON_BINARY_SUBTYPE_BYTE_ARRAY:2,BSON_BINARY_SUBTYPE_UUID:3,BSON_BINARY_SUBTYPE_MD5:4,BSON_BINARY_SUBTYPE_USER_DEFINED:128,BSON_INT32_MAX:2147483647,BSON_INT32_MIN:-2147483648};D.BSON_INT64_MAX=Math.pow(2,63)-1,D.BSON_INT64_MIN=-Math.pow(2,63),D.JS_INT_MAX=9007199254740992,D.JS_INT_MIN=-9007199254740992,t.exports=C}).call(this,r(1).Buffer)},function(t,e){e.readIEEE754=function(t,e,r,n,o){var i,s,a="big"===r,u=8*o-n-1,c=(1<<u)-1,l=c>>1,f=-7,p=a?0:o-1,h=a?1:-1,y=t[e+p];for(p+=h,i=y&(1<<-f)-1,y>>=-f,f+=u;f>0;i=256*i+t[e+p],p+=h,f-=8);for(s=i&(1<<-f)-1,i>>=-f,f+=n;f>0;s=256*s+t[e+p],p+=h,f-=8);if(0===i)i=1-l;else{if(i===c)return s?NaN:1/0*(y?-1:1);s+=Math.pow(2,n),i-=l}return(y?-1:1)*s*Math.pow(2,i-n)},e.writeIEEE754=function(t,e,r,n,o,i){var s,a,u,c="big"===n,l=8*i-o-1,f=(1<<l)-1,p=f>>1,h=23===o?Math.pow(2,-24)-Math.pow(2,-77):0,y=c?i-1:0,d=c?-1:1,m=e<0||0===e&&1/e<0?1:0;for(e=Math.abs(e),isNaN(e)||e===1/0?(a=isNaN(e)?1:0,s=f):(s=Math.floor(Math.log(e)/Math.LN2),e*(u=Math.pow(2,-s))<1&&(s--,u*=2),(e+=s+p>=1?h/u:h*Math.pow(2,1-p))*u>=2&&(s++,u/=2),s+p>=f?(a=0,s=f):s+p>=1?(a=(e*u-1)*Math.pow(2,o),s+=p):(a=e*Math.pow(2,p-1)*Math.pow(2,o),s=0));o>=8;t[r+y]=255&a,y+=d,a/=256,o-=8);for(s=s<<o|a,l+=o;l>0;t[r+y]=255&s,y+=d,s/=256,l-=8);t[r+y-d]|=128*m}},function(t,e,r){"use strict";(function(e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(23).Long,i=r(36).Double,s=r(37).Timestamp,a=r(38).ObjectID,u=r(40).Symbol,c=r(39).BSONRegExp,l=r(41).Code,f=r(42),p=r(43).MinKey,h=r(44).MaxKey,y=r(45).DBRef,d=r(27).Binary,m=r(16).normalizedFunctionString,_=function(t,e,r){var n=5;if(Array.isArray(t))for(var o=0;o<t.length;o++)n+=v(o.toString(),t[o],e,!0,r);else for(var i in t.toBSON&&(t=t.toBSON()),t)n+=v(i,t[i],e,!1,r);return n};function v(t,r,v,b,w){switch(r&&r.toBSON&&(r=r.toBSON()),n(r)){case"string":return 1+e.byteLength(t,"utf8")+1+4+e.byteLength(r,"utf8")+1;case"number":return Math.floor(r)===r&&r>=g.JS_INT_MIN&&r<=g.JS_INT_MAX&&r>=g.BSON_INT32_MIN&&r<=g.BSON_INT32_MAX?(null!=t?e.byteLength(t,"utf8")+1:0)+5:(null!=t?e.byteLength(t,"utf8")+1:0)+9;case"undefined":return b||!w?(null!=t?e.byteLength(t,"utf8")+1:0)+1:0;case"boolean":return(null!=t?e.byteLength(t,"utf8")+1:0)+2;case"object":if(null==r||r instanceof p||r instanceof h||"MinKey"===r._bsontype||"MaxKey"===r._bsontype)return(null!=t?e.byteLength(t,"utf8")+1:0)+1;if(r instanceof a||"ObjectID"===r._bsontype||"ObjectId"===r._bsontype)return(null!=t?e.byteLength(t,"utf8")+1:0)+13;if(r instanceof Date||"object"===n(S=r)&&"[object Date]"===Object.prototype.toString.call(S))return(null!=t?e.byteLength(t,"utf8")+1:0)+9;if(void 0!==e&&e.isBuffer(r))return(null!=t?e.byteLength(t,"utf8")+1:0)+6+r.length;if(r instanceof o||r instanceof i||r instanceof s||"Long"===r._bsontype||"Double"===r._bsontype||"Timestamp"===r._bsontype)return(null!=t?e.byteLength(t,"utf8")+1:0)+9;if(r instanceof f||"Decimal128"===r._bsontype)return(null!=t?e.byteLength(t,"utf8")+1:0)+17;if(r instanceof l||"Code"===r._bsontype)return null!=r.scope&&Object.keys(r.scope).length>0?(null!=t?e.byteLength(t,"utf8")+1:0)+1+4+4+e.byteLength(r.code.toString(),"utf8")+1+_(r.scope,v,w):(null!=t?e.byteLength(t,"utf8")+1:0)+1+4+e.byteLength(r.code.toString(),"utf8")+1;if(r instanceof d||"Binary"===r._bsontype)return r.sub_type===d.SUBTYPE_BYTE_ARRAY?(null!=t?e.byteLength(t,"utf8")+1:0)+(r.position+1+4+1+4):(null!=t?e.byteLength(t,"utf8")+1:0)+(r.position+1+4+1);if(r instanceof u||"Symbol"===r._bsontype)return(null!=t?e.byteLength(t,"utf8")+1:0)+e.byteLength(r.value,"utf8")+4+1+1;if(r instanceof y||"DBRef"===r._bsontype){var O={$ref:r.namespace,$id:r.oid};return null!=r.db&&(O.$db=r.db),(null!=t?e.byteLength(t,"utf8")+1:0)+1+_(O,v,w)}return r instanceof RegExp||"[object RegExp]"===Object.prototype.toString.call(r)?(null!=t?e.byteLength(t,"utf8")+1:0)+1+e.byteLength(r.source,"utf8")+1+(r.global?1:0)+(r.ignoreCase?1:0)+(r.multiline?1:0)+1:r instanceof c||"BSONRegExp"===r._bsontype?(null!=t?e.byteLength(t,"utf8")+1:0)+1+e.byteLength(r.pattern,"utf8")+1+e.byteLength(r.options,"utf8")+1:(null!=t?e.byteLength(t,"utf8")+1:0)+_(r,v,w)+1;case"function":if(r instanceof RegExp||"[object RegExp]"===Object.prototype.toString.call(r)||"[object RegExp]"===String.call(r))return(null!=t?e.byteLength(t,"utf8")+1:0)+1+e.byteLength(r.source,"utf8")+1+(r.global?1:0)+(r.ignoreCase?1:0)+(r.multiline?1:0)+1;if(v&&null!=r.scope&&Object.keys(r.scope).length>0)return(null!=t?e.byteLength(t,"utf8")+1:0)+1+4+4+e.byteLength(m(r),"utf8")+1+_(r.scope,v,w);if(v)return(null!=t?e.byteLength(t,"utf8")+1:0)+1+4+e.byteLength(m(r),"utf8")+1}var S;return 0}var g={BSON_INT32_MAX:2147483647,BSON_INT32_MIN:-2147483648,JS_INT_MAX:9007199254740992,JS_INT_MIN:-9007199254740992};t.exports=_}).call(this,r(1).Buffer)},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */t.exports=r(35).Decimal128},function(t,e,r){"use strict";
+/*!
+ * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId
+ * @constructor NodeMongoDbObjectId
+ * @see ObjectId
+ */var n=r(35).ObjectID;
+/*!
+ * Getter for convenience with populate, see gh-6115
+ */Object.defineProperty(n.prototype,"_id",{enumerable:!1,configurable:!0,get:function(){return this}}),
+/*!
+ * ignore
+ */
+t.exports=n},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */t.exports=function(){}},function(t,e,r){"use strict";
+/*!
+ * Dependencies
+ */var n=r(110).ctor("require","modify","init","default","ignore");t.exports=function(){this.strictMode=void 0,this.selected=void 0,this.shardval=void 0,this.saveError=void 0,this.validationError=void 0,this.adhocPaths=void 0,this.removing=void 0,this.inserting=void 0,this.saving=void 0,this.version=void 0,this.getters={},this._id=void 0,this.populate=void 0,this.populated=void 0,this.wasPopulated=!1,this.scope=void 0,this.activePaths=new n,this.pathsToScopes={},this.cachedRequired={},this.session=null,this.$setCalled=new Set,this.ownerDocument=void 0,this.fullPath=void 0}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(2),o=t.exports=function(){};
+/*!
+ * StateMachine represents a minimal `interface` for the
+ * constructors it builds via StateMachine.ctor(...).
+ *
+ * @api private
+ */
+/*!
+ * StateMachine.ctor('state1', 'state2', ...)
+ * A factory method for subclassing StateMachine.
+ * The arguments are a list of states. For each state,
+ * the constructor's prototype gets state transition
+ * methods named after each state. These transition methods
+ * place their path argument into the given state.
+ *
+ * @param {String} state
+ * @param {String} [state]
+ * @return {Function} subclass constructor
+ * @private
+ */
+o.ctor=function(){var t=n.args(arguments),e=function(){o.apply(this,arguments),this.paths={},this.states={},this.stateNames=t;for(var e,r=t.length;r--;)e=t[r],this.states[e]={}};return e.prototype=new o,t.forEach((function(t){e.prototype[t]=function(e){this._changeState(e,t)}})),e},
+/*!
+ * This function is wrapped by the state change functions:
+ *
+ * - `require(path)`
+ * - `modify(path)`
+ * - `init(path)`
+ *
+ * @api private
+ */
+o.prototype._changeState=function(t,e){var r=this.states[this.paths[t]];r&&delete r[t],this.paths[t]=e,this.states[e][t]=!0},
+/*!
+ * ignore
+ */
+o.prototype.clear=function(t){for(var e,r=Object.keys(this.states[t]),n=r.length;n--;)e=r[n],delete this.states[t][e],delete this.paths[e]},
+/*!
+ * Checks to see if at least one path is in the states passed in via `arguments`
+ * e.g., this.some('required', 'inited')
+ *
+ * @param {String} state that we want to check for.
+ * @private
+ */
+o.prototype.some=function(){var t=this,e=arguments.length?arguments:this.stateNames;return Array.prototype.some.call(e,(function(e){return Object.keys(t.states[e]).length}))},
+/*!
+ * This function builds the functions that get assigned to `forEach` and `map`,
+ * since both of those methods share a lot of the same logic.
+ *
+ * @param {String} iterMethod is either 'forEach' or 'map'
+ * @return {Function}
+ * @api private
+ */
+o.prototype._iter=function(t){return function(){var e=arguments.length,r=n.args(arguments,0,e-1),o=arguments[e-1];r.length||(r=this.stateNames);var i=this,s=r.reduce((function(t,e){return t.concat(Object.keys(i.states[e]))}),[]);return s[t]((function(t,e,r){return o(t,e,r)}))}},
+/*!
+ * Iterates over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @private
+ */
+o.prototype.forEach=function(){return this.forEach=this._iter("forEach"),this.forEach.apply(this,arguments)},
+/*!
+ * Maps over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @return {Array}
+ * @private
+ */
+o.prototype.map=function(){return this.map=this._iter("map"),this.map.apply(this,arguments)}},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n=1e3,o=6e4,i=60*o,s=24*i;function a(t,e,r,n){var o=e>=1.5*r;return Math.round(t/r)+" "+n+(o?"s":"")}t.exports=function(t,e){e=e||{};var u=r(t);if("string"===u&&t.length>0)return function(t){if((t=String(t)).length>100)return;var e=/^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(t);if(!e)return;var r=parseFloat(e[1]);switch((e[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*r;case"weeks":case"week":case"w":return 6048e5*r;case"days":case"day":case"d":return r*s;case"hours":case"hour":case"hrs":case"hr":case"h":return r*i;case"minutes":case"minute":case"mins":case"min":case"m":return r*o;case"seconds":case"second":case"secs":case"sec":case"s":return r*n;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}(t);if("number"===u&&isFinite(t))return e.long?function(t){var e=Math.abs(t);if(e>=s)return a(t,e,s,"day");if(e>=i)return a(t,e,i,"hour");if(e>=o)return a(t,e,o,"minute");if(e>=n)return a(t,e,n,"second");return t+" ms"}(t):function(t){var e=Math.abs(t);if(e>=s)return Math.round(t/s)+"d";if(e>=i)return Math.round(t/i)+"h";if(e>=o)return Math.round(t/o)+"m";if(e>=n)return Math.round(t/n)+"s";return t+"ms"}(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n=["__proto__","constructor","prototype"];
+/*!
+ * Returns the value passed to it.
+ */
+function o(t){return t}e.get=function(t,r,n,i){var s;"function"==typeof n&&(n.length<2?(i=n,n=void 0):(s=n,n=void 0)),i||(i=o);var a="string"==typeof t?t.split("."):t;if(!Array.isArray(a))throw new TypeError("Invalid `path`. Must be either string or array");for(var u,c=r,l=0;l<a.length;++l){if(u=a[l],Array.isArray(c)&&!/^\d+$/.test(u)){var f=a.slice(l);return[].concat(c).map((function(t){return t?e.get(f,t,n||s,i):i(void 0)}))}if(s)c=s(c,u);else{var p=n&&c[n]?c[n]:c;c=p instanceof Map?p.get(u):p[u]}if(!c)return i(c)}return i(c)},e.has=function(t,e){var n="string"==typeof t?t.split("."):t;if(!Array.isArray(n))throw new TypeError("Invalid `path`. Must be either string or array");for(var o=n.length,i=e,s=0;s<o;++s){if(null==i||"object"!==r(i)||!(n[s]in i))return!1;i=i[n[s]]}return!0},e.unset=function(t,e){var o="string"==typeof t?t.split("."):t;if(!Array.isArray(o))throw new TypeError("Invalid `path`. Must be either string or array");for(var i=o.length,s=e,a=0;a<i;++a){if(null==s||"object"!==r(s)||!(o[a]in s))return!1;if(-1!==n.indexOf(o[a]))return!1;if(a===i-1)return delete s[o[a]],!0;s=s instanceof Map?s.get(o[a]):s[o[a]]}return!0},e.set=function(t,r,i,s,a,u){var c;"function"==typeof s&&(s.length<2?(a=s,s=void 0):(c=s,s=void 0)),a||(a=o);var l="string"==typeof t?t.split("."):t;if(!Array.isArray(l))throw new TypeError("Invalid `path`. Must be either string or array");if(null!=i){for(var f=0;f<l.length;++f)if(-1!==n.indexOf(l[f]))return;for(var p,h=u||/\$/.test(t)&&!1!==u,y=i,d=(f=0,l.length-1);f<d;++f)if("$"!=(p=l[f])){if(Array.isArray(y)&&!/^\d+$/.test(p)){var m=l.slice(f);if(!h&&Array.isArray(r))for(var _=0;_<y.length&&_<r.length;++_)e.set(m,r[_],y[_],s||c,a,h);else for(_=0;_<y.length;++_)e.set(m,r,y[_],s||c,a,h);return}if(c)y=c(y,p);else{var v=s&&y[s]?y[s]:y;y=v instanceof Map?v.get(p):v[p]}if(!y)return}else if(f==d-1)break;if(p=l[d],s&&y[s]&&(y=y[s]),Array.isArray(y)&&!/^\d+$/.test(p))if(!h&&Array.isArray(r))!
+/*!
+ * Recursively set nested arrays
+ */
+function t(e,r,n,o,i,s){for(var a,u=0;u<e.length&&u<r.length;++u)a=e[u],Array.isArray(a)&&Array.isArray(r[u])?t(a,r[u],n,o,i,s):a&&(o?o(a,n,s(r[u])):(a[i]&&(a=a[i]),a[n]=s(r[u])))}(y,r,p,c,s,a);else for(_=0;_<y.length;++_)item=y[_],item&&(c?c(item,p,a(r)):(item[s]&&(item=item[s]),item[p]=a(r)));else c?c(y,p,a(r)):y instanceof Map?y.set(p,a(r)):y[p]=a(r)}}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(28);t.exports=function t(e){if(function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this._docs={},this._childDocs=[],null!=e&&(e=o(e),Object.assign(this,e),"object"===n(e.subPopulate)&&(this.populate=e.subPopulate),null!=e.perDocumentLimit&&null!=e.limit))throw new Error("Can not use `limit` and `perDocumentLimit` at the same time. Path: `"+e.path+"`.")}},function(t,e,r){"use strict";
+/*
+object-assign
+(c) Sindre Sorhus
+@license MIT
+*/var n=Object.getOwnPropertySymbols,o=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function s(t){if(null==t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}t.exports=function(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},r=0;r<10;r++)e["_"+String.fromCharCode(r)]=r;if("0123456789"!==Object.getOwnPropertyNames(e).map((function(t){return e[t]})).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach((function(t){n[t]=t})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(t){return!1}}()?Object.assign:function(t,e){for(var r,a,u=s(t),c=1;c<arguments.length;c++){for(var l in r=Object(arguments[c]))o.call(r,l)&&(u[l]=r[l]);if(n){a=n(r);for(var f=0;f<a.length;f++)i.call(r,a[f])&&(u[a[f]]=r[a[f]])}}return u}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(62),i=r(22),s=r(4),a=r(68),u=r(118)("mquery");function c(t,e){if(!(this instanceof c))return new c(t,e);var r=this.constructor.prototype;this.op=r.op||void 0,this.options=Object.assign({},r.options),this._conditions=r._conditions?a.clone(r._conditions):{},this._fields=r._fields?a.clone(r._fields):void 0,this._update=r._update?a.clone(r._update):void 0,this._path=r._path||void 0,this._distinct=r._distinct||void 0,this._collection=r._collection||void 0,this._traceFunction=r._traceFunction||void 0,e&&this.setOptions(e),t&&(t.find&&t.remove&&t.update?this.collection(t):this.find(t))}var l="$geoWithin";Object.defineProperty(c,"use$geoWithin",{get:function(){return"$geoWithin"==l},set:function(t){l=!0===t?"$geoWithin":"$within"}}),c.prototype.toConstructor=function(){function t(e,r){if(!(this instanceof t))return new t(e,r);c.call(this,e,r)}a.inherits(t,c);var e=t.prototype;return e.options={},e.setOptions(this.options),e.op=this.op,e._conditions=a.clone(this._conditions),e._fields=a.clone(this._fields),e._update=a.clone(this._update),e._path=this._path,e._distinct=this._distinct,e._collection=this._collection,e._traceFunction=this._traceFunction,t},c.prototype.setOptions=function(t){if(!t||!a.isObject(t))return this;for(var e,r=a.keys(t),n=0;n<r.length;++n)if("function"==typeof this[e=r[n]]){var o=a.isArray(t[e])?t[e]:[t[e]];this[e].apply(this,o)}else this.options[e]=t[e];return this},c.prototype.collection=function(t){return this._collection=new c.Collection(t),this},c.prototype.collation=function(t){return this.options.collation=t,this},c.prototype.$where=function(t){return this._conditions.$where=t,this},c.prototype.where=function(){if(!arguments.length)return this;this.op||(this.op="find");var t=n(arguments[0]);if("string"==t)return this._path=arguments[0],2===arguments.length&&(this._conditions[this._path]=arguments[1]),this;if("object"==t&&!Array.isArray(arguments[0]))return this.merge(arguments[0]);throw new TypeError("path must be a string or object")},c.prototype.equals=function(t){this._ensurePath("equals");var e=this._path;return this._conditions[e]=t,this},c.prototype.eq=function(t){this._ensurePath("eq");var e=this._path;return this._conditions[e]=t,this},c.prototype.or=function(t){var e=this._conditions.$or||(this._conditions.$or=[]);return a.isArray(t)||(t=[t]),e.push.apply(e,t),this},c.prototype.nor=function(t){var e=this._conditions.$nor||(this._conditions.$nor=[]);return a.isArray(t)||(t=[t]),e.push.apply(e,t),this},c.prototype.and=function(t){var e=this._conditions.$and||(this._conditions.$and=[]);return Array.isArray(t)||(t=[t]),e.push.apply(e,t),this},
+/*!
+ * gt, gte, lt, lte, ne, in, nin, all, regex, size, maxDistance
+ *
+ * Thing.where('type').nin(array)
+ */
+"gt gte lt lte ne in nin all regex size maxDistance minDistance".split(" ").forEach((function(t){c.prototype[t]=function(){var e,r;1===arguments.length?(this._ensurePath(t),r=arguments[0],e=this._path):(r=arguments[1],e=arguments[0]);var o=null===this._conditions[e]||"object"===n(this._conditions[e])?this._conditions[e]:this._conditions[e]={};return o["$"+t]=r,this}})),c.prototype.mod=function(){var t,e;1===arguments.length?(this._ensurePath("mod"),t=arguments[0],e=this._path):2!==arguments.length||a.isArray(arguments[1])?3===arguments.length?(t=o(arguments,1),e=arguments[0]):(t=arguments[1],e=arguments[0]):(this._ensurePath("mod"),t=o(arguments),e=this._path);var r=this._conditions[e]||(this._conditions[e]={});return r.$mod=t,this},c.prototype.exists=function(){var t,e;0===arguments.length?(this._ensurePath("exists"),t=this._path,e=!0):1===arguments.length?"boolean"==typeof arguments[0]?(this._ensurePath("exists"),t=this._path,e=arguments[0]):(t=arguments[0],e=!0):2===arguments.length&&(t=arguments[0],e=arguments[1]);var r=this._conditions[t]||(this._conditions[t]={});return r.$exists=e,this},c.prototype.elemMatch=function(){if(null==arguments[0])throw new TypeError("Invalid argument");var t,e,r;if("function"==typeof arguments[0])this._ensurePath("elemMatch"),e=this._path,t=arguments[0];else if(a.isObject(arguments[0]))this._ensurePath("elemMatch"),e=this._path,r=arguments[0];else if("function"==typeof arguments[1])e=arguments[0],t=arguments[1];else{if(!arguments[1]||!a.isObject(arguments[1]))throw new TypeError("Invalid argument");e=arguments[0],r=arguments[1]}t&&(t(r=new c),r=r._conditions);var n=this._conditions[e]||(this._conditions[e]={});return n.$elemMatch=r,this},c.prototype.within=function(){if(this._ensurePath("within"),this._geoComparison=l,0===arguments.length)return this;if(2===arguments.length)return this.box.apply(this,arguments);if(2<arguments.length)return this.polygon.apply(this,arguments);var t=arguments[0];if(!t)throw new TypeError("Invalid argument");if(t.center)return this.circle(t);if(t.box)return this.box.apply(this,t.box);if(t.polygon)return this.polygon.apply(this,t.polygon);if(t.type&&t.coordinates)return this.geometry(t);throw new TypeError("Invalid argument")},c.prototype.box=function(){var t,e;if(3===arguments.length)t=arguments[0],e=[arguments[1],arguments[2]];else{if(2!==arguments.length)throw new TypeError("Invalid argument");this._ensurePath("box"),t=this._path,e=[arguments[0],arguments[1]]}var r=this._conditions[t]||(this._conditions[t]={});return r[this._geoComparison||l]={$box:e},this},c.prototype.polygon=function(){var t,e;"string"==typeof arguments[0]?(e=arguments[0],t=o(arguments,1)):(this._ensurePath("polygon"),e=this._path,t=o(arguments));var r=this._conditions[e]||(this._conditions[e]={});return r[this._geoComparison||l]={$polygon:t},this},c.prototype.circle=function(){var t,e;if(1===arguments.length)this._ensurePath("circle"),t=this._path,e=arguments[0];else{if(2!==arguments.length)throw new TypeError("Invalid argument");t=arguments[0],e=arguments[1]}if(!("radius"in e)||!e.center)throw new Error("center and radius are required");var r=this._conditions[t]||(this._conditions[t]={}),n=e.spherical?"$centerSphere":"$center",o=this._geoComparison||l;return r[o]={},r[o][n]=[e.center,e.radius],"unique"in e&&(r[o].$uniqueDocs=!!e.unique),this},c.prototype.near=function(){var t,e;if(this._geoComparison="$near",0===arguments.length)return this;if(1===arguments.length)this._ensurePath("near"),t=this._path,e=arguments[0];else{if(2!==arguments.length)throw new TypeError("Invalid argument");t=arguments[0],e=arguments[1]}if(!e.center)throw new Error("center is required");var r=this._conditions[t]||(this._conditions[t]={}),n=e.spherical?"$nearSphere":"$near";if(Array.isArray(e.center)){r[n]=e.center;var o="maxDistance"in e?e.maxDistance:null;null!=o&&(r.$maxDistance=o),null!=e.minDistance&&(r.$minDistance=e.minDistance)}else{if("Point"!=e.center.type||!Array.isArray(e.center.coordinates))throw new Error(s.format("Invalid GeoJSON specified for %s",n));r[n]={$geometry:e.center},"maxDistance"in e&&(r[n].$maxDistance=e.maxDistance),"minDistance"in e&&(r[n].$minDistance=e.minDistance)}return this},c.prototype.intersects=function(){if(this._ensurePath("intersects"),this._geoComparison="$geoIntersects",0===arguments.length)return this;var t=arguments[0];if(null!=t&&t.type&&t.coordinates)return this.geometry(t);throw new TypeError("Invalid argument")},c.prototype.geometry=function(){if("$within"!=this._geoComparison&&"$geoWithin"!=this._geoComparison&&"$near"!=this._geoComparison&&"$geoIntersects"!=this._geoComparison)throw new Error("geometry() must come after `within()`, `intersects()`, or `near()");var t,e;if(1!==arguments.length)throw new TypeError("Invalid argument");if(this._ensurePath("geometry"),e=this._path,!(t=arguments[0]).type||!Array.isArray(t.coordinates))throw new TypeError("Invalid argument");var r=this._conditions[e]||(this._conditions[e]={});return r[this._geoComparison]={$geometry:t},this},c.prototype.select=function(){var t=arguments[0];if(!t)return this;if(1!==arguments.length)throw new Error("Invalid select: select only takes 1 argument");this._validate("select");var e,r,o=this._fields||(this._fields={}),i=n(t);if(("string"==i||a.isArgumentsObject(t))&&"number"==typeof t.length||Array.isArray(t)){for("string"==i&&(t=t.split(/\s+/)),e=0,r=t.length;e<r;++e){var s=t[e];if(s){var u="-"==s[0]?0:1;0===u&&(s=s.substring(1)),o[s]=u}}return this}if(a.isObject(t)){var c=a.keys(t);for(e=0;e<c.length;++e)o[c[e]]=t[c[e]];return this}throw new TypeError("Invalid select() argument. Must be string or object.")},c.prototype.slice=function(){if(0===arguments.length)return this;var t,e;if(this._validate("slice"),1===arguments.length){var r=arguments[0];if("object"===n(r)&&!Array.isArray(r)){for(var i=Object.keys(r),s=i.length,a=0;a<s;++a)this.slice(i[a],r[i[a]]);return this}this._ensurePath("slice"),t=this._path,e=arguments[0]}else 2===arguments.length?"number"==typeof arguments[0]?(this._ensurePath("slice"),t=this._path,e=o(arguments)):(t=arguments[0],e=arguments[1]):3===arguments.length&&(t=arguments[0],e=o(arguments,1));var u=this._fields||(this._fields={});return u[t]={$slice:e},this},c.prototype.sort=function(t){if(!t)return this;var e,r,o;this._validate("sort");var i=n(t);if(Array.isArray(t)){for(r=t.length,e=0;e<t.length;++e){if(!Array.isArray(t[e]))throw new Error("Invalid sort() argument, must be array of arrays");h(this.options,t[e][0],t[e][1])}return this}if(1===arguments.length&&"string"==i){for(r=(t=t.split(/\s+/)).length,e=0;e<r;++e)if(o=t[e]){var s="-"==o[0]?-1:1;-1===s&&(o=o.substring(1)),p(this.options,o,s)}return this}if(a.isObject(t)){var u=a.keys(t);for(e=0;e<u.length;++e)o=u[e],p(this.options,o,t[o]);return this}if("undefined"!=typeof Map&&t instanceof Map)return y(this.options,t),this;throw new TypeError("Invalid sort() argument. Must be a string, object, or array.")};
+/*!
+ * @ignore
+ */
+var f={1:1,"-1":-1,asc:1,ascending:1,desc:-1,descending:-1};function p(t,e,r){if(Array.isArray(t.sort))throw new TypeError("Can't mix sort syntaxes. Use either array or object:\n- `.sort([['field', 1], ['test', -1]])`\n- `.sort({ field: 1, test: -1 })`");var n;if(r&&r.$meta)(n=t.sort||(t.sort={}))[e]={$meta:r.$meta};else{n=t.sort||(t.sort={});var o=String(r||1).toLowerCase();if(!(o=f[o]))throw new TypeError("Invalid sort value: { "+e+": "+r+" }");n[e]=o}}function h(t,e,r){if(t.sort=t.sort||[],!Array.isArray(t.sort))throw new TypeError("Can't mix sort syntaxes. Use either array or object:\n- `.sort([['field', 1], ['test', -1]])`\n- `.sort({ field: 1, test: -1 })`");var n=String(r||1).toLowerCase();if(!(n=f[n]))throw new TypeError("Invalid sort value: [ "+e+", "+r+" ]");t.sort.push([e,n])}function y(t,e){if(t.sort=t.sort||new Map,!(t.sort instanceof Map))throw new TypeError("Can't mix sort syntaxes. Use either array or object or map consistently");e.forEach((function(e,r){var n=String(e||1).toLowerCase();if(!(n=f[n]))throw new TypeError("Invalid sort value: < "+r+": "+e+" >");t.sort.set(r,n)}))}
+/*!
+ * limit, skip, maxScan, batchSize, comment
+ *
+ * Sets these associated options.
+ *
+ * query.comment('feed query');
+ */
+/*!
+ * Internal helper for update, updateMany, updateOne
+ */
+function d(t,e,r,n,o,i,s){return t.op=e,c.canMerge(r)&&t.merge(r),n&&t._mergeUpdate(n),a.isObject(o)&&t.setOptions(o),i||s?!t._update||!t.options.overwrite&&0===a.keys(t._update).length?(s&&a.soon(s.bind(null,null,0)),t):(o=t._optionsForExec(),s||(o.safe=!1),r=t._conditions,n=t._updateForExec(),u("update",t._collection.collectionName,r,n,o),s=t._wrapCallback(e,s,{conditions:r,doc:n,options:o}),t._collection[e](r,n,o,a.tick(s)),t):t}["limit","skip","maxScan","batchSize","comment"].forEach((function(t){c.prototype[t]=function(e){return this._validate(t),this.options[t]=e,this}})),c.prototype.maxTime=c.prototype.maxTimeMS=function(t){return this._validate("maxTime"),this.options.maxTimeMS=t,this},c.prototype.snapshot=function(){return this._validate("snapshot"),this.options.snapshot=!arguments.length||!!arguments[0],this},c.prototype.hint=function(){if(0===arguments.length)return this;this._validate("hint");var t=arguments[0];if(a.isObject(t)){var e=this.options.hint||(this.options.hint={});for(var r in t)e[r]=t[r];return this}if("string"==typeof t)return this.options.hint=t,this;throw new TypeError("Invalid hint. "+t)},c.prototype.j=function(t){return this.options.j=t,this},c.prototype.slaveOk=function(t){return this.options.slaveOk=!arguments.length||!!t,this},c.prototype.read=c.prototype.setReadPreference=function(t){return arguments.length>1&&!c.prototype.read.deprecationWarningIssued&&(console.error("Deprecation warning: 'tags' argument is not supported anymore in Query.read() method. Please use mongodb.ReadPreference object instead."),c.prototype.read.deprecationWarningIssued=!0),this.options.readPreference=a.readPref(t),this},c.prototype.readConcern=c.prototype.r=function(t){return this.options.readConcern=a.readConcern(t),this},c.prototype.tailable=function(){return this._validate("tailable"),this.options.tailable=!arguments.length||!!arguments[0],this},c.prototype.writeConcern=c.prototype.w=function(t){return"object"===n(t)?(void 0!==t.j&&(this.options.j=t.j),void 0!==t.w&&(this.options.w=t.w),void 0!==t.wtimeout&&(this.options.wtimeout=t.wtimeout)):this.options.w="m"===t?"majority":t,this},c.prototype.wtimeout=c.prototype.wTimeout=function(t){return this.options.wtimeout=t,this},c.prototype.merge=function(t){if(!t)return this;if(!c.canMerge(t))throw new TypeError("Invalid argument. Expected instanceof mquery or plain object");return t instanceof c?(t._conditions&&a.merge(this._conditions,t._conditions),t._fields&&(this._fields||(this._fields={}),a.merge(this._fields,t._fields)),t.options&&(this.options||(this.options={}),a.merge(this.options,t.options)),t._update&&(this._update||(this._update={}),a.mergeClone(this._update,t._update)),t._distinct&&(this._distinct=t._distinct),this):(a.merge(this._conditions,t),this)},c.prototype.find=function(t,e){if(this.op="find","function"==typeof t?(e=t,t=void 0):c.canMerge(t)&&this.merge(t),!e)return this;var r=this._conditions,n=this._optionsForExec();return this.$useProjection?n.projection=this._fieldsForExec():n.fields=this._fieldsForExec(),u("find",this._collection.collectionName,r,n),e=this._wrapCallback("find",e,{conditions:r,options:n}),this._collection.find(r,n,a.tick(e)),this},c.prototype.cursor=function(t){if(this.op){if("find"!==this.op)throw new TypeError(".cursor only support .find method")}else this.find(t);var e=this._conditions,r=this._optionsForExec();return this.$useProjection?r.projection=this._fieldsForExec():r.fields=this._fieldsForExec(),u("findCursor",this._collection.collectionName,e,r),this._collection.findCursor(e,r)},c.prototype.findOne=function(t,e){if(this.op="findOne","function"==typeof t?(e=t,t=void 0):c.canMerge(t)&&this.merge(t),!e)return this;var r=this._conditions,n=this._optionsForExec();return this.$useProjection?n.projection=this._fieldsForExec():n.fields=this._fieldsForExec(),u("findOne",this._collection.collectionName,r,n),e=this._wrapCallback("findOne",e,{conditions:r,options:n}),this._collection.findOne(r,n,a.tick(e)),this},c.prototype.count=function(t,e){if(this.op="count",this._validate(),"function"==typeof t?(e=t,t=void 0):c.canMerge(t)&&this.merge(t),!e)return this;var r=this._conditions,n=this._optionsForExec();return u("count",this._collection.collectionName,r,n),e=this._wrapCallback("count",e,{conditions:r,options:n}),this._collection.count(r,n,a.tick(e)),this},c.prototype.distinct=function(t,e,r){if(this.op="distinct",this._validate(),!r){switch(n(e)){case"function":r=e,"string"==typeof t&&(e=t,t=void 0);break;case"undefined":case"string":break;default:throw new TypeError("Invalid `field` argument. Must be string or function")}switch(n(t)){case"function":r=t,t=e=void 0;break;case"string":e=t,t=void 0}}if("string"==typeof e&&(this._distinct=e),c.canMerge(t)&&this.merge(t),!r)return this;if(!this._distinct)throw new Error("No value for `distinct` has been declared");var o=this._conditions,i=this._optionsForExec();return u("distinct",this._collection.collectionName,o,i),r=this._wrapCallback("distinct",r,{conditions:o,options:i}),this._collection.distinct(this._distinct,o,i,a.tick(r)),this},c.prototype.update=function(t,e,r,o){var i;switch(arguments.length){case 3:"function"==typeof r&&(o=r,r=void 0);break;case 2:"function"==typeof e&&(o=e,e=t,t=void 0);break;case 1:switch(n(t)){case"function":o=t,t=r=e=void 0;break;case"boolean":i=t,t=void 0;break;default:e=t,t=r=void 0}}return d(this,"update",t,e,r,i,o)},c.prototype.updateMany=function(t,e,r,o){var i;switch(arguments.length){case 3:"function"==typeof r&&(o=r,r=void 0);break;case 2:"function"==typeof e&&(o=e,e=t,t=void 0);break;case 1:switch(n(t)){case"function":o=t,t=r=e=void 0;break;case"boolean":i=t,t=void 0;break;default:e=t,t=r=void 0}}return d(this,"updateMany",t,e,r,i,o)},c.prototype.updateOne=function(t,e,r,o){var i;switch(arguments.length){case 3:"function"==typeof r&&(o=r,r=void 0);break;case 2:"function"==typeof e&&(o=e,e=t,t=void 0);break;case 1:switch(n(t)){case"function":o=t,t=r=e=void 0;break;case"boolean":i=t,t=void 0;break;default:e=t,t=r=void 0}}return d(this,"updateOne",t,e,r,i,o)},c.prototype.replaceOne=function(t,e,r,o){var i;switch(arguments.length){case 3:"function"==typeof r&&(o=r,r=void 0);break;case 2:"function"==typeof e&&(o=e,e=t,t=void 0);break;case 1:switch(n(t)){case"function":o=t,t=r=e=void 0;break;case"boolean":i=t,t=void 0;break;default:e=t,t=r=void 0}}return this.setOptions({overwrite:!0}),d(this,"replaceOne",t,e,r,i,o)},c.prototype.remove=function(t,e){var r;if(this.op="remove","function"==typeof t?(e=t,t=void 0):c.canMerge(t)?this.merge(t):!0===t&&(r=t,t=void 0),!r&&!e)return this;var n=this._optionsForExec();e||(n.safe=!1);var o=this._conditions;return u("remove",this._collection.collectionName,o,n),e=this._wrapCallback("remove",e,{conditions:o,options:n}),this._collection.remove(o,n,a.tick(e)),this},c.prototype.deleteOne=function(t,e){var r;if(this.op="deleteOne","function"==typeof t?(e=t,t=void 0):c.canMerge(t)?this.merge(t):!0===t&&(r=t,t=void 0),!r&&!e)return this;var n=this._optionsForExec();e||(n.safe=!1),delete n.justOne;var o=this._conditions;return u("deleteOne",this._collection.collectionName,o,n),e=this._wrapCallback("deleteOne",e,{conditions:o,options:n}),this._collection.deleteOne(o,n,a.tick(e)),this},c.prototype.deleteMany=function(t,e){var r;if(this.op="deleteMany","function"==typeof t?(e=t,t=void 0):c.canMerge(t)?this.merge(t):!0===t&&(r=t,t=void 0),!r&&!e)return this;var n=this._optionsForExec();e||(n.safe=!1),delete n.justOne;var o=this._conditions;return u("deleteOne",this._collection.collectionName,o,n),e=this._wrapCallback("deleteOne",e,{conditions:o,options:n}),this._collection.deleteMany(o,n,a.tick(e)),this},c.prototype.findOneAndUpdate=function(t,e,r,n){switch(this.op="findOneAndUpdate",this._validate(),arguments.length){case 3:"function"==typeof r&&(n=r,r={});break;case 2:"function"==typeof e&&(n=e,e=t,t=void 0),r=void 0;break;case 1:"function"==typeof t?(n=t,t=r=e=void 0):(e=t,t=r=void 0)}return c.canMerge(t)&&this.merge(t),e&&this._mergeUpdate(e),r&&this.setOptions(r),n?this._findAndModify("update",n):this},c.prototype.findOneAndRemove=c.prototype.findOneAndDelete=function(t,e,r){return this.op="findOneAndRemove",this._validate(),"function"==typeof e?(r=e,e=void 0):"function"==typeof t&&(r=t,t=void 0),c.canMerge(t)&&this.merge(t),e&&this.setOptions(e),r?this._findAndModify("remove",r):this},c.prototype._findAndModify=function(t,e){i.equal("function",n(e));var r,o=this._optionsForExec();if("remove"==t)o.remove=!0;else if("new"in o||(o.new=!0),"upsert"in o||(o.upsert=!1),!(r=this._updateForExec())){if(!o.upsert)return this.findOne(e);r={$set:{}}}null!=this._fieldsForExec()&&(this.$useProjection?o.projection=this._fieldsForExec():o.fields=this._fieldsForExec());var s=this._conditions;return u("findAndModify",this._collection.collectionName,s,r,o),e=this._wrapCallback("findAndModify",e,{conditions:s,doc:r,options:o}),this._collection.findAndModify(s,r,o,a.tick(e)),this},c.prototype._wrapCallback=function(t,e,r){var n=this._traceFunction||c.traceFunction;if(n){r.collectionName=this._collection.collectionName;var o=n&&n.call(null,t,r,this),i=(new Date).getTime();return function(t,r){if(o){var n=(new Date).getTime()-i;o.call(null,t,r,n)}e&&e.apply(null,arguments)}}return e},c.prototype.setTraceFunction=function(t){return this._traceFunction=t,this},c.prototype.exec=function(t,e){switch(n(t)){case"function":e=t,t=null;break;case"string":this.op=t}i.ok(this.op,"Missing query type: (find, update, etc)"),"update"!=this.op&&"remove"!=this.op||e||(e=!0);var r=this;if("function"!=typeof e)return new c.Promise((function(t,e){r[r.op]((function(r,n){r?e(r):t(n),t=e=null}))}));this[this.op](e)},c.prototype.thunk=function(){var t=this;return function(e){t.exec(e)}},c.prototype.then=function(t,e){var r=this;return new c.Promise((function(t,e){r.exec((function(r,n){r?e(r):t(n),t=e=null}))})).then(t,e)},c.prototype.stream=function(t){if("find"!=this.op)throw new Error("stream() is only available for find");var e=this._conditions,r=this._optionsForExec();return this.$useProjection?r.projection=this._fieldsForExec():r.fields=this._fieldsForExec(),u("stream",this._collection.collectionName,e,r,t),this._collection.findStream(e,r,t)},c.prototype.selected=function(){return!!(this._fields&&Object.keys(this._fields).length>0)},c.prototype.selectedInclusively=function(){if(!this._fields)return!1;var t=Object.keys(this._fields);if(0===t.length)return!1;for(var e=0;e<t.length;++e){var r=t[e];if(0===this._fields[r])return!1;if(this._fields[r]&&"object"===n(this._fields[r])&&this._fields[r].$meta)return!1}return!0},c.prototype.selectedExclusively=function(){if(!this._fields)return!1;var t=Object.keys(this._fields);if(0===t.length)return!1;for(var e=0;e<t.length;++e){var r=t[e];if(0===this._fields[r])return!0}return!1},c.prototype._mergeUpdate=function(t){this._update||(this._update={}),t instanceof c?t._update&&a.mergeClone(this._update,t._update):a.mergeClone(this._update,t)},c.prototype._optionsForExec=function(){return a.clone(this.options)},c.prototype._fieldsForExec=function(){return a.clone(this._fields)},c.prototype._updateForExec=function(){for(var t=a.clone(this._update),e=a.keys(t),r=e.length,n={};r--;){var o=e[r];this.options.overwrite?n[o]=t[o]:"$"!==o[0]?(n.$set||(t.$set?n.$set=t.$set:n.$set={}),n.$set[o]=t[o],e.splice(r,1),~e.indexOf("$set")||e.push("$set")):"$set"===o&&n.$set||(n[o]=t[o])}return this._compiledUpdate=n,n},c.prototype._ensurePath=function(t){if(!this._path)throw new Error(t+"() must be used after where() when called with these arguments")},
+/*!
+ * Permissions
+ */
+c.permissions=r(121),c._isPermitted=function(t,e){var r=c.permissions[e];return!r||!0!==r[t]},c.prototype._validate=function(t){var e,r;if(void 0===t){if("function"!=typeof(r=c.permissions[this.op]))return!0;e=r(this)}else c._isPermitted(t,this.op)||(e=t);if(e)throw new Error(e+" cannot be used with "+this.op)},c.canMerge=function(t){return t instanceof c||a.isObject(t)},c.setGlobalTraceFunction=function(t){c.traceFunction=t},
+/*!
+ * Exports.
+ */
+c.utils=a,c.env=r(70),c.Collection=r(123),c.BaseCollection=r(30),c.Promise=r(125),t.exports=c},function(t,e,r){(function(t,e){!function(t,r){"use strict";if(!t.setImmediate){var n,o,i,s,a,u=1,c={},l=!1,f=t.document,p=Object.getPrototypeOf&&Object.getPrototypeOf(t);p=p&&p.setTimeout?p:t,"[object process]"==={}.toString.call(t.process)?n=function(t){e.nextTick((function(){y(t)}))}:!function(){if(t.postMessage&&!t.importScripts){var e=!0,r=t.onmessage;return t.onmessage=function(){e=!1},t.postMessage("","*"),t.onmessage=r,e}}()?t.MessageChannel?((i=new MessageChannel).port1.onmessage=function(t){y(t.data)},n=function(t){i.port2.postMessage(t)}):f&&"onreadystatechange"in f.createElement("script")?(o=f.documentElement,n=function(t){var e=f.createElement("script");e.onreadystatechange=function(){y(t),e.onreadystatechange=null,o.removeChild(e),e=null},o.appendChild(e)}):n=function(t){setTimeout(y,0,t)}:(s="setImmediate$"+Math.random()+"$",a=function(e){e.source===t&&"string"==typeof e.data&&0===e.data.indexOf(s)&&y(+e.data.slice(s.length))},t.addEventListener?t.addEventListener("message",a,!1):t.attachEvent("onmessage",a),n=function(e){t.postMessage(s+e,"*")}),p.setImmediate=function(t){"function"!=typeof t&&(t=new Function(""+t));for(var e=new Array(arguments.length-1),r=0;r<e.length;r++)e[r]=arguments[r+1];var o={callback:t,args:e};return c[u]=o,n(u),u++},p.clearImmediate=h}function h(t){delete c[t]}function y(t){if(l)setTimeout(y,0,t);else{var e=c[t];if(e){l=!0;try{!function(t){var e=t.callback,r=t.args;switch(r.length){case 0:e();break;case 1:e(r[0]);break;case 2:e(r[0],r[1]);break;case 3:e(r[0],r[1],r[2]);break;default:e.apply(void 0,r)}}(e)}finally{h(t),l=!1}}}}}("undefined"==typeof self?void 0===t?this:t:self)}).call(this,r(11),r(8))},function(t,e,r){var n=r(1),o=n.Buffer;function i(t,e){for(var r in t)e[r]=t[r]}function s(t,e,r){return o(t,e,r)}o.from&&o.alloc&&o.allocUnsafe&&o.allocUnsafeSlow?t.exports=n:(i(n,e),e.Buffer=s),i(o,s),s.from=function(t,e,r){if("number"==typeof t)throw new TypeError("Argument must not be a number");return o(t,e,r)},s.alloc=function(t,e,r){if("number"!=typeof t)throw new TypeError("Argument must be a number");var n=o(t);return void 0!==e?"string"==typeof r?n.fill(e,r):n.fill(e):n.fill(0),n},s.allocUnsafe=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return o(t)},s.allocUnsafeSlow=function(t){if("number"!=typeof t)throw new TypeError("Argument must be a number");return n.SlowBuffer(t)}},function(t,e,r){(function(n){function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function i(){var t;try{t=e.storage.debug}catch(t){}return!t&&void 0!==n&&"env"in n&&(t=n.env.DEBUG),t}(e=t.exports=r(119)).log=function(){return"object"===("undefined"==typeof console?"undefined":o(console))&&console.log&&Function.prototype.apply.call(console.log,console,arguments)},e.formatArgs=function(t){var r=this.useColors;if(t[0]=(r?"%c":"")+this.namespace+(r?" %c":" ")+t[0]+(r?"%c ":" ")+"+"+e.humanize(this.diff),!r)return;var n="color: "+this.color;t.splice(1,0,n,"color: inherit");var o=0,i=0;t[0].replace(/%[a-zA-Z%]/g,(function(t){"%%"!==t&&(o++,"%c"===t&&(i=o))})),t.splice(i,0,n)},e.save=function(t){try{null==t?e.storage.removeItem("debug"):e.storage.debug=t}catch(t){}},e.load=i,e.useColors=function(){if("undefined"!=typeof window&&window.process&&"renderer"===window.process.type)return!0;if("undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/(edge|trident)\/(\d+)/))return!1;return"undefined"!=typeof document&&document.documentElement&&document.documentElement.style&&document.documentElement.style.WebkitAppearance||"undefined"!=typeof window&&window.console&&(window.console.firebug||window.console.exception&&window.console.table)||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/)&&parseInt(RegExp.$1,10)>=31||"undefined"!=typeof navigator&&navigator.userAgent&&navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/)},e.storage="undefined"!=typeof chrome&&void 0!==chrome.storage?chrome.storage.local:function(){try{return window.localStorage}catch(t){}}(),e.colors=["#0000CC","#0000FF","#0033CC","#0033FF","#0066CC","#0066FF","#0099CC","#0099FF","#00CC00","#00CC33","#00CC66","#00CC99","#00CCCC","#00CCFF","#3300CC","#3300FF","#3333CC","#3333FF","#3366CC","#3366FF","#3399CC","#3399FF","#33CC00","#33CC33","#33CC66","#33CC99","#33CCCC","#33CCFF","#6600CC","#6600FF","#6633CC","#6633FF","#66CC00","#66CC33","#9900CC","#9900FF","#9933CC","#9933FF","#99CC00","#99CC33","#CC0000","#CC0033","#CC0066","#CC0099","#CC00CC","#CC00FF","#CC3300","#CC3333","#CC3366","#CC3399","#CC33CC","#CC33FF","#CC6600","#CC6633","#CC9900","#CC9933","#CCCC00","#CCCC33","#FF0000","#FF0033","#FF0066","#FF0099","#FF00CC","#FF00FF","#FF3300","#FF3333","#FF3366","#FF3399","#FF33CC","#FF33FF","#FF6600","#FF6633","#FF9900","#FF9933","#FFCC00","#FFCC33"],e.formatters.j=function(t){try{return JSON.stringify(t)}catch(t){return"[UnexpectedJSONParseError]: "+t.message}},e.enable(i())}).call(this,r(8))},function(t,e,r){function n(t){var r;function n(){if(n.enabled){var t=n,o=+new Date,i=o-(r||o);t.diff=i,t.prev=r,t.curr=o,r=o;for(var s=new Array(arguments.length),a=0;a<s.length;a++)s[a]=arguments[a];s[0]=e.coerce(s[0]),"string"!=typeof s[0]&&s.unshift("%O");var u=0;s[0]=s[0].replace(/%([a-zA-Z%])/g,(function(r,n){if("%%"===r)return r;u++;var o=e.formatters[n];if("function"==typeof o){var i=s[u];r=o.call(t,i),s.splice(u,1),u--}return r})),e.formatArgs.call(t,s);var c=n.log||e.log||console.log.bind(console);c.apply(t,s)}}return n.namespace=t,n.enabled=e.enabled(t),n.useColors=e.useColors(),n.color=function(t){var r,n=0;for(r in t)n=(n<<5)-n+t.charCodeAt(r),n|=0;return e.colors[Math.abs(n)%e.colors.length]}(t),n.destroy=o,"function"==typeof e.init&&e.init(n),e.instances.push(n),n}function o(){var t=e.instances.indexOf(this);return-1!==t&&(e.instances.splice(t,1),!0)}(e=t.exports=n.debug=n.default=n).coerce=function(t){return t instanceof Error?t.stack||t.message:t},e.disable=function(){e.enable("")},e.enable=function(t){var r;e.save(t),e.names=[],e.skips=[];var n=("string"==typeof t?t:"").split(/[\s,]+/),o=n.length;for(r=0;r<o;r++)n[r]&&("-"===(t=n[r].replace(/\*/g,".*?"))[0]?e.skips.push(new RegExp("^"+t.substr(1)+"$")):e.names.push(new RegExp("^"+t+"$")));for(r=0;r<e.instances.length;r++){var i=e.instances[r];i.enabled=e.enabled(i.namespace)}},e.enabled=function(t){if("*"===t[t.length-1])return!0;var r,n;for(r=0,n=e.skips.length;r<n;r++)if(e.skips[r].test(t))return!1;for(r=0,n=e.names.length;r<n;r++)if(e.names[r].test(t))return!0;return!1},e.humanize=r(120),e.instances=[],e.names=[],e.skips=[],e.formatters={}},function(t,e){function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var n=1e3,o=6e4,i=60*o,s=24*i;function a(t,e,r){if(!(t<e))return t<1.5*e?Math.floor(t/e)+" "+r:Math.ceil(t/e)+" "+r+"s"}t.exports=function(t,e){e=e||{};var u,c=r(t);if("string"===c&&t.length>0)return function(t){if((t=String(t)).length>100)return;var e=/^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(t);if(!e)return;var r=parseFloat(e[1]);switch((e[2]||"ms").toLowerCase()){case"years":case"year":case"yrs":case"yr":case"y":return 315576e5*r;case"days":case"day":case"d":return r*s;case"hours":case"hour":case"hrs":case"hr":case"h":return r*i;case"minutes":case"minute":case"mins":case"min":case"m":return r*o;case"seconds":case"second":case"secs":case"sec":case"s":return r*n;case"milliseconds":case"millisecond":case"msecs":case"msec":case"ms":return r;default:return}}(t);if("number"===c&&!1===isNaN(t))return e.long?a(u=t,s,"day")||a(u,i,"hour")||a(u,o,"minute")||a(u,n,"second")||u+" ms":function(t){if(t>=s)return Math.round(t/s)+"d";if(t>=i)return Math.round(t/i)+"h";if(t>=o)return Math.round(t/o)+"m";if(t>=n)return Math.round(t/n)+"s";return t+"ms"}(t);throw new Error("val is not a non-empty string or a valid number. val="+JSON.stringify(t))}},function(t,e,r){"use strict";var n=e;n.distinct=function(t){return t._fields&&Object.keys(t._fields).length>0?"field selection and slice":(Object.keys(n.distinct).every((function(r){return!t.options[r]||(e=r,!1)})),e);var e},n.distinct.select=n.distinct.slice=n.distinct.sort=n.distinct.limit=n.distinct.skip=n.distinct.batchSize=n.distinct.comment=n.distinct.maxScan=n.distinct.snapshot=n.distinct.hint=n.distinct.tailable=!0,n.findOneAndUpdate=n.findOneAndRemove=function(t){var e;return Object.keys(n.findOneAndUpdate).every((function(r){return!t.options[r]||(e=r,!1)})),e},n.findOneAndUpdate.limit=n.findOneAndUpdate.skip=n.findOneAndUpdate.batchSize=n.findOneAndUpdate.maxScan=n.findOneAndUpdate.snapshot=n.findOneAndUpdate.hint=n.findOneAndUpdate.tailable=n.findOneAndUpdate.comment=!0,n.count=function(t){return t._fields&&Object.keys(t._fields).length>0?"field selection and slice":(Object.keys(n.count).every((function(r){return!t.options[r]||(e=r,!1)})),e);var e},n.count.slice=n.count.batchSize=n.count.comment=n.count.maxScan=n.count.snapshot=n.count.tailable=!0},function(t,e){t.exports=function(t){return t.webpackPolyfill||(t.deprecate=function(){},t.paths=[],t.children||(t.children=[]),Object.defineProperty(t,"loaded",{enumerable:!0,get:function(){return t.l}}),Object.defineProperty(t,"id",{enumerable:!0,get:function(){return t.i}}),t.webpackPolyfill=1),t}},function(t,e,r){"use strict";var n=r(70);if("unknown"==n.type)throw new Error("Unknown environment");t.exports=n.isNode?r(124):(n.isMongo,r(30))},function(t,e,r){"use strict";var n=r(30);function o(t){this.collection=t,this.collectionName=t.collectionName}r(68).inherits(o,n),o.prototype.find=function(t,e,r){this.collection.find(t,e,(function(t,e){if(t)return r(t);try{e.toArray(r)}catch(t){r(t)}}))},o.prototype.findOne=function(t,e,r){this.collection.findOne(t,e,r)},o.prototype.count=function(t,e,r){this.collection.count(t,e,r)},o.prototype.distinct=function(t,e,r,n){this.collection.distinct(t,e,r,n)},o.prototype.update=function(t,e,r,n){this.collection.update(t,e,r,n)},o.prototype.updateMany=function(t,e,r,n){this.collection.updateMany(t,e,r,n)},o.prototype.updateOne=function(t,e,r,n){this.collection.updateOne(t,e,r,n)},o.prototype.replaceOne=function(t,e,r,n){this.collection.replaceOne(t,e,r,n)},o.prototype.deleteOne=function(t,e,r){this.collection.deleteOne(t,e,r)},o.prototype.deleteMany=function(t,e,r){this.collection.deleteMany(t,e,r)},o.prototype.remove=function(t,e,r){this.collection.remove(t,e,r)},o.prototype.findAndModify=function(t,e,r,n){var o=Array.isArray(r.sort)?r.sort:[];this.collection.findAndModify(t,o,e,r,n)},o.prototype.findStream=function(t,e,r){return this.collection.find(t,e).stream(r)},o.prototype.findCursor=function(t,e){return this.collection.find(t,e)},t.exports=o},function(t,e,r){(function(r,n,o){var i,s,a,u;function c(t){return(c="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}
+/* @preserve
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2013-2017 Petka Antonov
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */u=function(){var t,e,i;return function t(e,r,n){function o(s,a){if(!r[s]){if(!e[s]){var u="function"==typeof _dereq_&&_dereq_;if(!a&&u)return u(s,!0);if(i)return i(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var l=r[s]={exports:{}};e[s][0].call(l.exports,(function(t){var r=e[s][1][t];return o(r||t)}),l,l.exports,t,e,r,n)}return r[s].exports}for(var i="function"==typeof _dereq_&&_dereq_,s=0;s<n.length;s++)o(n[s]);return o}({1:[function(t,e,r){"use strict";e.exports=function(t){var e=t._SomePromiseArray;function r(t){var r=new e(t),n=r.promise();return r.setHowMany(1),r.setUnwrap(),r.init(),n}t.any=function(t){return r(t)},t.prototype.any=function(){return r(this)}}},{}],2:[function(t,e,n){"use strict";var o;try{throw new Error}catch(t){o=t}var i=t("./schedule"),s=t("./queue"),a=t("./util");function u(){this._customScheduler=!1,this._isTickUsed=!1,this._lateQueue=new s(16),this._normalQueue=new s(16),this._haveDrainedQueues=!1,this._trampolineEnabled=!0;var t=this;this.drainQueues=function(){t._drainQueues()},this._schedule=i}function c(t,e,r){this._lateQueue.push(t,e,r),this._queueTick()}function l(t,e,r){this._normalQueue.push(t,e,r),this._queueTick()}function f(t){this._normalQueue._pushOne(t),this._queueTick()}u.prototype.setScheduler=function(t){var e=this._schedule;return this._schedule=t,this._customScheduler=!0,e},u.prototype.hasCustomScheduler=function(){return this._customScheduler},u.prototype.enableTrampoline=function(){this._trampolineEnabled=!0},u.prototype.disableTrampolineIfNecessary=function(){a.hasDevTools&&(this._trampolineEnabled=!1)},u.prototype.haveItemsQueued=function(){return this._isTickUsed||this._haveDrainedQueues},u.prototype.fatalError=function(t,e){e?(r.stderr.write("Fatal "+(t instanceof Error?t.stack:t)+"\n"),r.exit(2)):this.throwLater(t)},u.prototype.throwLater=function(t,e){if(1===arguments.length&&(e=t,t=function(){throw e}),"undefined"!=typeof setTimeout)setTimeout((function(){t(e)}),0);else try{this._schedule((function(){t(e)}))}catch(t){throw new Error("No async scheduler available\n\n See http://goo.gl/MqrFmX\n")}},a.hasDevTools?(u.prototype.invokeLater=function(t,e,r){this._trampolineEnabled?c.call(this,t,e,r):this._schedule((function(){setTimeout((function(){t.call(e,r)}),100)}))},u.prototype.invoke=function(t,e,r){this._trampolineEnabled?l.call(this,t,e,r):this._schedule((function(){t.call(e,r)}))},u.prototype.settlePromises=function(t){this._trampolineEnabled?f.call(this,t):this._schedule((function(){t._settlePromises()}))}):(u.prototype.invokeLater=c,u.prototype.invoke=l,u.prototype.settlePromises=f),u.prototype._drainQueue=function(t){for(;t.length()>0;){var e=t.shift();if("function"==typeof e){var r=t.shift(),n=t.shift();e.call(r,n)}else e._settlePromises()}},u.prototype._drainQueues=function(){this._drainQueue(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,this._drainQueue(this._lateQueue)},u.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},u.prototype._reset=function(){this._isTickUsed=!1},e.exports=u,e.exports.firstLineError=o},{"./queue":26,"./schedule":29,"./util":36}],3:[function(t,e,r){"use strict";e.exports=function(t,e,r,n){var o=!1,i=function(t,e){this._reject(e)},s=function(t,e){e.promiseRejectionQueued=!0,e.bindingPromise._then(i,i,null,this,t)},a=function(t,e){0==(50397184&this._bitField)&&this._resolveCallback(e.target)},u=function(t,e){e.promiseRejectionQueued||this._reject(t)};t.prototype.bind=function(i){o||(o=!0,t.prototype._propagateFrom=n.propagateFromFunction(),t.prototype._boundValue=n.boundValueFunction());var c=r(i),l=new t(e);l._propagateFrom(this,1);var f=this._target();if(l._setBoundTo(c),c instanceof t){var p={promiseRejectionQueued:!1,promise:l,target:f,bindingPromise:c};f._then(e,s,void 0,l,p),c._then(a,u,void 0,l,p),l._setOnCancel(c)}else l._resolveCallback(f);return l},t.prototype._setBoundTo=function(t){void 0!==t?(this._bitField=2097152|this._bitField,this._boundTo=t):this._bitField=-2097153&this._bitField},t.prototype._isBound=function(){return 2097152==(2097152&this._bitField)},t.bind=function(e,r){return t.resolve(r).bind(e)}}},{}],4:[function(t,e,r){"use strict";var n;"undefined"!=typeof Promise&&(n=Promise);var o=t("./promise")();o.noConflict=function(){try{Promise===o&&(Promise=n)}catch(t){}return o},e.exports=o},{"./promise":22}],5:[function(t,e,r){"use strict";var n=Object.create;if(n){var o=n(null),i=n(null);o[" size"]=i[" size"]=0}e.exports=function(e){var r=t("./util"),n=r.canEvaluate;function o(t){return function(t,n){var o;if(null!=t&&(o=t[n]),"function"!=typeof o){var i="Object "+r.classString(t)+" has no method '"+r.toString(n)+"'";throw new e.TypeError(i)}return o}(t,this.pop()).apply(t,this)}function i(t){return t[this]}function s(t){var e=+this;return e<0&&(e=Math.max(0,e+t.length)),t[e]}r.isIdentifier,e.prototype.call=function(t){var e=[].slice.call(arguments,1);return e.push(t),this._then(o,void 0,void 0,e,void 0)},e.prototype.get=function(t){var e;if("number"==typeof t)e=s;else if(n){var r=(void 0)(t);e=null!==r?r:i}else e=i;return this._then(e,void 0,void 0,t,void 0)}}},{"./util":36}],6:[function(t,e,r){"use strict";e.exports=function(e,r,n,o){var i=t("./util"),s=i.tryCatch,a=i.errorObj,u=e._async;e.prototype.break=e.prototype.cancel=function(){if(!o.cancellation())return this._warn("cancellation is disabled");for(var t=this,e=t;t._isCancellable();){if(!t._cancelBy(e)){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}var r=t._cancellationParent;if(null==r||!r._isCancellable()){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}t._isFollowing()&&t._followee().cancel(),t._setWillBeCancelled(),e=t,t=r}},e.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},e.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},e.prototype._cancelBy=function(t){return t===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),!!this._enoughBranchesHaveCancelled()&&(this._invokeOnCancel(),!0))},e.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},e.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),u.invoke(this._cancelPromises,this,void 0))},e.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},e.prototype._unsetOnCancel=function(){this._onCancelField=void 0},e.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},e.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},e.prototype._doInvokeOnCancel=function(t,e){if(i.isArray(t))for(var r=0;r<t.length;++r)this._doInvokeOnCancel(t[r],e);else if(void 0!==t)if("function"==typeof t){if(!e){var n=s(t).call(this._boundValue());n===a&&(this._attachExtraTrace(n.e),u.throwLater(n.e))}}else t._resultCancelled(this)},e.prototype._invokeOnCancel=function(){var t=this._onCancel();this._unsetOnCancel(),u.invoke(this._doInvokeOnCancel,this,t)},e.prototype._invokeInternalOnCancel=function(){this._isCancellable()&&(this._doInvokeOnCancel(this._onCancel(),!0),this._unsetOnCancel())},e.prototype._resultCancelled=function(){this.cancel()}}},{"./util":36}],7:[function(t,e,r){"use strict";e.exports=function(e){var r=t("./util"),n=t("./es5").keys,o=r.tryCatch,i=r.errorObj;return function(t,s,a){return function(u){var c=a._boundValue();t:for(var l=0;l<t.length;++l){var f=t[l];if(f===Error||null!=f&&f.prototype instanceof Error){if(u instanceof f)return o(s).call(c,u)}else if("function"==typeof f){var p=o(f).call(c,u);if(p===i)return p;if(p)return o(s).call(c,u)}else if(r.isObject(u)){for(var h=n(f),y=0;y<h.length;++y){var d=h[y];if(f[d]!=u[d])continue t}return o(s).call(c,u)}}return e}}}},{"./es5":13,"./util":36}],8:[function(t,e,r){"use strict";e.exports=function(t){var e=!1,r=[];function n(){this._trace=new n.CapturedTrace(o())}function o(){var t=r.length-1;if(t>=0)return r[t]}return t.prototype._promiseCreated=function(){},t.prototype._pushContext=function(){},t.prototype._popContext=function(){return null},t._peekContext=t.prototype._peekContext=function(){},n.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,r.push(this._trace))},n.prototype._popContext=function(){if(void 0!==this._trace){var t=r.pop(),e=t._promiseCreated;return t._promiseCreated=null,e}return null},n.CapturedTrace=null,n.create=function(){if(e)return new n},n.deactivateLongStackTraces=function(){},n.activateLongStackTraces=function(){var r=t.prototype._pushContext,i=t.prototype._popContext,s=t._peekContext,a=t.prototype._peekContext,u=t.prototype._promiseCreated;n.deactivateLongStackTraces=function(){t.prototype._pushContext=r,t.prototype._popContext=i,t._peekContext=s,t.prototype._peekContext=a,t.prototype._promiseCreated=u,e=!1},e=!0,t.prototype._pushContext=n.prototype._pushContext,t.prototype._popContext=n.prototype._popContext,t._peekContext=t.prototype._peekContext=o,t.prototype._promiseCreated=function(){var t=this._peekContext();t&&null==t._promiseCreated&&(t._promiseCreated=this)}},n}},{}],9:[function(t,e,n){"use strict";e.exports=function(e,n){var o,i,s,a=e._getDomain,u=e._async,l=t("./errors").Warning,f=t("./util"),p=f.canAttachTrace,h=/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/,y=/\((?:timers\.js):\d+:\d+\)/,d=/[\/<\(](.+?):(\d+):(\d+)\)?\s*$/,m=null,_=null,v=!1,g=!(0==f.env("BLUEBIRD_DEBUG")),b=!(0==f.env("BLUEBIRD_WARNINGS")||!g&&!f.env("BLUEBIRD_WARNINGS")),w=!(0==f.env("BLUEBIRD_LONG_STACK_TRACES")||!g&&!f.env("BLUEBIRD_LONG_STACK_TRACES")),O=0!=f.env("BLUEBIRD_W_FORGOTTEN_RETURN")&&(b||!!f.env("BLUEBIRD_W_FORGOTTEN_RETURN"));e.prototype.suppressUnhandledRejections=function(){var t=this._target();t._bitField=-1048577&t._bitField|524288},e.prototype._ensurePossibleRejectionHandled=function(){if(0==(524288&this._bitField)){this._setRejectionIsUnhandled();var t=this;setTimeout((function(){t._notifyUnhandledRejection()}),1)}},e.prototype._notifyUnhandledRejectionIsHandled=function(){W("rejectionHandled",o,void 0,this)},e.prototype._setReturnedNonUndefined=function(){this._bitField=268435456|this._bitField},e.prototype._returnedNonUndefined=function(){return 0!=(268435456&this._bitField)},e.prototype._notifyUnhandledRejection=function(){if(this._isRejectionUnhandled()){var t=this._settledValue();this._setUnhandledRejectionIsNotified(),W("unhandledRejection",i,t,this)}},e.prototype._setUnhandledRejectionIsNotified=function(){this._bitField=262144|this._bitField},e.prototype._unsetUnhandledRejectionIsNotified=function(){this._bitField=-262145&this._bitField},e.prototype._isUnhandledRejectionNotified=function(){return(262144&this._bitField)>0},e.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},e.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},e.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},e.prototype._warn=function(t,e,r){return L(t,e,r||this)},e.onPossiblyUnhandledRejection=function(t){var e=a();i="function"==typeof t?null===e?t:f.domainBind(e,t):void 0},e.onUnhandledRejectionHandled=function(t){var e=a();o="function"==typeof t?null===e?t:f.domainBind(e,t):void 0};var S=function(){};e.longStackTraces=function(){if(u.haveItemsQueued()&&!X.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");if(!X.longStackTraces&&Y()){var t=e.prototype._captureStackTrace,r=e.prototype._attachExtraTrace;X.longStackTraces=!0,S=function(){if(u.haveItemsQueued()&&!X.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n See http://goo.gl/MqrFmX\n");e.prototype._captureStackTrace=t,e.prototype._attachExtraTrace=r,n.deactivateLongStackTraces(),u.enableTrampoline(),X.longStackTraces=!1},e.prototype._captureStackTrace=I,e.prototype._attachExtraTrace=F,n.activateLongStackTraces(),u.disableTrampolineIfNecessary()}},e.hasLongStackTraces=function(){return X.longStackTraces&&Y()};var A=function(){try{if("function"==typeof CustomEvent){var t=new CustomEvent("CustomEvent");return f.global.dispatchEvent(t),function(t,e){var r=new CustomEvent(t.toLowerCase(),{detail:e,cancelable:!0});return!f.global.dispatchEvent(r)}}return"function"==typeof Event?(t=new Event("CustomEvent"),f.global.dispatchEvent(t),function(t,e){var r=new Event(t.toLowerCase(),{cancelable:!0});return r.detail=e,!f.global.dispatchEvent(r)}):((t=document.createEvent("CustomEvent")).initCustomEvent("testingtheevent",!1,!0,{}),f.global.dispatchEvent(t),function(t,e){var r=document.createEvent("CustomEvent");return r.initCustomEvent(t.toLowerCase(),!1,!0,e),!f.global.dispatchEvent(r)})}catch(t){}return function(){return!1}}(),j=f.isNode?function(){return r.emit.apply(r,arguments)}:f.global?function(t){var e="on"+t.toLowerCase(),r=f.global[e];return!!r&&(r.apply(f.global,[].slice.call(arguments,1)),!0)}:function(){return!1};function E(t,e){return{promise:e}}var $={promiseCreated:E,promiseFulfilled:E,promiseRejected:E,promiseResolved:E,promiseCancelled:E,promiseChained:function(t,e,r){return{promise:e,child:r}},warning:function(t,e){return{warning:e}},unhandledRejection:function(t,e,r){return{reason:e,promise:r}},rejectionHandled:E},x=function(t){var e=!1;try{e=j.apply(null,arguments)}catch(t){u.throwLater(t),e=!0}var r=!1;try{r=A(t,$[t].apply(null,arguments))}catch(t){u.throwLater(t),r=!0}return r||e};function P(){return!1}function N(t,e,r){var n=this;try{t(e,r,(function(t){if("function"!=typeof t)throw new TypeError("onCancel must be a function, got: "+f.toString(t));n._attachCancellationCallback(t)}))}catch(t){return t}}function T(t){if(!this._isCancellable())return this;var e=this._onCancel();void 0!==e?f.isArray(e)?e.push(t):this._setOnCancel([e,t]):this._setOnCancel(t)}function k(){return this._onCancelField}function C(t){this._onCancelField=t}function D(){this._cancellationParent=void 0,this._onCancelField=void 0}function R(t,e){if(0!=(1&e)){this._cancellationParent=t;var r=t._branchesRemainingToCancel;void 0===r&&(r=0),t._branchesRemainingToCancel=r+1}0!=(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}e.config=function(t){if("longStackTraces"in(t=Object(t))&&(t.longStackTraces?e.longStackTraces():!t.longStackTraces&&e.hasLongStackTraces()&&S()),"warnings"in t){var r=t.warnings;X.warnings=!!r,O=X.warnings,f.isObject(r)&&"wForgottenReturn"in r&&(O=!!r.wForgottenReturn)}if("cancellation"in t&&t.cancellation&&!X.cancellation){if(u.haveItemsQueued())throw new Error("cannot enable cancellation after promises are in use");e.prototype._clearCancellationData=D,e.prototype._propagateFrom=R,e.prototype._onCancel=k,e.prototype._setOnCancel=C,e.prototype._attachCancellationCallback=T,e.prototype._execute=N,B=R,X.cancellation=!0}return"monitoring"in t&&(t.monitoring&&!X.monitoring?(X.monitoring=!0,e.prototype._fireEvent=x):!t.monitoring&&X.monitoring&&(X.monitoring=!1,e.prototype._fireEvent=P)),e},e.prototype._fireEvent=P,e.prototype._execute=function(t,e,r){try{t(e,r)}catch(t){return t}},e.prototype._onCancel=function(){},e.prototype._setOnCancel=function(t){},e.prototype._attachCancellationCallback=function(t){},e.prototype._captureStackTrace=function(){},e.prototype._attachExtraTrace=function(){},e.prototype._clearCancellationData=function(){},e.prototype._propagateFrom=function(t,e){};var B=function(t,e){0!=(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)};function M(){var t=this._boundTo;return void 0!==t&&t instanceof e?t.isFulfilled()?t.value():void 0:t}function I(){this._trace=new J(this._peekContext())}function F(t,e){if(p(t)){var r=this._trace;if(void 0!==r&&e&&(r=r._parent),void 0!==r)r.attachExtraTrace(t);else if(!t.__stackCleaned__){var n=V(t);f.notEnumerableProp(t,"stack",n.message+"\n"+n.stack.join("\n")),f.notEnumerableProp(t,"__stackCleaned__",!0)}}}function L(t,r,n){if(X.warnings){var o,i=new l(t);if(r)n._attachExtraTrace(i);else if(X.longStackTraces&&(o=e._peekContext()))o.attachExtraTrace(i);else{var s=V(i);i.stack=s.message+"\n"+s.stack.join("\n")}x("warning",i)||q(i,"",!0)}}function U(t){for(var e=[],r=0;r<t.length;++r){var n=t[r],o=" (No stack trace)"===n||m.test(n),i=o&&K(n);o&&!i&&(v&&" "!==n.charAt(0)&&(n=" "+n),e.push(n))}return e}function V(t){var e=t.stack,r=t.toString();return e="string"==typeof e&&e.length>0?function(t){for(var e=t.stack.replace(/\s+$/g,"").split("\n"),r=0;r<e.length;++r){var n=e[r];if(" (No stack trace)"===n||m.test(n))break}return r>0&&"SyntaxError"!=t.name&&(e=e.slice(r)),e}(t):[" (No stack trace)"],{message:r,stack:"SyntaxError"==t.name?e:U(e)}}function q(t,e,r){if("undefined"!=typeof console){var n;if(f.isObject(t)){var o=t.stack;n=e+_(o,t)}else n=e+String(t);"function"==typeof s?s(n,r):"function"!=typeof console.log&&"object"!==c(console.log)||console.log(n)}}function W(t,e,r,n){var o=!1;try{"function"==typeof e&&(o=!0,"rejectionHandled"===t?e(n):e(r,n))}catch(t){u.throwLater(t)}"unhandledRejection"===t?x(t,r,n)||o||q(r,"Unhandled rejection "):x(t,n)}function H(t){var e;if("function"==typeof t)e="[function "+(t.name||"anonymous")+"]";else{if(e=t&&"function"==typeof t.toString?t.toString():f.toString(t),/\[object [a-zA-Z0-9$_]+\]/.test(e))try{e=JSON.stringify(t)}catch(t){}0===e.length&&(e="(empty array)")}return"(<"+function(t){return t.length<41?t:t.substr(0,38)+"..."}(e)+">, no stack trace)"}function Y(){return"function"==typeof G}var K=function(){return!1},z=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;function Q(t){var e=t.match(z);if(e)return{fileName:e[1],line:parseInt(e[2],10)}}function J(t){this._parent=t,this._promisesCreated=0;var e=this._length=1+(void 0===t?0:t._length);G(this,J),e>32&&this.uncycle()}f.inherits(J,Error),n.CapturedTrace=J,J.prototype.uncycle=function(){var t=this._length;if(!(t<2)){for(var e=[],r={},n=0,o=this;void 0!==o;++n)e.push(o),o=o._parent;for(n=(t=this._length=n)-1;n>=0;--n){var i=e[n].stack;void 0===r[i]&&(r[i]=n)}for(n=0;n<t;++n){var s=r[e[n].stack];if(void 0!==s&&s!==n){s>0&&(e[s-1]._parent=void 0,e[s-1]._length=1),e[n]._parent=void 0,e[n]._length=1;var a=n>0?e[n-1]:this;s<t-1?(a._parent=e[s+1],a._parent.uncycle(),a._length=a._parent._length+1):(a._parent=void 0,a._length=1);for(var u=a._length+1,c=n-2;c>=0;--c)e[c]._length=u,u++;return}}}},J.prototype.attachExtraTrace=function(t){if(!t.__stackCleaned__){this.uncycle();for(var e=V(t),r=e.message,n=[e.stack],o=this;void 0!==o;)n.push(U(o.stack.split("\n"))),o=o._parent;!function(t){for(var e=t[0],r=1;r<t.length;++r){for(var n=t[r],o=e.length-1,i=e[o],s=-1,a=n.length-1;a>=0;--a)if(n[a]===i){s=a;break}for(a=s;a>=0;--a){var u=n[a];if(e[o]!==u)break;e.pop(),o--}e=n}}(n),function(t){for(var e=0;e<t.length;++e)(0===t[e].length||e+1<t.length&&t[e][0]===t[e+1][0])&&(t.splice(e,1),e--)}(n),f.notEnumerableProp(t,"stack",function(t,e){for(var r=0;r<e.length-1;++r)e[r].push("From previous event:"),e[r]=e[r].join("\n");return r<e.length&&(e[r]=e[r].join("\n")),t+"\n"+e.join("\n")}(r,n)),f.notEnumerableProp(t,"__stackCleaned__",!0)}};var G=function(){var t=/^\s*at\s*/,e=function(t,e){return"string"==typeof t?t:void 0!==e.name&&void 0!==e.message?e.toString():H(e)};if("number"==typeof Error.stackTraceLimit&&"function"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,m=t,_=e;var r=Error.captureStackTrace;return K=function(t){return h.test(t)},function(t,e){Error.stackTraceLimit+=6,r(t,e),Error.stackTraceLimit-=6}}var n,o=new Error;if("string"==typeof o.stack&&o.stack.split("\n")[0].indexOf("stackDetection@")>=0)return m=/@/,_=e,v=!0,function(t){t.stack=(new Error).stack};try{throw new Error}catch(t){n="stack"in t}return!("stack"in o)&&n&&"number"==typeof Error.stackTraceLimit?(m=t,_=e,function(t){Error.stackTraceLimit+=6;try{throw new Error}catch(e){t.stack=e.stack}Error.stackTraceLimit-=6}):(_=function(t,e){return"string"==typeof t?t:"object"!==c(e)&&"function"!=typeof e||void 0===e.name||void 0===e.message?H(e):e.toString()},null)}();"undefined"!=typeof console&&void 0!==console.warn&&(s=function(t){console.warn(t)},f.isNode&&r.stderr.isTTY?s=function(t,e){var r=e?"":"";console.warn(r+t+"\n")}:f.isNode||"string"!=typeof(new Error).stack||(s=function(t,e){console.warn("%c"+t,e?"color: darkorange":"color: red")}));var X={warnings:b,longStackTraces:!1,cancellation:!1,monitoring:!1};return w&&e.longStackTraces(),{longStackTraces:function(){return X.longStackTraces},warnings:function(){return X.warnings},cancellation:function(){return X.cancellation},monitoring:function(){return X.monitoring},propagateFromFunction:function(){return B},boundValueFunction:function(){return M},checkForgottenReturns:function(t,e,r,n,o){if(void 0===t&&null!==e&&O){if(void 0!==o&&o._returnedNonUndefined())return;if(0==(65535&n._bitField))return;r&&(r+=" ");var i="",s="";if(e._trace){for(var a=e._trace.stack.split("\n"),u=U(a),c=u.length-1;c>=0;--c){var l=u[c];if(!y.test(l)){var f=l.match(d);f&&(i="at "+f[1]+":"+f[2]+":"+f[3]+" ");break}}if(u.length>0){var p=u[0];for(c=0;c<a.length;++c)if(a[c]===p){c>0&&(s="\n"+a[c-1]);break}}}var h="a promise was created in a "+r+"handler "+i+"but was not returned from it, see http://goo.gl/rRqMUw"+s;n._warn(h,!0,e)}},setBounds:function(t,e){if(Y()){for(var r,n,o=t.stack.split("\n"),i=e.stack.split("\n"),s=-1,a=-1,u=0;u<o.length;++u)if(c=Q(o[u])){r=c.fileName,s=c.line;break}for(u=0;u<i.length;++u){var c;if(c=Q(i[u])){n=c.fileName,a=c.line;break}}s<0||a<0||!r||!n||r!==n||s>=a||(K=function(t){if(h.test(t))return!0;var e=Q(t);return!!(e&&e.fileName===r&&s<=e.line&&e.line<=a)})}},warn:L,deprecated:function(t,e){var r=t+" is deprecated and will be removed in a future version.";return e&&(r+=" Use "+e+" instead."),L(r)},CapturedTrace:J,fireDomEvent:A,fireGlobalEvent:j}}},{"./errors":12,"./util":36}],10:[function(t,e,r){"use strict";e.exports=function(t){function e(){return this.value}function r(){throw this.reason}t.prototype.return=t.prototype.thenReturn=function(r){return r instanceof t&&r.suppressUnhandledRejections(),this._then(e,void 0,void 0,{value:r},void 0)},t.prototype.throw=t.prototype.thenThrow=function(t){return this._then(r,void 0,void 0,{reason:t},void 0)},t.prototype.catchThrow=function(t){if(arguments.length<=1)return this._then(void 0,r,void 0,{reason:t},void 0);var e=arguments[1],n=function(){throw e};return this.caught(t,n)},t.prototype.catchReturn=function(r){if(arguments.length<=1)return r instanceof t&&r.suppressUnhandledRejections(),this._then(void 0,e,void 0,{value:r},void 0);var n=arguments[1];n instanceof t&&n.suppressUnhandledRejections();var o=function(){return n};return this.caught(r,o)}}},{}],11:[function(t,e,r){"use strict";e.exports=function(t,e){var r=t.reduce,n=t.all;function o(){return n(this)}t.prototype.each=function(t){return r(this,t,e,0)._then(o,void 0,void 0,this,void 0)},t.prototype.mapSeries=function(t){return r(this,t,e,e)},t.each=function(t,n){return r(t,n,e,0)._then(o,void 0,void 0,t,void 0)},t.mapSeries=function(t,n){return r(t,n,e,e)}}},{}],12:[function(t,e,r){"use strict";var n,o,i=t("./es5"),s=i.freeze,a=t("./util"),u=a.inherits,c=a.notEnumerableProp;function l(t,e){function r(n){if(!(this instanceof r))return new r(n);c(this,"message","string"==typeof n?n:e),c(this,"name",t),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this)}return u(r,Error),r}var f=l("Warning","warning"),p=l("CancellationError","cancellation error"),h=l("TimeoutError","timeout error"),y=l("AggregateError","aggregate error");try{n=TypeError,o=RangeError}catch(t){n=l("TypeError","type error"),o=l("RangeError","range error")}for(var d="join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse".split(" "),m=0;m<d.length;++m)"function"==typeof Array.prototype[d[m]]&&(y.prototype[d[m]]=Array.prototype[d[m]]);i.defineProperty(y.prototype,"length",{value:0,configurable:!1,writable:!0,enumerable:!0}),y.prototype.isOperational=!0;var _=0;function v(t){if(!(this instanceof v))return new v(t);c(this,"name","OperationalError"),c(this,"message",t),this.cause=t,this.isOperational=!0,t instanceof Error?(c(this,"message",t.message),c(this,"stack",t.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor)}y.prototype.toString=function(){var t=Array(4*_+1).join(" "),e="\n"+t+"AggregateError of:\n";_++,t=Array(4*_+1).join(" ");for(var r=0;r<this.length;++r){for(var n=this[r]===this?"[Circular AggregateError]":this[r]+"",o=n.split("\n"),i=0;i<o.length;++i)o[i]=t+o[i];e+=(n=o.join("\n"))+"\n"}return _--,e},u(v,Error);var g=Error.__BluebirdErrorTypes__;g||(g=s({CancellationError:p,TimeoutError:h,OperationalError:v,RejectionError:v,AggregateError:y}),i.defineProperty(Error,"__BluebirdErrorTypes__",{value:g,writable:!1,enumerable:!1,configurable:!1})),e.exports={Error:Error,TypeError:n,RangeError:o,CancellationError:g.CancellationError,OperationalError:g.OperationalError,TimeoutError:g.TimeoutError,AggregateError:g.AggregateError,Warning:f}},{"./es5":13,"./util":36}],13:[function(t,e,r){var n=function(){"use strict";return void 0===this}();if(n)e.exports={freeze:Object.freeze,defineProperty:Object.defineProperty,getDescriptor:Object.getOwnPropertyDescriptor,keys:Object.keys,names:Object.getOwnPropertyNames,getPrototypeOf:Object.getPrototypeOf,isArray:Array.isArray,isES5:n,propertyIsWritable:function(t,e){var r=Object.getOwnPropertyDescriptor(t,e);return!(r&&!r.writable&&!r.set)}};else{var o={}.hasOwnProperty,i={}.toString,s={}.constructor.prototype,a=function(t){var e=[];for(var r in t)o.call(t,r)&&e.push(r);return e};e.exports={isArray:function(t){try{return"[object Array]"===i.call(t)}catch(t){return!1}},keys:a,names:a,defineProperty:function(t,e,r){return t[e]=r.value,t},getDescriptor:function(t,e){return{value:t[e]}},freeze:function(t){return t},getPrototypeOf:function(t){try{return Object(t).constructor.prototype}catch(t){return s}},isES5:n,propertyIsWritable:function(){return!0}}}},{}],14:[function(t,e,r){"use strict";e.exports=function(t,e){var r=t.map;t.prototype.filter=function(t,n){return r(this,t,n,e)},t.filter=function(t,n,o){return r(t,n,o,e)}}},{}],15:[function(t,e,r){"use strict";e.exports=function(e,r,n){var o=t("./util"),i=e.CancellationError,s=o.errorObj,a=t("./catch_filter")(n);function u(t,e,r){this.promise=t,this.type=e,this.handler=r,this.called=!1,this.cancelPromise=null}function c(t){this.finallyHandler=t}function l(t,e){return null!=t.cancelPromise&&(arguments.length>1?t.cancelPromise._reject(e):t.cancelPromise._cancel(),t.cancelPromise=null,!0)}function f(){return h.call(this,this.promise._target()._settledValue())}function p(t){if(!l(this,t))return s.e=t,s}function h(t){var o=this.promise,a=this.handler;if(!this.called){this.called=!0;var u=this.isFinallyHandler()?a.call(o._boundValue()):a.call(o._boundValue(),t);if(u===n)return u;if(void 0!==u){o._setReturnedNonUndefined();var h=r(u,o);if(h instanceof e){if(null!=this.cancelPromise){if(h._isCancelled()){var y=new i("late cancellation observer");return o._attachExtraTrace(y),s.e=y,s}h.isPending()&&h._attachCancellationCallback(new c(this))}return h._then(f,p,void 0,this,void 0)}}}return o.isRejected()?(l(this),s.e=t,s):(l(this),t)}return u.prototype.isFinallyHandler=function(){return 0===this.type},c.prototype._resultCancelled=function(){l(this.finallyHandler)},e.prototype._passThrough=function(t,e,r,n){return"function"!=typeof t?this.then():this._then(r,n,void 0,new u(this,e,t),void 0)},e.prototype.lastly=e.prototype.finally=function(t){return this._passThrough(t,0,h,h)},e.prototype.tap=function(t){return this._passThrough(t,1,h)},e.prototype.tapCatch=function(t){var r=arguments.length;if(1===r)return this._passThrough(t,1,void 0,h);var n,i=new Array(r-1),s=0;for(n=0;n<r-1;++n){var u=arguments[n];if(!o.isObject(u))return e.reject(new TypeError("tapCatch statement predicate: expecting an object but got "+o.classString(u)));i[s++]=u}i.length=s;var c=arguments[n];return this._passThrough(a(i,c,this),1,void 0,h)},u}},{"./catch_filter":7,"./util":36}],16:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i,s){var a=t("./errors").TypeError,u=t("./util"),c=u.errorObj,l=u.tryCatch,f=[];function p(t,r,o,i){if(s.cancellation()){var a=new e(n),u=this._finallyPromise=new e(n);this._promise=a.lastly((function(){return u})),a._captureStackTrace(),a._setOnCancel(this)}else(this._promise=new e(n))._captureStackTrace();this._stack=i,this._generatorFunction=t,this._receiver=r,this._generator=void 0,this._yieldHandlers="function"==typeof o?[o].concat(f):f,this._yieldedPromise=null,this._cancellationPhase=!1}u.inherits(p,i),p.prototype._isResolved=function(){return null===this._promise},p.prototype._cleanup=function(){this._promise=this._generator=null,s.cancellation()&&null!==this._finallyPromise&&(this._finallyPromise._fulfill(),this._finallyPromise=null)},p.prototype._promiseCancelled=function(){if(!this._isResolved()){var t;if(void 0!==this._generator.return)this._promise._pushContext(),t=l(this._generator.return).call(this._generator,void 0),this._promise._popContext();else{var r=new e.CancellationError("generator .return() sentinel");e.coroutine.returnSentinel=r,this._promise._attachExtraTrace(r),this._promise._pushContext(),t=l(this._generator.throw).call(this._generator,r),this._promise._popContext()}this._cancellationPhase=!0,this._yieldedPromise=null,this._continue(t)}},p.prototype._promiseFulfilled=function(t){this._yieldedPromise=null,this._promise._pushContext();var e=l(this._generator.next).call(this._generator,t);this._promise._popContext(),this._continue(e)},p.prototype._promiseRejected=function(t){this._yieldedPromise=null,this._promise._attachExtraTrace(t),this._promise._pushContext();var e=l(this._generator.throw).call(this._generator,t);this._promise._popContext(),this._continue(e)},p.prototype._resultCancelled=function(){if(this._yieldedPromise instanceof e){var t=this._yieldedPromise;this._yieldedPromise=null,t.cancel()}},p.prototype.promise=function(){return this._promise},p.prototype._run=function(){this._generator=this._generatorFunction.call(this._receiver),this._receiver=this._generatorFunction=void 0,this._promiseFulfilled(void 0)},p.prototype._continue=function(t){var r=this._promise;if(t===c)return this._cleanup(),this._cancellationPhase?r.cancel():r._rejectCallback(t.e,!1);var n=t.value;if(!0===t.done)return this._cleanup(),this._cancellationPhase?r.cancel():r._resolveCallback(n);var i=o(n,this._promise);if(i instanceof e||null!==(i=function(t,r,n){for(var i=0;i<r.length;++i){n._pushContext();var s=l(r[i])(t);if(n._popContext(),s===c){n._pushContext();var a=e.reject(c.e);return n._popContext(),a}var u=o(s,n);if(u instanceof e)return u}return null}(i,this._yieldHandlers,this._promise))){var s=(i=i._target())._bitField;0==(50397184&s)?(this._yieldedPromise=i,i._proxy(this,null)):0!=(33554432&s)?e._async.invoke(this._promiseFulfilled,this,i._value()):0!=(16777216&s)?e._async.invoke(this._promiseRejected,this,i._reason()):this._promiseCancelled()}else this._promiseRejected(new a("A value %s was yielded that could not be treated as a promise\n\n See http://goo.gl/MqrFmX\n\n".replace("%s",String(n))+"From coroutine:\n"+this._stack.split("\n").slice(1,-7).join("\n")))},e.coroutine=function(t,e){if("function"!=typeof t)throw new a("generatorFunction must be a function\n\n See http://goo.gl/MqrFmX\n");var r=Object(e).yieldHandler,n=p,o=(new Error).stack;return function(){var e=t.apply(this,arguments),i=new n(void 0,void 0,r,o),s=i.promise();return i._generator=e,i._promiseFulfilled(void 0),s}},e.coroutine.addYieldHandler=function(t){if("function"!=typeof t)throw new a("expecting a function but got "+u.classString(t));f.push(t)},e.spawn=function(t){if(s.deprecated("Promise.spawn()","Promise.coroutine()"),"function"!=typeof t)return r("generatorFunction must be a function\n\n See http://goo.gl/MqrFmX\n");var n=new p(t,this),o=n.promise();return n._run(e.spawn),o}}},{"./errors":12,"./util":36}],17:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i,s){var a=t("./util");a.canEvaluate,a.tryCatch,a.errorObj,e.join=function(){var t,e=arguments.length-1;e>0&&"function"==typeof arguments[e]&&(t=arguments[e]);var n=[].slice.call(arguments);t&&n.pop();var o=new r(n).promise();return void 0!==t?o.spread(t):o}}},{"./util":36}],18:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i,s){var a=e._getDomain,u=t("./util"),l=u.tryCatch,f=u.errorObj,p=e._async;function h(t,e,r,n){this.constructor$(t),this._promise._captureStackTrace();var o=a();this._callback=null===o?e:u.domainBind(o,e),this._preservedValues=n===i?new Array(this.length()):null,this._limit=r,this._inFlight=0,this._queue=[],p.invoke(this._asyncInit,this,void 0)}function y(t,r,o,i){if("function"!=typeof r)return n("expecting a function but got "+u.classString(r));var s=0;if(void 0!==o){if("object"!==c(o)||null===o)return e.reject(new TypeError("options argument must be an object but it is "+u.classString(o)));if("number"!=typeof o.concurrency)return e.reject(new TypeError("'concurrency' must be a number but it is "+u.classString(o.concurrency)));s=o.concurrency}return new h(t,r,s="number"==typeof s&&isFinite(s)&&s>=1?s:0,i).promise()}u.inherits(h,r),h.prototype._asyncInit=function(){this._init$(void 0,-2)},h.prototype._init=function(){},h.prototype._promiseFulfilled=function(t,r){var n=this._values,i=this.length(),a=this._preservedValues,u=this._limit;if(r<0){if(n[r=-1*r-1]=t,u>=1&&(this._inFlight--,this._drainQueue(),this._isResolved()))return!0}else{if(u>=1&&this._inFlight>=u)return n[r]=t,this._queue.push(r),!1;null!==a&&(a[r]=t);var c=this._promise,p=this._callback,h=c._boundValue();c._pushContext();var y=l(p).call(h,t,r,i),d=c._popContext();if(s.checkForgottenReturns(y,d,null!==a?"Promise.filter":"Promise.map",c),y===f)return this._reject(y.e),!0;var m=o(y,this._promise);if(m instanceof e){var _=(m=m._target())._bitField;if(0==(50397184&_))return u>=1&&this._inFlight++,n[r]=m,m._proxy(this,-1*(r+1)),!1;if(0==(33554432&_))return 0!=(16777216&_)?(this._reject(m._reason()),!0):(this._cancel(),!0);y=m._value()}n[r]=y}return++this._totalResolved>=i&&(null!==a?this._filter(n,a):this._resolve(n),!0)},h.prototype._drainQueue=function(){for(var t=this._queue,e=this._limit,r=this._values;t.length>0&&this._inFlight<e;){if(this._isResolved())return;var n=t.pop();this._promiseFulfilled(r[n],n)}},h.prototype._filter=function(t,e){for(var r=e.length,n=new Array(r),o=0,i=0;i<r;++i)t[i]&&(n[o++]=e[i]);n.length=o,this._resolve(n)},h.prototype.preservedValues=function(){return this._preservedValues},e.prototype.map=function(t,e){return y(this,t,e,null)},e.map=function(t,e,r,n){return y(t,e,r,n)}}},{"./util":36}],19:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i){var s=t("./util"),a=s.tryCatch;e.method=function(t){if("function"!=typeof t)throw new e.TypeError("expecting a function but got "+s.classString(t));return function(){var n=new e(r);n._captureStackTrace(),n._pushContext();var o=a(t).apply(this,arguments),s=n._popContext();return i.checkForgottenReturns(o,s,"Promise.method",n),n._resolveFromSyncValue(o),n}},e.attempt=e.try=function(t){if("function"!=typeof t)return o("expecting a function but got "+s.classString(t));var n,u=new e(r);if(u._captureStackTrace(),u._pushContext(),arguments.length>1){i.deprecated("calling Promise.try with more than 1 argument");var c=arguments[1],l=arguments[2];n=s.isArray(c)?a(t).apply(l,c):a(t).call(l,c)}else n=a(t)();var f=u._popContext();return i.checkForgottenReturns(n,f,"Promise.try",u),u._resolveFromSyncValue(n),u},e.prototype._resolveFromSyncValue=function(t){t===s.errorObj?this._rejectCallback(t.e,!1):this._resolveCallback(t,!0)}}},{"./util":36}],20:[function(t,e,r){"use strict";var n=t("./util"),o=n.maybeWrapAsError,i=t("./errors").OperationalError,s=t("./es5"),a=/^(?:name|message|stack|cause)$/;function u(t){var e;if(function(t){return t instanceof Error&&s.getPrototypeOf(t)===Error.prototype}(t)){(e=new i(t)).name=t.name,e.message=t.message,e.stack=t.stack;for(var r=s.keys(t),o=0;o<r.length;++o){var u=r[o];a.test(u)||(e[u]=t[u])}return e}return n.markAsOriginatingFromRejection(t),t}e.exports=function(t,e){return function(r,n){if(null!==t){if(r){var i=u(o(r));t._attachExtraTrace(i),t._reject(i)}else if(e){var s=[].slice.call(arguments,1);t._fulfill(s)}else t._fulfill(n);t=null}}}},{"./errors":12,"./es5":13,"./util":36}],21:[function(t,e,r){"use strict";e.exports=function(e){var r=t("./util"),n=e._async,o=r.tryCatch,i=r.errorObj;function s(t,e){if(!r.isArray(t))return a.call(this,t,e);var s=o(e).apply(this._boundValue(),[null].concat(t));s===i&&n.throwLater(s.e)}function a(t,e){var r=this._boundValue(),s=void 0===t?o(e).call(r,null):o(e).call(r,null,t);s===i&&n.throwLater(s.e)}function u(t,e){if(!t){var r=new Error(t+"");r.cause=t,t=r}var s=o(e).call(this._boundValue(),t);s===i&&n.throwLater(s.e)}e.prototype.asCallback=e.prototype.nodeify=function(t,e){if("function"==typeof t){var r=a;void 0!==e&&Object(e).spread&&(r=s),this._then(r,u,void 0,this,t)}return this}}},{"./util":36}],22:[function(t,e,n){"use strict";e.exports=function(){var n=function(){return new y("circular promise resolution chain\n\n See http://goo.gl/MqrFmX\n")},o=function(){return new P.PromiseInspection(this._target())},i=function(t){return P.reject(new y(t))};function s(){}var a,u={},c=t("./util");a=c.isNode?function(){var t=r.domain;return void 0===t&&(t=null),t}:function(){return null},c.notEnumerableProp(P,"_getDomain",a);var l=t("./es5"),f=t("./async"),p=new f;l.defineProperty(P,"_async",{value:p});var h=t("./errors"),y=P.TypeError=h.TypeError;P.RangeError=h.RangeError;var d=P.CancellationError=h.CancellationError;P.TimeoutError=h.TimeoutError,P.OperationalError=h.OperationalError,P.RejectionError=h.OperationalError,P.AggregateError=h.AggregateError;var m=function(){},_={},v={},g=t("./thenables")(P,m),b=t("./promise_array")(P,m,g,i,s),w=t("./context")(P),O=w.create,S=t("./debuggability")(P,w),A=(S.CapturedTrace,t("./finally")(P,g,v)),j=t("./catch_filter")(v),E=t("./nodeback"),$=c.errorObj,x=c.tryCatch;function P(t){t!==m&&function(t,e){if(null==t||t.constructor!==P)throw new y("the promise constructor cannot be invoked directly\n\n See http://goo.gl/MqrFmX\n");if("function"!=typeof e)throw new y("expecting a function but got "+c.classString(e))}(this,t),this._bitField=0,this._fulfillmentHandler0=void 0,this._rejectionHandler0=void 0,this._promise0=void 0,this._receiver0=void 0,this._resolveFromExecutor(t),this._promiseCreated(),this._fireEvent("promiseCreated",this)}function N(t){this.promise._resolveCallback(t)}function T(t){this.promise._rejectCallback(t,!1)}function k(t){var e=new P(m);e._fulfillmentHandler0=t,e._rejectionHandler0=t,e._promise0=t,e._receiver0=t}return P.prototype.toString=function(){return"[object Promise]"},P.prototype.caught=P.prototype.catch=function(t){var e=arguments.length;if(e>1){var r,n=new Array(e-1),o=0;for(r=0;r<e-1;++r){var s=arguments[r];if(!c.isObject(s))return i("Catch statement predicate: expecting an object but got "+c.classString(s));n[o++]=s}return n.length=o,t=arguments[r],this.then(void 0,j(n,t,this))}return this.then(void 0,t)},P.prototype.reflect=function(){return this._then(o,o,void 0,this,void 0)},P.prototype.then=function(t,e){if(S.warnings()&&arguments.length>0&&"function"!=typeof t&&"function"!=typeof e){var r=".then() only accepts functions but was passed: "+c.classString(t);arguments.length>1&&(r+=", "+c.classString(e)),this._warn(r)}return this._then(t,e,void 0,void 0,void 0)},P.prototype.done=function(t,e){this._then(t,e,void 0,void 0,void 0)._setIsFinal()},P.prototype.spread=function(t){return"function"!=typeof t?i("expecting a function but got "+c.classString(t)):this.all()._then(t,void 0,void 0,_,void 0)},P.prototype.toJSON=function(){var t={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(t.fulfillmentValue=this.value(),t.isFulfilled=!0):this.isRejected()&&(t.rejectionReason=this.reason(),t.isRejected=!0),t},P.prototype.all=function(){return arguments.length>0&&this._warn(".all() was passed arguments but it does not take any"),new b(this).promise()},P.prototype.error=function(t){return this.caught(c.originatesFromRejection,t)},P.getNewLibraryCopy=e.exports,P.is=function(t){return t instanceof P},P.fromNode=P.fromCallback=function(t){var e=new P(m);e._captureStackTrace();var r=arguments.length>1&&!!Object(arguments[1]).multiArgs,n=x(t)(E(e,r));return n===$&&e._rejectCallback(n.e,!0),e._isFateSealed()||e._setAsyncGuaranteed(),e},P.all=function(t){return new b(t).promise()},P.cast=function(t){var e=g(t);return e instanceof P||((e=new P(m))._captureStackTrace(),e._setFulfilled(),e._rejectionHandler0=t),e},P.resolve=P.fulfilled=P.cast,P.reject=P.rejected=function(t){var e=new P(m);return e._captureStackTrace(),e._rejectCallback(t,!0),e},P.setScheduler=function(t){if("function"!=typeof t)throw new y("expecting a function but got "+c.classString(t));return p.setScheduler(t)},P.prototype._then=function(t,e,r,n,o){var i=void 0!==o,s=i?o:new P(m),u=this._target(),l=u._bitField;i||(s._propagateFrom(this,3),s._captureStackTrace(),void 0===n&&0!=(2097152&this._bitField)&&(n=0!=(50397184&l)?this._boundValue():u===this?void 0:this._boundTo),this._fireEvent("promiseChained",this,s));var f=a();if(0!=(50397184&l)){var h,y,_=u._settlePromiseCtx;0!=(33554432&l)?(y=u._rejectionHandler0,h=t):0!=(16777216&l)?(y=u._fulfillmentHandler0,h=e,u._unsetRejectionIsUnhandled()):(_=u._settlePromiseLateCancellationObserver,y=new d("late cancellation observer"),u._attachExtraTrace(y),h=e),p.invoke(_,u,{handler:null===f?h:"function"==typeof h&&c.domainBind(f,h),promise:s,receiver:n,value:y})}else u._addCallbacks(t,e,s,n,f);return s},P.prototype._length=function(){return 65535&this._bitField},P.prototype._isFateSealed=function(){return 0!=(117506048&this._bitField)},P.prototype._isFollowing=function(){return 67108864==(67108864&this._bitField)},P.prototype._setLength=function(t){this._bitField=-65536&this._bitField|65535&t},P.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent("promiseFulfilled",this)},P.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent("promiseRejected",this)},P.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent("promiseResolved",this)},P.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},P.prototype._isFinal=function(){return(4194304&this._bitField)>0},P.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},P.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent("promiseCancelled",this)},P.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},P.prototype._setAsyncGuaranteed=function(){p.hasCustomScheduler()||(this._bitField=134217728|this._bitField)},P.prototype._receiverAt=function(t){var e=0===t?this._receiver0:this[4*t-4+3];if(e!==u)return void 0===e&&this._isBound()?this._boundValue():e},P.prototype._promiseAt=function(t){return this[4*t-4+2]},P.prototype._fulfillmentHandlerAt=function(t){return this[4*t-4+0]},P.prototype._rejectionHandlerAt=function(t){return this[4*t-4+1]},P.prototype._boundValue=function(){},P.prototype._migrateCallback0=function(t){t._bitField;var e=t._fulfillmentHandler0,r=t._rejectionHandler0,n=t._promise0,o=t._receiverAt(0);void 0===o&&(o=u),this._addCallbacks(e,r,n,o,null)},P.prototype._migrateCallbackAt=function(t,e){var r=t._fulfillmentHandlerAt(e),n=t._rejectionHandlerAt(e),o=t._promiseAt(e),i=t._receiverAt(e);void 0===i&&(i=u),this._addCallbacks(r,n,o,i,null)},P.prototype._addCallbacks=function(t,e,r,n,o){var i=this._length();if(i>=65531&&(i=0,this._setLength(0)),0===i)this._promise0=r,this._receiver0=n,"function"==typeof t&&(this._fulfillmentHandler0=null===o?t:c.domainBind(o,t)),"function"==typeof e&&(this._rejectionHandler0=null===o?e:c.domainBind(o,e));else{var s=4*i-4;this[s+2]=r,this[s+3]=n,"function"==typeof t&&(this[s+0]=null===o?t:c.domainBind(o,t)),"function"==typeof e&&(this[s+1]=null===o?e:c.domainBind(o,e))}return this._setLength(i+1),i},P.prototype._proxy=function(t,e){this._addCallbacks(void 0,void 0,e,t,null)},P.prototype._resolveCallback=function(t,e){if(0==(117506048&this._bitField)){if(t===this)return this._rejectCallback(n(),!1);var r=g(t,this);if(!(r instanceof P))return this._fulfill(t);e&&this._propagateFrom(r,2);var o=r._target();if(o!==this){var i=o._bitField;if(0==(50397184&i)){var s=this._length();s>0&&o._migrateCallback0(this);for(var a=1;a<s;++a)o._migrateCallbackAt(this,a);this._setFollowing(),this._setLength(0),this._setFollowee(o)}else if(0!=(33554432&i))this._fulfill(o._value());else if(0!=(16777216&i))this._reject(o._reason());else{var u=new d("late cancellation observer");o._attachExtraTrace(u),this._reject(u)}}else this._reject(n())}},P.prototype._rejectCallback=function(t,e,r){var n=c.ensureErrorObject(t),o=n===t;if(!o&&!r&&S.warnings()){var i="a promise was rejected with a non-error: "+c.classString(t);this._warn(i,!0)}this._attachExtraTrace(n,!!e&&o),this._reject(t)},P.prototype._resolveFromExecutor=function(t){if(t!==m){var e=this;this._captureStackTrace(),this._pushContext();var r=!0,n=this._execute(t,(function(t){e._resolveCallback(t)}),(function(t){e._rejectCallback(t,r)}));r=!1,this._popContext(),void 0!==n&&e._rejectCallback(n,!0)}},P.prototype._settlePromiseFromHandler=function(t,e,r,n){var o=n._bitField;if(0==(65536&o)){var i;n._pushContext(),e===_?r&&"number"==typeof r.length?i=x(t).apply(this._boundValue(),r):(i=$).e=new y("cannot .spread() a non-array: "+c.classString(r)):i=x(t).call(e,r);var s=n._popContext();0==(65536&(o=n._bitField))&&(i===v?n._reject(r):i===$?n._rejectCallback(i.e,!1):(S.checkForgottenReturns(i,s,"",n,this),n._resolveCallback(i)))}},P.prototype._target=function(){for(var t=this;t._isFollowing();)t=t._followee();return t},P.prototype._followee=function(){return this._rejectionHandler0},P.prototype._setFollowee=function(t){this._rejectionHandler0=t},P.prototype._settlePromise=function(t,e,r,n){var i=t instanceof P,a=this._bitField,u=0!=(134217728&a);0!=(65536&a)?(i&&t._invokeInternalOnCancel(),r instanceof A&&r.isFinallyHandler()?(r.cancelPromise=t,x(e).call(r,n)===$&&t._reject($.e)):e===o?t._fulfill(o.call(r)):r instanceof s?r._promiseCancelled(t):i||t instanceof b?t._cancel():r.cancel()):"function"==typeof e?i?(u&&t._setAsyncGuaranteed(),this._settlePromiseFromHandler(e,r,n,t)):e.call(r,n,t):r instanceof s?r._isResolved()||(0!=(33554432&a)?r._promiseFulfilled(n,t):r._promiseRejected(n,t)):i&&(u&&t._setAsyncGuaranteed(),0!=(33554432&a)?t._fulfill(n):t._reject(n))},P.prototype._settlePromiseLateCancellationObserver=function(t){var e=t.handler,r=t.promise,n=t.receiver,o=t.value;"function"==typeof e?r instanceof P?this._settlePromiseFromHandler(e,n,o,r):e.call(n,o,r):r instanceof P&&r._reject(o)},P.prototype._settlePromiseCtx=function(t){this._settlePromise(t.promise,t.handler,t.receiver,t.value)},P.prototype._settlePromise0=function(t,e,r){var n=this._promise0,o=this._receiverAt(0);this._promise0=void 0,this._receiver0=void 0,this._settlePromise(n,t,o,e)},P.prototype._clearCallbackDataAtIndex=function(t){var e=4*t-4;this[e+2]=this[e+3]=this[e+0]=this[e+1]=void 0},P.prototype._fulfill=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(t===this){var r=n();return this._attachExtraTrace(r),this._reject(r)}this._setFulfilled(),this._rejectionHandler0=t,(65535&e)>0&&(0!=(134217728&e)?this._settlePromises():p.settlePromises(this))}},P.prototype._reject=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(this._setRejected(),this._fulfillmentHandler0=t,this._isFinal())return p.fatalError(t,c.isNode);(65535&e)>0?p.settlePromises(this):this._ensurePossibleRejectionHandled()}},P.prototype._fulfillPromises=function(t,e){for(var r=1;r<t;r++){var n=this._fulfillmentHandlerAt(r),o=this._promiseAt(r),i=this._receiverAt(r);this._clearCallbackDataAtIndex(r),this._settlePromise(o,n,i,e)}},P.prototype._rejectPromises=function(t,e){for(var r=1;r<t;r++){var n=this._rejectionHandlerAt(r),o=this._promiseAt(r),i=this._receiverAt(r);this._clearCallbackDataAtIndex(r),this._settlePromise(o,n,i,e)}},P.prototype._settlePromises=function(){var t=this._bitField,e=65535&t;if(e>0){if(0!=(16842752&t)){var r=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,r,t),this._rejectPromises(e,r)}else{var n=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,n,t),this._fulfillPromises(e,n)}this._setLength(0)}this._clearCancellationData()},P.prototype._settledValue=function(){var t=this._bitField;return 0!=(33554432&t)?this._rejectionHandler0:0!=(16777216&t)?this._fulfillmentHandler0:void 0},P.defer=P.pending=function(){return S.deprecated("Promise.defer","new Promise"),{promise:new P(m),resolve:N,reject:T}},c.notEnumerableProp(P,"_makeSelfResolutionError",n),t("./method")(P,m,g,i,S),t("./bind")(P,m,g,S),t("./cancel")(P,b,i,S),t("./direct_resolve")(P),t("./synchronous_inspection")(P),t("./join")(P,b,g,m,p,a),P.Promise=P,P.version="3.5.1",t("./map.js")(P,b,i,g,m,S),t("./call_get.js")(P),t("./using.js")(P,i,g,O,m,S),t("./timers.js")(P,m,S),t("./generators.js")(P,i,m,g,s,S),t("./nodeify.js")(P),t("./promisify.js")(P,m),t("./props.js")(P,b,g,i),t("./race.js")(P,m,g,i),t("./reduce.js")(P,b,i,g,m,S),t("./settle.js")(P,b,S),t("./some.js")(P,b,i),t("./filter.js")(P,m),t("./each.js")(P,m),t("./any.js")(P),c.toFastProperties(P),c.toFastProperties(P.prototype),k({a:1}),k({b:2}),k({c:3}),k(1),k((function(){})),k(void 0),k(!1),k(new P(m)),S.setBounds(f.firstLineError,c.lastLineError),P}},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i){var s=t("./util");function a(t){var n=this._promise=new e(r);t instanceof e&&n._propagateFrom(t,3),n._setOnCancel(this),this._values=t,this._length=0,this._totalResolved=0,this._init(void 0,-2)}return s.isArray,s.inherits(a,i),a.prototype.length=function(){return this._length},a.prototype.promise=function(){return this._promise},a.prototype._init=function t(r,i){var a=n(this._values,this._promise);if(a instanceof e){var u=(a=a._target())._bitField;if(this._values=a,0==(50397184&u))return this._promise._setAsyncGuaranteed(),a._then(t,this._reject,void 0,this,i);if(0==(33554432&u))return 0!=(16777216&u)?this._reject(a._reason()):this._cancel();a=a._value()}if(null!==(a=s.asArray(a)))0!==a.length?this._iterate(a):-5===i?this._resolveEmptyArray():this._resolve(function(t){switch(t){case-2:return[];case-3:return{};case-6:return new Map}}(i));else{var c=o("expecting an array or an iterable object but got "+s.classString(a)).reason();this._promise._rejectCallback(c,!1)}},a.prototype._iterate=function(t){var r=this.getActualLength(t.length);this._length=r,this._values=this.shouldCopyValues()?new Array(r):this._values;for(var o=this._promise,i=!1,s=null,a=0;a<r;++a){var u=n(t[a],o);s=u instanceof e?(u=u._target())._bitField:null,i?null!==s&&u.suppressUnhandledRejections():null!==s?0==(50397184&s)?(u._proxy(this,a),this._values[a]=u):i=0!=(33554432&s)?this._promiseFulfilled(u._value(),a):0!=(16777216&s)?this._promiseRejected(u._reason(),a):this._promiseCancelled(a):i=this._promiseFulfilled(u,a)}i||o._setAsyncGuaranteed()},a.prototype._isResolved=function(){return null===this._values},a.prototype._resolve=function(t){this._values=null,this._promise._fulfill(t)},a.prototype._cancel=function(){!this._isResolved()&&this._promise._isCancellable()&&(this._values=null,this._promise._cancel())},a.prototype._reject=function(t){this._values=null,this._promise._rejectCallback(t,!1)},a.prototype._promiseFulfilled=function(t,e){return this._values[e]=t,++this._totalResolved>=this._length&&(this._resolve(this._values),!0)},a.prototype._promiseCancelled=function(){return this._cancel(),!0},a.prototype._promiseRejected=function(t){return this._totalResolved++,this._reject(t),!0},a.prototype._resultCancelled=function(){if(!this._isResolved()){var t=this._values;if(this._cancel(),t instanceof e)t.cancel();else for(var r=0;r<t.length;++r)t[r]instanceof e&&t[r].cancel()}},a.prototype.shouldCopyValues=function(){return!0},a.prototype.getActualLength=function(t){return t},a}},{"./util":36}],24:[function(t,e,r){"use strict";e.exports=function(e,r){var n={},o=t("./util"),i=t("./nodeback"),s=o.withAppended,a=o.maybeWrapAsError,u=o.canEvaluate,l=t("./errors").TypeError,f={__isPromisified__:!0},p=new RegExp("^(?:"+["arity","length","name","arguments","caller","callee","prototype","__isPromisified__"].join("|")+")$"),h=function(t){return o.isIdentifier(t)&&"_"!==t.charAt(0)&&"constructor"!==t};function y(t){return!p.test(t)}function d(t){try{return!0===t.__isPromisified__}catch(t){return!1}}function m(t,e,r){var n=o.getDataPropertyOrDefault(t,e+r,f);return!!n&&d(n)}function _(t,e,r,n){for(var i=o.inheritedDataKeys(t),s=[],a=0;a<i.length;++a){var u=i[a],c=t[u],f=n===h||h(u);"function"!=typeof c||d(c)||m(t,u,e)||!n(u,c,t,f)||s.push(u,c)}return function(t,e,r){for(var n=0;n<t.length;n+=2){var o=t[n];if(r.test(o))for(var i=o.replace(r,""),s=0;s<t.length;s+=2)if(t[s]===i)throw new l("Cannot promisify an API that has normal methods with '%s'-suffix\n\n See http://goo.gl/MqrFmX\n".replace("%s",e))}}(s,e,r),s}var v=u?void 0:function(t,u,c,l,f,p){var h=function(){return this}(),y=t;function d(){var o=u;u===n&&(o=this);var c=new e(r);c._captureStackTrace();var l="string"==typeof y&&this!==h?this[y]:t,f=i(c,p);try{l.apply(o,s(arguments,f))}catch(t){c._rejectCallback(a(t),!0,!0)}return c._isFateSealed()||c._setAsyncGuaranteed(),c}return"string"==typeof y&&(t=l),o.notEnumerableProp(d,"__isPromisified__",!0),d};function g(t,e,r,i,s){for(var a=new RegExp(e.replace(/([$])/,"\\$")+"$"),u=_(t,e,a,r),c=0,l=u.length;c<l;c+=2){var f=u[c],p=u[c+1],h=f+e;if(i===v)t[h]=v(f,n,f,p,e,s);else{var y=i(p,(function(){return v(f,n,f,p,e,s)}));o.notEnumerableProp(y,"__isPromisified__",!0),t[h]=y}}return o.toFastProperties(t),t}e.promisify=function(t,e){if("function"!=typeof t)throw new l("expecting a function but got "+o.classString(t));if(d(t))return t;var r=function(t,e,r){return v(t,e,void 0,t,null,r)}(t,void 0===(e=Object(e)).context?n:e.context,!!e.multiArgs);return o.copyDescriptors(t,r,y),r},e.promisifyAll=function(t,e){if("function"!=typeof t&&"object"!==c(t))throw new l("the target of promisifyAll must be an object or a function\n\n See http://goo.gl/MqrFmX\n");var r=!!(e=Object(e)).multiArgs,n=e.suffix;"string"!=typeof n&&(n="Async");var i=e.filter;"function"!=typeof i&&(i=h);var s=e.promisifier;if("function"!=typeof s&&(s=v),!o.isIdentifier(n))throw new RangeError("suffix must be a valid identifier\n\n See http://goo.gl/MqrFmX\n");for(var a=o.inheritedDataKeys(t),u=0;u<a.length;++u){var f=t[a[u]];"constructor"!==a[u]&&o.isClass(f)&&(g(f.prototype,n,i,s,r),g(f,n,i,s,r))}return g(t,n,i,s,r)}}},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(t,e,r){"use strict";e.exports=function(e,r,n,o){var i,s=t("./util"),a=s.isObject,u=t("./es5");"function"==typeof Map&&(i=Map);var c=function(){var t=0,e=0;function r(r,n){this[t]=r,this[t+e]=n,t++}return function(n){e=n.size,t=0;var o=new Array(2*n.size);return n.forEach(r,o),o}}();function l(t){var e,r=!1;if(void 0!==i&&t instanceof i)e=c(t),r=!0;else{var n=u.keys(t),o=n.length;e=new Array(2*o);for(var s=0;s<o;++s){var a=n[s];e[s]=t[a],e[s+o]=a}}this.constructor$(e),this._isMap=r,this._init$(void 0,r?-6:-3)}function f(t){var r,i=n(t);return a(i)?(r=i instanceof e?i._then(e.props,void 0,void 0,void 0,void 0):new l(i).promise(),i instanceof e&&r._propagateFrom(i,2),r):o("cannot await properties of a non-object\n\n See http://goo.gl/MqrFmX\n")}s.inherits(l,r),l.prototype._init=function(){},l.prototype._promiseFulfilled=function(t,e){if(this._values[e]=t,++this._totalResolved>=this._length){var r;if(this._isMap)r=function(t){for(var e=new i,r=t.length/2|0,n=0;n<r;++n){var o=t[r+n],s=t[n];e.set(o,s)}return e}(this._values);else{r={};for(var n=this.length(),o=0,s=this.length();o<s;++o)r[this._values[o+n]]=this._values[o]}return this._resolve(r),!0}return!1},l.prototype.shouldCopyValues=function(){return!1},l.prototype.getActualLength=function(t){return t>>1},e.prototype.props=function(){return f(this)},e.props=function(t){return f(t)}}},{"./es5":13,"./util":36}],26:[function(t,e,r){"use strict";function n(t){this._capacity=t,this._length=0,this._front=0}n.prototype._willBeOverCapacity=function(t){return this._capacity<t},n.prototype._pushOne=function(t){var e=this.length();this._checkCapacity(e+1),this[this._front+e&this._capacity-1]=t,this._length=e+1},n.prototype.push=function(t,e,r){var n=this.length()+3;if(this._willBeOverCapacity(n))return this._pushOne(t),this._pushOne(e),void this._pushOne(r);var o=this._front+n-3;this._checkCapacity(n);var i=this._capacity-1;this[o+0&i]=t,this[o+1&i]=e,this[o+2&i]=r,this._length=n},n.prototype.shift=function(){var t=this._front,e=this[t];return this[t]=void 0,this._front=t+1&this._capacity-1,this._length--,e},n.prototype.length=function(){return this._length},n.prototype._checkCapacity=function(t){this._capacity<t&&this._resizeTo(this._capacity<<1)},n.prototype._resizeTo=function(t){var e=this._capacity;this._capacity=t,function(t,e,r,n,o){for(var i=0;i<o;++i)r[i+n]=t[i+e],t[i+e]=void 0}(this,0,this,e,this._front+this._length&e-1)},e.exports=n},{}],27:[function(t,e,r){"use strict";e.exports=function(e,r,n,o){var i=t("./util");function s(t,a){var u,c=n(t);if(c instanceof e)return(u=c).then((function(t){return s(t,u)}));if(null===(t=i.asArray(t)))return o("expecting an array or an iterable object but got "+i.classString(t));var l=new e(r);void 0!==a&&l._propagateFrom(a,3);for(var f=l._fulfill,p=l._reject,h=0,y=t.length;h<y;++h){var d=t[h];(void 0!==d||h in t)&&e.cast(d)._then(f,p,void 0,l,null)}return l}e.race=function(t){return s(t,void 0)},e.prototype.race=function(){return s(this,void 0)}}},{"./util":36}],28:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i,s){var a=e._getDomain,u=t("./util"),c=u.tryCatch;function l(t,r,n,o){this.constructor$(t);var s=a();this._fn=null===s?r:u.domainBind(s,r),void 0!==n&&(n=e.resolve(n))._attachCancellationCallback(this),this._initialValue=n,this._currentCancellable=null,this._eachValues=o===i?Array(this._length):0===o?null:void 0,this._promise._captureStackTrace(),this._init$(void 0,-5)}function f(t,e){this.isFulfilled()?e._resolve(t):e._reject(t)}function p(t,e,r,o){return"function"!=typeof e?n("expecting a function but got "+u.classString(e)):new l(t,e,r,o).promise()}function h(t){this.accum=t,this.array._gotAccum(t);var r=o(this.value,this.array._promise);return r instanceof e?(this.array._currentCancellable=r,r._then(y,void 0,void 0,this,void 0)):y.call(this,r)}function y(t){var r,n=this.array,o=n._promise,i=c(n._fn);o._pushContext(),(r=void 0!==n._eachValues?i.call(o._boundValue(),t,this.index,this.length):i.call(o._boundValue(),this.accum,t,this.index,this.length))instanceof e&&(n._currentCancellable=r);var a=o._popContext();return s.checkForgottenReturns(r,a,void 0!==n._eachValues?"Promise.each":"Promise.reduce",o),r}u.inherits(l,r),l.prototype._gotAccum=function(t){void 0!==this._eachValues&&null!==this._eachValues&&t!==i&&this._eachValues.push(t)},l.prototype._eachComplete=function(t){return null!==this._eachValues&&this._eachValues.push(t),this._eachValues},l.prototype._init=function(){},l.prototype._resolveEmptyArray=function(){this._resolve(void 0!==this._eachValues?this._eachValues:this._initialValue)},l.prototype.shouldCopyValues=function(){return!1},l.prototype._resolve=function(t){this._promise._resolveCallback(t),this._values=null},l.prototype._resultCancelled=function(t){if(t===this._initialValue)return this._cancel();this._isResolved()||(this._resultCancelled$(),this._currentCancellable instanceof e&&this._currentCancellable.cancel(),this._initialValue instanceof e&&this._initialValue.cancel())},l.prototype._iterate=function(t){var r,n;this._values=t;var o=t.length;if(void 0!==this._initialValue?(r=this._initialValue,n=0):(r=e.resolve(t[0]),n=1),this._currentCancellable=r,!r.isRejected())for(;n<o;++n){var i={accum:null,value:t[n],index:n,length:o,array:this};r=r._then(h,void 0,void 0,i,void 0)}void 0!==this._eachValues&&(r=r._then(this._eachComplete,void 0,void 0,this,void 0)),r._then(f,f,void 0,r,this)},e.prototype.reduce=function(t,e){return p(this,t,e,null)},e.reduce=function(t,e,r,n){return p(t,e,r,n)}}},{"./util":36}],29:[function(t,e,i){"use strict";var s,a,u,c,l,f=t("./util"),p=f.getNativePromise();if(f.isNode&&"undefined"==typeof MutationObserver){var h=n.setImmediate,y=r.nextTick;s=f.isRecentNode?function(t){h.call(n,t)}:function(t){y.call(r,t)}}else if("function"==typeof p&&"function"==typeof p.resolve){var d=p.resolve();s=function(t){d.then(t)}}else s="undefined"==typeof MutationObserver||"undefined"!=typeof window&&window.navigator&&(window.navigator.standalone||window.cordova)?void 0!==o?function(t){o(t)}:"undefined"!=typeof setTimeout?function(t){setTimeout(t,0)}:function(){throw new Error("No async scheduler available\n\n See http://goo.gl/MqrFmX\n")}:(a=document.createElement("div"),u={attributes:!0},c=!1,l=document.createElement("div"),new MutationObserver((function(){a.classList.toggle("foo"),c=!1})).observe(l,u),function(t){var e=new MutationObserver((function(){e.disconnect(),t()}));e.observe(a,u),c||(c=!0,l.classList.toggle("foo"))});e.exports=s},{"./util":36}],30:[function(t,e,r){"use strict";e.exports=function(e,r,n){var o=e.PromiseInspection;function i(t){this.constructor$(t)}t("./util").inherits(i,r),i.prototype._promiseResolved=function(t,e){return this._values[t]=e,++this._totalResolved>=this._length&&(this._resolve(this._values),!0)},i.prototype._promiseFulfilled=function(t,e){var r=new o;return r._bitField=33554432,r._settledValueField=t,this._promiseResolved(e,r)},i.prototype._promiseRejected=function(t,e){var r=new o;return r._bitField=16777216,r._settledValueField=t,this._promiseResolved(e,r)},e.settle=function(t){return n.deprecated(".settle()",".reflect()"),new i(t).promise()},e.prototype.settle=function(){return e.settle(this)}}},{"./util":36}],31:[function(t,e,r){"use strict";e.exports=function(e,r,n){var o=t("./util"),i=t("./errors").RangeError,s=t("./errors").AggregateError,a=o.isArray,u={};function c(t){this.constructor$(t),this._howMany=0,this._unwrap=!1,this._initialized=!1}function l(t,e){if((0|e)!==e||e<0)return n("expecting a positive integer\n\n See http://goo.gl/MqrFmX\n");var r=new c(t),o=r.promise();return r.setHowMany(e),r.init(),o}o.inherits(c,r),c.prototype._init=function(){if(this._initialized)if(0!==this._howMany){this._init$(void 0,-5);var t=a(this._values);!this._isResolved()&&t&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))}else this._resolve([])},c.prototype.init=function(){this._initialized=!0,this._init()},c.prototype.setUnwrap=function(){this._unwrap=!0},c.prototype.howMany=function(){return this._howMany},c.prototype.setHowMany=function(t){this._howMany=t},c.prototype._promiseFulfilled=function(t){return this._addFulfilled(t),this._fulfilled()===this.howMany()&&(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0)},c.prototype._promiseRejected=function(t){return this._addRejected(t),this._checkOutcome()},c.prototype._promiseCancelled=function(){return this._values instanceof e||null==this._values?this._cancel():(this._addRejected(u),this._checkOutcome())},c.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var t=new s,e=this.length();e<this._values.length;++e)this._values[e]!==u&&t.push(this._values[e]);return t.length>0?this._reject(t):this._cancel(),!0}return!1},c.prototype._fulfilled=function(){return this._totalResolved},c.prototype._rejected=function(){return this._values.length-this.length()},c.prototype._addRejected=function(t){this._values.push(t)},c.prototype._addFulfilled=function(t){this._values[this._totalResolved++]=t},c.prototype._canPossiblyFulfill=function(){return this.length()-this._rejected()},c.prototype._getRangeError=function(t){var e="Input array must contain at least "+this._howMany+" items but contains only "+t+" items";return new i(e)},c.prototype._resolveEmptyArray=function(){this._reject(this._getRangeError(0))},e.some=function(t,e){return l(t,e)},e.prototype.some=function(t){return l(this,t)},e._SomePromiseArray=c}},{"./errors":12,"./util":36}],32:[function(t,e,r){"use strict";e.exports=function(t){function e(t){void 0!==t?(t=t._target(),this._bitField=t._bitField,this._settledValueField=t._isFateSealed()?t._settledValue():void 0):(this._bitField=0,this._settledValueField=void 0)}e.prototype._settledValue=function(){return this._settledValueField};var r=e.prototype.value=function(){if(!this.isFulfilled())throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},n=e.prototype.error=e.prototype.reason=function(){if(!this.isRejected())throw new TypeError("cannot get rejection reason of a non-rejected promise\n\n See http://goo.gl/MqrFmX\n");return this._settledValue()},o=e.prototype.isFulfilled=function(){return 0!=(33554432&this._bitField)},i=e.prototype.isRejected=function(){return 0!=(16777216&this._bitField)},s=e.prototype.isPending=function(){return 0==(50397184&this._bitField)},a=e.prototype.isResolved=function(){return 0!=(50331648&this._bitField)};e.prototype.isCancelled=function(){return 0!=(8454144&this._bitField)},t.prototype.__isCancelled=function(){return 65536==(65536&this._bitField)},t.prototype._isCancelled=function(){return this._target().__isCancelled()},t.prototype.isCancelled=function(){return 0!=(8454144&this._target()._bitField)},t.prototype.isPending=function(){return s.call(this._target())},t.prototype.isRejected=function(){return i.call(this._target())},t.prototype.isFulfilled=function(){return o.call(this._target())},t.prototype.isResolved=function(){return a.call(this._target())},t.prototype.value=function(){return r.call(this._target())},t.prototype.reason=function(){var t=this._target();return t._unsetRejectionIsUnhandled(),n.call(t)},t.prototype._value=function(){return this._settledValue()},t.prototype._reason=function(){return this._unsetRejectionIsUnhandled(),this._settledValue()},t.PromiseInspection=e}},{}],33:[function(t,e,r){"use strict";e.exports=function(e,r){var n=t("./util"),o=n.errorObj,i=n.isObject,s={}.hasOwnProperty;return function(t,a){if(i(t)){if(t instanceof e)return t;var u=function(t){try{return function(t){return t.then}(t)}catch(t){return o.e=t,o}}(t);if(u===o){a&&a._pushContext();var c=e.reject(u.e);return a&&a._popContext(),c}if("function"==typeof u)return function(t){try{return s.call(t,"_promise0")}catch(t){return!1}}(t)?(c=new e(r),t._then(c._fulfill,c._reject,void 0,c,null),c):function(t,i,s){var a=new e(r),u=a;s&&s._pushContext(),a._captureStackTrace(),s&&s._popContext();var c=n.tryCatch(i).call(t,(function(t){a&&(a._resolveCallback(t),a=null)}),(function(t){a&&(a._rejectCallback(t,!1,!0),a=null)}));return a&&c===o&&(a._rejectCallback(c.e,!0,!0),a=null),u}(t,u,a)}return t}}},{"./util":36}],34:[function(t,e,r){"use strict";e.exports=function(e,r,n){var o=t("./util"),i=e.TimeoutError;function s(t){this.handle=t}s.prototype._resultCancelled=function(){clearTimeout(this.handle)};var a=function(t){return u(+this).thenReturn(t)},u=e.delay=function(t,o){var i,u;return void 0!==o?(i=e.resolve(o)._then(a,null,null,t,void 0),n.cancellation()&&o instanceof e&&i._setOnCancel(o)):(i=new e(r),u=setTimeout((function(){i._fulfill()}),+t),n.cancellation()&&i._setOnCancel(new s(u)),i._captureStackTrace()),i._setAsyncGuaranteed(),i};function c(t){return clearTimeout(this.handle),t}function l(t){throw clearTimeout(this.handle),t}e.prototype.delay=function(t){return u(t,this)},e.prototype.timeout=function(t,e){var r,a;t=+t;var u=new s(setTimeout((function(){r.isPending()&&function(t,e,r){var n;n="string"!=typeof e?e instanceof Error?e:new i("operation timed out"):new i(e),o.markAsOriginatingFromRejection(n),t._attachExtraTrace(n),t._reject(n),null!=r&&r.cancel()}(r,e,a)}),t));return n.cancellation()?(a=this.then(),(r=a._then(c,l,void 0,u,void 0))._setOnCancel(u)):r=this._then(c,l,void 0,u,void 0),r}}},{"./util":36}],35:[function(t,e,r){"use strict";e.exports=function(e,r,n,o,i,s){var a=t("./util"),u=t("./errors").TypeError,c=t("./util").inherits,l=a.errorObj,f=a.tryCatch,p={};function h(t){setTimeout((function(){throw t}),0)}function y(t,r){var o=0,s=t.length,a=new e(i);return function i(){if(o>=s)return a._fulfill();var u=function(t){var e=n(t);return e!==t&&"function"==typeof t._isDisposable&&"function"==typeof t._getDisposer&&t._isDisposable()&&e._setDisposable(t._getDisposer()),e}(t[o++]);if(u instanceof e&&u._isDisposable()){try{u=n(u._getDisposer().tryDispose(r),t.promise)}catch(t){return h(t)}if(u instanceof e)return u._then(i,h,null,null,null)}i()}(),a}function d(t,e,r){this._data=t,this._promise=e,this._context=r}function m(t,e,r){this.constructor$(t,e,r)}function _(t){return d.isDisposer(t)?(this.resources[this.index]._setDisposable(t),t.promise()):t}function v(t){this.length=t,this.promise=null,this[t-1]=null}d.prototype.data=function(){return this._data},d.prototype.promise=function(){return this._promise},d.prototype.resource=function(){return this.promise().isFulfilled()?this.promise().value():p},d.prototype.tryDispose=function(t){var e=this.resource(),r=this._context;void 0!==r&&r._pushContext();var n=e!==p?this.doDispose(e,t):null;return void 0!==r&&r._popContext(),this._promise._unsetDisposable(),this._data=null,n},d.isDisposer=function(t){return null!=t&&"function"==typeof t.resource&&"function"==typeof t.tryDispose},c(m,d),m.prototype.doDispose=function(t,e){return this.data().call(t,t,e)},v.prototype._resultCancelled=function(){for(var t=this.length,r=0;r<t;++r){var n=this[r];n instanceof e&&n.cancel()}},e.using=function(){var t=arguments.length;if(t<2)return r("you must pass at least 2 arguments to Promise.using");var o,i=arguments[t-1];if("function"!=typeof i)return r("expecting a function but got "+a.classString(i));var u=!0;2===t&&Array.isArray(arguments[0])?(t=(o=arguments[0]).length,u=!1):(o=arguments,t--);for(var c=new v(t),p=0;p<t;++p){var h=o[p];if(d.isDisposer(h)){var m=h;(h=h.promise())._setDisposable(m)}else{var g=n(h);g instanceof e&&(h=g._then(_,null,null,{resources:c,index:p},void 0))}c[p]=h}var b=new Array(c.length);for(p=0;p<b.length;++p)b[p]=e.resolve(c[p]).reflect();var w=e.all(b).then((function(t){for(var e=0;e<t.length;++e){var r=t[e];if(r.isRejected())return l.e=r.error(),l;if(!r.isFulfilled())return void w.cancel();t[e]=r.value()}O._pushContext(),i=f(i);var n=u?i.apply(void 0,t):i(t),o=O._popContext();return s.checkForgottenReturns(n,o,"Promise.using",O),n})),O=w.lastly((function(){var t=new e.PromiseInspection(w);return y(c,t)}));return c.promise=O,O._setOnCancel(c),O},e.prototype._setDisposable=function(t){this._bitField=131072|this._bitField,this._disposer=t},e.prototype._isDisposable=function(){return(131072&this._bitField)>0},e.prototype._getDisposer=function(){return this._disposer},e.prototype._unsetDisposable=function(){this._bitField=-131073&this._bitField,this._disposer=void 0},e.prototype.disposer=function(t){if("function"==typeof t)return new m(t,this,o());throw new u}}},{"./errors":12,"./util":36}],36:[function(t,e,o){"use strict";var i=t("./es5"),s="undefined"==typeof navigator,a={e:{}},u,l="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n?n:void 0!==this?this:null;function f(){try{var t=u;return u=null,t.apply(this,arguments)}catch(t){return a.e=t,a}}function p(t){return u=t,f}var h=function(t,e){var r={}.hasOwnProperty;function n(){for(var n in this.constructor=t,this.constructor$=e,e.prototype)r.call(e.prototype,n)&&"$"!==n.charAt(n.length-1)&&(this[n+"$"]=e.prototype[n])}return n.prototype=e.prototype,t.prototype=new n,t.prototype};function y(t){return null==t||!0===t||!1===t||"string"==typeof t||"number"==typeof t}function d(t){return"function"==typeof t||"object"===c(t)&&null!==t}function m(t){return y(t)?new Error(x(t)):t}function _(t,e){var r,n=t.length,o=new Array(n+1);for(r=0;r<n;++r)o[r]=t[r];return o[r]=e,o}function v(t,e,r){if(!i.isES5)return{}.hasOwnProperty.call(t,e)?t[e]:void 0;var n=Object.getOwnPropertyDescriptor(t,e);return null!=n?null==n.get&&null==n.set?n.value:r:void 0}function g(t,e,r){if(y(t))return t;var n={value:r,configurable:!0,enumerable:!1,writable:!0};return i.defineProperty(t,e,n),t}function b(t){throw t}var w=function(){var t=[Array.prototype,Object.prototype,Function.prototype],e=function(e){for(var r=0;r<t.length;++r)if(t[r]===e)return!0;return!1};if(i.isES5){var r=Object.getOwnPropertyNames;return function(t){for(var n=[],o=Object.create(null);null!=t&&!e(t);){var s;try{s=r(t)}catch(t){return n}for(var a=0;a<s.length;++a){var u=s[a];if(!o[u]){o[u]=!0;var c=Object.getOwnPropertyDescriptor(t,u);null!=c&&null==c.get&&null==c.set&&n.push(u)}}t=i.getPrototypeOf(t)}return n}}var n={}.hasOwnProperty;return function(r){if(e(r))return[];var o=[];t:for(var i in r)if(n.call(r,i))o.push(i);else{for(var s=0;s<t.length;++s)if(n.call(t[s],i))continue t;o.push(i)}return o}}(),O=/this\s*\.\s*\S+\s*=/;function S(t){try{if("function"==typeof t){var e=i.names(t.prototype),r=i.isES5&&e.length>1,n=e.length>0&&!(1===e.length&&"constructor"===e[0]),o=O.test(t+"")&&i.names(t).length>0;if(r||n||o)return!0}return!1}catch(t){return!1}}function A(t){function e(){}e.prototype=t;for(var r=8;r--;)new e;return t}var j=/^[a-z$_][a-z$_0-9]*$/i;function E(t){return j.test(t)}function $(t,e,r){for(var n=new Array(t),o=0;o<t;++o)n[o]=e+o+r;return n}function x(t){try{return t+""}catch(t){return"[no string representation]"}}function P(t){return t instanceof Error||null!==t&&"object"===c(t)&&"string"==typeof t.message&&"string"==typeof t.name}function N(t){try{g(t,"isOperational",!0)}catch(t){}}function T(t){return null!=t&&(t instanceof Error.__BluebirdErrorTypes__.OperationalError||!0===t.isOperational)}function k(t){return P(t)&&i.propertyIsWritable(t,"stack")}var C="stack"in new Error?function(t){return k(t)?t:new Error(x(t))}:function(t){if(k(t))return t;try{throw new Error(x(t))}catch(t){return t}};function D(t){return{}.toString.call(t)}function R(t,e,r){for(var n=i.names(t),o=0;o<n.length;++o){var s=n[o];if(r(s))try{i.defineProperty(e,s,i.getDescriptor(t,s))}catch(t){}}}var B=function(t){return i.isArray(t)?t:null};if("undefined"!=typeof Symbol&&Symbol.iterator){var M="function"==typeof Array.from?function(t){return Array.from(t)}:function(t){for(var e,r=[],n=t[Symbol.iterator]();!(e=n.next()).done;)r.push(e.value);return r};B=function(t){return i.isArray(t)?t:null!=t&&"function"==typeof t[Symbol.iterator]?M(t):null}}var I=void 0!==r&&"[object process]"===D(r).toLowerCase(),F=void 0!==r&&void 0!==r.env;function L(t){return F?r.env[t]:void 0}function U(){if("function"==typeof Promise)try{var t=new Promise((function(){}));if("[object Promise]"==={}.toString.call(t))return Promise}catch(t){}}function V(t,e){return t.bind(e)}var q={isClass:S,isIdentifier:E,inheritedDataKeys:w,getDataPropertyOrDefault:v,thrower:b,isArray:i.isArray,asArray:B,notEnumerableProp:g,isPrimitive:y,isObject:d,isError:P,canEvaluate:s,errorObj:a,tryCatch:p,inherits:h,withAppended:_,maybeWrapAsError:m,toFastProperties:A,filledRange:$,toString:x,canAttachTrace:k,ensureErrorObject:C,originatesFromRejection:T,markAsOriginatingFromRejection:N,classString:D,copyDescriptors:R,hasDevTools:"undefined"!=typeof chrome&&chrome&&"function"==typeof chrome.loadTimes,isNode:I,hasEnvVariables:F,env:L,global:l,getNativePromise:U,domainBind:V},W;q.isRecentNode=q.isNode&&(W=r.versions.node.split(".").map(Number),0===W[0]&&W[1]>10||W[0]>0),q.isNode&&q.toFastProperties(r);try{throw new Error}catch(t){q.lastLineError=t}e.exports=q},{"./es5":13}]},{},[4])(4)},"object"==c(e)&&void 0!==t?t.exports=u():(s=[],void 0===(a="function"==typeof(i=u)?i.apply(e,s):i)||(t.exports=a)),"undefined"!=typeof window&&null!==window?window.P=window.Promise:"undefined"!=typeof self&&null!==self&&(self.P=self.Promise)}).call(this,r(8),r(11),r(69).setImmediate)},function(t,e,r){"use strict";var n=t.exports={};n.DocumentNotFoundError=null,n.general={},n.general.default="Validator failed for path `{PATH}` with value `{VALUE}`",n.general.required="Path `{PATH}` is required.",n.Number={},n.Number.min="Path `{PATH}` ({VALUE}) is less than minimum allowed value ({MIN}).",n.Number.max="Path `{PATH}` ({VALUE}) is more than maximum allowed value ({MAX}).",n.Number.enum="`{VALUE}` is not a valid enum value for path `{PATH}`.",n.Date={},n.Date.min="Path `{PATH}` ({VALUE}) is before minimum allowed value ({MIN}).",n.Date.max="Path `{PATH}` ({VALUE}) is after maximum allowed value ({MAX}).",n.String={},n.String.enum="`{VALUE}` is not a valid enum value for path `{PATH}`.",n.String.match="Path `{PATH}` is invalid ({VALUE}).",n.String.minlength="Path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).",n.String.maxlength="Path `{PATH}` (`{VALUE}`) is longer than the maximum allowed length ({MAXLENGTH})."},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=r(5),c=r(4),l=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);
+/*!
+ * OverwriteModel Error constructor.
+ */function r(t,n,o,i){var s,a;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);var l=u.messages;return a=null!=l.DocumentNotFoundError?"function"==typeof l.DocumentNotFoundError?l.DocumentNotFoundError(t,n):l.DocumentNotFoundError:'No document found for query "'+c.inspect(t)+'" on model "'+n+'"',(s=e.call(this,a)).result=i,s.numAffected=o,s.filter=t,s.query=t,s}return r}(u);Object.defineProperty(l.prototype,"name",{value:"DocumentNotFoundError"}),
+/*!
+ * exports
+ */
+t.exports=l},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t,n,o){var i;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);var s=o.join(", ");return(i=e.call(this,'No matching document found for id "'+t._id+'" version '+n+' modifiedPaths "'+s+'"')).version=n,i.modifiedPaths=o,i}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"VersionError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);return e.call(this,"Can't save() the same doc multiple times in parallel. Document: "+t._id)}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"ParallelSaveError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);
+/*!
+ * OverwriteModel Error constructor.
+ * @param {String} name
+ */function r(t){return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r),e.call(this,"Cannot overwrite `"+t+"` model once compiled.")}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"OverwriteModelError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);
+/*!
+ * MissingSchema Error constructor.
+ * @param {String} name
+ */function r(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);var n="Schema hasn't been registered for model \""+t+'".\nUse mongoose.model(name, schema)';return e.call(this,n)}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"MissingSchemaError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);
+/*!
+ * DivergentArrayError constructor.
+ * @param {Array<String>} paths
+ */function r(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);var n="For your own good, using `document.save()` to update an array which was selected using an $elemMatch projection OR populated using skip, limit, query conditions, or exclusion of the _id field when the operation results in a $pop or $set of the entire array is not supported. The following path(s) would have been modified unsafely:\n "+t.join("\n ")+"\nUse Model.update() to update these arrays instead.";return e.call(this,n)}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"DivergentArrayError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";var n=r(32);
+/*!
+ * ignore
+ */t.exports=function(t){var e,r;t.$immutable?(t.$immutableSetter=(e=t.path,r=t.options.immutable,function(t){if(null==this||null==this.$__)return t;if(this.isNew)return t;if(!("function"==typeof r?r.call(this,this):r))return t;var o=this.$__getValue(e);if("throw"===this.$__.strictMode&&t!==o)throw new n(e,"Path `"+e+"` is immutable and strict mode is set to throw.",!0);return o}),t.set(t.$immutableSetter)):t.$immutableSetter&&(t.setters=t.setters.filter((function(e){return e!==t.$immutableSetter})),delete t.$immutableSetter)}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t,n,o){return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r),e.call(this,'Parameter "'+n+'" to '+o+"() must be an object, got "+t.toString())}return r}(r(5));Object.defineProperty(u.prototype,"name",{value:"ObjectParameterError"}),t.exports=u},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){return(o=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function i(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=a(t);if(e){var o=a(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return s(this,r)}}function s(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function a(t){return(a=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var u=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&o(t,e)}(r,t);var e=i(r);function r(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,r);return e.call(this,"Can't validate() the same doc multiple times in parallel. Document: "+t._id)}return r}(r(14));Object.defineProperty(u.prototype,"name",{value:"ParallelValidateError"}),
+/*!
+ * exports
+ */
+t.exports=u},function(t,e,r){"use strict";(function(e){function r(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return n(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return n(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var o=0,i=function(){};return{s:i,n:function(){return o>=t.length?{done:!0}:{done:!1,value:t[o++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function n(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function o(t){return(o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function i(){this._pres=new Map,this._posts=new Map}function s(t,e,r,n,o,i,s){if(i.useErrorHandlers){var a={error:e};return t.execPost(r,n,o,a,(function(t){return"function"==typeof s&&s(t)}))}return"function"==typeof s?s(e):void 0}function a(t,e,r){return t.has(e)?t.get(e):r}function u(t,e,r,n){var o;try{o=t.apply(e,r)}catch(t){return n(t)}c(o)&&o.then((function(){return n()}),(function(t){return n(t)}))}function c(t){return null!=t&&"function"==typeof t.then}function l(t){var r=!1,n=this;return function(){var o=arguments;if(!r)return r=!0,e.nextTick((function(){return t.apply(n,o)}))}}i.prototype.execPre=function(t,r,n,o){3===arguments.length&&(o=n,n=[]);var i=a(this._pres,t,[]),s=i.length,f=i.numAsync||0,p=0,h=f,y=!1,d=n;if(!s)return e.nextTick((function(){o(null)}));var m=function t(){if(!(p>=s)){var n=i[p];if(n.isAsync){var a=[l(_),l((function(t){if(t){if(y)return;return y=!0,o(t)}if(0==--h&&p>=s)return o(null)}))];u(n.fn,r,a,a[0])}else if(n.fn.length>0){a=[l(_)];for(var f=arguments.length>=2?arguments:[null].concat(d),m=1;m<f.length;++m)a.push(f[m]);u(n.fn,r,a,a[0])}else{var v=null,g=null;try{g=n.fn.call(r)}catch(t){v=t}if(c(g))g.then((function(){return _()}),(function(t){return _(t)}));else{if(++p>=s)return h>0?void 0:e.nextTick((function(){o(v)}));t(v)}}}};function _(t){if(t){if(y)return;return y=!0,o(t)}if(++p>=s)return h>0?void 0:o(null);m.apply(r,arguments)}m.apply(null,[null].concat(n))},i.prototype.execPreSync=function(t,e,r){for(var n=a(this._pres,t,[]),o=n.length,i=0;i<o;++i)n[i].fn.apply(e,r||[])},i.prototype.execPost=function(t,r,n,o,i){arguments.length<5&&(i=o,o=null);var s=a(this._posts,t,[]),f=s.length,p=0,h=null;if(o&&o.error&&(h=o.error),!f)return e.nextTick((function(){i.apply(null,[h].concat(n))}));var y=function t(){for(var e=s[p].fn,o=0,a=n.length,y=[],d=0;d<a;++d)o+=n[d]&&n[d]._kareemIgnore?0:1,n[d]&&n[d]._kareemIgnore||y.push(n[d]);if(h)if(e.length===o+2){var m=l((function(e){if(e&&(h=e),++p>=f)return i.call(null,h);t()}));u(e,r,[h].concat(y).concat([m]),m)}else{if(++p>=f)return i.call(null,h);t()}else{var _=l((function(e){return e?(h=e,t()):++p>=f?i.apply(null,[null].concat(n)):void t()}));if(e.length===o+2)return++p>=f?i.apply(null,[null].concat(n)):t();if(e.length===o+1)u(e,r,y.concat([_]),_);else{var v,g;try{g=e.apply(r,y)}catch(t){v=t,h=t}if(c(g))return g.then((function(){return _()}),(function(t){return _(t)}));if(++p>=f)return i.apply(null,[v].concat(n));t()}}};y()},i.prototype.execPostSync=function(t,e,r){for(var n=a(this._posts,t,[]),o=n.length,i=0;i<o;++i)n[i].fn.apply(e,r||[])},i.prototype.createWrapperSync=function(t,e){var r=this;return function(){r.execPreSync(t,this,arguments);var n=e.apply(this,arguments);return r.execPostSync(t,this,[n]),n}},i.prototype.wrap=function(t,e,r,n,o){var i=n.length>0?n[n.length-1]:null,a=("function"==typeof i&&n.slice(0,n.length-1),this),u=(o=o||{}).checkForPromise;this.execPre(t,r,n,(function(c){if(c){for(var l=o.numCallbackParams||0,f=o.contextParameter?[r]:[],p=f.length;p<l;++p)f.push(null);return s(a,c,t,r,f,o,i)}var h="function"==typeof i?n.length-1:n.length,y=e.length,d=e.apply(r,n.slice(0,h).concat(m));if(u){if(null!=d&&"function"==typeof d.then)return d.then((function(t){return m(null,t)}),(function(t){return m(t)}));if(y<h+1)return m(null,d)}function m(){var e=Array.prototype.slice.call(arguments,1);if(o.nullResultByDefault&&0===e.length&&e.push(null),arguments[0])return s(a,arguments[0],t,r,e,o,i);a.execPost(t,r,e,(function(){return arguments[0]?"function"==typeof i?i(arguments[0]):void 0:"function"==typeof i?i.apply(r,arguments):void 0}))}}))},i.prototype.filter=function(t){for(var e=this,r=this.clone(),n=Array.from(r._pres.keys()),o=function(){var n=s[i],o=e._pres.get(n).map((function(t){return Object.assign({},t,{name:n})})).filter(t);if(0===o.length)return r._pres.delete(n),"continue";o.numAsync=o.filter((function(t){return t.isAsync})).length,r._pres.set(n,o)},i=0,s=n;i<s.length;i++)o();for(var a=Array.from(r._posts.keys()),u=function(){var n=l[c],o=e._posts.get(n).map((function(t){return Object.assign({},t,{name:n})})).filter(t);if(0===o.length)return r._posts.delete(n),"continue";r._posts.set(n,o)},c=0,l=a;c<l.length;c++)u();return r},i.prototype.hasHooks=function(t){return this._pres.has(t)||this._posts.has(t)},i.prototype.createWrapper=function(t,r,n,o){var i=this;return this.hasHooks(t)?function(){var e=n||this,s=Array.prototype.slice.call(arguments);i.wrap(t,r,e,s,o)}:function(){var t=arguments,n=this;e.nextTick((function(){return r.apply(n,t)}))}},i.prototype.pre=function(t,e,r,n,i){var s={};"object"===o(e)&&null!=e?e=(s=e).isAsync:"boolean"!=typeof arguments[1]&&(n=r,r=e,e=!1);var u=a(this._pres,t,[]);if(this._pres.set(t,u),e&&(u.numAsync=u.numAsync||0,++u.numAsync),"function"!=typeof r)throw new Error('pre() requires a function, got "'+o(r)+'"');return i?u.unshift(Object.assign({},s,{fn:r,isAsync:e})):u.push(Object.assign({},s,{fn:r,isAsync:e})),this},i.prototype.post=function(t,e,r,n){var i=a(this._posts,t,[]);if("function"==typeof e&&(n=!!r,r=e,e={}),"function"!=typeof r)throw new Error('post() requires a function, got "'+o(r)+'"');return n?i.unshift(Object.assign({},e,{fn:r})):i.push(Object.assign({},e,{fn:r})),this._posts.set(t,i),this},i.prototype.clone=function(){var t,e=new i,n=r(this._pres.keys());try{for(n.s();!(t=n.n()).done;){var o=t.value,s=this._pres.get(o).slice();s.numAsync=this._pres.get(o).numAsync,e._pres.set(o,s)}}catch(t){n.e(t)}finally{n.f()}var a,u=r(this._posts.keys());try{for(u.s();!(a=u.n()).done;){var c=a.value;e._posts.set(c,this._posts.get(c).slice())}}catch(t){u.e(t)}finally{u.f()}return e},i.prototype.merge=function(t,e){var n,o=(e=1===arguments.length||e)?this.clone():this,i=r(t._pres.keys());try{var s=function(){var e=n.value,r=a(o._pres,e,[]),i=t._pres.get(e).filter((function(t){return-1===r.map((function(t){return t.fn})).indexOf(t.fn)})),s=r.concat(i);s.numAsync=r.numAsync||0,s.numAsync+=i.filter((function(t){return t.isAsync})).length,o._pres.set(e,s)};for(i.s();!(n=i.n()).done;)s()}catch(t){i.e(t)}finally{i.f()}var u,c=r(t._posts.keys());try{var l=function(){var e=u.value,r=a(o._posts,e,[]),n=t._posts.get(e).filter((function(t){return-1===r.indexOf(t)}));o._posts.set(e,r.concat(n))};for(c.s();!(u=c.n()).done;)l()}catch(t){c.e(t)}finally{c.f()}return o},t.exports=i}).call(this,r(8))},function(t,e,r){"use strict";var n=r(10),o=function t(e){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),Object.assign(this,e),null!=e&&null!=e.options&&(this.options=Object.assign({},e.options))};Object.defineProperty(o.prototype,"ref",n),Object.defineProperty(o.prototype,"refPath",n),Object.defineProperty(o.prototype,"localField",n),Object.defineProperty(o.prototype,"foreignField",n),Object.defineProperty(o.prototype,"justOne",n),Object.defineProperty(o.prototype,"count",n),Object.defineProperty(o.prototype,"match",n),Object.defineProperty(o.prototype,"options",n),Object.defineProperty(o.prototype,"skip",n),Object.defineProperty(o.prototype,"limit",n),Object.defineProperty(o.prototype,"perDocumentLimit",n),t.exports=o},function(t,e,r){"use strict";var n=r(3),o=r(21);
+/*!
+ * Gather all indexes defined in the schema, including single nested,
+ * document arrays, and embedded discriminators.
+ */
+t.exports=function(t){var e=[],r=new WeakMap,i=t.constructor.indexTypes,s=new Map;return function t(a,u,c){if(r.has(a))return;r.set(a,!0),u=u||"";for(var l=Object.keys(a.paths),f=0,p=l;f<p.length;f++){var h=p[f],y=a.paths[h];if(null==c||!c.paths[h]){if(y.$isMongooseDocumentArray||y.$isSingleNested){if(!0!==n(y,"options.excludeIndexes")&&!0!==n(y,"schemaOptions.excludeIndexes")&&!0!==n(y,"schema.options.excludeIndexes")&&t(y.schema,u+h+"."),null!=y.schema.discriminators)for(var d=y.schema.discriminators,m=Object.keys(d),_=0,v=m;_<v.length;_++){var g=v[_];t(d[g],u+h+".",y.schema)}if(y.$isMongooseDocumentArray)continue}var b=y._index||y.caster&&y.caster._index;if(!1!==b&&null!=b){var w={},O=o(b),S=O?b:{},A="string"==typeof b?b:!!O&&b.type;if(A&&-1!==i.indexOf(A))w[u+h]=A;else if(S.text)w[u+h]="text",delete S.text;else{var j=-1===Number(b);w[u+h]=j?-1:1}delete S.type,"background"in S||(S.background=!0),null!=a.options.autoIndex&&(S._autoIndex=a.options.autoIndex);var E=S&&S.name;"string"==typeof E&&s.has(E)?Object.assign(s.get(E),w):(e.push([w,S]),s.set(E,w))}}}r.delete(a),u?
+/*!
+ * Checks for indexes added to subdocs using Schema.index().
+ * These indexes need their paths prefixed properly.
+ *
+ * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
+ */
+function(t,r){for(var n=t._indexes,o=n.length,i=0;i<o;++i){for(var s=n[i][0],a=n[i][1],u=Object.keys(s),c=u.length,l={},f=0;f<c;++f){var p=u[f];l[r+p]=s[p]}var h=Object.assign({},a);if(null!=a&&null!=a.partialFilterExpression){h.partialFilterExpression={};for(var y=a.partialFilterExpression,d=0,m=Object.keys(y);d<m.length;d++){var _=m[d];h.partialFilterExpression[r+_]=y[_]}}e.push([l,h])}}(a,u):(a._indexes.forEach((function(t){"background"in t[1]||(t[1].background=!0)})),e=e.concat(a._indexes))}(t),e}},function(t,e,r){"use strict";t.exports=function(t,e){for(var r in t.add(e.tree||{}),t.callQueue=t.callQueue.concat(e.callQueue),t.method(e.methods),t.static(e.statics),e.query)t.query[r]=e.query[r];for(var n in e.virtuals)t.virtuals[n]=e.virtuals[n].clone();t.s.hooks.merge(e.s.hooks,!1)}},function(t,e,r){"use strict";var n=r(141),o=r(143),i=r(3),s=r(75),a=r(51);t.exports=function(t,e){var r=t.childSchemas.find((function(t){return!!t.schema.options.timestamps}));if(e||r){var u=s(e,"createdAt"),c=s(e,"updatedAt"),l=null!=e&&e.hasOwnProperty("currentTime")?e.currentTime:null,f={};t.$timestamps={createdAt:u,updatedAt:c},c&&!t.paths[c]&&(f[c]=Date),u&&!t.paths[u]&&(f[u]=Date),t.add(f),t.pre("save",(function(t){var e=i(this,"$__.saveOptions.timestamps");if(!1===e)return t();var r=null!=e&&!1===e.updatedAt,n=null!=e&&!1===e.createdAt,o=null!=l?l():(this.ownerDocument?this.ownerDocument():this).constructor.base.now(),s=this._id&&this._id.auto;if(!n&&u&&!this.get(u)&&this.isSelected(u)&&this.$set(u,s?this._id.getTimestamp():o),!r&&c&&(this.isNew||this.isModified())){var a=o;this.isNew&&(null!=u?a=this.$__getValue(u):s&&(a=this._id.getTimestamp())),this.$set(c,a)}t()})),t.methods.initializeTimestamps=function(){var t=null!=l?l():this.constructor.base.now();return u&&!this.get(u)&&this.$set(u,t),c&&!this.get(c)&&this.$set(c,t),this},h[a.builtInMiddleware]=!0;var p={query:!0,model:!1};t.pre("findOneAndUpdate",p,h),t.pre("replaceOne",p,h),t.pre("update",p,h),t.pre("updateOne",p,h),t.pre("updateMany",p,h)}function h(t){var e=null!=l?l():this.model.base.now();o(e,u,c,this.getUpdate(),this.options,this.schema),n(e,this.getUpdate(),this.model.schema),t()}}},function(t,e,r){"use strict";function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i=r(142),s=r(75);
+/*!
+ * ignore
+ */
+function a(t,e,r){if(null!=e){if(Object.keys(e).some((function(t){return t.startsWith("$")}))){if(e.$push)for(var o=0,i=Object.keys(e.$push);o<i.length;o++){var a=i[o],c=r.path(a);e.$push[a]&&c&&c.$isMongooseDocumentArray&&c.schema.options.timestamps&&function(){var r=c.schema.options.timestamps,n=s(r,"createdAt"),o=s(r,"updatedAt");e.$push[a].$each?e.$push[a].$each.forEach((function(e){null!=o&&(e[o]=t),null!=n&&(e[n]=t)})):(null!=o&&(e.$push[a][o]=t),null!=n&&(e.$push[a][n]=t))}()}if(null!=e.$set)for(var l=0,f=Object.keys(e.$set);l<f.length;l++){u(r,f[l],e.$set,t)}}var p,h=n(Object.keys(e).filter((function(t){return!t.startsWith("$")})));try{for(h.s();!(p=h.n()).done;){u(r,p.value,e,t)}}catch(t){h.e(t)}finally{h.f()}}}function u(t,e,r,o){var u=i(e),c=t.path(u);if(c){for(var l=[],f=u.split("."),p=f.length-1;p>0;--p){var h=t.path(f.slice(0,p).join("."));null!=h&&(h.$isMongooseDocumentArray||h.$isSingleNested)&&l.push({parentPath:e.split(".").slice(0,p).join("."),parentSchemaType:h})}if(Array.isArray(r[e])&&c.$isMongooseDocumentArray)!function(t,e,r){var n=e.schema.options.timestamps;if(n)for(var o=t.length,i=s(n,"createdAt"),u=s(n,"updatedAt"),c=0;c<o;++c)null!=u&&(t[c][u]=r),null!=i&&(t[c][i]=r),a(r,t[c],e.schema)}(r[e],c,o);else if(r[e]&&c.$isSingleNested)!function(t,e,r){var n=e.schema.options.timestamps;if(n){var o=s(n,"createdAt"),i=s(n,"updatedAt");null!=i&&(t[i]=r),null!=o&&(t[o]=r),a(r,t,e.schema)}}(r[e],c,o);else if(l.length>0){var y,d=n(l);try{for(d.s();!(y=d.n()).done;){var m=y.value,_=m.parentPath,v=m.parentSchemaType,g=v.schema.options.timestamps,b=s(g,"updatedAt");if(g&&null!=b)if(v.$isSingleNested)r[_+"."+b]=o;else if(v.$isMongooseDocumentArray){var w=e.substr(_.length+1);if(/^\d+$/.test(w)){r[_+"."+w][b]=o;continue}var O=w.indexOf(".");r[_+"."+(w=-1!==O?w.substr(0,O):w)+"."+b]=o}}}catch(t){d.e(t)}finally{d.f()}}else if(null!=c.schema&&c.schema!=t&&r[e]){var S=c.schema.options.timestamps,A=s(S,"createdAt"),j=s(S,"updatedAt");if(!S)return;null!=j&&(r[e][j]=o),null!=A&&(r[e][A]=o)}}}t.exports=a},function(t,e,r){"use strict";t.exports=function(t){return t.replace(/\.\$(\[[^\]]*\])?\./g,".0.").replace(/\.(\[[^\]]*\])?\$$/g,".0")}},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */var n=r(3);t.exports=
+/*!
+ * ignore
+ */
+function(t,e,r,o,i){var s=o,a=s,u=n(i,"overwrite",!1),c=n(i,"timestamps",!0);if(!c||null==s)return o;var l=null!=c&&!1===c.createdAt,f=null!=c&&!1===c.updatedAt;if(u)return o&&o.$set&&(o=o.$set,s.$set={},a=s.$set),f||!r||o[r]||(a[r]=t),l||!e||o[e]||(a[e]=t),s;if(o=o||{},Array.isArray(s))return s.push({$set:{updatedAt:t}}),s;if(s.$set=s.$set||{},!f&&r&&(!o.$currentDate||!o.$currentDate[r])){var p=!1;if(-1!==r.indexOf("."))for(var h=r.split("."),y=1;y<h.length;++y){var d=h.slice(-y).join("."),m=h.slice(0,-y).join(".");if(null!=o[m]){o[m][d]=t,p=!0;break}if(o.$set&&o.$set[m]){o.$set[m][d]=t,p=!0;break}}p||(s.$set[r]=t),s.hasOwnProperty(r)&&delete s[r]}if(!l&&e){o[e]&&delete o[e],o.$set&&o.$set[e]&&delete o.$set[e];var _=!1;if(-1!==e.indexOf("."))for(var v=e.split("."),g=1;g<v.length;++g){var b=v.slice(-g).join("."),w=v.slice(0,-g).join(".");if(null!=o[w]){o[w][b]=t,_=!0;break}if(o.$set&&o.$set[w]){o.$set[w][b]=t,_=!0;break}}_||(s.$setOnInsert=s.$setOnInsert||{},s.$setOnInsert[e]=t)}0===Object.keys(s.$set).length&&delete s.$set;return s}},function(t,e,r){"use strict";var n=r(14),o=r(4);t.exports=function(t,e){if("string"==typeof t)return;if("function"==typeof t)return;throw new n('Invalid ref at path "'+e+'". Got '+o.inspect(t,{depth:0}))}},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */
+/*!
+ * Apply query middleware
+ *
+ * @param {Query} query constructor
+ * @param {Model} model
+ */
+function n(t,e){var r={useErrorHandlers:!0,numCallbackParams:1,nullResultByDefault:!0},o=e.hooks.filter((function(t){var e=function(t){var e={};t.hasOwnProperty("query")&&(e.query=t.query);t.hasOwnProperty("document")&&(e.document=t.document);return e}(t);return"updateOne"===t.name?null==e.query||!!e.query:"deleteOne"===t.name?!!e.query||0===Object.keys(e).length:"validate"!==t.name&&"remove"!==t.name||!!e.query}));t.prototype._execUpdate=o.createWrapper("update",t.prototype._execUpdate,null,r),t.prototype.__distinct=o.createWrapper("distinct",t.prototype.__distinct,null,r),t.prototype.validate=o.createWrapper("validate",t.prototype.validate,null,r),n.middlewareFunctions.filter((function(t){return"update"!==t&&"distinct"!==t&&"validate"!==t})).forEach((function(e){t.prototype["_".concat(e)]=o.createWrapper(e,t.prototype["_".concat(e)],null,r)}))}t.exports=n,
+/*!
+ * ignore
+ */
+n.middlewareFunctions=["count","countDocuments","deleteMany","deleteOne","distinct","estimatedDocumentCount","find","findOne","findOneAndDelete","findOneAndRemove","findOneAndReplace","findOneAndUpdate","remove","replaceOne","update","updateMany","updateOne","validate"]},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module dependencies.
+ */
+function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var i,s=r(7),a=r(5),u=r(147),c=r(77),l=r(2),f=r(0).populateModelSymbol,p=s.CastError;function h(t,e){this.enumValues=[],this.regExp=null,s.call(this,t,e,"String")}
+/*!
+ * ignore
+ */
+function y(t){return this.castForQuery(t)}h.schemaName="String",h.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+h.prototype=Object.create(s.prototype),h.prototype.constructor=h,Object.defineProperty(h.prototype,"OptionsConstructor",{configurable:!1,enumerable:!1,writable:!1,value:u}),
+/*!
+ * ignore
+ */
+h._cast=c,h.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if(null!=t&&"string"!=typeof t)throw new Error;return t}),this._cast=t),this._cast},h.get=s.get,h.set=s.set,
+/*!
+ * ignore
+ */
+h._checkRequired=function(t){return(t instanceof String||"string"==typeof t)&&t.length},h.checkRequired=s.checkRequired,h.prototype.enum=function(){if(this.enumValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.enumValidator}),this),this.enumValidator=!1),void 0===arguments[0]||!1===arguments[0])return this;var t,e;l.isObject(arguments[0])?(t=arguments[0].values,e=arguments[0].message):(t=arguments,e=a.messages.String.enum);var r,o=n(t);try{for(o.s();!(r=o.n()).done;){var i=r.value;void 0!==i&&this.enumValues.push(this.cast(i))}}catch(t){o.e(t)}finally{o.f()}var s=this.enumValues;return this.enumValidator=function(t){return void 0===t||~s.indexOf(t)},this.validators.push({validator:this.enumValidator,message:e,type:"enum",enumValues:s}),this},h.prototype.lowercase=function(t){return arguments.length>0&&!t?this:this.set((function(t,e){return"string"!=typeof t&&(t=e.cast(t)),t?t.toLowerCase():t}))},h.prototype.uppercase=function(t){return arguments.length>0&&!t?this:this.set((function(t,e){return"string"!=typeof t&&(t=e.cast(t)),t?t.toUpperCase():t}))},h.prototype.trim=function(t){return arguments.length>0&&!t?this:this.set((function(t,e){return"string"!=typeof t&&(t=e.cast(t)),t?t.trim():t}))},h.prototype.minlength=function(t,e){if(this.minlengthValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.minlengthValidator}),this)),null!=t){var r=e||a.messages.String.minlength;r=r.replace(/{MINLENGTH}/,t),this.validators.push({validator:this.minlengthValidator=function(e){return null===e||e.length>=t},message:r,type:"minlength",minlength:t})}return this},h.prototype.maxlength=function(t,e){if(this.maxlengthValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.maxlengthValidator}),this)),null!=t){var r=e||a.messages.String.maxlength;r=r.replace(/{MAXLENGTH}/,t),this.validators.push({validator:this.maxlengthValidator=function(e){return null===e||e.length<=t},message:r,type:"maxlength",maxlength:t})}return this},h.prototype.match=function(t,e){var r=e||a.messages.String.match;return this.validators.push({validator:function(e){return!!t&&(t.lastIndex=0,null==e||""===e||t.test(e))},message:r,type:"regexp",regexp:t}),this},h.prototype.checkRequired=function(t,e){return s._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():h.checkRequired())(t)},h.prototype.cast=function(t,n,o){if(s._isRef(this,t,n,o)){if(null==t)return t;if(i||(i=r(6)),t instanceof i)return t.$__.wasPopulated=!0,t;if("string"==typeof t)return t;if(e.isBuffer(t)||!l.isObject(t))throw new p("string",t,this.path,null,this);var a=n.$__fullPath(this.path),u=new((n.ownerDocument?n.ownerDocument():n).populated(a,!0).options[f])(t);return u.$__.wasPopulated=!0,u}var c="function"==typeof this.constructor.cast?this.constructor.cast():h.cast();try{return c(t)}catch(e){throw new p("string",t,this.path,null,this)}};var d=l.options(s.prototype.$conditionalHandlers,{$all:function(t){var e=this;return Array.isArray(t)?t.map((function(t){return e.castForQuery(t)})):[this.castForQuery(t)]},$gt:y,$gte:y,$lt:y,$lte:y,$options:String,$regex:y,$not:y});Object.defineProperty(h.prototype,"$conditionalHandlers",{configurable:!1,enumerable:!1,writable:!1,value:Object.freeze(d)}),h.prototype.castForQuery=function(t,e){var r;if(2===arguments.length){if(!(r=this.$conditionalHandlers[t]))throw new Error("Can't use "+t+" with String.");return r.call(this,e)}return e=t,"[object RegExp]"===Object.prototype.toString.call(e)?e:this._castForQuery(e)},
+/*!
+ * Module exports.
+ */
+t.exports=h}).call(this,r(1).Buffer)},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"enum",l),Object.defineProperty(c.prototype,"match",l),Object.defineProperty(c.prototype,"lowercase",l),Object.defineProperty(c.prototype,"trim",l),Object.defineProperty(c.prototype,"uppercase",l),Object.defineProperty(c.prototype,"minlength",l),Object.defineProperty(c.prototype,"maxlength",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"min",l),Object.defineProperty(c.prototype,"max",l),Object.defineProperty(c.prototype,"enum",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";var n=r(22);
+/*!
+ * Given a value, cast it to a number, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {Boolean|null|undefined}
+ * @throws {Error} if `value` is not one of the allowed values
+ * @api private
+ */t.exports=function(t){return null==t?t:""===t?null:("string"!=typeof t&&"boolean"!=typeof t||(t=Number(t)),n.ok(!isNaN(t)),t instanceof Number?t.valueOf():"number"==typeof t?t:Array.isArray(t)||"function"!=typeof t.valueOf?t.toString&&!Array.isArray(t)&&t.toString()==Number(t)?Number(t):void n.ok(!1):Number(t.valueOf()))}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(12),o=r(7),i=r(49),s=r(2);function a(t,e){o.call(this,t,e,"Boolean")}a.schemaName="Boolean",a.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+a.prototype=Object.create(o.prototype),a.prototype.constructor=a,
+/*!
+ * ignore
+ */
+a._cast=i,a.set=o.set,a.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if(null!=t&&"boolean"!=typeof t)throw new Error;return t}),this._cast=t),this._cast},
+/*!
+ * ignore
+ */
+a._checkRequired=function(t){return!0===t||!1===t},a.checkRequired=o.checkRequired,a.prototype.checkRequired=function(t){return this.constructor._checkRequired(t)},Object.defineProperty(a,"convertToTrue",{get:function(){return i.convertToTrue},set:function(t){i.convertToTrue=t}}),Object.defineProperty(a,"convertToFalse",{get:function(){return i.convertToFalse},set:function(t){i.convertToFalse=t}}),a.prototype.cast=function(t){var e="function"==typeof this.constructor.cast?this.constructor.cast():a.cast();try{return e(t)}catch(e){throw new n("Boolean",t,this.path,e,this)}},a.$conditionalHandlers=s.options(o.prototype.$conditionalHandlers,{}),a.prototype.castForQuery=function(t,e){var r;return 2===arguments.length?(r=a.$conditionalHandlers[t])?r.call(this,e):this._castForQuery(e):this._castForQuery(t)},a.prototype._castNullish=function(t){if(void 0===t&&null!=this.$$context&&null!=this.$$context._mongooseOptions&&this.$$context._mongooseOptions.omitUndefined)return t;var e="function"==typeof this.constructor.cast?this.constructor.cast():a.cast();return null==e?t:!(e.convertToFalse instanceof Set&&e.convertToFalse.has(t))&&(!!(e.convertToTrue instanceof Set&&e.convertToTrue.has(t))||t)},
+/*!
+ * Module exports.
+ */
+t.exports=a},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n,o,i=r(55),s=r(12),a=r(19).EventEmitter,u=r(157),c=r(7),l=r(31),f=r(90),p=r(3),h=r(91),y=r(4),d=r(2),m=r(92),_=r(0).arrayPathSymbol,v=r(0).documentArrayParent;function g(t,e,r,n){null!=n&&null!=n._id?e=h(e,n):null!=r&&null!=r._id&&(e=h(e,r));var o=b(e,r);o.prototype.$basePath=t,i.call(this,t,o,r),this.schema=e,this.schemaOptions=n||{},this.$isMongooseDocumentArray=!0,this.Constructor=o,o.base=e.base;var s=this.defaultValue;"defaultValue"in this&&void 0===s||this.default((function(){var t=s.call(this);return Array.isArray(t)||(t=[t]),t}));var a=this;this.$embeddedSchemaType=new c(t+".$",{required:p(this,"schemaOptions.required",!1)}),this.$embeddedSchemaType.cast=function(t,e,r){return a.cast(t,e,r)[0]},this.$embeddedSchemaType.$isMongooseDocumentArrayElement=!0,this.$embeddedSchemaType.caster=this.Constructor,this.$embeddedSchemaType.schema=this.schema}
+/*!
+ * Ignore
+ */
+function b(t,e,n){function i(){o.apply(this,arguments),this.$session(this.ownerDocument().$session())}o||(o=r(26));var s=null!=n?n.prototype:o.prototype;for(var u in i.prototype=Object.create(s),i.prototype.$__setSchema(t),i.schema=t,i.prototype.constructor=i,i.$isArraySubdocument=!0,i.events=new a,t.methods)i.prototype[u]=t.methods[u];for(var c in t.statics)i[c]=t.statics[c];for(var l in a.prototype)i[l]=a.prototype[l];return i.options=e,i}
+/*!
+ * Scopes paths selected in a query to this array.
+ * Necessary for proper default application of subdocument values.
+ *
+ * @param {DocumentArrayPath} array - the array to scope `fields` paths
+ * @param {Object|undefined} fields - the root fields selected in the query
+ * @param {Boolean|undefined} init - if we are being created part of a query result
+ */
+function w(t,e,r){if(r&&e){for(var n,o,i,s=t.path+".",a=Object.keys(e),u=a.length,c={};u--;)if((o=a[u]).startsWith(s)){if("$"===(i=o.substring(s.length)))continue;i.startsWith("$.")&&(i=i.substr(2)),n||(n=!0),c[i]=e[o]}return n&&c||void 0}}g.schemaName="DocumentArray",g.options={castNonArrays:!0},
+/*!
+ * Inherits from ArrayType.
+ */
+g.prototype=Object.create(i.prototype),g.prototype.constructor=g,g.prototype.OptionsConstructor=u,g.prototype.discriminator=function(t,e,r){"function"==typeof t&&(t=d.getFunctionName(t));var n=b(e=f(this.casterConstructor,t,e,r),null,this.casterConstructor);n.baseCasterConstructor=this.casterConstructor;try{Object.defineProperty(n,"name",{value:t})}catch(t){}return this.casterConstructor.discriminators[t]=n,this.casterConstructor.discriminators[t]},g.prototype.doValidate=function(t,e,i,s){n||(n=r(18));var a=this;try{c.prototype.doValidate.call(this,t,(function(r){if(r)return r.$isArrayValidatorError=!0,e(r);var u,c=t&&t.length;if(!c)return e();if(s&&s.updateValidator)return e();t.isMongooseDocumentArray||(t=new n(t,a.path,i));function f(t){null!=t&&((u=t)instanceof l||(u.$isArrayValidatorError=!0)),--c||e(u)}for(var p=0,h=c;p<h;++p){var y=t[p];if(null!=y){if(!(y instanceof o)){var d=m(a.casterConstructor,t[p]);y=t[p]=new d(y,t,void 0,void 0,p)}y.$__validate(f)}else--c||e(u)}}),i)}catch(t){return t.$isArrayValidatorError=!0,e(t)}},g.prototype.doValidateSync=function(t,e){var r=c.prototype.doValidateSync.call(this,t,e);if(null!=r)return r.$isArrayValidatorError=!0,r;var n=t&&t.length,i=null;if(n){for(var s=0,a=n;s<a;++s){var u=t[s];if(u){if(!(u instanceof o)){var l=m(this.casterConstructor,t[s]);u=t[s]=new l(u,t,void 0,void 0,s)}var f=u.validateSync();f&&null==i&&(i=f)}}return i}},
+/*!
+ * ignore
+ */
+g.prototype.getDefault=function(t){var e="function"==typeof this.defaultValue?this.defaultValue.call(t):this.defaultValue;if(null==e)return e;n||(n=r(18)),Array.isArray(e)||(e=[e]),e=new n(e,this.path,t);for(var o=0;o<e.length;++o){var i=new(m(this.casterConstructor,e[o]))({},e,void 0,void 0,o);i.init(e[o]),i.isNew=!0,Object.assign(i.$__.activePaths.default,i.$__.activePaths.init),i.$__.activePaths.init={},e[o]=i}return e},g.prototype.cast=function(t,e,i,a,u){if(n||(n=r(18)),null!=t&&null!=t[_]&&t===a)return t;var c,l,f={transform:!1,virtuals:!1};if(u=u||{},!Array.isArray(t)){if(!i&&!g.options.castNonArrays)throw new s("DocumentArray",y.inspect(t),this.path,null,this);return e&&i&&e.markModified(this.path),this.cast([t],e,i,a,u)}t&&t.isMongooseDocumentArray||u.skipDocumentArrayCast?t&&t.isMongooseDocumentArray&&(t=new n(t,this.path,e)):t=new n(t,this.path,e),null!=u.arrayPath&&(t[_]=u.arrayPath);for(var p=t.length,h={skipId:!0,willInit:!0},b=0;b<p;++b)if(t[b]){var O=m(this.casterConstructor,t[b]);if(!t[b].$__||t[b]instanceof O&&t[b][v]===e||(t[b]=t[b].toObject({transform:!1,virtuals:t[b].schema===O.schema})),t[b]instanceof o)null==t[b].__index&&t[b].$setIndex(b);else if(null!=t[b])if(i)e?c||(c=w(this,e.$__.selected,i)):c=!0,l=new O(null,t,h,c,b),t[b]=l.init(t[b]);else if(a&&"function"==typeof a.id&&(l=a.id(t[b]._id)),a&&l&&d.deepEqual(l.toObject(f),t[b]))l.set(t[b]),t[b]=l;else try{l=new O(t[b],t,void 0,void 0,b),t[b]=l}catch(e){var S=y.inspect(t[b]);throw new s("embedded",S,t[_],e,this)}}return t},
+/*!
+ * ignore
+ */
+g.prototype.clone=function(){var t=Object.assign({},this.options),e=new this.constructor(this.path,this.schema,t,this.schemaOptions);return e.validators=this.validators.slice(),void 0!==this.requiredValidator&&(e.requiredValidator=this.requiredValidator),e.Constructor.discriminators=Object.assign({},this.Constructor.discriminators),e},g.defaultOptions={},g.set=c.set,
+/*!
+ * Module exports.
+ */
+t.exports=g},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"enum",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";t.exports=function t(e){if(!Array.isArray(e))return{min:0,max:0,containsNonArrayItem:!0};if(0===e.length)return{min:1,max:1,containsNonArrayItem:!1};for(var r=t(e[0]),n=1;n<e.length;++n){var o=t(e[n]);o.min<r.min&&(r.min=o.min),o.max>r.max&&(r.max=o.max),r.containsNonArrayItem=r.containsNonArrayItem||o.containsNonArrayItem}return r.min=r.min+1,r.max=r.max+1,r}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return o(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,i=function(){};return{s:i,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:i}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function i(t){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var s=r(12),a=r(32),u=r(54),c=r(155),l=r(3),f=r(156),p=r(80),h=r(4),y=r(21),d=r(29),m=["Polygon","MultiPolygon"];function _(t,e,r){if(Array.isArray(t))t.forEach((function(n,o){if(Array.isArray(n)||y(n))return _(n,e,r);t[o]=e.castForQueryWrapper({val:n,context:r})}));else for(var n=Object.keys(t),o=n.length;o--;){var i=n[o],s=t[i];Array.isArray(s)||y(s)?(_(s,e,r),t[i]=s):t[i]=e.castForQuery({val:s,context:r})}}t.exports=function t(e,r,o,v){if(Array.isArray(r))throw new Error("Query filter must be an object, got an array ",h.inspect(r));if(null==r)return r;r.hasOwnProperty("_bsontype")&&"ObjectID"!==r._bsontype&&delete r._bsontype,null!=e&&null!=e.discriminators&&null!=r[e.options.discriminatorKey]&&(e=f(e,r[e.options.discriminatorKey])||e);var g,b,w,O,S,A,j=Object.keys(r),E=j.length;for(o=o||{};E--;)if(A=r[O=j[E]],"$or"===O||"$nor"===O||"$and"===O){if(!Array.isArray(A))throw new s("Array",A,O);for(var $=0;$<A.length;++$){if(null==A[$]||"object"!==i(A[$]))throw new s("Object",A[$],O+"."+$);A[$]=t(e,A[$],o,v)}}else{if("$where"===O){if("string"!==(S=i(A))&&"function"!==S)throw new Error("Must have a string or function for $where");"function"===S&&(r[O]=A.toString());continue}if("$elemMatch"===O)A=t(e,A,o,v);else if("$text"===O)A=c(A,O);else{if(!e)continue;if(!(b=e.path(O)))for(var x=O.split("."),P=x.length;P--;){var N=x.slice(0,P).join("."),T=x.slice(P).join("."),k=e.path(N),C=l(k,"schema.options.discriminatorKey");if(null!=k&&null!=l(k,"schema.discriminators")&&null!=C&&T!==C){var D=l(r,N+"."+C);null!=D&&(b=k.schema.discriminators[D].path(T))}}if(b){if(null==A)continue;if("Object"===A.constructor.name)if(Object.keys(A).some(p))for(var R=Object.keys(A),B=void 0,M=R.length;M--;)if(w=A[B=R[M]],"$not"===B){if(w&&b&&!b.caster){if((g=Object.keys(w)).length&&p(g[0]))for(var I in w)w[I]=b.castForQueryWrapper({$conditional:I,val:w[I],context:v});else A[B]=b.castForQueryWrapper({$conditional:B,val:w,context:v});continue}t(b.caster?b.caster.schema:e,w,o,v)}else A[B]=b.castForQueryWrapper({$conditional:B,val:w,context:v});else r[O]=b.castForQueryWrapper({val:A,context:v});else if(Array.isArray(A)&&-1===["Buffer","Array"].indexOf(b.instance)){var F,L=[],U=n(A);try{for(U.s();!(F=U.n()).done;){var V=F.value;L.push(b.castForQueryWrapper({val:V,context:v}))}}catch(t){U.e(t)}finally{U.f()}r[O]={$in:L}}else r[O]=b.castForQueryWrapper({val:A,context:v})}else{for(var q=O.split("."),W=q.length,H=void 0,Y=void 0,K=void 0;W--&&(H=q.slice(0,W).join("."),!(b=e.path(H))););if(b){b.caster&&b.caster.schema?((K={})[Y=q.slice(W).join(".")]=A,r[O]=t(b.caster.schema,K,o,v)[Y]):r[O]=A;continue}if(y(A)){var z="";if(A.$near?z="$near":A.$nearSphere?z="$nearSphere":A.$within?z="$within":A.$geoIntersects?z="$geoIntersects":A.$geoWithin&&(z="$geoWithin"),z){var Q=new u.Number("__QueryCasting__"),J=A[z];if(null!=A.$maxDistance&&(A.$maxDistance=Q.castForQueryWrapper({val:A.$maxDistance,context:v})),null!=A.$minDistance&&(A.$minDistance=Q.castForQueryWrapper({val:A.$minDistance,context:v})),"$within"===z){var G=J.$center||J.$centerSphere||J.$box||J.$polygon;if(!G)throw new Error("Bad $within parameter: "+JSON.stringify(A));J=G}else if("$near"===z&&"string"==typeof J.type&&Array.isArray(J.coordinates))J=J.coordinates;else if(("$near"===z||"$nearSphere"===z||"$geoIntersects"===z)&&J.$geometry&&"string"==typeof J.$geometry.type&&Array.isArray(J.$geometry.coordinates))null!=J.$maxDistance&&(J.$maxDistance=Q.castForQueryWrapper({val:J.$maxDistance,context:v})),null!=J.$minDistance&&(J.$minDistance=Q.castForQueryWrapper({val:J.$minDistance,context:v})),d(J.$geometry)&&(J.$geometry=J.$geometry.toObject({transform:!1,virtuals:!1})),J=J.$geometry.coordinates;else if("$geoWithin"===z)if(J.$geometry){d(J.$geometry)&&(J.$geometry=J.$geometry.toObject({virtuals:!1}));var X=J.$geometry.type;if(-1===m.indexOf(X))throw new Error('Invalid geoJSON type for $geoWithin "'+X+'", must be "Polygon" or "MultiPolygon"');J=J.$geometry.coordinates}else J=J.$box||J.$polygon||J.$center||J.$centerSphere,d(J)&&(J=J.toObject({virtuals:!1}));_(J,Q,v);continue}}if(e.nested[O])continue;if(o.upsert&&o.strict){if("throw"===o.strict)throw new a(O);throw new a(O,'Path "'+O+'" is not in schema, strict mode is `true`, and upsert is `true`.')}if("throw"===o.strictQuery)throw new a(O,'Path "'+O+"\" is not in schema and strictQuery is 'throw'.");o.strictQuery&&delete r[O]}}}return r}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(12),i=r(49),s=r(77);
+/*!
+ * Casts val to an object suitable for `$text`. Throws an error if the object
+ * can't be casted.
+ *
+ * @param {Any} val value to cast
+ * @param {String} [path] path to associate with any errors that occured
+ * @return {Object} casted object
+ * @see https://docs.mongodb.com/manual/reference/operator/query/text/
+ * @api private
+ */
+t.exports=function(t,e){if(null==t||"object"!==n(t))throw new o("$text",t,e);return null!=t.$search&&(t.$search=s(t.$search,e+".$search")),null!=t.$language&&(t.$language=s(t.$language,e+".$language")),null!=t.$caseSensitive&&(t.$caseSensitive=i(t.$caseSensitive,e+".$castSensitive")),null!=t.$diacriticSensitive&&(t.$diacriticSensitive=i(t.$diacriticSensitive,e+".$diacriticSensitive")),t}},function(t,e,r){"use strict";
+/*!
+* returns discriminator by discriminatorMapping.value
+*
+* @param {Schema} schema
+* @param {string} value
+*/t.exports=function(t,e){if(null==t||null==t.discriminators)return null;for(var r=0,n=Object.keys(t.discriminators);r<n.length;r++){var o=n[r],i=t.discriminators[o];if(null!=i.discriminatorMapping&&i.discriminatorMapping.value===e)return i}return null}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"excludeIndexes",l),Object.defineProperty(c.prototype,"_id",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o,i=r(12),s=r(19).EventEmitter,a=r(73),u=r(159),c=r(7),l=r(48),f=r(33).castToNumber,p=r(90),h=r(81),y=r(3),d=r(92),m=r(91),_=r(17).internalToObjectOptions;function v(t,e,r){t=m(t,r),this.caster=g(t),this.caster.path=e,this.caster.prototype.$basePath=e,this.schema=t,this.$isSingleNested=!0,c.call(this,e,r,"Embedded")}
+/*!
+ * ignore
+ */
+/*!
+ * ignore
+ */
+function g(t,e){o||(o=r(89));var n=function(t,e,r){var n=this;this.$parent=r,o.apply(this,arguments),this.$session(this.ownerDocument().$session()),r&&(r.on("save",(function(){n.emit("save",n),n.constructor.emit("save",n)})),r.on("isNew",(function(t){n.isNew=t,n.emit("isNew",t),n.constructor.emit("isNew",t)})))},i=null!=e?e.prototype:o.prototype;for(var a in(n.prototype=Object.create(i)).$__setSchema(t),n.prototype.constructor=n,n.schema=t,n.$isSingleNested=!0,n.events=new s,n.prototype.toBSON=function(){return this.toObject(_)},t.methods)n.prototype[a]=t.methods[a];for(var u in t.statics)n[u]=t.statics[u];for(var c in s.prototype)n[c]=s.prototype[c];return n}
+/*!
+ * Special case for when users use a common location schema to represent
+ * locations for use with $geoWithin.
+ * https://docs.mongodb.org/manual/reference/operator/query/geoWithin/
+ *
+ * @param {Object} val
+ * @api private
+ */t.exports=v,v.prototype=Object.create(c.prototype),v.prototype.constructor=v,v.prototype.OptionsConstructor=u,v.prototype.$conditionalHandlers.$geoWithin=function(t){return{$geometry:this.castForQuery(t.$geometry)}},
+/*!
+ * ignore
+ */
+v.prototype.$conditionalHandlers.$near=v.prototype.$conditionalHandlers.$nearSphere=h.cast$near,v.prototype.$conditionalHandlers.$within=v.prototype.$conditionalHandlers.$geoWithin=h.cast$within,v.prototype.$conditionalHandlers.$geoIntersects=h.cast$geoIntersects,v.prototype.$conditionalHandlers.$minDistance=f,v.prototype.$conditionalHandlers.$maxDistance=f,v.prototype.$conditionalHandlers.$exists=l,v.prototype.cast=function(t,e,r,o){if(t&&t.$isSingleNested&&t.parent===e)return t;if(null!=t&&("object"!==n(t)||Array.isArray(t)))throw new a(this.path,t);var i,s=d(this.caster,t),u=y(e,"$__.selected",{}),c=this.path,l=Object.keys(u).reduce((function(t,e){return e.startsWith(c+".")&&(t[e.substr(c.length+1)]=u[e]),t}),{});return r?((i=new s(void 0,l,e)).init(t),i):0===Object.keys(t).length?new s({},l,e,void 0,{priorDoc:o}):new s(t,l,e,void 0,{priorDoc:o})},v.prototype.castForQuery=function(t,e,r){var n;if(2===arguments.length){if(!(n=this.$conditionalHandlers[t]))throw new Error("Can't use "+t);return n.call(this,e)}if(null==(e=t))return e;this.options.runSetters&&(e=this._applySetters(e));var o=d(this.caster,e),s=null!=r&&null!=r.strict?r.strict:void 0;try{e=new o(e,s)}catch(t){if(!(t instanceof i))throw new i("Embedded",e,this.path,t,this);throw t}return e},v.prototype.doValidate=function(t,e,r,n){var o=d(this.caster,t);if(n&&n.skipSchemaValidators)return t instanceof o||(t=new o(t,null,r)),t.validate(e);c.prototype.doValidate.call(this,t,(function(r){return r?e(r):t?void t.validate(e):e(null)}),r,n)},v.prototype.doValidateSync=function(t,e,r){if(!r||!r.skipSchemaValidators){var n=c.prototype.doValidateSync.call(this,t,e);if(n)return n}if(t)return t.validateSync()},v.prototype.discriminator=function(t,e,r){return e=p(this.caster,t,e,r),this.caster.discriminators[t]=g(e,this.caster),this.caster.discriminators[t]},v.defaultOptions={},v.set=c.set,
+/*!
+ * ignore
+ */
+v.prototype.clone=function(){var t=Object.assign({},this.options),e=new this.constructor(this.schema,this.path,t);return e.validators=this.validators.slice(),void 0!==this.requiredValidator&&(e.requiredValidator=this.requiredValidator),e.caster.discriminators=Object.assign({},this.caster.discriminators),e}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"_id",l),t.exports=c},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module dependencies.
+ */
+function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o,i=r(85),s=r(161),a=r(7),u=r(79),c=r(2),l=r(0).populateModelSymbol,f=i.Binary,p=a.CastError;function h(t,e){a.call(this,t,e,"Buffer")}
+/*!
+ * ignore
+ */
+function y(t){return this.castForQuery(t)}h.schemaName="Buffer",h.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+h.prototype=Object.create(a.prototype),h.prototype.constructor=h,h.prototype.OptionsConstructor=s,
+/*!
+ * ignore
+ */
+h._checkRequired=function(t){return!(!t||!t.length)},h.set=a.set,h.checkRequired=a.checkRequired,h.prototype.checkRequired=function(t,e){return a._isRef(this,t,e,!0)?!!t:this.constructor._checkRequired(t)},h.prototype.cast=function(t,s,u){var h;if(a._isRef(this,t,s,u)){if(null==t)return t;if(o||(o=r(6)),t instanceof o)return t.$__.wasPopulated=!0,t;if(e.isBuffer(t))return t;if(!c.isObject(t))throw new p("Buffer",t,this.path,null,this);var y=s.$__fullPath(this.path);return(h=new((s.ownerDocument?s.ownerDocument():s).populated(y,!0).options[l])(t)).$__.wasPopulated=!0,h}if(t&&t._id&&(t=t._id),t&&t.isMongooseBuffer)return t;if(e.isBuffer(t))return t&&t.isMongooseBuffer||(t=new i(t,[this.path,s]),null!=this.options.subtype&&(t._subtype=this.options.subtype)),t;if(t instanceof f){if(h=new i(t.value(!0),[this.path,s]),"number"!=typeof t.sub_type)throw new p("Buffer",t,this.path,null,this);return h._subtype=t.sub_type,h}if(null===t)return t;var d=n(t);if("string"===d||"number"===d||Array.isArray(t)||"object"===d&&"Buffer"===t.type&&Array.isArray(t.data))return"number"===d&&(t=[t]),h=new i(t,[this.path,s]),null!=this.options.subtype&&(h._subtype=this.options.subtype),h;throw new p("Buffer",t,this.path,null,this)},h.prototype.subtype=function(t){return this.options.subtype=t,this},h.prototype.$conditionalHandlers=c.options(a.prototype.$conditionalHandlers,{$bitsAllClear:u,$bitsAnyClear:u,$bitsAllSet:u,$bitsAnySet:u,$gt:y,$gte:y,$lt:y,$lte:y}),h.prototype.castForQuery=function(t,e){var r;if(2===arguments.length){if(!(r=this.$conditionalHandlers[t]))throw new Error("Can't use "+t+" with Buffer.");return r.call(this,e)}e=t;var n=this._castForQuery(e);return n?n.toObject({transform:!1,virtuals:!1}):n},
+/*!
+ * Module exports.
+ */
+t.exports=h}).call(this,r(1).Buffer)},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"subtype",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";
+/*!
+ * Module requirements.
+ */var n=r(5),o=r(163),i=r(7),s=r(164),a=r(2),u=i.CastError;function c(t,e){i.call(this,t,e,"Date")}
+/*!
+ * Date Query casting.
+ *
+ * @api private
+ */
+function l(t){return this.cast(t)}c.schemaName="Date",c.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+c.prototype=Object.create(i.prototype),c.prototype.constructor=c,c.prototype.OptionsConstructor=o,
+/*!
+ * ignore
+ */
+c._cast=s,c.set=i.set,c.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if(null!=t&&!(t instanceof Date))throw new Error;return t}),this._cast=t),this._cast},c.prototype.expires=function(t){return this._index&&"Object"===this._index.constructor.name||(this._index={}),this._index.expires=t,a.expires(this._index),this},
+/*!
+ * ignore
+ */
+c._checkRequired=function(t){return t instanceof Date},c.checkRequired=i.checkRequired,c.prototype.checkRequired=function(t,e){return i._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():c.checkRequired())(t)},c.prototype.min=function(t,e){if(this.minValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.minValidator}),this)),t){var r=e||n.messages.Date.min;"string"==typeof r&&(r=r.replace(/{MIN}/,t===Date.now?"Date.now()":t.toString()));var o=this;this.validators.push({validator:this.minValidator=function(e){var r=t;"function"==typeof t&&t!==Date.now&&(r=r.call(this));var n=r===Date.now?r():o.cast(r);return null===e||e.valueOf()>=n.valueOf()},message:r,type:"min",min:t})}return this},c.prototype.max=function(t,e){if(this.maxValidator&&(this.validators=this.validators.filter((function(t){return t.validator!==this.maxValidator}),this)),t){var r=e||n.messages.Date.max;"string"==typeof r&&(r=r.replace(/{MAX}/,t===Date.now?"Date.now()":t.toString()));var o=this;this.validators.push({validator:this.maxValidator=function(e){var r=t;"function"==typeof r&&r!==Date.now&&(r=r.call(this));var n=r===Date.now?r():o.cast(r);return null===e||e.valueOf()<=n.valueOf()},message:r,type:"max",max:t})}return this},c.prototype.cast=function(t){var e="function"==typeof this.constructor.cast?this.constructor.cast():c.cast();try{return e(t)}catch(e){throw new u("date",t,this.path,e,this)}},c.prototype.$conditionalHandlers=a.options(i.prototype.$conditionalHandlers,{$gt:l,$gte:l,$lt:l,$lte:l}),c.prototype.castForQuery=function(t,e){if(2!==arguments.length)return this._castForQuery(t);var r=this.$conditionalHandlers[t];if(!r)throw new Error("Can't use "+t+" with Date.");return r.call(this,e)},
+/*!
+ * Module exports.
+ */
+t.exports=c},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"min",l),Object.defineProperty(c.prototype,"max",l),Object.defineProperty(c.prototype,"expires",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";var n=r(22);t.exports=function(t){return null==t||""===t?null:t instanceof Date?(n.ok(!isNaN(t.valueOf())),t):(n.ok("boolean"!=typeof t),e=t instanceof Number||"number"==typeof t?new Date(t):"string"==typeof t&&!isNaN(Number(t))&&(Number(t)>=275761||Number(t)<-271820)?new Date(Number(t)):"function"==typeof t.valueOf?new Date(t.valueOf()):new Date(t),isNaN(e.valueOf())?void n.ok(!1):e);var e}},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module dependencies.
+ */
+var n,o=r(166),i=r(7),s=r(86),a=r(13),u=r(2),c=r(0).populateModelSymbol,l=i.CastError;function f(t,e){var r="string"==typeof t&&24===t.length&&/^[a-f0-9]+$/i.test(t),n=e&&e.suppressWarning;!r&&void 0!==t||n||(console.warn("mongoose: To create a new ObjectId please try `Mongoose.Types.ObjectId` instead of using `Mongoose.Schema.ObjectId`. Set the `suppressWarning` option if you're trying to create a hex char path in your schema."),console.trace()),i.call(this,t,e,"ObjectID")}
+/*!
+ * ignore
+ */
+function p(t){return this.cast(t)}
+/*!
+ * ignore
+ */
+function h(){return new a}function y(t){if(n||(n=r(6)),this instanceof n){if(void 0===t){var e=new a;return this.$__._id=e,e}this.$__._id=t}return t}
+/*!
+ * Module exports.
+ */f.schemaName="ObjectId",f.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+f.prototype=Object.create(i.prototype),f.prototype.constructor=f,f.prototype.OptionsConstructor=o,f.get=i.get,f.set=i.set,f.prototype.auto=function(t){return t&&(this.default(h),this.set(y)),this},
+/*!
+ * ignore
+ */
+f._checkRequired=function(t){return t instanceof a},
+/*!
+ * ignore
+ */
+f._cast=s,f.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if(!(t instanceof a))throw new Error(t+" is not an instance of ObjectId");return t}),this._cast=t),this._cast},f.checkRequired=i.checkRequired,f.prototype.checkRequired=function(t,e){return i._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():f.checkRequired())(t)},f.prototype.cast=function(t,o,s){if(i._isRef(this,t,o,s)){if(null==t)return t;if(n||(n=r(6)),t instanceof n)return t.$__.wasPopulated=!0,t;if(t instanceof a)return t;if("objectid"===(t.constructor.name||"").toLowerCase())return new a(t.toHexString());if(e.isBuffer(t)||!u.isObject(t))throw new l("ObjectId",t,this.path,null,this);var p=o.$__fullPath(this.path),h=(o.ownerDocument?o.ownerDocument():o).populated(p,!0),y=t;return o.$__.populated&&o.$__.populated[p]&&o.$__.populated[p].options&&o.$__.populated[p].options.options&&o.$__.populated[p].options.options.lean||((y=new h.options[c](t)).$__.wasPopulated=!0),y}var d="function"==typeof this.constructor.cast?this.constructor.cast():f.cast();try{return d(t)}catch(e){throw new l("ObjectId",t,this.path,e,this)}},f.prototype.$conditionalHandlers=u.options(i.prototype.$conditionalHandlers,{$gt:p,$gte:p,$lt:p,$lte:p}),h.$runBeforeSetters=!0,t.exports=f}).call(this,r(1).Buffer)},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"auto",l),
+/*!
+ * ignore
+ */
+t.exports=c},function(t,e,r){"use strict";(function(e){
+/*!
+ * Module dependencies.
+ */
+var n,o=r(7),i=o.CastError,s=r(20),a=r(168),u=r(2),c=r(0).populateModelSymbol;function l(t,e){o.call(this,t,e,"Decimal128")}
+/*!
+ * ignore
+ */
+function f(t){return this.cast(t)}l.schemaName="Decimal128",l.defaultOptions={},
+/*!
+ * Inherits from SchemaType.
+ */
+l.prototype=Object.create(o.prototype),l.prototype.constructor=l,
+/*!
+ * ignore
+ */
+l._cast=a,l.set=o.set,l.cast=function(t){return 0===arguments.length||(!1===t&&(t=function(t){if(null!=t&&!(t instanceof s))throw new Error;return t}),this._cast=t),this._cast},
+/*!
+ * ignore
+ */
+l._checkRequired=function(t){return t instanceof s},l.checkRequired=o.checkRequired,l.prototype.checkRequired=function(t,e){return o._isRef(this,t,e,!0)?!!t:("function"==typeof this.constructor.checkRequired?this.constructor.checkRequired():l.checkRequired())(t)},l.prototype.cast=function(t,a,f){if(o._isRef(this,t,a,f)){if(null==t)return t;if(n||(n=r(6)),t instanceof n)return t.$__.wasPopulated=!0,t;if(t instanceof s)return t;if(e.isBuffer(t)||!u.isObject(t))throw new i("Decimal128",t,this.path,null,this);var p=a.$__fullPath(this.path),h=(a.ownerDocument?a.ownerDocument():a).populated(p,!0),y=t;return a.$__.populated&&a.$__.populated[p]&&a.$__.populated[p].options&&a.$__.populated[p].options.options&&a.$__.populated[p].options.options.lean||((y=new h.options[c](t)).$__.wasPopulated=!0),y}var d="function"==typeof this.constructor.cast?this.constructor.cast():l.cast();try{return d(t)}catch(e){throw new i("Decimal128",t,this.path,e,this)}},l.prototype.$conditionalHandlers=u.options(o.prototype.$conditionalHandlers,{$gt:f,$gte:f,$lt:f,$lte:f}),
+/*!
+ * Module exports.
+ */
+t.exports=l}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(e){function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(20),i=r(22);t.exports=function(t){return null==t?t:"object"===n(t)&&"string"==typeof t.$numberDecimal?o.fromString(t.$numberDecimal):t instanceof o?t:"string"==typeof t?o.fromString(t):e.isBuffer(t)?new o(t):"number"==typeof t?o.fromString(String(t)):"function"==typeof t.valueOf&&"string"==typeof t.valueOf()?o.fromString(t.valueOf()):void i.ok(!1)}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";(function(e){
+/*!
+ * ignore
+ */
+function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function s(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}function a(t,e,r){return(a="undefined"!=typeof Reflect&&Reflect.get?Reflect.get:function(t,e,r){var n=function(t,e){for(;!Object.prototype.hasOwnProperty.call(t,e)&&null!==(t=f(t)););return t}(t,e);if(n){var o=Object.getOwnPropertyDescriptor(n,e);return o.get?o.get.call(r):o.value}})(t,e,r||t)}function u(t,e){return(u=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function c(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=f(t);if(e){var o=f(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return l(this,r)}}function l(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function f(t){return(f=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var p=r(87),h=r(170),y=r(7),d=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&u(t,e)}(h,t);var r,n,i,l=c(h);function h(t,e){var r;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,h),(r=l.call(this,t,e,"Map")).$isSchemaMap=!0,r}return r=h,(n=[{key:"set",value:function(t,e){return y.set(t,e)}},{key:"cast",value:function(t,r,n){if(t instanceof p)return t;if(n){var i=new p({},this.path,r,this.$__schemaType);if(t instanceof e.Map){var s,a=o(t.keys());try{for(a.s();!(s=a.n()).done;){var u=s.value;i.$init(u,i.$__schemaType.cast(t.get(u),r,!0))}}catch(t){a.e(t)}finally{a.f()}}else for(var c=0,l=Object.keys(t);c<l.length;c++){var f=l[c];i.$init(f,i.$__schemaType.cast(t[f],r,!0))}return i}return new p(t,this.path,r,this.$__schemaType)}},{key:"clone",value:function(){var t=a(f(h.prototype),"clone",this).call(this);return null!=this.$__schemaType&&(t.$__schemaType=this.$__schemaType.clone()),t}}])&&s(r.prototype,n),i&&s(r,i),h}(y);d.prototype.OptionsConstructor=h,d.defaultOptions={},t.exports=d}).call(this,r(11))},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function i(t,e){return(i=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function s(t){var e=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],(function(){}))),!0}catch(t){return!1}}();return function(){var r,n=u(t);if(e){var o=u(this).constructor;r=Reflect.construct(n,arguments,o)}else r=n.apply(this,arguments);return a(this,r)}}function a(t,e){return!e||"object"!==n(e)&&"function"!=typeof e?function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t):e}function u(t){return(u=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}var c=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&i(t,e)}(r,t);var e=s(r);function r(){return o(this,r),e.apply(this,arguments)}return r}(r(9)),l=r(10);Object.defineProperty(c.prototype,"of",l),t.exports=c},function(t,e,r){"use strict";(function(t){
+/*!
+ * Module dependencies.
+ */
+function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var o=r(15).get().Binary,i=r(20),s=r(13),a=r(29);
+/*!
+ * ignore
+ */
+function u(e){return e&&"object"===n(e)&&!(e instanceof Date)&&!(e instanceof s)&&(!Array.isArray(e)||e.length>0)&&!(e instanceof t)&&!(e instanceof i)&&!(e instanceof o)}e.flatten=
+/*!
+ * ignore
+ */
+function e(r,n,o,i){var s;s=r&&a(r)&&!t.isBuffer(r)?Object.keys(r.toObject({transform:!1,virtuals:!1})):Object.keys(r||{});var c=s.length,l={};n=n?n+".":"";for(var f=0;f<c;++f){var p=s[f],h=r[p];l[n+p]=h;var y=i&&i.path&&i.path(n+p),d=i&&i.nested&&i.nested[n+p];if(!y||"Mixed"!==y.instance){if(u(h)){if(o&&o.skipArrays&&Array.isArray(h))continue;var m=e(h,n+p,o,i);for(var _ in m)l[_]=m[_];Array.isArray(h)&&(l[n+p]=h)}if(d)for(var v=Object.keys(i.paths),g=0,b=v;g<b.length;g++){var w=b[g];w.startsWith(n+p+".")&&!l.hasOwnProperty(w)&&(l[w]=void 0)}}}return l}
+/*!
+ * ignore
+ */,e.modifiedPaths=function e(r,n,o){var i=Object.keys(r||{}),s=i.length;o=o||{},n=n?n+".":"";for(var c=0;c<s;++c){var l=i[c],f=r[l];o[n+l]=!0,a(f)&&!t.isBuffer(f)&&(f=f.toObject({transform:!1,virtuals:!1})),u(f)&&e(f,n+l,o)}return o}}).call(this,r(1).Buffer)},function(t,e,r){"use strict";var n=r(3);
+/*!
+ * Like `schema.path()`, except with a document, because impossible to
+ * determine path type without knowing the embedded discriminator key.
+ */t.exports=function t(e,r,o){for(var i=(o=o||{}).typeOnly,s=r.split("."),a=null,u="adhocOrUndefined",c=0;c<s.length;++c){var l=s.slice(0,c+1).join(".");if(null!=(a=e.schema.path(l))){if("Mixed"===a.instance)return i?"real":a;if(u=e.schema.pathType(l),(a.$isSingleNested||a.$isMongooseDocumentArrayElement)&&null!=a.schema.discriminators){var f=a.schema.discriminators,p=e.get(l+"."+n(a,"schema.options.discriminatorKey"));if(null==p||null==f[p])continue;var h=s.slice(c+1).join(".");return t(e.get(l),h,o)}}else u="adhocOrUndefined"}return i?u:a}},function(t,e,r){"use strict";
+/*!
+ * ignore
+ */
+/*!
+ * Returns this documents _id cast to a string.
+ */
+function n(){return null!=this._id?String(this._id):null}t.exports=function(t){!t.paths.id&&!t.options.noVirtualId&&t.options.id&&t.virtual("id").get(n)}},function(t,e,r){"use strict";var n=r(58);
+/*!
+ * ignore
+ */t.exports=function(t){var e=Object.keys(t),r=e.length,o=null;if(1===r&&"_id"===e[0])o=!!t[e[r]];else for(;r--;)if("_id"!==e[r]&&n(t[e[r]])){o=!t[e[r]];break}return o}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies
+ */function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function o(t,e){var r;if("undefined"==typeof Symbol||null==t[Symbol.iterator]){if(Array.isArray(t)||(r=function(t,e){if(!t)return;if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);"Object"===r&&t.constructor&&(r=t.constructor.name);if("Map"===r||"Set"===r)return Array.from(t);if("Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r))return i(t,e)}(t))||e&&t&&"number"==typeof t.length){r&&(t=r);var n=0,o=function(){};return{s:o,n:function(){return n>=t.length?{done:!0}:{done:!1,value:t[n++]}},e:function(t){throw t},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var s,a=!0,u=!1;return{s:function(){r=t[Symbol.iterator]()},n:function(){var t=r.next();return a=t.done,t},e:function(t){u=!0,s=t},f:function(){try{a||null==r.return||r.return()}finally{if(u)throw s}}}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}var s=r(176),a=r(3),u=r(34),c=r(58),l=r(28);
+/*!
+ * Set each path query option to lean
+ *
+ * @param {Object} option
+ */
+function f(t){return function(e){e.options||(e.options={}),e.options.lean=t}}
+/*!
+ * Handle the `WriteOpResult` from the server
+ */
+/*!
+ * Prepare a set of path options for query population.
+ *
+ * @param {Query} query
+ * @param {Object} options
+ * @return {Array}
+ */
+e.preparePopulationOptions=function(t,e){var r=t.options.populate,n=Object.keys(r).reduce((function(t,e){return t.concat([r[e]])}),[]);return null!=e.lean&&n.filter((function(t){return null==a(t,"options.lean")})).forEach(f(e.lean)),n},
+/*!
+ * Prepare a set of path options for query population. This is the MongooseQuery
+ * version
+ *
+ * @param {Query} query
+ * @param {Object} options
+ * @return {Array}
+ */
+e.preparePopulationOptionsMQ=function(t,e){var r=t._mongooseOptions.populate,n=Object.keys(r).reduce((function(t,e){return t.concat([r[e]])}),[]);null!=e.lean&&n.filter((function(t){return null==a(t,"options.lean")})).forEach(f(e.lean));var o=a(t,"options.session",null);null!=o&&n.forEach((function(t){null!=t.options?"session"in t.options||(t.options.session=o):t.options={session:o}}));var i=t._fieldsForExec();return n.forEach((function(t){t._queryProjection=i})),n},
+/*!
+ * If the document is a mapped discriminator type, it returns a model instance for that type, otherwise,
+ * it returns an instance of the given model.
+ *
+ * @param {Model} model
+ * @param {Object} doc
+ * @param {Object} fields
+ *
+ * @return {Document}
+ */
+e.createModel=function(t,r,n,o){t.hooks.execPreSync("createModel",r);var i=t.schema?t.schema.discriminatorMapping:null,s=i&&i.isRoot?i.key:null,a=r[s];if(s&&a&&t.discriminators){var c=t.discriminators[a]||u(t,a);if(c){var f=l(o);return e.applyPaths(f,c.schema),new c(void 0,f,!0)}}return new t(void 0,n,{skipId:!0,isNew:!1,willInit:!0})},
+/*!
+ * ignore
+ */
+e.applyPaths=function(t,e){var r,i,u;if(t)for(u=(i=Object.keys(t)).length;u--;)if("+"!==i[u][0]){var l=t[i[u]];if(c(l)){r=!l;break}}var f=[],p=[],h=[];switch(function e(o,u){if(u||(u=""),-1!==h.indexOf(o))return[];h.push(o);var c=[];return o.eachPath((function(o,l){u&&(o=u+"."+o);var h=function(e,o){var s="+"+e,u=t&&s in t;u&&delete t[s];if("boolean"!=typeof o.selected)return;if(u)return delete t[s],void(!1===r&&i.length>1&&!~i.indexOf(e)&&(t[e]=1));for(var c=e.split("."),l="",h=0;h<c.length;++h)if(l+=l.length?"."+c[h]:c[h],-1!==p.indexOf(l))return;if(!r&&a(o,"options.$skipDiscriminatorCheck",!1))for(var y="",d=0;d<c.length;++d){y+=(0===y.length?"":".")+c[d];var m=a(t,y,!1)||a(t,y+".$",!1);if(m&&"object"!==n(m))return}return(o.selected?f:p).push(e),e}(o,l);if(null!=h&&c.push(h),l.schema){var y=e(l.schema,o);!1===r&&s(t,o,l.schema,f,y)}})),h.pop(),c}(e),r){case!0:var y,d=o(p);try{for(d.s();!(y=d.n()).done;){var m=y.value;t[m]=0}}catch(t){d.e(t)}finally{d.f()}break;case!1:e&&e.paths._id&&e.paths._id.options&&!1===e.paths._id.options.select&&(t._id=0);var _,v=o(f);try{for(v.s();!(_=v.n()).done;){var g=_.value;t[g]=t[g]||1}}catch(t){v.e(t)}finally{v.f()}break;case void 0:if(null==t)break;for(var b=0,w=Object.keys(t||{});b<w.length;b++){var O=w[b];O.startsWith("+")&&delete t[O]}var S,A=o(p);try{for(A.s();!(S=A.n()).done;){var j=S.value;t[j]=0}}catch(t){A.e(t)}finally{A.f()}}},e.handleDeleteWriteOpResult=function(t){return function(e,r){if(e)return t(e);var n=Object.assign({},r.result);return null!=a(r,"result.n",null)&&(n.deletedCount=r.result.n),null!=r.deletedCount&&(n.deletedCount=r.deletedCount),t(null,n)}}},function(t,e,r){"use strict";t.exports=function(t,e,r,n,o){var i=Object.keys(t).reduce((function(t,r){return t||r.startsWith(e+".")}),!1),s=e+"."+r.options.discriminatorKey;i||1!==o.length||o[0]!==s||n.splice(n.indexOf(s),1)}},function(t,e,r){"use strict";function n(t){return(n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}t.exports=function(t){return!!t&&("object"===n(t)||"function"==typeof t)&&"function"==typeof t.then}},function(t,e,r){"use strict";
+/*!
+ * Module dependencies.
+ */var n=r(6),o=r(19).EventEmitter,i=r(5),s=r(52),a=r(13),u=i.ValidationError,c=r(76),l=r(21);function f(t,e,r,o,u){if(!(this instanceof f))return new f(t,e,r,o,u);if(l(e)&&!e.instanceOfSchema&&(e=new s(e)),e=this.schema||e,!this.schema&&e.options._id&&void 0===(t=t||{})._id&&(t._id=new a),!e)throw new i.MissingSchemaError;for(var p in this.$__setSchema(e),n.call(this,t,r,o,u),c(this,e,{decorateDoc:!0}),e.methods)this[p]=e.methods[p];for(var h in e.statics)this[h]=e.statics[h]}
+/*!
+ * Inherit from the NodeJS document
+ */f.prototype=Object.create(n.prototype),f.prototype.constructor=f,
+/*!
+ * ignore
+ */
+f.events=new o,
+/*!
+ * Browser doc exposes the event emitter API
+ */
+f.$emitter=new o,["on","once","emit","listeners","removeListener","setMaxListeners","removeAllListeners","addListener"].forEach((function(t){f[t]=function(){return f.$emitter[t].apply(f.$emitter,arguments)}})),
+/*!
+ * Module exports.
+ */
+f.ValidationError=u,t.exports=f}])})); \ No newline at end of file
diff --git a/node_modules/mongoose/dist/createBasicSchemaDefinition.js b/node_modules/mongoose/dist/createBasicSchemaDefinition.js
new file mode 100644
index 0000000..e7a58fe
--- /dev/null
+++ b/node_modules/mongoose/dist/createBasicSchemaDefinition.js
@@ -0,0 +1,7 @@
+"use strict";
+exports.__esModule = true;
+var mongoose_1 = require("mongoose");
+var schema = new mongoose_1.Schema({ name: { type: 'String' } });
+var Test = mongoose_1.model('Test', schema);
+var doc = new Test({ name: 'foo' });
+doc.name = 'bar';
diff --git a/node_modules/mongoose/index.js b/node_modules/mongoose/index.js
new file mode 100644
index 0000000..a938b44
--- /dev/null
+++ b/node_modules/mongoose/index.js
@@ -0,0 +1,9 @@
+
+/**
+ * Export lib/mongoose
+ *
+ */
+
+'use strict';
+
+module.exports = require('./lib/');
diff --git a/node_modules/mongoose/lib/aggregate.js b/node_modules/mongoose/lib/aggregate.js
new file mode 100644
index 0000000..f562e57
--- /dev/null
+++ b/node_modules/mongoose/lib/aggregate.js
@@ -0,0 +1,1162 @@
+'use strict';
+
+/*!
+ * Module dependencies
+ */
+
+const AggregationCursor = require('./cursor/AggregationCursor');
+const Query = require('./query');
+const applyGlobalMaxTimeMS = require('./helpers/query/applyGlobalMaxTimeMS');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const stringifyAccumulatorOptions = require('./helpers/aggregate/stringifyAccumulatorOptions');
+const util = require('util');
+const utils = require('./utils');
+const read = Query.prototype.read;
+const readConcern = Query.prototype.readConcern;
+
+/**
+ * Aggregate constructor used for building aggregation pipelines. Do not
+ * instantiate this class directly, use [Model.aggregate()](/docs/api.html#model_Model.aggregate) instead.
+ *
+ * ####Example:
+ *
+ * const aggregate = Model.aggregate([
+ * { $project: { a: 1, b: 1 } },
+ * { $skip: 5 }
+ * ]);
+ *
+ * Model.
+ * aggregate([{ $match: { age: { $gte: 21 }}}]).
+ * unwind('tags').
+ * exec(callback);
+ *
+ * ####Note:
+ *
+ * - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
+ * - Mongoose does **not** cast pipeline stages. The below will **not** work unless `_id` is a string in the database
+ *
+ * ```javascript
+ * new Aggregate([{ $match: { _id: '00000000000000000000000a' } }]);
+ * // Do this instead to cast to an ObjectId
+ * new Aggregate([{ $match: { _id: mongoose.Types.ObjectId('00000000000000000000000a') } }]);
+ * ```
+ *
+ * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
+ * @see driver http://mongodb.github.com/node-mongodb-native/api-generated/collection.html#aggregate
+ * @param {Array} [pipeline] aggregation pipeline as an array of objects
+ * @api public
+ */
+
+function Aggregate(pipeline) {
+ this._pipeline = [];
+ this._model = undefined;
+ this.options = {};
+
+ if (arguments.length === 1 && util.isArray(pipeline)) {
+ this.append.apply(this, pipeline);
+ }
+}
+
+/**
+ * Contains options passed down to the [aggregate command](https://docs.mongodb.com/manual/reference/command/aggregate/).
+ * Supported options are:
+ *
+ * - `readPreference`
+ * - [`cursor`](./api.html#aggregate_Aggregate-cursor)
+ * - [`explain`](./api.html#aggregate_Aggregate-explain)
+ * - [`allowDiskUse`](./api.html#aggregate_Aggregate-allowDiskUse)
+ * - `maxTimeMS`
+ * - `bypassDocumentValidation`
+ * - `raw`
+ * - `promoteLongs`
+ * - `promoteValues`
+ * - `promoteBuffers`
+ * - [`collation`](./api.html#aggregate_Aggregate-collation)
+ * - `comment`
+ * - [`session`](./api.html#aggregate_Aggregate-session)
+ *
+ * @property options
+ * @memberOf Aggregate
+ * @api public
+ */
+
+Aggregate.prototype.options;
+
+/**
+ * Get/set the model that this aggregation will execute on.
+ *
+ * ####Example:
+ * const aggregate = MyModel.aggregate([{ $match: { answer: 42 } }]);
+ * aggregate.model() === MyModel; // true
+ *
+ * // Change the model. There's rarely any reason to do this.
+ * aggregate.model(SomeOtherModel);
+ * aggregate.model() === SomeOtherModel; // true
+ *
+ * @param {Model} [model] the model to which the aggregate is to be bound
+ * @return {Aggregate|Model} if model is passed, will return `this`, otherwise will return the model
+ * @api public
+ */
+
+Aggregate.prototype.model = function(model) {
+ if (arguments.length === 0) {
+ return this._model;
+ }
+
+ this._model = model;
+ if (model.schema != null) {
+ if (this.options.readPreference == null &&
+ model.schema.options.read != null) {
+ this.options.readPreference = model.schema.options.read;
+ }
+ if (this.options.collation == null &&
+ model.schema.options.collation != null) {
+ this.options.collation = model.schema.options.collation;
+ }
+ }
+ return this;
+};
+
+/**
+ * Appends new operators to this aggregate pipeline
+ *
+ * ####Examples:
+ *
+ * aggregate.append({ $project: { field: 1 }}, { $limit: 2 });
+ *
+ * // or pass an array
+ * const pipeline = [{ $match: { daw: 'Logic Audio X' }} ];
+ * aggregate.append(pipeline);
+ *
+ * @param {Object} ops operator(s) to append
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.append = function() {
+ const args = (arguments.length === 1 && util.isArray(arguments[0]))
+ ? arguments[0]
+ : utils.args(arguments);
+
+ if (!args.every(isOperator)) {
+ throw new Error('Arguments must be aggregate pipeline operators');
+ }
+
+ this._pipeline = this._pipeline.concat(args);
+
+ return this;
+};
+
+/**
+ * Appends a new $addFields operator to this aggregate pipeline.
+ * Requires MongoDB v3.4+ to work
+ *
+ * ####Examples:
+ *
+ * // adding new fields based on existing fields
+ * aggregate.addFields({
+ * newField: '$b.nested'
+ * , plusTen: { $add: ['$val', 10]}
+ * , sub: {
+ * name: '$a'
+ * }
+ * })
+ *
+ * // etc
+ * aggregate.addFields({ salary_k: { $divide: [ "$salary", 1000 ] } });
+ *
+ * @param {Object} arg field specification
+ * @see $addFields https://docs.mongodb.com/manual/reference/operator/aggregation/addFields/
+ * @return {Aggregate}
+ * @api public
+ */
+Aggregate.prototype.addFields = function(arg) {
+ const fields = {};
+ if (typeof arg === 'object' && !util.isArray(arg)) {
+ Object.keys(arg).forEach(function(field) {
+ fields[field] = arg[field];
+ });
+ } else {
+ throw new Error('Invalid addFields() argument. Must be an object');
+ }
+ return this.append({ $addFields: fields });
+};
+
+/**
+ * Appends a new $project operator to this aggregate pipeline.
+ *
+ * Mongoose query [selection syntax](#query_Query-select) is also supported.
+ *
+ * ####Examples:
+ *
+ * // include a, include b, exclude _id
+ * aggregate.project("a b -_id");
+ *
+ * // or you may use object notation, useful when
+ * // you have keys already prefixed with a "-"
+ * aggregate.project({a: 1, b: 1, _id: 0});
+ *
+ * // reshaping documents
+ * aggregate.project({
+ * newField: '$b.nested'
+ * , plusTen: { $add: ['$val', 10]}
+ * , sub: {
+ * name: '$a'
+ * }
+ * })
+ *
+ * // etc
+ * aggregate.project({ salary_k: { $divide: [ "$salary", 1000 ] } });
+ *
+ * @param {Object|String} arg field specification
+ * @see projection http://docs.mongodb.org/manual/reference/aggregation/project/
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.project = function(arg) {
+ const fields = {};
+
+ if (typeof arg === 'object' && !util.isArray(arg)) {
+ Object.keys(arg).forEach(function(field) {
+ fields[field] = arg[field];
+ });
+ } else if (arguments.length === 1 && typeof arg === 'string') {
+ arg.split(/\s+/).forEach(function(field) {
+ if (!field) {
+ return;
+ }
+ const include = field[0] === '-' ? 0 : 1;
+ if (include === 0) {
+ field = field.substring(1);
+ }
+ fields[field] = include;
+ });
+ } else {
+ throw new Error('Invalid project() argument. Must be string or object');
+ }
+
+ return this.append({ $project: fields });
+};
+
+/**
+ * Appends a new custom $group operator to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.group({ _id: "$department" });
+ *
+ * @see $group http://docs.mongodb.org/manual/reference/aggregation/group/
+ * @method group
+ * @memberOf Aggregate
+ * @instance
+ * @param {Object} arg $group operator contents
+ * @return {Aggregate}
+ * @api public
+ */
+
+/**
+ * Appends a new custom $match operator to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.match({ department: { $in: [ "sales", "engineering" ] } });
+ *
+ * @see $match http://docs.mongodb.org/manual/reference/aggregation/match/
+ * @method match
+ * @memberOf Aggregate
+ * @instance
+ * @param {Object} arg $match operator contents
+ * @return {Aggregate}
+ * @api public
+ */
+
+/**
+ * Appends a new $skip operator to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.skip(10);
+ *
+ * @see $skip http://docs.mongodb.org/manual/reference/aggregation/skip/
+ * @method skip
+ * @memberOf Aggregate
+ * @instance
+ * @param {Number} num number of records to skip before next stage
+ * @return {Aggregate}
+ * @api public
+ */
+
+/**
+ * Appends a new $limit operator to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.limit(10);
+ *
+ * @see $limit http://docs.mongodb.org/manual/reference/aggregation/limit/
+ * @method limit
+ * @memberOf Aggregate
+ * @instance
+ * @param {Number} num maximum number of records to pass to the next stage
+ * @return {Aggregate}
+ * @api public
+ */
+
+/**
+ * Appends a new $geoNear operator to this aggregate pipeline.
+ *
+ * ####NOTE:
+ *
+ * **MUST** be used as the first operator in the pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.near({
+ * near: [40.724, -73.997],
+ * distanceField: "dist.calculated", // required
+ * maxDistance: 0.008,
+ * query: { type: "public" },
+ * includeLocs: "dist.location",
+ * uniqueDocs: true,
+ * num: 5
+ * });
+ *
+ * @see $geoNear http://docs.mongodb.org/manual/reference/aggregation/geoNear/
+ * @method near
+ * @memberOf Aggregate
+ * @instance
+ * @param {Object} arg
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.near = function(arg) {
+ const op = {};
+ op.$geoNear = arg;
+ return this.append(op);
+};
+
+/*!
+ * define methods
+ */
+
+'group match skip limit out'.split(' ').forEach(function($operator) {
+ Aggregate.prototype[$operator] = function(arg) {
+ const op = {};
+ op['$' + $operator] = arg;
+ return this.append(op);
+ };
+});
+
+/**
+ * Appends new custom $unwind operator(s) to this aggregate pipeline.
+ *
+ * Note that the `$unwind` operator requires the path name to start with '$'.
+ * Mongoose will prepend '$' if the specified field doesn't start '$'.
+ *
+ * ####Examples:
+ *
+ * aggregate.unwind("tags");
+ * aggregate.unwind("a", "b", "c");
+ * aggregate.unwind({ path: '$tags', preserveNullAndEmptyArrays: true });
+ *
+ * @see $unwind http://docs.mongodb.org/manual/reference/aggregation/unwind/
+ * @param {String|Object} fields the field(s) to unwind, either as field names or as [objects with options](https://docs.mongodb.com/manual/reference/operator/aggregation/unwind/#document-operand-with-options). If passing a string, prefixing the field name with '$' is optional. If passing an object, `path` must start with '$'.
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.unwind = function() {
+ const args = utils.args(arguments);
+
+ const res = [];
+ for (const arg of args) {
+ if (arg && typeof arg === 'object') {
+ res.push({ $unwind: arg });
+ } else if (typeof arg === 'string') {
+ res.push({
+ $unwind: (arg && arg.startsWith('$')) ? arg : '$' + arg
+ });
+ } else {
+ throw new Error('Invalid arg "' + arg + '" to unwind(), ' +
+ 'must be string or object');
+ }
+ }
+
+ return this.append.apply(this, res);
+};
+
+/**
+ * Appends a new $replaceRoot operator to this aggregate pipeline.
+ *
+ * Note that the `$replaceRoot` operator requires field strings to start with '$'.
+ * If you are passing in a string Mongoose will prepend '$' if the specified field doesn't start '$'.
+ * If you are passing in an object the strings in your expression will not be altered.
+ *
+ * ####Examples:
+ *
+ * aggregate.replaceRoot("user");
+ *
+ * aggregate.replaceRoot({ x: { $concat: ['$this', '$that'] } });
+ *
+ * @see $replaceRoot https://docs.mongodb.org/manual/reference/operator/aggregation/replaceRoot
+ * @param {String|Object} the field or document which will become the new root document
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.replaceRoot = function(newRoot) {
+ let ret;
+
+ if (typeof newRoot === 'string') {
+ ret = newRoot.startsWith('$') ? newRoot : '$' + newRoot;
+ } else {
+ ret = newRoot;
+ }
+
+ return this.append({
+ $replaceRoot: {
+ newRoot: ret
+ }
+ });
+};
+
+/**
+ * Appends a new $count operator to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.count("userCount");
+ *
+ * @see $count https://docs.mongodb.org/manual/reference/operator/aggregation/count
+ * @param {String} the name of the count field
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.count = function(countName) {
+ return this.append({ $count: countName });
+};
+
+/**
+ * Appends a new $sortByCount operator to this aggregate pipeline. Accepts either a string field name
+ * or a pipeline object.
+ *
+ * Note that the `$sortByCount` operator requires the new root to start with '$'.
+ * Mongoose will prepend '$' if the specified field name doesn't start with '$'.
+ *
+ * ####Examples:
+ *
+ * aggregate.sortByCount('users');
+ * aggregate.sortByCount({ $mergeObjects: [ "$employee", "$business" ] })
+ *
+ * @see $sortByCount https://docs.mongodb.com/manual/reference/operator/aggregation/sortByCount/
+ * @param {Object|String} arg
+ * @return {Aggregate} this
+ * @api public
+ */
+
+Aggregate.prototype.sortByCount = function(arg) {
+ if (arg && typeof arg === 'object') {
+ return this.append({ $sortByCount: arg });
+ } else if (typeof arg === 'string') {
+ return this.append({
+ $sortByCount: (arg && arg.startsWith('$')) ? arg : '$' + arg
+ });
+ } else {
+ throw new TypeError('Invalid arg "' + arg + '" to sortByCount(), ' +
+ 'must be string or object');
+ }
+};
+
+/**
+ * Appends new custom $lookup operator(s) to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.lookup({ from: 'users', localField: 'userId', foreignField: '_id', as: 'users' });
+ *
+ * @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
+ */
+
+Aggregate.prototype.lookup = function(options) {
+ return this.append({ $lookup: options });
+};
+
+/**
+ * Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection.
+ *
+ * Note that graphLookup can only consume at most 100MB of memory, and does not allow disk use even if `{ allowDiskUse: true }` is specified.
+ *
+ * #### Examples:
+ * // Suppose we have a collection of courses, where a document might look like `{ _id: 0, name: 'Calculus', prerequisite: 'Trigonometry'}` and `{ _id: 0, name: 'Trigonometry', prerequisite: 'Algebra' }`
+ * aggregate.graphLookup({ from: 'courses', startWith: '$prerequisite', connectFromField: 'prerequisite', connectToField: 'name', as: 'prerequisites', maxDepth: 3 }) // this will recursively search the 'courses' collection up to 3 prerequisites
+ *
+ * @see $graphLookup https://docs.mongodb.com/manual/reference/operator/aggregation/graphLookup/#pipe._S_graphLookup
+ * @param {Object} options to $graphLookup as described in the above link
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.graphLookup = function(options) {
+ const cloneOptions = {};
+ if (options) {
+ if (!utils.isObject(options)) {
+ throw new TypeError('Invalid graphLookup() argument. Must be an object.');
+ }
+
+ utils.mergeClone(cloneOptions, options);
+ const startWith = cloneOptions.startWith;
+
+ if (startWith && typeof startWith === 'string') {
+ cloneOptions.startWith = cloneOptions.startWith.startsWith('$') ?
+ cloneOptions.startWith :
+ '$' + cloneOptions.startWith;
+ }
+
+ }
+ return this.append({ $graphLookup: cloneOptions });
+};
+
+/**
+ * Appends new custom $sample operator(s) to this aggregate pipeline.
+ *
+ * ####Examples:
+ *
+ * aggregate.sample(3); // Add a pipeline that picks 3 random documents
+ *
+ * @see $sample https://docs.mongodb.org/manual/reference/operator/aggregation/sample/#pipe._S_sample
+ * @param {Number} size number of random documents to pick
+ * @return {Aggregate}
+ * @api public
+ */
+
+Aggregate.prototype.sample = function(size) {
+ return this.append({ $sample: { size: size } });
+};
+
+/**
+ * Appends a new $sort operator to this aggregate pipeline.
+ *
+ * If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`.
+ *
+ * If a string is passed, it must be a space delimited list of path names. The sort order of each path is ascending unless the path name is prefixed with `-` which will be treated as descending.
+ *
+ * ####Examples:
+ *
+ * // these are equivalent
+ * aggregate.sort({ field: 'asc', test: -1 });
+ * aggregate.sort('field -test');
+ *
+ * @see $sort http://docs.mongodb.org/manual/reference/aggregation/sort/
+ * @param {Object|String} arg
+ * @return {Aggregate} this
+ * @api public
+ */
+
+Aggregate.prototype.sort = function(arg) {
+ // TODO refactor to reuse the query builder logic
+
+ const sort = {};
+
+ if (arg.constructor.name === 'Object') {
+ const desc = ['desc', 'descending', -1];
+ Object.keys(arg).forEach(function(field) {
+ // If sorting by text score, skip coercing into 1/-1
+ if (arg[field] instanceof Object && arg[field].$meta) {
+ sort[field] = arg[field];
+ return;
+ }
+ sort[field] = desc.indexOf(arg[field]) === -1 ? 1 : -1;
+ });
+ } else if (arguments.length === 1 && typeof arg === 'string') {
+ arg.split(/\s+/).forEach(function(field) {
+ if (!field) {
+ return;
+ }
+ const ascend = field[0] === '-' ? -1 : 1;
+ if (ascend === -1) {
+ field = field.substring(1);
+ }
+ sort[field] = ascend;
+ });
+ } else {
+ throw new TypeError('Invalid sort() argument. Must be a string or object.');
+ }
+
+ return this.append({ $sort: sort });
+};
+
+/**
+ * Sets the readPreference option for the aggregation query.
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).read('primaryPreferred').exec(callback)
+ *
+ * @param {String} pref one of the listed preference options or their aliases
+ * @param {Array} [tags] optional tags for this query
+ * @return {Aggregate} this
+ * @api public
+ * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
+ * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
+ */
+
+Aggregate.prototype.read = function(pref, tags) {
+ if (!this.options) {
+ this.options = {};
+ }
+ read.call(this, pref, tags);
+ return this;
+};
+
+/**
+ * Sets the readConcern level for the aggregation query.
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).readConcern('majority').exec(callback)
+ *
+ * @param {String} level one of the listed read concern level or their aliases
+ * @see mongodb https://docs.mongodb.com/manual/reference/read-concern/
+ * @return {Aggregate} this
+ * @api public
+ */
+
+Aggregate.prototype.readConcern = function(level) {
+ if (!this.options) {
+ this.options = {};
+ }
+ readConcern.call(this, level);
+ return this;
+};
+
+/**
+ * Appends a new $redact operator to this aggregate pipeline.
+ *
+ * If 3 arguments are supplied, Mongoose will wrap them with if-then-else of $cond operator respectively
+ * If `thenExpr` or `elseExpr` is string, make sure it starts with $$, like `$$DESCEND`, `$$PRUNE` or `$$KEEP`.
+ *
+ * ####Example:
+ *
+ * Model.aggregate(...)
+ * .redact({
+ * $cond: {
+ * if: { $eq: [ '$level', 5 ] },
+ * then: '$$PRUNE',
+ * else: '$$DESCEND'
+ * }
+ * })
+ * .exec();
+ *
+ * // $redact often comes with $cond operator, you can also use the following syntax provided by mongoose
+ * Model.aggregate(...)
+ * .redact({ $eq: [ '$level', 5 ] }, '$$PRUNE', '$$DESCEND')
+ * .exec();
+ *
+ * @param {Object} expression redact options or conditional expression
+ * @param {String|Object} [thenExpr] true case for the condition
+ * @param {String|Object} [elseExpr] false case for the condition
+ * @return {Aggregate} this
+ * @see $redact https://docs.mongodb.com/manual/reference/operator/aggregation/redact/
+ * @api public
+ */
+
+Aggregate.prototype.redact = function(expression, thenExpr, elseExpr) {
+ if (arguments.length === 3) {
+ if ((typeof thenExpr === 'string' && !thenExpr.startsWith('$$')) ||
+ (typeof elseExpr === 'string' && !elseExpr.startsWith('$$'))) {
+ throw new Error('If thenExpr or elseExpr is string, it must start with $$. e.g. $$DESCEND, $$PRUNE, $$KEEP');
+ }
+
+ expression = {
+ $cond: {
+ if: expression,
+ then: thenExpr,
+ else: elseExpr
+ }
+ };
+ } else if (arguments.length !== 1) {
+ throw new TypeError('Invalid arguments');
+ }
+
+ return this.append({ $redact: expression });
+};
+
+/**
+ * Execute the aggregation with explain
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).explain(callback)
+ *
+ * @param {Function} callback
+ * @return {Promise}
+ */
+
+Aggregate.prototype.explain = function(callback) {
+ const model = this._model;
+
+ return promiseOrCallback(callback, cb => {
+ if (!this._pipeline.length) {
+ const err = new Error('Aggregate has empty pipeline');
+ return cb(err);
+ }
+
+ prepareDiscriminatorPipeline(this);
+
+ model.hooks.execPre('aggregate', this, error => {
+ if (error) {
+ const _opts = { error: error };
+ return model.hooks.execPost('aggregate', this, [null], _opts, error => {
+ cb(error);
+ });
+ }
+
+ this.options.explain = true;
+
+ model.collection.
+ aggregate(this._pipeline, this.options || {}).
+ explain((error, result) => {
+ const _opts = { error: error };
+ return model.hooks.execPost('aggregate', this, [result], _opts, error => {
+ if (error) {
+ return cb(error);
+ }
+ return cb(null, result);
+ });
+ });
+ });
+ }, model.events);
+};
+
+/**
+ * Sets the allowDiskUse option for the aggregation query (ignored for < 2.6.0)
+ *
+ * ####Example:
+ *
+ * await Model.aggregate([{ $match: { foo: 'bar' } }]).allowDiskUse(true);
+ *
+ * @param {Boolean} value Should tell server it can use hard drive to store data during aggregation.
+ * @param {Array} [tags] optional tags for this query
+ * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
+ */
+
+Aggregate.prototype.allowDiskUse = function(value) {
+ this.options.allowDiskUse = value;
+ return this;
+};
+
+/**
+ * Sets the hint option for the aggregation query (ignored for < 3.6.0)
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).hint({ qty: 1, category: 1 }).exec(callback)
+ *
+ * @param {Object|String} value a hint object or the index name
+ * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
+ */
+
+Aggregate.prototype.hint = function(value) {
+ this.options.hint = value;
+ return this;
+};
+
+/**
+ * Sets the session for this aggregation. Useful for [transactions](/docs/transactions.html).
+ *
+ * ####Example:
+ *
+ * const session = await Model.startSession();
+ * await Model.aggregate(..).session(session);
+ *
+ * @param {ClientSession} session
+ * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
+ */
+
+Aggregate.prototype.session = function(session) {
+ if (session == null) {
+ delete this.options.session;
+ } else {
+ this.options.session = session;
+ }
+ return this;
+};
+
+/**
+ * Lets you set arbitrary options, for middleware or plugins.
+ *
+ * ####Example:
+ *
+ * const agg = Model.aggregate(..).option({ allowDiskUse: true }); // Set the `allowDiskUse` option
+ * agg.options; // `{ allowDiskUse: true }`
+ *
+ * @param {Object} options keys to merge into current options
+ * @param [options.maxTimeMS] number limits the time this aggregation will run, see [MongoDB docs on `maxTimeMS`](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/)
+ * @param [options.allowDiskUse] boolean if true, the MongoDB server will use the hard drive to store data during this aggregation
+ * @param [options.collation] object see [`Aggregate.prototype.collation()`](./docs/api.html#aggregate_Aggregate-collation)
+ * @param [options.session] ClientSession see [`Aggregate.prototype.session()`](./docs/api.html#aggregate_Aggregate-session)
+ * @see mongodb http://docs.mongodb.org/manual/reference/command/aggregate/
+ * @return {Aggregate} this
+ * @api public
+ */
+
+Aggregate.prototype.option = function(value) {
+ for (const key in value) {
+ this.options[key] = value[key];
+ }
+ return this;
+};
+
+/**
+ * Sets the cursor option option for the aggregation query (ignored for < 2.6.0).
+ * Note the different syntax below: .exec() returns a cursor object, and no callback
+ * is necessary.
+ *
+ * ####Example:
+ *
+ * const cursor = Model.aggregate(..).cursor({ batchSize: 1000 }).exec();
+ * cursor.eachAsync(function(doc, i) {
+ * // use doc
+ * });
+ *
+ * @param {Object} options
+ * @param {Number} options.batchSize set the cursor batch size
+ * @param {Boolean} [options.useMongooseAggCursor] use experimental mongoose-specific aggregation cursor (for `eachAsync()` and other query cursor semantics)
+ * @return {Aggregate} this
+ * @api public
+ * @see mongodb http://mongodb.github.io/node-mongodb-native/2.0/api/AggregationCursor.html
+ */
+
+Aggregate.prototype.cursor = function(options) {
+ if (!this.options) {
+ this.options = {};
+ }
+ this.options.cursor = options || {};
+ return this;
+};
+
+/**
+ * Sets an option on this aggregation. This function will be deprecated in a
+ * future release. Use the [`cursor()`](./api.html#aggregate_Aggregate-cursor),
+ * [`collation()`](./api.html#aggregate_Aggregate-collation), etc. helpers to
+ * set individual options, or access `agg.options` directly.
+ *
+ * Note that MongoDB aggregations [do **not** support the `noCursorTimeout` flag](https://jira.mongodb.org/browse/SERVER-6036),
+ * if you try setting that flag with this function you will get a "unrecognized field 'noCursorTimeout'" error.
+ *
+ * @param {String} flag
+ * @param {Boolean} value
+ * @return {Aggregate} this
+ * @api public
+ * @deprecated Use [`.option()`](api.html#aggregate_Aggregate-option) instead. Note that MongoDB aggregations do **not** support a `noCursorTimeout` option.
+ */
+
+Aggregate.prototype.addCursorFlag = util.deprecate(function(flag, value) {
+ if (!this.options) {
+ this.options = {};
+ }
+ this.options[flag] = value;
+ return this;
+}, 'Mongoose: `Aggregate#addCursorFlag()` is deprecated, use `option()` instead');
+
+/**
+ * Adds a collation
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).collation({ locale: 'en_US', strength: 1 }).exec();
+ *
+ * @param {Object} collation options
+ * @return {Aggregate} this
+ * @api public
+ * @see mongodb http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#aggregate
+ */
+
+Aggregate.prototype.collation = function(collation) {
+ if (!this.options) {
+ this.options = {};
+ }
+ this.options.collation = collation;
+ return this;
+};
+
+/**
+ * Combines multiple aggregation pipelines.
+ *
+ * ####Example:
+ *
+ * Model.aggregate(...)
+ * .facet({
+ * books: [{ groupBy: '$author' }],
+ * price: [{ $bucketAuto: { groupBy: '$price', buckets: 2 } }]
+ * })
+ * .exec();
+ *
+ * // Output: { books: [...], price: [{...}, {...}] }
+ *
+ * @param {Object} facet options
+ * @return {Aggregate} this
+ * @see $facet https://docs.mongodb.com/v3.4/reference/operator/aggregation/facet/
+ * @api public
+ */
+
+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
+ *
+ * ####Example:
+ *
+ * MyModel.aggregate().match({ test: 1 }).pipeline(); // [{ $match: { test: 1 } }]
+ *
+ * @return {Array}
+ * @api public
+ */
+
+
+Aggregate.prototype.pipeline = function() {
+ return this._pipeline;
+};
+
+/**
+ * Executes the aggregate pipeline on the currently bound Model.
+ *
+ * ####Example:
+ *
+ * aggregate.exec(callback);
+ *
+ * // Because a promise is returned, the `callback` is optional.
+ * const promise = aggregate.exec();
+ * promise.then(..);
+ *
+ * @see Promise #promise_Promise
+ * @param {Function} [callback]
+ * @return {Promise}
+ * @api public
+ */
+
+Aggregate.prototype.exec = function(callback) {
+ if (!this._model) {
+ throw new Error('Aggregate not bound to any Model');
+ }
+ const model = this._model;
+ const collection = this._model.collection;
+
+ applyGlobalMaxTimeMS(this.options, model);
+
+ if (this.options && this.options.cursor) {
+ return new AggregationCursor(this);
+ }
+
+ return promiseOrCallback(callback, cb => {
+ prepareDiscriminatorPipeline(this);
+ stringifyAccumulatorOptions(this._pipeline);
+
+ model.hooks.execPre('aggregate', this, error => {
+ if (error) {
+ const _opts = { error: error };
+ return model.hooks.execPost('aggregate', this, [null], _opts, error => {
+ cb(error);
+ });
+ }
+ if (!this._pipeline.length) {
+ return cb(new Error('Aggregate has empty pipeline'));
+ }
+
+ const options = utils.clone(this.options || {});
+ collection.aggregate(this._pipeline, options, (error, cursor) => {
+ if (error) {
+ const _opts = { error: error };
+ return model.hooks.execPost('aggregate', this, [null], _opts, error => {
+ if (error) {
+ return cb(error);
+ }
+ return cb(null);
+ });
+ }
+ cursor.toArray((error, result) => {
+ const _opts = { error: error };
+ model.hooks.execPost('aggregate', this, [result], _opts, (error, result) => {
+ if (error) {
+ return cb(error);
+ }
+
+ cb(null, result);
+ });
+ });
+ });
+ });
+ }, model.events);
+};
+
+/**
+ * Provides promise for aggregate.
+ *
+ * ####Example:
+ *
+ * Model.aggregate(..).then(successCallback, errorCallback);
+ *
+ * @see Promise #promise_Promise
+ * @param {Function} [resolve] successCallback
+ * @param {Function} [reject] errorCallback
+ * @return {Promise}
+ */
+Aggregate.prototype.then = function(resolve, reject) {
+ return this.exec().then(resolve, reject);
+};
+
+/**
+ * Executes the query returning a `Promise` which will be
+ * resolved with either the doc(s) or rejected with the error.
+ * Like [`.then()`](#query_Query-then), but only takes a rejection handler.
+ *
+ * @param {Function} [reject]
+ * @return {Promise}
+ * @api public
+ */
+
+Aggregate.prototype.catch = function(reject) {
+ return this.exec().then(null, reject);
+};
+
+/**
+ * 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
+ *
+ * const agg = Model.aggregate([{ $match: { age: { $gte: 25 } } }]);
+ * for await (const doc of agg) {
+ * 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 Aggregate
+ * @instance
+ * @api public
+ */
+
+if (Symbol.asyncIterator != null) {
+ Aggregate.prototype[Symbol.asyncIterator] = function() {
+ return this.cursor({ useMongooseAggCursor: true }).
+ exec().
+ transformNull().
+ _transformForAsyncIterator();
+ };
+}
+
+/*!
+ * Helpers
+ */
+
+/**
+ * Checks whether an object is likely a pipeline operator
+ *
+ * @param {Object} obj object to check
+ * @return {Boolean}
+ * @api private
+ */
+
+function isOperator(obj) {
+ if (typeof obj !== 'object') {
+ return false;
+ }
+
+ const k = Object.keys(obj);
+
+ return k.length === 1 && k.some(key => { return key[0] === '$'; });
+}
+
+/*!
+ * Adds the appropriate `$match` pipeline step to the top of an aggregate's
+ * pipeline, should it's model is a non-root discriminator type. This is
+ * analogous to the `prepareDiscriminatorCriteria` function in `lib/query.js`.
+ *
+ * @param {Aggregate} aggregate Aggregate to prepare
+ */
+
+Aggregate._prepareDiscriminatorPipeline = prepareDiscriminatorPipeline;
+
+function prepareDiscriminatorPipeline(aggregate) {
+ const schema = aggregate._model.schema;
+ const discriminatorMapping = schema && schema.discriminatorMapping;
+
+ if (discriminatorMapping && !discriminatorMapping.isRoot) {
+ const originalPipeline = aggregate._pipeline;
+ const discriminatorKey = discriminatorMapping.key;
+ const discriminatorValue = discriminatorMapping.value;
+
+ // If the first pipeline stage is a match and it doesn't specify a `__t`
+ // key, add the discriminator key to it. This allows for potential
+ // aggregation query optimizations not to be disturbed by this feature.
+ if (originalPipeline[0] && originalPipeline[0].$match && !originalPipeline[0].$match[discriminatorKey]) {
+ originalPipeline[0].$match[discriminatorKey] = discriminatorValue;
+ // `originalPipeline` is a ref, so there's no need for
+ // aggregate._pipeline = originalPipeline
+ } else if (originalPipeline[0] && originalPipeline[0].$geoNear) {
+ 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;
+ aggregate._pipeline.unshift({ $match: match });
+ }
+ }
+}
+
+/*!
+ * Exports
+ */
+
+module.exports = Aggregate;
diff --git a/node_modules/mongoose/lib/browser.js b/node_modules/mongoose/lib/browser.js
new file mode 100644
index 0000000..f716f2a
--- /dev/null
+++ b/node_modules/mongoose/lib/browser.js
@@ -0,0 +1,155 @@
+/* eslint-env browser */
+
+'use strict';
+
+require('./driver').set(require('./drivers/browser'));
+
+const DocumentProvider = require('./document_provider.js');
+const PromiseProvider = require('./promise_provider');
+
+DocumentProvider.setBrowser(true);
+
+/**
+ * The Mongoose [Promise](#promise_Promise) constructor.
+ *
+ * @method Promise
+ * @api public
+ */
+
+Object.defineProperty(exports, 'Promise', {
+ get: function() {
+ return PromiseProvider.get();
+ },
+ set: function(lib) {
+ PromiseProvider.set(lib);
+ }
+});
+
+/**
+ * Storage layer for mongoose promises
+ *
+ * @method PromiseProvider
+ * @api public
+ */
+
+exports.PromiseProvider = PromiseProvider;
+
+/**
+ * The [MongooseError](#error_MongooseError) constructor.
+ *
+ * @method Error
+ * @api public
+ */
+
+exports.Error = require('./error/index');
+
+/**
+ * The Mongoose [Schema](#schema_Schema) constructor
+ *
+ * ####Example:
+ *
+ * const mongoose = require('mongoose');
+ * const Schema = mongoose.Schema;
+ * const CatSchema = new Schema(..);
+ *
+ * @method Schema
+ * @api public
+ */
+
+exports.Schema = require('./schema');
+
+/**
+ * The various Mongoose Types.
+ *
+ * ####Example:
+ *
+ * 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)
+ *
+ * Using this exposed access to the `ObjectId` type, we can construct ids on demand.
+ *
+ * const ObjectId = mongoose.Types.ObjectId;
+ * const id1 = new ObjectId;
+ *
+ * @property Types
+ * @api public
+ */
+exports.Types = require('./types');
+
+/**
+ * The Mongoose [VirtualType](#virtualtype_VirtualType) constructor
+ *
+ * @method VirtualType
+ * @api public
+ */
+exports.VirtualType = require('./virtualtype');
+
+/**
+ * The various Mongoose SchemaTypes.
+ *
+ * ####Note:
+ *
+ * _Alias of mongoose.Schema.Types for backwards compatibility._
+ *
+ * @property SchemaTypes
+ * @see Schema.SchemaTypes #schema_Schema.Types
+ * @api public
+ */
+
+exports.SchemaType = require('./schematype.js');
+
+/**
+ * Internal utils
+ *
+ * @property utils
+ * @api private
+ */
+
+exports.utils = require('./utils.js');
+
+/**
+ * The Mongoose browser [Document](/api/document.html) constructor.
+ *
+ * @method Document
+ * @api public
+ */
+exports.Document = DocumentProvider();
+
+/**
+ * Return a new browser model. In the browser, a model is just
+ * a simplified document with a schema - it does **not** have
+ * functions like `findOne()`, etc.
+ *
+ * @method model
+ * @api public
+ * @param {String} name
+ * @param {Schema} schema
+ * @return Class
+ */
+exports.model = function(name, schema) {
+ class Model extends exports.Document {
+ constructor(obj, fields) {
+ super(obj, schema, fields);
+ }
+ }
+ Model.modelName = name;
+
+ return Model;
+};
+
+/*!
+ * Module exports.
+ */
+
+if (typeof window !== 'undefined') {
+ window.mongoose = module.exports;
+ window.Buffer = Buffer;
+}
diff --git a/node_modules/mongoose/lib/browserDocument.js b/node_modules/mongoose/lib/browserDocument.js
new file mode 100644
index 0000000..a44f307
--- /dev/null
+++ b/node_modules/mongoose/lib/browserDocument.js
@@ -0,0 +1,100 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const NodeJSDocument = require('./document');
+const EventEmitter = require('events').EventEmitter;
+const MongooseError = require('./error/index');
+const Schema = require('./schema');
+const ObjectId = require('./types/objectid');
+const ValidationError = MongooseError.ValidationError;
+const applyHooks = require('./helpers/model/applyHooks');
+const isObject = require('./helpers/isObject');
+
+/**
+ * Document constructor.
+ *
+ * @param {Object} obj the values to set
+ * @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
+ * @param {Boolean} [skipId] bool, should we auto create an ObjectId _id
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `init`: Emitted on a document after it has was retrieved from the db and fully hydrated by Mongoose.
+ * @event `save`: Emitted when the document is successfully saved
+ * @api private
+ */
+
+function Document(obj, schema, fields, skipId, skipInit) {
+ if (!(this instanceof Document)) {
+ return new Document(obj, schema, fields, skipId, skipInit);
+ }
+
+ if (isObject(schema) && !schema.instanceOfSchema) {
+ schema = new Schema(schema);
+ }
+
+ // When creating EmbeddedDocument, it already has the schema and he doesn't need the _id
+ schema = this.schema || schema;
+
+ // Generate ObjectId if it is missing, but it requires a scheme
+ if (!this.schema && schema.options._id) {
+ obj = obj || {};
+
+ if (obj._id === undefined) {
+ obj._id = new ObjectId();
+ }
+ }
+
+ if (!schema) {
+ throw new MongooseError.MissingSchemaError();
+ }
+
+ this.$__setSchema(schema);
+
+ NodeJSDocument.call(this, obj, fields, skipId, skipInit);
+
+ applyHooks(this, schema, { decorateDoc: true });
+
+ // apply methods
+ for (const m in schema.methods) {
+ this[m] = schema.methods[m];
+ }
+ // apply statics
+ for (const s in schema.statics) {
+ this[s] = schema.statics[s];
+ }
+}
+
+/*!
+ * Inherit from the NodeJS document
+ */
+
+Document.prototype = Object.create(NodeJSDocument.prototype);
+Document.prototype.constructor = Document;
+
+/*!
+ * ignore
+ */
+
+Document.events = new EventEmitter();
+
+/*!
+ * Browser doc exposes the event emitter API
+ */
+
+Document.$emitter = new EventEmitter();
+
+['on', 'once', 'emit', 'listeners', 'removeListener', 'setMaxListeners',
+ 'removeAllListeners', 'addListener'].forEach(function(emitterFn) {
+ Document[emitterFn] = function() {
+ return Document.$emitter[emitterFn].apply(Document.$emitter, arguments);
+ };
+});
+
+/*!
+ * Module exports.
+ */
+
+Document.ValidationError = ValidationError;
+module.exports = exports = Document;
diff --git a/node_modules/mongoose/lib/cast.js b/node_modules/mongoose/lib/cast.js
new file mode 100644
index 0000000..1c24bc7
--- /dev/null
+++ b/node_modules/mongoose/lib/cast.js
@@ -0,0 +1,364 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CastError = require('./error/cast');
+const StrictModeError = require('./error/strict');
+const Types = require('./schema/index');
+const castTextSearch = require('./schema/operators/text');
+const get = require('./helpers/get');
+const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
+const isOperator = require('./helpers/query/isOperator');
+const util = require('util');
+const isObject = require('./helpers/isObject');
+const isMongooseObject = require('./helpers/isMongooseObject');
+
+const ALLOWED_GEOWITHIN_GEOJSON_TYPES = ['Polygon', 'MultiPolygon'];
+
+/**
+ * Handles internal casting for query filters.
+ *
+ * @param {Schema} schema
+ * @param {Object} obj Object to cast
+ * @param {Object} options the query options
+ * @param {Query} context passed to setters
+ * @api private
+ */
+module.exports = function cast(schema, obj, options, context) {
+ if (Array.isArray(obj)) {
+ throw new Error('Query filter must be an object, got an array ', util.inspect(obj));
+ }
+
+ if (obj == null) {
+ return obj;
+ }
+
+ // bson 1.x has the unfortunate tendency to remove filters that have a top-level
+ // `_bsontype` property. But we should still allow ObjectIds because
+ // `Collection#find()` has a special case to support `find(objectid)`.
+ // Should remove this when we upgrade to bson 4.x. See gh-8222, gh-8268
+ if (obj.hasOwnProperty('_bsontype') && obj._bsontype !== 'ObjectID') {
+ 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;
+ let any$conditionals;
+ let schematype;
+ let nested;
+ let path;
+ let type;
+ let val;
+
+ options = options || {};
+
+ while (i--) {
+ path = paths[i];
+ val = obj[path];
+
+ if (path === '$or' || path === '$nor' || path === '$and') {
+ if (!Array.isArray(val)) {
+ throw new CastError('Array', val, path);
+ }
+ for (let k = 0; k < val.length; ++k) {
+ if (val[k] == null || typeof val[k] !== 'object') {
+ throw new CastError('Object', val[k], path + '.' + k);
+ }
+ val[k] = cast(schema, val[k], options, context);
+ }
+ } else if (path === '$where') {
+ type = typeof val;
+
+ if (type !== 'string' && type !== 'function') {
+ throw new Error('Must have a string or function for $where');
+ }
+
+ if (type === 'function') {
+ obj[path] = val.toString();
+ }
+
+ continue;
+ } else if (path === '$elemMatch') {
+ val = cast(schema, val, options, context);
+ } else if (path === '$text') {
+ val = castTextSearch(val, path);
+ } else {
+ if (!schema) {
+ // no casting for Mixed types
+ continue;
+ }
+
+ schematype = schema.path(path);
+
+ // Check for embedded discriminator paths
+ if (!schematype) {
+ const split = path.split('.');
+ let j = split.length;
+ while (j--) {
+ const pathFirstHalf = split.slice(0, j).join('.');
+ const pathLastHalf = split.slice(j).join('.');
+ const _schematype = schema.path(pathFirstHalf);
+ const discriminatorKey = get(_schematype, 'schema.options.discriminatorKey');
+
+ // gh-6027: if we haven't found the schematype but this path is
+ // underneath an embedded discriminator and the embedded discriminator
+ // key is in the query, use the embedded discriminator schema
+ if (_schematype != null &&
+ get(_schematype, 'schema.discriminators') != null &&
+ discriminatorKey != null &&
+ pathLastHalf !== discriminatorKey) {
+ const discriminatorVal = get(obj, pathFirstHalf + '.' + discriminatorKey);
+ if (discriminatorVal != null) {
+ schematype = _schematype.schema.discriminators[discriminatorVal].
+ path(pathLastHalf);
+ }
+ }
+ }
+ }
+
+ if (!schematype) {
+ // Handle potential embedded array queries
+ const split = path.split('.');
+ let j = split.length;
+ let pathFirstHalf;
+ let pathLastHalf;
+ let remainingConds;
+
+ // Find the part of the var path that is a path of the Schema
+ while (j--) {
+ pathFirstHalf = split.slice(0, j).join('.');
+ schematype = schema.path(pathFirstHalf);
+ if (schematype) {
+ break;
+ }
+ }
+
+ // If a substring of the input path resolves to an actual real path...
+ if (schematype) {
+ // Apply the casting; similar code for $elemMatch in schema/array.js
+ if (schematype.caster && schematype.caster.schema) {
+ remainingConds = {};
+ pathLastHalf = split.slice(j).join('.');
+ remainingConds[pathLastHalf] = val;
+ obj[path] = cast(schematype.caster.schema, remainingConds, options, context)[pathLastHalf];
+ } else {
+ obj[path] = val;
+ }
+ continue;
+ }
+
+ if (isObject(val)) {
+ // handle geo schemas that use object notation
+ // { loc: { long: Number, lat: Number }
+
+ let geo = '';
+ if (val.$near) {
+ geo = '$near';
+ } else if (val.$nearSphere) {
+ geo = '$nearSphere';
+ } else if (val.$within) {
+ geo = '$within';
+ } else if (val.$geoIntersects) {
+ geo = '$geoIntersects';
+ } else if (val.$geoWithin) {
+ geo = '$geoWithin';
+ }
+
+ if (geo) {
+ const numbertype = new Types.Number('__QueryCasting__');
+ let value = val[geo];
+
+ if (val.$maxDistance != null) {
+ val.$maxDistance = numbertype.castForQueryWrapper({
+ val: val.$maxDistance,
+ context: context
+ });
+ }
+ if (val.$minDistance != null) {
+ val.$minDistance = numbertype.castForQueryWrapper({
+ val: val.$minDistance,
+ context: context
+ });
+ }
+
+ if (geo === '$within') {
+ const withinType = value.$center
+ || value.$centerSphere
+ || value.$box
+ || value.$polygon;
+
+ if (!withinType) {
+ throw new Error('Bad $within parameter: ' + JSON.stringify(val));
+ }
+
+ value = withinType;
+ } else if (geo === '$near' &&
+ typeof value.type === 'string' && Array.isArray(value.coordinates)) {
+ // geojson; cast the coordinates
+ value = value.coordinates;
+ } else if ((geo === '$near' || geo === '$nearSphere' || geo === '$geoIntersects') &&
+ value.$geometry && typeof value.$geometry.type === 'string' &&
+ Array.isArray(value.$geometry.coordinates)) {
+ if (value.$maxDistance != null) {
+ value.$maxDistance = numbertype.castForQueryWrapper({
+ val: value.$maxDistance,
+ context: context
+ });
+ }
+ if (value.$minDistance != null) {
+ value.$minDistance = numbertype.castForQueryWrapper({
+ val: value.$minDistance,
+ context: context
+ });
+ }
+ if (isMongooseObject(value.$geometry)) {
+ value.$geometry = value.$geometry.toObject({
+ transform: false,
+ virtuals: false
+ });
+ }
+ value = value.$geometry.coordinates;
+ } else if (geo === '$geoWithin') {
+ if (value.$geometry) {
+ if (isMongooseObject(value.$geometry)) {
+ value.$geometry = value.$geometry.toObject({ virtuals: false });
+ }
+ const geoWithinType = value.$geometry.type;
+ if (ALLOWED_GEOWITHIN_GEOJSON_TYPES.indexOf(geoWithinType) === -1) {
+ throw new Error('Invalid geoJSON type for $geoWithin "' +
+ geoWithinType + '", must be "Polygon" or "MultiPolygon"');
+ }
+ value = value.$geometry.coordinates;
+ } else {
+ value = value.$box || value.$polygon || value.$center ||
+ value.$centerSphere;
+ if (isMongooseObject(value)) {
+ value = value.toObject({ virtuals: false });
+ }
+ }
+ }
+
+ _cast(value, numbertype, context);
+ continue;
+ }
+ }
+
+ if (schema.nested[path]) {
+ continue;
+ }
+ if (options.upsert && options.strict) {
+ if (options.strict === 'throw') {
+ throw new StrictModeError(path);
+ }
+ throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
+ 'schema, strict mode is `true`, and upsert is `true`.');
+ } else if (options.strictQuery === 'throw') {
+ throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
+ 'schema and strictQuery is \'throw\'.');
+ } else if (options.strictQuery) {
+ delete obj[path];
+ }
+ } else if (val == null) {
+ continue;
+ } else if (val.constructor.name === 'Object') {
+ any$conditionals = Object.keys(val).some(isOperator);
+
+ if (!any$conditionals) {
+ obj[path] = schematype.castForQueryWrapper({
+ val: val,
+ context: context
+ });
+ } else {
+ const ks = Object.keys(val);
+ let $cond;
+
+ let k = ks.length;
+
+ while (k--) {
+ $cond = ks[k];
+ nested = val[$cond];
+
+ if ($cond === '$not') {
+ if (nested && schematype && !schematype.caster) {
+ _keys = Object.keys(nested);
+ if (_keys.length && isOperator(_keys[0])) {
+ for (const key in nested) {
+ nested[key] = schematype.castForQueryWrapper({
+ $conditional: key,
+ val: nested[key],
+ context: context
+ });
+ }
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: context
+ });
+ }
+ continue;
+ }
+ cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: context
+ });
+ }
+ }
+ }
+ } else if (Array.isArray(val) && ['Buffer', 'Array'].indexOf(schematype.instance) === -1) {
+ const casted = [];
+ const valuesArray = val;
+
+ for (const _val of valuesArray) {
+ casted.push(schematype.castForQueryWrapper({
+ val: _val,
+ context: context
+ }));
+ }
+
+ obj[path] = { $in: casted };
+ } else {
+ obj[path] = schematype.castForQueryWrapper({
+ val: val,
+ context: context
+ });
+ }
+ }
+ }
+
+ return obj;
+};
+
+function _cast(val, numbertype, context) {
+ if (Array.isArray(val)) {
+ val.forEach(function(item, i) {
+ if (Array.isArray(item) || isObject(item)) {
+ return _cast(item, numbertype, context);
+ }
+ val[i] = numbertype.castForQueryWrapper({ val: item, context: context });
+ });
+ } else {
+ const nearKeys = Object.keys(val);
+ let nearLen = nearKeys.length;
+ while (nearLen--) {
+ const nkey = nearKeys[nearLen];
+ const item = val[nkey];
+ if (Array.isArray(item) || isObject(item)) {
+ _cast(item, numbertype, context);
+ val[nkey] = item;
+ } else {
+ val[nkey] = numbertype.castForQuery({ val: item, context: context });
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/cast/boolean.js b/node_modules/mongoose/lib/cast/boolean.js
new file mode 100644
index 0000000..92551d4
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/boolean.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const CastError = require('../error/cast');
+
+/*!
+ * Given a value, cast it to a boolean, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {Boolean|null|undefined}
+ * @throws {CastError} if `value` is not one of the allowed values
+ * @api private
+ */
+
+module.exports = function castBoolean(value, path) {
+ 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);
+};
+
+module.exports.convertToTrue = new Set([true, 'true', 1, '1', 'yes']);
+module.exports.convertToFalse = new Set([false, 'false', 0, '0', 'no']);
diff --git a/node_modules/mongoose/lib/cast/date.js b/node_modules/mongoose/lib/cast/date.js
new file mode 100644
index 0000000..ac17006
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/date.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const assert = require('assert');
+
+module.exports = function castDate(value) {
+ // Support empty string because of empty form values. Originally introduced
+ // in https://github.com/Automattic/mongoose/commit/efc72a1898fc3c33a319d915b8c5463a22938dfe
+ if (value == null || value === '') {
+ return null;
+ }
+
+ if (value instanceof Date) {
+ assert.ok(!isNaN(value.valueOf()));
+
+ return value;
+ }
+
+ let date;
+
+ assert.ok(typeof value !== 'boolean');
+
+ if (value instanceof Number || typeof value === 'number') {
+ date = new Date(value);
+ } else if (typeof value === 'string' && !isNaN(Number(value)) && (Number(value) >= 275761 || Number(value) < -271820)) {
+ // string representation of milliseconds take this path
+ date = new Date(Number(value));
+ } else if (typeof value.valueOf === 'function') {
+ // support for moment.js. This is also the path strings will take because
+ // strings have a `valueOf()`
+ date = new Date(value.valueOf());
+ } else {
+ // fallback
+ date = new Date(value);
+ }
+
+ if (!isNaN(date.valueOf())) {
+ return date;
+ }
+
+ assert.ok(false);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/cast/decimal128.js b/node_modules/mongoose/lib/cast/decimal128.js
new file mode 100644
index 0000000..bfb1578
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/decimal128.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const Decimal128Type = require('../types/decimal128');
+const assert = require('assert');
+
+module.exports = function castDecimal128(value) {
+ if (value == null) {
+ return value;
+ }
+
+ if (typeof value === 'object' && typeof value.$numberDecimal === 'string') {
+ return Decimal128Type.fromString(value.$numberDecimal);
+ }
+
+ if (value instanceof Decimal128Type) {
+ return value;
+ }
+
+ if (typeof value === 'string') {
+ return Decimal128Type.fromString(value);
+ }
+
+ if (Buffer.isBuffer(value)) {
+ return new Decimal128Type(value);
+ }
+
+ if (typeof value === 'number') {
+ return Decimal128Type.fromString(String(value));
+ }
+
+ if (typeof value.valueOf === 'function' && typeof value.valueOf() === 'string') {
+ return Decimal128Type.fromString(value.valueOf());
+ }
+
+ assert.ok(false);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/cast/number.js b/node_modules/mongoose/lib/cast/number.js
new file mode 100644
index 0000000..7cd7f84
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/number.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const assert = require('assert');
+
+/*!
+ * Given a value, cast it to a number, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {Boolean|null|undefined}
+ * @throws {Error} if `value` is not one of the allowed values
+ * @api private
+ */
+
+module.exports = function castNumber(val) {
+ if (val == null) {
+ return val;
+ }
+ if (val === '') {
+ return null;
+ }
+
+ if (typeof val === 'string' || typeof val === 'boolean') {
+ val = Number(val);
+ }
+
+ assert.ok(!isNaN(val));
+ if (val instanceof Number) {
+ return val.valueOf();
+ }
+ if (typeof val === 'number') {
+ return val;
+ }
+ if (!Array.isArray(val) && typeof val.valueOf === 'function') {
+ return Number(val.valueOf());
+ }
+ if (val.toString && !Array.isArray(val) && val.toString() == Number(val)) {
+ return Number(val);
+ }
+
+ assert.ok(false);
+};
diff --git a/node_modules/mongoose/lib/cast/objectid.js b/node_modules/mongoose/lib/cast/objectid.js
new file mode 100644
index 0000000..67cffb5
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/objectid.js
@@ -0,0 +1,29 @@
+'use strict';
+
+const ObjectId = require('../driver').get().ObjectId;
+const assert = require('assert');
+
+module.exports = function castObjectId(value) {
+ if (value == null) {
+ return value;
+ }
+
+ if (value instanceof ObjectId) {
+ return value;
+ }
+
+ if (value._id) {
+ if (value._id instanceof ObjectId) {
+ return value._id;
+ }
+ if (value._id.toString instanceof Function) {
+ return new ObjectId(value._id.toString());
+ }
+ }
+
+ if (value.toString instanceof Function) {
+ return new ObjectId(value.toString());
+ }
+
+ assert.ok(false);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/cast/string.js b/node_modules/mongoose/lib/cast/string.js
new file mode 100644
index 0000000..4d89f8e
--- /dev/null
+++ b/node_modules/mongoose/lib/cast/string.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const CastError = require('../error/cast');
+
+/*!
+ * Given a value, cast it to a string, or throw a `CastError` if the value
+ * cannot be casted. `null` and `undefined` are considered valid.
+ *
+ * @param {Any} value
+ * @param {String} [path] optional the path to set on the CastError
+ * @return {string|null|undefined}
+ * @throws {CastError}
+ * @api private
+ */
+
+module.exports = function castString(value, path) {
+ // If null or undefined
+ if (value == null) {
+ return value;
+ }
+
+ // handle documents being passed
+ if (value._id && typeof value._id === 'string') {
+ return value._id;
+ }
+
+ // Re: gh-647 and gh-3030, we're ok with casting using `toString()`
+ // **unless** its the default Object.toString, because "[object Object]"
+ // doesn't really qualify as useful data
+ if (value.toString &&
+ value.toString !== Object.prototype.toString &&
+ !Array.isArray(value)) {
+ return value.toString();
+ }
+
+ throw new CastError('string', value, path);
+};
diff --git a/node_modules/mongoose/lib/collection.js b/node_modules/mongoose/lib/collection.js
new file mode 100644
index 0000000..1f60a63
--- /dev/null
+++ b/node_modules/mongoose/lib/collection.js
@@ -0,0 +1,282 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const EventEmitter = require('events').EventEmitter;
+const STATES = require('./connectionstate');
+const immediate = require('./helpers/immediate');
+
+/**
+ * Abstract Collection constructor
+ *
+ * This is the base class that drivers inherit from and implement.
+ *
+ * @param {String} name name of the collection
+ * @param {Connection} conn A MongooseConnection instance
+ * @param {Object} opts optional collection options
+ * @api public
+ */
+
+function Collection(name, conn, opts) {
+ if (opts === void 0) {
+ opts = {};
+ }
+ if (opts.capped === void 0) {
+ opts.capped = {};
+ }
+
+ if (typeof opts.capped === 'number') {
+ opts.capped = { size: opts.capped };
+ }
+
+ this.opts = opts;
+ this.name = name;
+ this.collectionName = name;
+ this.conn = conn;
+ this.queue = [];
+ this.buffer = true;
+ this.emitter = new EventEmitter();
+
+ if (STATES.connected === this.conn.readyState) {
+ this.onOpen();
+ }
+}
+
+/**
+ * The collection name
+ *
+ * @api public
+ * @property name
+ */
+
+Collection.prototype.name;
+
+/**
+ * The collection name
+ *
+ * @api public
+ * @property collectionName
+ */
+
+Collection.prototype.collectionName;
+
+/**
+ * The Connection instance
+ *
+ * @api public
+ * @property conn
+ */
+
+Collection.prototype.conn;
+
+/**
+ * Called when the database connects
+ *
+ * @api private
+ */
+
+Collection.prototype.onOpen = function() {
+ this.buffer = false;
+ immediate(() => this.doQueue());
+};
+
+/**
+ * Called when the database disconnects
+ *
+ * @api private
+ */
+
+Collection.prototype.onClose = function(force) {
+ if (this._shouldBufferCommands() && !force) {
+ this.buffer = true;
+ }
+};
+
+/**
+ * Queues a method for later execution when its
+ * database connection opens.
+ *
+ * @param {String} name name of the method to queue
+ * @param {Array} args arguments to pass to the method when executed
+ * @api private
+ */
+
+Collection.prototype.addQueue = function(name, args) {
+ this.queue.push([name, args]);
+ return this;
+};
+
+/**
+ * Executes all queued methods and clears the queue.
+ *
+ * @api private
+ */
+
+Collection.prototype.doQueue = function() {
+ for (const method of this.queue) {
+ if (typeof method[0] === 'function') {
+ method[0].apply(this, method[1]);
+ } else {
+ this[method[0]].apply(this, method[1]);
+ }
+ }
+ this.queue = [];
+ const _this = this;
+ process.nextTick(function() {
+ _this.emitter.emit('queue');
+ });
+ return this;
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.ensureIndex = function() {
+ throw new Error('Collection#ensureIndex unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.createIndex = function() {
+ throw new Error('Collection#createIndex unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findAndModify = function() {
+ throw new Error('Collection#findAndModify unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findOneAndUpdate = function() {
+ throw new Error('Collection#findOneAndUpdate unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findOneAndDelete = function() {
+ throw new Error('Collection#findOneAndDelete unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findOneAndReplace = function() {
+ throw new Error('Collection#findOneAndReplace unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.findOne = function() {
+ throw new Error('Collection#findOne unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.find = function() {
+ throw new Error('Collection#find unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.insert = function() {
+ throw new Error('Collection#insert unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.insertOne = function() {
+ throw new Error('Collection#insertOne unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.insertMany = function() {
+ throw new Error('Collection#insertMany unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.save = function() {
+ throw new Error('Collection#save unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.update = function() {
+ throw new Error('Collection#update unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.getIndexes = function() {
+ throw new Error('Collection#getIndexes unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+Collection.prototype.mapReduce = function() {
+ throw new Error('Collection#mapReduce unimplemented by driver');
+};
+
+/**
+ * Abstract method that drivers must implement.
+ */
+
+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();
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Collection;
diff --git a/node_modules/mongoose/lib/connection.js b/node_modules/mongoose/lib/connection.js
new file mode 100644
index 0000000..2d2e7fd
--- /dev/null
+++ b/node_modules/mongoose/lib/connection.js
@@ -0,0 +1,1459 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const ChangeStream = require('./cursor/ChangeStream');
+const EventEmitter = require('events').EventEmitter;
+const Schema = require('./schema');
+const Collection = require('./driver').get().Collection;
+const STATES = require('./connectionstate');
+const MongooseError = require('./error/index');
+const PromiseProvider = require('./promise_provider');
+const ServerSelectionError = require('./error/serverSelection');
+const applyPlugins = require('./helpers/schema/applyPlugins');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const get = require('./helpers/get');
+const immediate = require('./helpers/immediate');
+const mongodb = require('mongodb');
+const pkg = require('../package.json');
+const utils = require('./utils');
+
+const parseConnectionString = require('mongodb/lib/core').parseConnectionString;
+
+const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
+const sessionNewDocuments = require('./helpers/symbols').sessionNewDocuments;
+
+let id = 0;
+
+/*!
+ * A list of authentication mechanisms that don't require a password for authentication.
+ * This is used by the authMechanismDoesNotRequirePassword method.
+ *
+ * @api private
+ */
+const noPasswordAuthMechanisms = [
+ 'MONGODB-X509'
+];
+
+/**
+ * Connection constructor
+ *
+ * For practical reasons, a Connection equals a Db.
+ *
+ * @param {Mongoose} base a mongoose instance
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `connecting`: Emitted when `connection.openUri()` is executed on this connection.
+ * @event `connected`: Emitted when this connection successfully connects to the db. May be emitted _multiple_ times in `reconnected` scenarios.
+ * @event `open`: Emitted after we `connected` and `onOpen` is executed on all of this connections models.
+ * @event `disconnecting`: Emitted when `connection.close()` was executed.
+ * @event `disconnected`: Emitted after getting disconnected from the db.
+ * @event `close`: Emitted after we `disconnected` and `onClose` executed on all of this connections models.
+ * @event `reconnected`: Emitted after we `connected` and subsequently `disconnected`, followed by successfully another successful connection.
+ * @event `error`: Emitted when an error occurs on this connection.
+ * @event `fullsetup`: Emitted after the driver has connected to primary and all secondaries if specified in the connection string.
+ * @api public
+ */
+
+function Connection(base) {
+ this.base = base;
+ this.collections = {};
+ this.models = {};
+ this.config = { autoIndex: true };
+ this.replica = false;
+ this.options = null;
+ this.otherDbs = []; // FIXME: To be replaced with relatedDbs
+ this.relatedDbs = {}; // Hashmap of other dbs that share underlying connection
+ this.states = STATES;
+ this._readyState = STATES.disconnected;
+ this._closeCalled = false;
+ this._hasOpened = false;
+ this.plugins = [];
+ this.id = id++;
+}
+
+/*!
+ * Inherit from EventEmitter
+ */
+
+Connection.prototype.__proto__ = EventEmitter.prototype;
+
+/**
+ * Connection ready state
+ *
+ * - 0 = disconnected
+ * - 1 = connected
+ * - 2 = connecting
+ * - 3 = disconnecting
+ *
+ * Each state change emits its associated event name.
+ *
+ * ####Example
+ *
+ * conn.on('connected', callback);
+ * conn.on('disconnected', callback);
+ *
+ * @property readyState
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'readyState', {
+ get: function() {
+ return this._readyState;
+ },
+ set: function(val) {
+ if (!(val in STATES)) {
+ throw new Error('Invalid connection state: ' + val);
+ }
+
+ if (this._readyState !== val) {
+ this._readyState = val;
+ // [legacy] loop over the otherDbs on this connection and change their state
+ for (const db of this.otherDbs) {
+ 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;
+ }
+
+ this.emit(STATES[val]);
+ }
+ }
+});
+
+/**
+ * Gets the value of the option `key`. Equivalent to `conn.options[key]`
+ *
+ * ####Example:
+ *
+ * conn.get('test'); // returns the 'test' value
+ *
+ * @param {String} key
+ * @method get
+ * @api public
+ */
+
+Connection.prototype.get = function(key) {
+ return get(this.options, key);
+};
+
+/**
+ * Sets the value of the option `key`. Equivalent to `conn.options[key] = val`
+ *
+ * Supported options include:
+ *
+ * - `maxTimeMS`: Set [`maxTimeMS`](/docs/api.html#query_Query-maxTimeMS) for all queries on this connection.
+ * - `useFindAndModify`: Set to `false` to work around the [`findAndModify()` deprecation warning](/docs/deprecations.html#findandmodify)
+ *
+ * ####Example:
+ *
+ * conn.set('test', 'foo');
+ * conn.get('test'); // 'foo'
+ * conn.options.test; // 'foo'
+ *
+ * @param {String} key
+ * @param {Any} val
+ * @method set
+ * @api public
+ */
+
+Connection.prototype.set = function(key, val) {
+ this.options = this.options || {};
+ this.options[key] = val;
+ return val;
+};
+
+/**
+ * A hash of the collections associated with this connection
+ *
+ * @property collections
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.collections;
+
+/**
+ * The name of the database this connection points to.
+ *
+ * ####Example
+ *
+ * mongoose.createConnection('mongodb://localhost:27017/mydb').name; // "mydb"
+ *
+ * @property name
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.name;
+
+/**
+ * A [POJO](https://masteringjs.io/tutorials/fundamentals/pojo) containing
+ * a map from model names to models. Contains all models that have been
+ * added to this connection using [`Connection#model()`](/docs/api/connection.html#connection_Connection-model).
+ *
+ * ####Example
+ *
+ * const conn = mongoose.createConnection();
+ * const Test = conn.model('Test', mongoose.Schema({ name: String }));
+ *
+ * Object.keys(conn.models).length; // 1
+ * conn.models.Test === Test; // true
+ *
+ * @property models
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.models;
+
+/**
+ * A number identifier for this connection. Used for debugging when
+ * you have [multiple connections](/docs/connections.html#multiple_connections).
+ *
+ * ####Example
+ *
+ * // The default connection has `id = 0`
+ * mongoose.connection.id; // 0
+ *
+ * // If you create a new connection, Mongoose increments id
+ * const conn = mongoose.createConnection();
+ * conn.id; // 1
+ *
+ * @property id
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.id;
+
+/**
+ * The plugins that will be applied to all models created on this connection.
+ *
+ * ####Example:
+ *
+ * const db = mongoose.createConnection('mongodb://localhost:27017/mydb');
+ * db.plugin(() => console.log('Applied'));
+ * db.plugins.length; // 1
+ *
+ * db.model('Test', new Schema({})); // Prints "Applied"
+ *
+ * @property plugins
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'plugins', {
+ configurable: false,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The host name portion of the URI. If multiple hosts, such as a replica set,
+ * this will contain the first host name in the URI
+ *
+ * ####Example
+ *
+ * mongoose.createConnection('mongodb://localhost:27017/mydb').host; // "localhost"
+ *
+ * @property host
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'host', {
+ configurable: true,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The port portion of the URI. If multiple hosts, such as a replica set,
+ * this will contain the port from the first host name in the URI.
+ *
+ * ####Example
+ *
+ * mongoose.createConnection('mongodb://localhost:27017/mydb').port; // 27017
+ *
+ * @property port
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'port', {
+ configurable: true,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The username specified in the URI
+ *
+ * ####Example
+ *
+ * mongoose.createConnection('mongodb://val:psw@localhost:27017/mydb').user; // "val"
+ *
+ * @property user
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'user', {
+ configurable: true,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The password specified in the URI
+ *
+ * ####Example
+ *
+ * mongoose.createConnection('mongodb://val:psw@localhost:27017/mydb').pass; // "psw"
+ *
+ * @property pass
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Object.defineProperty(Connection.prototype, 'pass', {
+ configurable: true,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The mongodb.Db instance, set when the connection is opened
+ *
+ * @property db
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.db;
+
+/**
+ * A hash of the global options that are associated with this connection
+ *
+ * @property config
+ * @memberOf Connection
+ * @instance
+ * @api public
+ */
+
+Connection.prototype.config;
+
+/**
+ * Helper for `createCollection()`. Will explicitly create the given collection
+ * with specified options. Used to create [capped collections](https://docs.mongodb.com/manual/core/capped-collections/)
+ * and [views](https://docs.mongodb.com/manual/core/views/) from mongoose.
+ *
+ * Options are passed down without modification to the [MongoDB driver's `createCollection()` function](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#createCollection)
+ *
+ * @method createCollection
+ * @param {string} collection The collection to create
+ * @param {Object} [options] see [MongoDB driver docs](http://mongodb.github.io/node-mongodb-native/2.2/api/Db.html#createCollection)
+ * @param {Function} [callback]
+ * @return {Promise}
+ * @api public
+ */
+
+Connection.prototype.createCollection = _wrapConnHelper(function createCollection(collection, options, cb) {
+ if (typeof options === 'function') {
+ cb = options;
+ options = {};
+ }
+ this.db.createCollection(collection, options, cb);
+});
+
+/**
+ * _Requires MongoDB >= 3.6.0._ Starts a [MongoDB session](https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions)
+ * for benefits like causal consistency, [retryable writes](https://docs.mongodb.com/manual/core/retryable-writes/),
+ * and [transactions](http://thecodebarbarian.com/a-node-js-perspective-on-mongodb-4-transactions.html).
+ *
+ * ####Example:
+ *
+ * const session = await conn.startSession();
+ * let doc = await Person.findOne({ name: 'Ned Stark' }, null, { session });
+ * await doc.remove();
+ * // `doc` will always be null, even if reading from a replica set
+ * // secondary. Without causal consistency, it is possible to
+ * // get a doc back from the below query if the query reads from a
+ * // secondary that is experiencing replication lag.
+ * doc = await Person.findOne({ name: 'Ned Stark' }, null, { session, readPreference: 'secondary' });
+ *
+ *
+ * @method startSession
+ * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html#startSession)
+ * @param {Boolean} [options.causalConsistency=true] set to false to disable causal consistency
+ * @param {Function} [callback]
+ * @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
+ * @api public
+ */
+
+Connection.prototype.startSession = _wrapConnHelper(function startSession(options, cb) {
+ if (typeof options === 'function') {
+ cb = options;
+ options = null;
+ }
+ const session = this.client.startSession(options);
+ 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!');
+ * }).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
+ * @return {Promise<Any>} promise that resolves to the returned value of `fn`
+ * @api public
+ */
+
+Connection.prototype.transaction = function transaction(fn) {
+ return this.startSession().then(session => {
+ session[sessionNewDocuments] = new Map();
+ return session.withTransaction(() => fn(session)).
+ 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.
+ *
+ * @method dropCollection
+ * @param {string} collection The collection to delete
+ * @param {Function} [callback]
+ * @return {Promise}
+ * @api public
+ */
+
+Connection.prototype.dropCollection = _wrapConnHelper(function dropCollection(collection, cb) {
+ this.db.dropCollection(collection, cb);
+});
+
+/**
+ * Helper for `dropDatabase()`. Deletes the given database, including all
+ * collections, documents, and indexes.
+ *
+ * ####Example:
+ *
+ * const conn = mongoose.createConnection('mongodb://localhost:27017/mydb');
+ * // Deletes the entire 'mydb' database
+ * await conn.dropDatabase();
+ *
+ * @method dropDatabase
+ * @param {Function} [callback]
+ * @return {Promise}
+ * @api public
+ */
+
+Connection.prototype.dropDatabase = _wrapConnHelper(function dropDatabase(cb) {
+ // If `dropDatabase()` is called, this model's collection will not be
+ // init-ed. It is sufficiently common to call `dropDatabase()` after
+ // `mongoose.connect()` but before creating models that we want to
+ // support this. See gh-6967
+ for (const name of Object.keys(this.models)) {
+ delete this.models[name].$init;
+ }
+ this.db.dropDatabase(cb);
+});
+
+/*!
+ * ignore
+ */
+
+function _wrapConnHelper(fn) {
+ return function() {
+ const cb = arguments.length > 0 ? arguments[arguments.length - 1] : null;
+ const argsWithoutCb = typeof cb === 'function' ?
+ Array.prototype.slice.call(arguments, 0, arguments.length - 1) :
+ Array.prototype.slice.call(arguments);
+ const disconnectedError = new MongooseError('Connection ' + this.id +
+ ' was disconnected when calling `' + fn.name + '`');
+ return promiseOrCallback(cb, cb => {
+ // Make it ok to call collection helpers before `mongoose.connect()`
+ // as long as `mongoose.connect()` is called on the same tick.
+ // Re: gh-8534
+ immediate(() => {
+ if (this.readyState === STATES.connecting && this._shouldBufferCommands()) {
+ this.once('open', function() {
+ fn.apply(this, argsWithoutCb.concat([cb]));
+ });
+ } else if (this.readyState === STATES.disconnected && this.db == null) {
+ cb(disconnectedError);
+ } else {
+ 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 != null && this.base.get('bufferCommands') != null) {
+ return this.base.get('bufferCommands');
+ }
+ return true;
+};
+
+/**
+ * error
+ *
+ * Graceful error handling, passes error to callback
+ * if available, else emits error on the connection.
+ *
+ * @param {Error} err
+ * @param {Function} callback optional
+ * @api private
+ */
+
+Connection.prototype.error = function(err, callback) {
+ if (callback) {
+ callback(err);
+ return null;
+ }
+ if (this.listeners('error').length > 0) {
+ this.emit('error', err);
+ }
+ return Promise.reject(err);
+};
+
+/**
+ * Called when the connection is opened
+ *
+ * @api private
+ */
+
+Connection.prototype.onOpen = function() {
+ this.readyState = STATES.connected;
+
+ // avoid having the collection subscribe to our event emitter
+ // to prevent 0.3 warning
+ for (const i in this.collections) {
+ if (utils.object.hasOwnProperty(this.collections, i)) {
+ this.collections[i].onOpen();
+ }
+ }
+
+ this.emit('open');
+};
+
+/**
+ * Opens the connection with a URI using `MongoClient.connect()`.
+ *
+ * @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 {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.
+ * @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 {Boolean} [options.useUnifiedTopology=false] False by default. Set to `true` to opt in to the MongoDB driver's replica set and sharded cluster monitoring engine.
+ * @param {Number} [options.serverSelectionTimeoutMS] If `useUnifiedTopology = true`, the MongoDB driver will try to find a server to send any given operation to, and keep retrying for `serverSelectionTimeoutMS` milliseconds before erroring out. If not set, the MongoDB driver defaults to using `30000` (30 seconds).
+ * @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.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.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 {Function} [callback]
+ * @returns {Connection} this
+ * @api public
+ */
+
+Connection.prototype.openUri = function(uri, options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ if (['string', 'number'].indexOf(typeof options) !== -1) {
+ throw new MongooseError('Mongoose 5.x no longer supports ' +
+ '`mongoose.connect(host, dbname, port)` or ' +
+ '`mongoose.createConnection(host, dbname, port)`. See ' +
+ 'http://mongoosejs.com/docs/connections.html for supported connection syntax');
+ }
+
+ if (typeof uri !== 'string') {
+ throw new MongooseError('The `uri` parameter to `openUri()` must be a ' +
+ `string, got "${typeof uri}". Make sure the first parameter to ` +
+ '`mongoose.connect()` or `mongoose.createConnection()` is a string.');
+ }
+
+ if (callback != null && typeof callback !== 'function') {
+ throw new MongooseError('3rd parameter to `mongoose.connect()` or ' +
+ '`mongoose.createConnection()` must be a function, got "' +
+ 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;
+ if (autoIndex != null) {
+ this.config.autoIndex = autoIndex !== false;
+ delete options.config;
+ delete options.autoIndex;
+ }
+
+ if ('autoCreate' in options) {
+ this.config.autoCreate = !!options.autoCreate;
+ delete options.autoCreate;
+ }
+ if ('useCreateIndex' in options) {
+ this.config.useCreateIndex = !!options.useCreateIndex;
+ delete options.useCreateIndex;
+ }
+
+ if ('useFindAndModify' in options) {
+ this.config.useFindAndModify = !!options.useFindAndModify;
+ delete options.useFindAndModify;
+ }
+
+ // Backwards compat
+ if (options.user || options.pass) {
+ options.auth = options.auth || {};
+ options.auth.user = options.user;
+ options.auth.password = options.pass;
+
+ this.user = options.user;
+ this.pass = options.pass;
+ }
+ delete options.user;
+ delete options.pass;
+
+ if (options.bufferCommands != null) {
+ if (options.bufferMaxEntries == null) {
+ options.bufferMaxEntries = 0;
+ }
+ this.config.bufferCommands = options.bufferCommands;
+ delete options.bufferCommands;
+ }
+
+ if (options.useMongoClient != null) {
+ handleUseMongoClient(options);
+ }
+ } else {
+ options = {};
+ }
+
+ this._connectionOptions = options;
+ const dbName = options.dbName;
+ if (dbName != null) {
+ this.$dbName = dbName;
+ }
+ delete options.dbName;
+
+ if (!('promiseLibrary' in options)) {
+ options.promiseLibrary = PromiseProvider.get();
+ }
+ if (!('useNewUrlParser' in options)) {
+ if ('useNewUrlParser' in this.base.options) {
+ options.useNewUrlParser = this.base.options.useNewUrlParser;
+ } else {
+ options.useNewUrlParser = false;
+ }
+ }
+ if (!utils.hasUserDefinedProperty(options, 'useUnifiedTopology')) {
+ if (utils.hasUserDefinedProperty(this.base.options, 'useUnifiedTopology')) {
+ options.useUnifiedTopology = this.base.options.useUnifiedTopology;
+ } else {
+ options.useUnifiedTopology = false;
+ }
+ }
+ if (!utils.hasUserDefinedProperty(options, 'driverInfo')) {
+ options.driverInfo = {
+ name: 'Mongoose',
+ version: pkg.version
+ };
+ }
+
+ const parsePromise = new Promise((resolve, reject) => {
+ parseConnectionString(uri, options, (err, parsed) => {
+ if (err) {
+ return reject(err);
+ }
+ if (dbName) {
+ this.name = dbName;
+ } else if (parsed.defaultDatabase) {
+ this.name = parsed.defaultDatabase;
+ } else {
+ this.name = get(parsed, 'auth.db', null);
+ }
+ this.host = get(parsed, 'hosts.0.host', 'localhost');
+ this.port = get(parsed, 'hosts.0.port', 27017);
+ this.user = this.user || get(parsed, 'auth.username');
+ this.pass = this.pass || get(parsed, 'auth.password');
+ resolve();
+ });
+ });
+
+ const promise = new Promise((resolve, reject) => {
+ const client = new mongodb.MongoClient(uri, options);
+ _this.client = client;
+ client.connect((error) => {
+ if (error) {
+ _this.readyState = STATES.disconnected;
+ return reject(error);
+ }
+
+ _setClient(_this, client, options, dbName);
+
+ resolve(_this);
+ });
+ });
+
+ const serverSelectionError = new ServerSelectionError();
+ this.$initialConnection = Promise.all([promise, parsePromise]).
+ then(res => res[0]).
+ catch(err => {
+ if (err != null && err.name === 'MongoServerSelectionError') {
+ err = serverSelectionError.assimilateError(err);
+ }
+
+ if (this.listeners('error').length > 0) {
+ process.nextTick(() => this.emit('error', err));
+ }
+ throw err;
+ });
+ this.then = function(resolve, reject) {
+ return this.$initialConnection.then(() => {
+ if (typeof resolve === 'function') {
+ resolve(_this);
+ }
+ }, reject);
+ };
+ this.catch = function(reject) {
+ return this.$initialConnection.catch(reject);
+ };
+
+ if (callback != null) {
+ this.$initialConnection = this.$initialConnection.then(
+ () => callback(null, this),
+ err => callback(err)
+ );
+ }
+
+ return this;
+};
+
+function _setClient(conn, client, options, dbName) {
+ const db = dbName != null ? client.db(dbName) : client.db();
+ conn.db = db;
+ conn.client = client;
+
+ 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();
+ }
+ });
+
+ db.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.on('reconnect', function() {
+ _handleReconnect();
+ });
+ db.s.topology.on('reconnectFailed', function() {
+ conn.emit('reconnectFailed');
+ });
+
+ if (!options.useUnifiedTopology) {
+ 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 || !type.startsWith('ReplicaSet')) {
+ db.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;
+ }
+ });
+ }
+
+ db.on('timeout', function() {
+ conn.emit('timeout');
+ });
+
+ delete conn.then;
+ delete conn.catch;
+ conn.readyState = STATES.connected;
+
+ for (const i in conn.collections) {
+ if (utils.object.hasOwnProperty(conn.collections, i)) {
+ conn.collections[i].onOpen();
+ }
+ }
+
+ conn.emit('open');
+}
+
+/*!
+ * ignore
+ */
+
+const handleUseMongoClient = function handleUseMongoClient(options) {
+ console.warn('WARNING: The `useMongoClient` option is no longer ' +
+ 'necessary in mongoose 5.x, please remove it.');
+ const stack = new Error().stack;
+ console.warn(stack.substr(stack.indexOf('\n') + 1));
+ delete options.useMongoClient;
+};
+
+/**
+ * Closes the connection
+ *
+ * @param {Boolean} [force] optional
+ * @param {Function} [callback] optional
+ * @return {Promise}
+ * @api public
+ */
+
+Connection.prototype.close = function(force, callback) {
+ if (typeof force === 'function') {
+ callback = force;
+ force = false;
+ }
+
+ this.$wasForceClosed = !!force;
+
+ return promiseOrCallback(callback, cb => {
+ this._close(force, cb);
+ });
+};
+
+/**
+ * Handles closing the connection
+ *
+ * @param {Boolean} force
+ * @param {Function} callback
+ * @api private
+ */
+Connection.prototype._close = function(force, callback) {
+ const _this = this;
+ this._closeCalled = true;
+
+ switch (this.readyState) {
+ case STATES.disconnected:
+ callback();
+ break;
+
+ case STATES.connected:
+ this.readyState = STATES.disconnecting;
+ this.doClose(force, function(err) {
+ if (err) {
+ return callback(err);
+ }
+ _this.onClose(force);
+ callback(null);
+ });
+
+ break;
+ case STATES.connecting:
+ this.once('open', function() {
+ _this.close(callback);
+ });
+ break;
+
+ case STATES.disconnecting:
+ this.once('close', function() {
+ callback();
+ });
+ break;
+ }
+
+ return this;
+};
+
+/**
+ * Called when the connection closes
+ *
+ * @api private
+ */
+
+Connection.prototype.onClose = function(force) {
+ this.readyState = STATES.disconnected;
+
+ // avoid having the collection subscribe to our event emitter
+ // to prevent 0.3 warning
+ for (const i in this.collections) {
+ if (utils.object.hasOwnProperty(this.collections, i)) {
+ this.collections[i].onClose(force);
+ }
+ }
+
+ this.emit('close', force);
+};
+
+/**
+ * Retrieves a collection, creating it if not cached.
+ *
+ * Not typically needed by applications. Just talk to your collection through your model.
+ *
+ * @param {String} name of the collection
+ * @param {Object} [options] optional collection options
+ * @return {Collection} collection instance
+ * @api public
+ */
+
+Connection.prototype.collection = function(name, options) {
+ options = options ? utils.clone(options) : {};
+ options.$wasForceClosed = this.$wasForceClosed;
+ if (!(name in this.collections)) {
+ this.collections[name] = new Collection(name, this, options);
+ }
+ return this.collections[name];
+};
+
+/**
+ * Declares a plugin executed on all schemas you pass to `conn.model()`
+ *
+ * Equivalent to calling `.plugin(fn)` on each schema you create.
+ *
+ * ####Example:
+ * const db = mongoose.createConnection('mongodb://localhost:27017/mydb');
+ * db.plugin(() => console.log('Applied'));
+ * db.plugins.length; // 1
+ *
+ * db.model('Test', new Schema({})); // Prints "Applied"
+ *
+ * @param {Function} fn plugin callback
+ * @param {Object} [opts] optional options
+ * @return {Connection} this
+ * @see plugins ./plugins.html
+ * @api public
+ */
+
+Connection.prototype.plugin = function(fn, opts) {
+ this.plugins.push([fn, opts]);
+ return this;
+};
+
+/**
+ * Defines or retrieves a model.
+ *
+ * const mongoose = require('mongoose');
+ * const db = mongoose.createConnection(..);
+ * db.model('Venue', new Schema(..));
+ * 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:
+ *
+ * const schema = new Schema({ name: String }, { collection: 'actor' });
+ *
+ * // or
+ *
+ * schema.set('collection', 'actor');
+ *
+ * // or
+ *
+ * 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
+ * @see Mongoose#model #index_Mongoose-model
+ * @return {Model} The compiled model
+ * @api public
+ */
+
+Connection.prototype.model = function(name, schema, collection) {
+ 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 ' +
+ '`db.model(foo)(bar)` instead');
+ }
+
+ let fn;
+ if (typeof name === 'function') {
+ fn = name;
+ name = fn.name;
+ }
+
+ // collection name discovery
+ if (typeof schema === 'string') {
+ collection = schema;
+ schema = false;
+ }
+
+ if (utils.isObject(schema) && !schema.instanceOfSchema) {
+ schema = new Schema(schema);
+ }
+ if (schema && !schema.instanceOfSchema) {
+ throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
+ 'schema or a POJO');
+ }
+
+ if (this.models[name] && !collection) {
+ // model exists but we are not subclassing with custom collection
+ if (schema && schema.instanceOfSchema && schema !== this.models[name].schema) {
+ throw new MongooseError.OverwriteModelError(name);
+ }
+ return this.models[name];
+ }
+
+ const opts = { cache: false, connection: this };
+ let model;
+
+ if (schema && schema.instanceOfSchema) {
+ applyPlugins(schema, this.plugins, null, '$connectionPluginsApplied');
+
+ // compile a model
+ model = this.base.model(fn || name, schema, collection, opts);
+
+ // only the first model with this name is cached to allow
+ // for one-offs with custom collection names etc.
+ if (!this.models[name]) {
+ this.models[name] = model;
+ }
+
+ // Errors handled internally, so safe to ignore error
+ model.init(function $modelInitNoop() {});
+
+ return model;
+ }
+
+ if (this.models[name] && collection) {
+ // subclassing current model with alternate collection
+ model = this.models[name];
+ schema = model.prototype.schema;
+ const sub = model.__subclass(this, schema, collection);
+ // do not cache the sub model
+ return sub;
+ }
+
+ // lookup model in mongoose module
+ model = this.base.models[name];
+
+ if (!model) {
+ throw new MongooseError.MissingSchemaError(name);
+ }
+
+ if (this === model.prototype.db
+ && (!collection || collection === model.collection.name)) {
+ // model already uses this connection.
+
+ // only the first model with this name is cached to allow
+ // for one-offs with custom collection names etc.
+ if (!this.models[name]) {
+ this.models[name] = model;
+ }
+
+ return model;
+ }
+ this.models[name] = model.__subclass(this, schema, collection);
+ return this.models[name];
+};
+
+/**
+ * Removes the model named `name` from this connection, if it exists. You can
+ * use this function to clean up any models you created in your tests to
+ * prevent OverwriteModelErrors.
+ *
+ * ####Example:
+ *
+ * conn.model('User', new Schema({ name: String }));
+ * console.log(conn.model('User')); // Model object
+ * conn.deleteModel('User');
+ * console.log(conn.model('User')); // undefined
+ *
+ * // Usually useful in a Mocha `afterEach()` hook
+ * afterEach(function() {
+ * conn.deleteModel(/.+/); // Delete every model
+ * });
+ *
+ * @api public
+ * @param {String|RegExp} name if string, the name of the model to remove. If regexp, removes all models whose name matches the regexp.
+ * @return {Connection} this
+ */
+
+Connection.prototype.deleteModel = function(name) {
+ if (typeof name === 'string') {
+ const model = this.model(name);
+ if (model == null) {
+ return this;
+ }
+ const collectionName = model.collection.name;
+ delete this.models[name];
+ delete this.collections[collectionName];
+ delete this.base.modelSchemas[name];
+ } else if (name instanceof RegExp) {
+ const pattern = name;
+ const names = this.modelNames();
+ for (const name of names) {
+ if (pattern.test(name)) {
+ this.deleteModel(name);
+ }
+ }
+ } else {
+ throw new Error('First parameter to `deleteModel()` must be a string ' +
+ 'or regexp, got "' + name + '"');
+ }
+
+ return this;
+};
+
+/**
+ * Watches the entire underlying database for changes. Similar to
+ * [`Model.watch()`](/docs/api/model.html#model_Model.watch).
+ *
+ * This function does **not** trigger any middleware. In particular, it
+ * does **not** trigger aggregate middleware.
+ *
+ * The ChangeStream object is an event emitter that emits the following events:
+ *
+ * - 'change': A change occurred, see below example
+ * - 'error': An unrecoverable error occurred. In particular, change streams currently error out if they lose connection to the replica set primary. Follow [this GitHub issue](https://github.com/Automattic/mongoose/issues/6799) for updates.
+ * - 'end': Emitted if the underlying stream is closed
+ * - 'close': Emitted if the underlying stream is closed
+ *
+ * ####Example:
+ *
+ * const User = conn.model('User', new Schema({ name: String }));
+ *
+ * const changeStream = conn.watch().on('change', data => console.log(data));
+ *
+ * // Triggers a 'change' event on the change stream.
+ * await User.create({ name: 'test' });
+ *
+ * @api public
+ * @param {Array} [pipeline]
+ * @param {Object} [options] passed without changes to [the MongoDB driver's `Db#watch()` function](https://mongodb.github.io/node-mongodb-native/3.4/api/Db.html#watch)
+ * @return {ChangeStream} mongoose-specific change stream wrapper, inherits from EventEmitter
+ */
+
+Connection.prototype.watch = function(pipeline, options) {
+ const disconnectedError = new MongooseError('Connection ' + this.id +
+ ' was disconnected when calling `watch()`');
+
+ const changeStreamThunk = cb => {
+ immediate(() => {
+ if (this.readyState === STATES.connecting) {
+ this.once('open', function() {
+ const driverChangeStream = this.db.watch(pipeline, options);
+ cb(null, driverChangeStream);
+ });
+ } else if (this.readyState === STATES.disconnected && this.db == null) {
+ cb(disconnectedError);
+ } else {
+ const driverChangeStream = this.db.watch(pipeline, options);
+ cb(null, driverChangeStream);
+ }
+ });
+ };
+
+ const changeStream = new ChangeStream(changeStreamThunk, pipeline, options);
+ return changeStream;
+};
+
+/**
+ * Returns an array of model names created on this connection.
+ * @api public
+ * @return {Array}
+ */
+
+Connection.prototype.modelNames = function() {
+ return Object.keys(this.models);
+};
+
+/**
+ * @brief Returns if the connection requires authentication after it is opened. Generally if a
+ * username and password are both provided than authentication is needed, but in some cases a
+ * password is not required.
+ * @api private
+ * @return {Boolean} true if the connection should be authenticated after it is opened, otherwise false.
+ */
+Connection.prototype.shouldAuthenticate = function() {
+ return this.user != null &&
+ (this.pass != null || this.authMechanismDoesNotRequirePassword());
+};
+
+/**
+ * @brief Returns a boolean value that specifies if the current authentication mechanism needs a
+ * password to authenticate according to the auth objects passed into the openUri methods.
+ * @api private
+ * @return {Boolean} true if the authentication mechanism specified in the options object requires
+ * a password, otherwise false.
+ */
+Connection.prototype.authMechanismDoesNotRequirePassword = function() {
+ if (this.options && this.options.auth) {
+ return noPasswordAuthMechanisms.indexOf(this.options.auth.authMechanism) >= 0;
+ }
+ return true;
+};
+
+/**
+ * @brief Returns a boolean value that specifies if the provided objects object provides enough
+ * data to authenticate with. Generally this is true if the username and password are both specified
+ * but in some authentication methods, a password is not required for authentication so only a username
+ * is required.
+ * @param {Object} [options] the options object passed into the openUri methods.
+ * @api private
+ * @return {Boolean} true if the provided options object provides enough data to authenticate with,
+ * otherwise false.
+ */
+Connection.prototype.optionsProvideAuthenticationData = function(options) {
+ return (options) &&
+ (options.user) &&
+ ((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.
+ *
+ * Returns a new connection object, with the new db.
+ *
+ * @method useDb
+ * @memberOf Connection
+ * @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.
+ * @return {Connection} New Connection Object
+ * @api public
+ */
+
+/*!
+ * Module exports.
+ */
+
+Connection.STATES = STATES;
+module.exports = Connection;
diff --git a/node_modules/mongoose/lib/connectionstate.js b/node_modules/mongoose/lib/connectionstate.js
new file mode 100644
index 0000000..920f45b
--- /dev/null
+++ b/node_modules/mongoose/lib/connectionstate.js
@@ -0,0 +1,26 @@
+
+/*!
+ * Connection states
+ */
+
+'use strict';
+
+const STATES = module.exports = exports = Object.create(null);
+
+const disconnected = 'disconnected';
+const connected = 'connected';
+const connecting = 'connecting';
+const disconnecting = 'disconnecting';
+const uninitialized = 'uninitialized';
+
+STATES[0] = disconnected;
+STATES[1] = connected;
+STATES[2] = connecting;
+STATES[3] = disconnecting;
+STATES[99] = uninitialized;
+
+STATES[disconnected] = 0;
+STATES[connected] = 1;
+STATES[connecting] = 2;
+STATES[disconnecting] = 3;
+STATES[uninitialized] = 99;
diff --git a/node_modules/mongoose/lib/cursor/AggregationCursor.js b/node_modules/mongoose/lib/cursor/AggregationCursor.js
new file mode 100644
index 0000000..5023b1c
--- /dev/null
+++ b/node_modules/mongoose/lib/cursor/AggregationCursor.js
@@ -0,0 +1,368 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('../error/mongooseError');
+const Readable = require('stream').Readable;
+const promiseOrCallback = require('../helpers/promiseOrCallback');
+const eachAsync = require('../helpers/cursor/eachAsync');
+const util = require('util');
+
+/**
+ * An AggregationCursor is a concurrency primitive for processing aggregation
+ * results one document at a time. It is analogous to QueryCursor.
+ *
+ * An AggregationCursor fulfills the Node.js streams3 API,
+ * in addition to several other mechanisms for loading documents from MongoDB
+ * one at a time.
+ *
+ * Creating an AggregationCursor executes the model's pre aggregate hooks,
+ * but **not** the model's post aggregate hooks.
+ *
+ * Unless you're an advanced user, do **not** instantiate this class directly.
+ * Use [`Aggregate#cursor()`](/docs/api.html#aggregate_Aggregate-cursor) instead.
+ *
+ * @param {Aggregate} agg
+ * @param {Object} options
+ * @inherits Readable
+ * @event `cursor`: Emitted when the cursor is created
+ * @event `error`: Emitted when an error occurred
+ * @event `data`: Emitted when the stream is flowing and the next doc is ready
+ * @event `end`: Emitted when the stream is exhausted
+ * @api public
+ */
+
+function AggregationCursor(agg) {
+ Readable.call(this, { objectMode: true });
+
+ this.cursor = null;
+ this.agg = agg;
+ this._transforms = [];
+ const model = agg._model;
+ delete agg.options.cursor.useMongooseAggCursor;
+ this._mongooseOptions = {};
+
+ _init(model, this, agg);
+}
+
+util.inherits(AggregationCursor, Readable);
+
+/*!
+ * ignore
+ */
+
+function _init(model, c, agg) {
+ if (!model.collection.buffer) {
+ model.hooks.execPre('aggregate', agg, function() {
+ c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {});
+ c.emit('cursor', c.cursor);
+ });
+ } else {
+ model.collection.emitter.once('queue', function() {
+ model.hooks.execPre('aggregate', agg, function() {
+ c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {});
+ c.emit('cursor', c.cursor);
+ });
+ });
+ }
+}
+
+/*!
+ * Necessary to satisfy the Readable API
+ */
+
+AggregationCursor.prototype._read = function() {
+ const _this = this;
+ _next(this, function(error, doc) {
+ if (error) {
+ return _this.emit('error', error);
+ }
+ if (!doc) {
+ _this.push(null);
+ _this.cursor.close(function(error) {
+ 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);
+ });
+ return;
+ }
+ _this.push(doc);
+ });
+};
+
+if (Symbol.asyncIterator != null) {
+ const msg = 'Mongoose does not support using async iterators with an ' +
+ 'existing aggregation cursor. See http://bit.ly/mongoose-async-iterate-aggregation';
+
+ AggregationCursor.prototype[Symbol.asyncIterator] = function() {
+ throw new MongooseError(msg);
+ };
+}
+
+/**
+ * Registers a transform function which subsequently maps documents retrieved
+ * via the streams interface or `.next()`
+ *
+ * ####Example
+ *
+ * // Map documents returned by `data` events
+ * Thing.
+ * find({ name: /^hello/ }).
+ * cursor().
+ * map(function (doc) {
+ * doc.foo = "bar";
+ * return doc;
+ * })
+ * on('data', function(doc) { console.log(doc.foo); });
+ *
+ * // Or map documents returned by `.next()`
+ * const cursor = Thing.find({ name: /^hello/ }).
+ * cursor().
+ * map(function (doc) {
+ * doc.foo = "bar";
+ * return doc;
+ * });
+ * cursor.next(function(error, doc) {
+ * console.log(doc.foo);
+ * });
+ *
+ * @param {Function} fn
+ * @return {AggregationCursor}
+ * @api public
+ * @method map
+ */
+
+AggregationCursor.prototype.map = function(fn) {
+ this._transforms.push(fn);
+ return this;
+};
+
+/*!
+ * Marks this cursor as errored
+ */
+
+AggregationCursor.prototype._markError = function(error) {
+ this._error = error;
+ return this;
+};
+
+/**
+ * Marks this cursor as closed. Will stop streaming and subsequent calls to
+ * `next()` will error.
+ *
+ * @param {Function} callback
+ * @return {Promise}
+ * @api public
+ * @method close
+ * @emits close
+ * @see MongoDB driver cursor#close http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#close
+ */
+
+AggregationCursor.prototype.close = function(callback) {
+ return promiseOrCallback(callback, cb => {
+ this.cursor.close(error => {
+ if (error) {
+ cb(error);
+ return this.listeners('error').length > 0 && this.emit('error', error);
+ }
+ this.emit('close');
+ cb(null);
+ });
+ });
+};
+
+/**
+ * Get the next document from this cursor. Will return `null` when there are
+ * no documents left.
+ *
+ * @param {Function} callback
+ * @return {Promise}
+ * @api public
+ * @method next
+ */
+
+AggregationCursor.prototype.next = function(callback) {
+ return promiseOrCallback(callback, cb => {
+ _next(this, cb);
+ });
+};
+
+/**
+ * Execute `fn` for every document in the cursor. If `fn` returns a promise,
+ * will wait for the promise to resolve before iterating on to the next one.
+ * Returns a promise that resolves when done.
+ *
+ * @param {Function} fn
+ * @param {Object} [options]
+ * @param {Number} [options.parallel] the number of promises to execute in parallel. Defaults to 1.
+ * @param {Function} [callback] executed when all docs have been processed
+ * @return {Promise}
+ * @api public
+ * @method eachAsync
+ */
+
+AggregationCursor.prototype.eachAsync = function(fn, opts, callback) {
+ const _this = this;
+ if (typeof opts === 'function') {
+ callback = opts;
+ opts = {};
+ }
+ opts = opts || {};
+
+ 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
+ */
+
+AggregationCursor.prototype.transformNull = function(val) {
+ if (arguments.length === 0) {
+ val = true;
+ }
+ this._mongooseOptions.transformNull = 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.
+ *
+ * @param {String} flag
+ * @param {Boolean} value
+ * @return {AggregationCursor} this
+ * @api public
+ * @method addCursorFlag
+ */
+
+AggregationCursor.prototype.addCursorFlag = function(flag, value) {
+ const _this = this;
+ _waitForCursor(this, function() {
+ _this.cursor.addCursorFlag(flag, value);
+ });
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+function _waitForCursor(ctx, cb) {
+ if (ctx.cursor) {
+ return cb();
+ }
+ ctx.once('cursor', function() {
+ cb();
+ });
+}
+
+/*!
+ * Get the next doc from the underlying cursor and mongooseify it
+ * (populate, etc.)
+ */
+
+function _next(ctx, cb) {
+ let callback = cb;
+ if (ctx._transforms.length) {
+ callback = function(err, doc) {
+ if (err || (doc === null && !ctx._mongooseOptions.transformNull)) {
+ return cb(err, doc);
+ }
+ cb(err, ctx._transforms.reduce(function(doc, fn) {
+ return fn(doc);
+ }, doc));
+ };
+ }
+
+ if (ctx._error) {
+ return process.nextTick(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);
+ }
+
+ callback(null, doc);
+ });
+ } else {
+ ctx.once('cursor', function() {
+ _next(ctx, cb);
+ });
+ }
+}
+
+module.exports = AggregationCursor;
diff --git a/node_modules/mongoose/lib/cursor/ChangeStream.js b/node_modules/mongoose/lib/cursor/ChangeStream.js
new file mode 100644
index 0000000..b3445b0
--- /dev/null
+++ b/node_modules/mongoose/lib/cursor/ChangeStream.js
@@ -0,0 +1,61 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const EventEmitter = require('events').EventEmitter;
+
+/*!
+ * ignore
+ */
+
+class ChangeStream extends EventEmitter {
+ constructor(changeStreamThunk, pipeline, options) {
+ super();
+
+ this.driverChangeStream = null;
+ this.closed = false;
+ this.pipeline = pipeline;
+ this.options = options;
+
+ // This wrapper is necessary because of buffering.
+ changeStreamThunk((err, driverChangeStream) => {
+ if (err != null) {
+ this.emit('error', err);
+ return;
+ }
+
+ this.driverChangeStream = driverChangeStream;
+ this._bindEvents();
+ this.emit('ready');
+ });
+ }
+
+ _bindEvents() {
+ this.driverChangeStream.on('close', () => {
+ this.closed = true;
+ });
+
+ ['close', 'change', 'end', 'error'].forEach(ev => {
+ this.driverChangeStream.on(ev, data => this.emit(ev, data));
+ });
+ }
+
+ _queue(cb) {
+ this.once('ready', () => cb());
+ }
+
+ close() {
+ this.closed = true;
+ if (this.driverChangeStream) {
+ this.driverChangeStream.close();
+ }
+ }
+}
+
+/*!
+ * ignore
+ */
+
+module.exports = ChangeStream;
diff --git a/node_modules/mongoose/lib/cursor/QueryCursor.js b/node_modules/mongoose/lib/cursor/QueryCursor.js
new file mode 100644
index 0000000..2b5f2c1
--- /dev/null
+++ b/node_modules/mongoose/lib/cursor/QueryCursor.js
@@ -0,0 +1,418 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const Readable = require('stream').Readable;
+const promiseOrCallback = require('../helpers/promiseOrCallback');
+const eachAsync = require('../helpers/cursor/eachAsync');
+const helpers = require('../queryhelpers');
+const util = require('util');
+
+/**
+ * A QueryCursor is a concurrency primitive for processing query results
+ * one document at a time. A QueryCursor fulfills the Node.js streams3 API,
+ * 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.
+ *
+ * Unless you're an advanced user, do **not** instantiate this class directly.
+ * Use [`Query#cursor()`](/docs/api.html#query_Query-cursor) instead.
+ *
+ * @param {Query} query
+ * @param {Object} options query options passed to `.find()`
+ * @inherits Readable
+ * @event `cursor`: Emitted when the cursor is created
+ * @event `error`: Emitted when an error occurred
+ * @event `data`: Emitted when the stream is flowing and the next doc is ready
+ * @event `end`: Emitted when the stream is exhausted
+ * @api public
+ */
+
+function QueryCursor(query, options) {
+ Readable.call(this, { objectMode: true });
+
+ this.cursor = null;
+ this.query = query;
+ const _this = this;
+ const model = query.model;
+ this._mongooseOptions = {};
+ this._transforms = [];
+ this.model = model;
+ this.options = options || {};
+
+ model.hooks.execPre('find', query, () => {
+ this._transforms = this._transforms.concat(query._transforms.slice());
+ if (this.options.transform) {
+ this._transforms.push(options.transform);
+ }
+ // Re: gh-8039, you need to set the `cursor.batchSize` option, top-level
+ // `batchSize` option doesn't work.
+ if (this.options.batchSize) {
+ this.options.cursor = options.cursor || {};
+ this.options.cursor.batchSize = options.batchSize;
+ }
+ model.collection.find(query._conditions, this.options, function(err, cursor) {
+ if (_this._error) {
+ cursor.close(function() {});
+ _this.listeners('error').length > 0 && _this.emit('error', _this._error);
+ }
+ if (err) {
+ return _this.emit('error', err);
+ }
+ _this.cursor = cursor;
+ _this.emit('cursor', cursor);
+ });
+ });
+}
+
+util.inherits(QueryCursor, Readable);
+
+/*!
+ * Necessary to satisfy the Readable API
+ */
+
+QueryCursor.prototype._read = function() {
+ const _this = this;
+ _next(this, function(error, doc) {
+ if (error) {
+ return _this.emit('error', error);
+ }
+ if (!doc) {
+ _this.push(null);
+ _this.cursor.close(function(error) {
+ 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);
+ });
+ return;
+ }
+ _this.push(doc);
+ });
+};
+
+/**
+ * Registers a transform function which subsequently maps documents retrieved
+ * via the streams interface or `.next()`
+ *
+ * ####Example
+ *
+ * // Map documents returned by `data` events
+ * Thing.
+ * find({ name: /^hello/ }).
+ * cursor().
+ * map(function (doc) {
+ * doc.foo = "bar";
+ * return doc;
+ * })
+ * on('data', function(doc) { console.log(doc.foo); });
+ *
+ * // Or map documents returned by `.next()`
+ * const cursor = Thing.find({ name: /^hello/ }).
+ * cursor().
+ * map(function (doc) {
+ * doc.foo = "bar";
+ * return doc;
+ * });
+ * cursor.next(function(error, doc) {
+ * console.log(doc.foo);
+ * });
+ *
+ * @param {Function} fn
+ * @return {QueryCursor}
+ * @api public
+ * @method map
+ */
+
+QueryCursor.prototype.map = function(fn) {
+ this._transforms.push(fn);
+ return this;
+};
+
+/*!
+ * Marks this cursor as errored
+ */
+
+QueryCursor.prototype._markError = function(error) {
+ this._error = error;
+ return this;
+};
+
+/**
+ * Marks this cursor as closed. Will stop streaming and subsequent calls to
+ * `next()` will error.
+ *
+ * @param {Function} callback
+ * @return {Promise}
+ * @api public
+ * @method close
+ * @emits close
+ * @see MongoDB driver cursor#close http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html#close
+ */
+
+QueryCursor.prototype.close = function(callback) {
+ return promiseOrCallback(callback, cb => {
+ this.cursor.close(error => {
+ if (error) {
+ cb(error);
+ return this.listeners('error').length > 0 && this.emit('error', error);
+ }
+ this.emit('close');
+ cb(null);
+ });
+ }, this.model.events);
+};
+
+/**
+ * Get the next document from this cursor. Will return `null` when there are
+ * no documents left.
+ *
+ * @param {Function} callback
+ * @return {Promise}
+ * @api public
+ * @method next
+ */
+
+QueryCursor.prototype.next = function(callback) {
+ return promiseOrCallback(callback, cb => {
+ _next(this, function(error, doc) {
+ if (error) {
+ return cb(error);
+ }
+ cb(null, doc);
+ });
+ }, this.model.events);
+};
+
+/**
+ * Execute `fn` for every document in the cursor. If `fn` returns a promise,
+ * will wait for the promise to resolve before iterating on to the next one.
+ * Returns a promise that resolves when done.
+ *
+ * ####Example
+ *
+ * // Iterate over documents asynchronously
+ * Thing.
+ * find({ name: /^hello/ }).
+ * cursor().
+ * eachAsync(async function (doc, i) {
+ * doc.foo = doc.bar + i;
+ * await doc.save();
+ * })
+ *
+ * @param {Function} fn
+ * @param {Object} [options]
+ * @param {Number} [options.parallel] the number of promises to execute in parallel. Defaults to 1.
+ * @param {Function} [callback] executed when all docs have been processed
+ * @return {Promise}
+ * @api public
+ * @method eachAsync
+ */
+
+QueryCursor.prototype.eachAsync = function(fn, opts, callback) {
+ const _this = this;
+ if (typeof opts === 'function') {
+ callback = opts;
+ opts = {};
+ }
+ opts = opts || {};
+
+ return eachAsync(function(cb) { return _next(_this, cb); }, fn, opts, callback);
+};
+
+/**
+ * The `options` passed in to the `QueryCursor` constructor.
+ *
+ * @api public
+ * @property options
+ */
+
+QueryCursor.prototype.options;
+
+/**
+ * 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.
+ *
+ * @param {String} flag
+ * @param {Boolean} value
+ * @return {AggregationCursor} this
+ * @api public
+ * @method addCursorFlag
+ */
+
+QueryCursor.prototype.addCursorFlag = function(flag, value) {
+ const _this = this;
+ _waitForCursor(this, function() {
+ _this.cursor.addCursorFlag(flag, value);
+ });
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+QueryCursor.prototype.transformNull = function(val) {
+ if (arguments.length === 0) {
+ val = true;
+ }
+ this._mongooseOptions.transformNull = 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.)
+ */
+
+function _next(ctx, cb) {
+ let callback = cb;
+ if (ctx._transforms.length) {
+ callback = function(err, doc) {
+ if (err || (doc === null && !ctx._mongooseOptions.transformNull)) {
+ return cb(err, doc);
+ }
+ cb(err, ctx._transforms.reduce(function(doc, fn) {
+ return fn.call(ctx, doc);
+ }, doc));
+ };
+ }
+
+ if (ctx._error) {
+ return process.nextTick(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,
+ ctx.query._mongooseOptions);
+ pop.__noPromise = true;
+ ctx.query.model.populate(doc, pop, function(err, doc) {
+ if (err) {
+ return callback(err);
+ }
+ return opts.lean ?
+ callback(null, doc) :
+ _create(ctx, doc, pop, callback);
+ });
+ });
+ } else {
+ ctx.once('cursor', function() {
+ _next(ctx, cb);
+ });
+ }
+}
+
+/*!
+ * ignore
+ */
+
+function _waitForCursor(ctx, cb) {
+ if (ctx.cursor) {
+ return cb();
+ }
+ ctx.once('cursor', function() {
+ cb();
+ });
+}
+
+/*!
+ * Convert a raw doc into a full mongoose doc.
+ */
+
+function _create(ctx, doc, populatedIds, cb) {
+ const instance = helpers.createModel(ctx.query.model, doc, ctx.query._fields);
+ const opts = populatedIds ?
+ { populated: populatedIds } :
+ undefined;
+
+ instance.init(doc, opts, function(err) {
+ if (err) {
+ return cb(err);
+ }
+ cb(null, instance);
+ });
+}
+
+module.exports = QueryCursor;
diff --git a/node_modules/mongoose/lib/document.js b/node_modules/mongoose/lib/document.js
new file mode 100644
index 0000000..9e8cb9a
--- /dev/null
+++ b/node_modules/mongoose/lib/document.js
@@ -0,0 +1,4056 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const EventEmitter = require('events').EventEmitter;
+const InternalCache = require('./internal');
+const MongooseError = require('./error/index');
+const MixedSchema = require('./schema/mixed');
+const ObjectExpectedError = require('./error/objectExpected');
+const ObjectParameterError = require('./error/objectParameter');
+const ParallelValidateError = require('./error/parallelValidate');
+const Schema = require('./schema');
+const StrictModeError = require('./error/strict');
+const ValidationError = require('./error/validation');
+const ValidatorError = require('./error/validator');
+const VirtualType = require('./virtualtype');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const cleanModifiedSubpaths = require('./helpers/document/cleanModifiedSubpaths');
+const compile = require('./helpers/document/compile').compile;
+const defineKey = require('./helpers/document/compile').defineKey;
+const flatten = require('./helpers/common').flatten;
+const get = require('./helpers/get');
+const getEmbeddedDiscriminatorPath = require('./helpers/document/getEmbeddedDiscriminatorPath');
+const handleSpreadDoc = require('./helpers/document/handleSpreadDoc');
+const idGetter = require('./plugins/idGetter');
+const isDefiningProjection = require('./helpers/projection/isDefiningProjection');
+const isExclusive = require('./helpers/projection/isExclusive');
+const inspect = require('util').inspect;
+const internalToObjectOptions = require('./options').internalToObjectOptions;
+const mpath = require('mpath');
+const queryhelpers = require('./queryhelpers');
+const utils = require('./utils');
+const isPromise = require('./helpers/isPromise');
+
+const clone = utils.clone;
+const deepEqual = utils.deepEqual;
+const isMongooseObject = utils.isMongooseObject;
+
+const arrayAtomicsBackupSymbol = Symbol('mongoose.Array#atomicsBackup');
+const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
+const documentArrayParent = require('./helpers/symbols').documentArrayParent;
+const documentIsSelected = require('./helpers/symbols').documentIsSelected;
+const documentIsModified = require('./helpers/symbols').documentIsModified;
+const documentModifiedPaths = require('./helpers/symbols').documentModifiedPaths;
+const documentSchemaSymbol = require('./helpers/symbols').documentSchemaSymbol;
+const getSymbol = require('./helpers/symbols').getSymbol;
+const populateModelSymbol = require('./helpers/symbols').populateModelSymbol;
+const scopeSymbol = require('./helpers/symbols').scopeSymbol;
+
+let DocumentArray;
+let MongooseArray;
+let Embedded;
+
+const specialProperties = utils.specialProperties;
+
+/**
+ * The core Mongoose document constructor. You should not call this directly,
+ * the Mongoose [Model constructor](./api.html#Model) calls this for you.
+ *
+ * @param {Object} obj the values to set
+ * @param {Object} [fields] optional object containing the fields which were selected in the query returning this document and any populated paths data
+ * @param {Object} [options] various configuration options for the document
+ * @param {Boolean} [options.defaults=true] if `false`, skip applying default values to this document.
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `init`: Emitted on a document after it has been retrieved from the db and fully hydrated by Mongoose.
+ * @event `save`: Emitted when the document is successfully saved
+ * @api private
+ */
+
+function Document(obj, fields, skipId, options) {
+ if (typeof skipId === 'object' && skipId != null) {
+ options = skipId;
+ skipId = options.skipId;
+ }
+ options = Object.assign({}, options);
+ const defaults = get(options, 'defaults', true);
+ options.defaults = defaults;
+
+ // Support `browserDocument.js` syntax
+ if (this.schema == null) {
+ const _schema = utils.isObject(fields) && !fields.instanceOfSchema ?
+ new Schema(fields) :
+ fields;
+ this.$__setSchema(_schema);
+ fields = skipId;
+ skipId = options;
+ options = arguments[4] || {};
+ }
+
+ this.$__ = new InternalCache;
+ this.$__.emitter = new EventEmitter();
+ this.isNew = 'isNew' in options ? options.isNew : true;
+ this.errors = undefined;
+ this.$__.$options = options || {};
+ this.$locals = {};
+ this.$op = null;
+
+ if (obj != null && typeof obj !== 'object') {
+ throw new ObjectParameterError(obj, 'obj', 'Document');
+ }
+
+ const schema = this.schema;
+
+ if (typeof fields === 'boolean' || fields === 'throw') {
+ this.$__.strictMode = fields;
+ fields = undefined;
+ } else {
+ this.$__.strictMode = schema.options.strict;
+ this.$__.selected = fields;
+ }
+
+ const requiredPaths = schema.requiredPaths(true);
+ for (const path of requiredPaths) {
+ this.$__.activePaths.require(path);
+ }
+
+ this.$__.emitter.setMaxListeners(0);
+
+ let exclude = null;
+
+ // determine if this doc is a result of a query with
+ // excluded fields
+ if (utils.isPOJO(fields)) {
+ exclude = isExclusive(fields);
+ }
+
+ const hasIncludedChildren = exclude === false && fields ?
+ $__hasIncludedChildren(fields) :
+ {};
+
+ if (this._doc == null) {
+ this.$__buildDoc(obj, fields, skipId, exclude, hasIncludedChildren, false);
+
+ // By default, defaults get applied **before** setting initial values
+ // Re: gh-6155
+ if (defaults) {
+ $__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, true, {
+ isNew: this.isNew
+ });
+ }
+ }
+
+ if (obj) {
+ // Skip set hooks
+ if (this.$__original_set) {
+ this.$__original_set(obj, undefined, true);
+ } else {
+ this.$set(obj, undefined, true);
+ }
+
+ if (obj instanceof Document) {
+ this.isNew = obj.isNew;
+ }
+ }
+
+ // Function defaults get applied **after** setting initial values so they
+ // see the full doc rather than an empty one, unless they opt out.
+ // Re: gh-3781, gh-6155
+ if (options.willInit && defaults) {
+ EventEmitter.prototype.once.call(this, 'init', () => {
+ $__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, false, options.skipDefaults, {
+ isNew: this.isNew
+ });
+ });
+ } else if (defaults) {
+ $__applyDefaults(this, fields, skipId, exclude, hasIncludedChildren, false, options.skipDefaults, {
+ isNew: this.isNew
+ });
+ }
+
+ this.$__._id = this._id;
+
+ if (!this.$__.strictMode && obj) {
+ const _this = this;
+ const keys = Object.keys(this._doc);
+
+ keys.forEach(function(key) {
+ if (!(key in schema.tree)) {
+ defineKey(key, null, _this);
+ }
+ });
+ }
+
+ applyQueue(this);
+}
+
+/*!
+ * Document exposes the NodeJS event emitter API, so you can use
+ * `on`, `once`, etc.
+ */
+utils.each(
+ ['on', 'once', 'emit', 'listeners', 'removeListener', 'setMaxListeners',
+ 'removeAllListeners', 'addListener'],
+ function(emitterFn) {
+ Document.prototype[emitterFn] = function() {
+ return this.$__.emitter[emitterFn].apply(this.$__.emitter, arguments);
+ };
+ });
+
+Document.prototype.constructor = Document;
+
+for (const i in EventEmitter.prototype) {
+ Document[i] = EventEmitter.prototype[i];
+}
+
+/**
+ * The documents schema.
+ *
+ * @api public
+ * @property schema
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.schema;
+
+/**
+ * Empty object that you can use for storing properties on the document. This
+ * is handy for passing data to middleware without conflicting with Mongoose
+ * internals.
+ *
+ * ####Example:
+ *
+ * schema.pre('save', function() {
+ * // Mongoose will set `isNew` to `false` if `save()` succeeds
+ * this.$locals.wasNew = this.isNew;
+ * });
+ *
+ * schema.post('save', function() {
+ * // Prints true if `isNew` was set before `save()`
+ * console.log(this.$locals.wasNew);
+ * });
+ *
+ * @api public
+ * @property $locals
+ * @memberOf Document
+ * @instance
+ */
+
+Object.defineProperty(Document.prototype, '$locals', {
+ configurable: false,
+ enumerable: false,
+ writable: true
+});
+
+/**
+ * Boolean flag specifying if the document is new.
+ *
+ * @api public
+ * @property isNew
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.isNew;
+
+/**
+ * The string version of this documents _id.
+ *
+ * ####Note:
+ *
+ * This getter exists on all documents by default. The getter can be disabled by setting the `id` [option](/docs/guide.html#id) of its `Schema` to false at construction time.
+ *
+ * new Schema({ name: String }, { id: false });
+ *
+ * @api public
+ * @see Schema options /docs/guide.html#options
+ * @property id
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.id;
+
+/**
+ * Hash containing current validation errors.
+ *
+ * @api public
+ * @property errors
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.errors;
+
+/**
+ * A string containing the current operation that Mongoose is executing
+ * on this document. May be `null`, `'save'`, `'validate'`, or `'remove'`.
+ *
+ * ####Example:
+ *
+ * const doc = new Model({ name: 'test' });
+ * doc.$op; // null
+ *
+ * const promise = doc.save();
+ * doc.$op; // 'save'
+ *
+ * await promise;
+ * doc.$op; // null
+ *
+ * @api public
+ * @property $op
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$op;
+
+/*!
+ * ignore
+ */
+
+function $__hasIncludedChildren(fields) {
+ const hasIncludedChildren = {};
+ const keys = Object.keys(fields);
+
+ for (const key of keys) {
+ const parts = key.split('.');
+ const c = [];
+
+ for (const part of parts) {
+ c.push(part);
+ hasIncludedChildren[c.join('.')] = 1;
+ }
+ }
+
+ return hasIncludedChildren;
+}
+
+/*!
+ * ignore
+ */
+
+function $__applyDefaults(doc, fields, skipId, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip) {
+ const paths = Object.keys(doc.schema.paths);
+ const plen = paths.length;
+
+ for (let i = 0; i < plen; ++i) {
+ let def;
+ let curPath = '';
+ const p = paths[i];
+
+ if (p === '_id' && skipId) {
+ continue;
+ }
+
+ const type = doc.schema.paths[p];
+ const path = p.indexOf('.') === -1 ? [p] : p.split('.');
+ const len = path.length;
+ let included = false;
+ let doc_ = doc._doc;
+
+ for (let j = 0; j < len; ++j) {
+ if (doc_ == null) {
+ break;
+ }
+
+ const piece = path[j];
+ curPath += (!curPath.length ? '' : '.') + piece;
+
+ if (exclude === true) {
+ if (curPath in fields) {
+ break;
+ }
+ } else if (exclude === false && fields && !included) {
+ if (curPath in fields) {
+ included = true;
+ } else if (!hasIncludedChildren[curPath]) {
+ break;
+ }
+ }
+
+ if (j === len - 1) {
+ if (doc_[piece] !== void 0) {
+ break;
+ }
+
+ if (typeof type.defaultValue === 'function') {
+ if (!type.defaultValue.$runBeforeSetters && isBeforeSetters) {
+ break;
+ }
+ if (type.defaultValue.$runBeforeSetters && !isBeforeSetters) {
+ break;
+ }
+ } else if (!isBeforeSetters) {
+ // Non-function defaults should always run **before** setters
+ continue;
+ }
+
+ if (pathsToSkip && pathsToSkip[curPath]) {
+ break;
+ }
+
+ if (fields && exclude !== null) {
+ if (exclude === true) {
+ // apply defaults to all non-excluded fields
+ if (p in fields) {
+ continue;
+ }
+
+ try {
+ def = type.getDefault(doc, false);
+ } catch (err) {
+ doc.invalidate(p, err);
+ break;
+ }
+
+ if (typeof def !== 'undefined') {
+ doc_[piece] = def;
+ doc.$__.activePaths.default(p);
+ }
+ } else if (included) {
+ // selected field
+ try {
+ def = type.getDefault(doc, false);
+ } catch (err) {
+ doc.invalidate(p, err);
+ break;
+ }
+
+ if (typeof def !== 'undefined') {
+ doc_[piece] = def;
+ doc.$__.activePaths.default(p);
+ }
+ }
+ } else {
+ try {
+ def = type.getDefault(doc, false);
+ } catch (err) {
+ doc.invalidate(p, err);
+ break;
+ }
+
+ if (typeof def !== 'undefined') {
+ doc_[piece] = def;
+ doc.$__.activePaths.default(p);
+ }
+ }
+ } else {
+ doc_ = doc_[piece];
+ }
+ }
+ }
+}
+
+/**
+ * Builds the default doc structure
+ *
+ * @param {Object} obj
+ * @param {Object} [fields]
+ * @param {Boolean} [skipId]
+ * @api private
+ * @method $__buildDoc
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__buildDoc = function(obj, fields, skipId, exclude, hasIncludedChildren) {
+ const doc = {};
+
+ const paths = Object.keys(this.schema.paths).
+ // Don't build up any paths that are underneath a map, we don't know
+ // what the keys will be
+ filter(p => !p.includes('$*'));
+ const plen = paths.length;
+ let ii = 0;
+
+ for (; ii < plen; ++ii) {
+ const p = paths[ii];
+
+ if (p === '_id') {
+ if (skipId) {
+ continue;
+ }
+ if (obj && '_id' in obj) {
+ continue;
+ }
+ }
+
+ const path = p.split('.');
+ const len = path.length;
+ const last = len - 1;
+ let curPath = '';
+ let doc_ = doc;
+ let included = false;
+
+ for (let i = 0; i < len; ++i) {
+ const piece = path[i];
+
+ curPath += (!curPath.length ? '' : '.') + piece;
+
+ // support excluding intermediary levels
+ if (exclude === true) {
+ if (curPath in fields) {
+ break;
+ }
+ } else if (exclude === false && fields && !included) {
+ if (curPath in fields) {
+ included = true;
+ } else if (!hasIncludedChildren[curPath]) {
+ break;
+ }
+ }
+
+ if (i < last) {
+ doc_ = doc_[piece] || (doc_[piece] = {});
+ }
+ }
+ }
+
+ this._doc = doc;
+};
+
+/*!
+ * Converts to POJO when you use the document for querying
+ */
+
+Document.prototype.toBSON = function() {
+ return this.toObject(internalToObjectOptions);
+};
+
+/**
+ * Initializes the document without setters or marking anything modified.
+ *
+ * Called internally after a document is returned from mongodb. Normally,
+ * you do **not** need to call this function on your own.
+ *
+ * This function triggers `init` [middleware](/docs/middleware.html).
+ * Note that `init` hooks are [synchronous](/docs/middleware.html#synchronous).
+ *
+ * @param {Object} doc document returned by mongo
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.init = function(doc, opts, fn) {
+ if (typeof opts === 'function') {
+ fn = opts;
+ opts = null;
+ }
+
+ this.$__init(doc, opts);
+
+ if (fn) {
+ fn(null, this);
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Document.prototype.$__init = function(doc, opts) {
+ this.isNew = false;
+ this.$init = true;
+ opts = opts || {};
+
+ // handle docs with populated paths
+ // If doc._id is not null or undefined
+ if (doc._id != null && opts.populated && opts.populated.length) {
+ const id = String(doc._id);
+ for (const item of opts.populated) {
+ if (item.isVirtual) {
+ this.populated(item.path, utils.getValue(item.path, doc), item);
+ } else {
+ this.populated(item.path, item._docs[id], item);
+ }
+
+ if (item._childDocs == null) {
+ continue;
+ }
+ for (const child of item._childDocs) {
+ if (child == null || child.$__ == null) {
+ continue;
+ }
+ child.$__.parent = this;
+ }
+ }
+ }
+
+ init(this, doc, this._doc, opts);
+
+ markArraySubdocsPopulated(this, opts.populated);
+
+ this.emit('init', this);
+ this.constructor.emit('init', this);
+
+ this.$__._id = this._id;
+
+ return this;
+};
+
+/*!
+ * If populating a path within a document array, make sure each
+ * subdoc within the array knows its subpaths are populated.
+ *
+ * ####Example:
+ * const doc = await Article.findOne().populate('comments.author');
+ * doc.comments[0].populated('author'); // Should be set
+ */
+
+function markArraySubdocsPopulated(doc, populated) {
+ if (doc._id == null || populated == null || populated.length === 0) {
+ return;
+ }
+
+ const id = String(doc._id);
+ for (const item of populated) {
+ if (item.isVirtual) {
+ continue;
+ }
+ const path = item.path;
+ const pieces = path.split('.');
+ for (let i = 0; i < pieces.length - 1; ++i) {
+ const subpath = pieces.slice(0, i + 1).join('.');
+ const rest = pieces.slice(i + 1).join('.');
+ const val = doc.get(subpath);
+ if (val == null) {
+ continue;
+ }
+
+ if (val.isMongooseDocumentArray) {
+ for (let j = 0; j < val.length; ++j) {
+ val[j].populated(rest, item._docs[id] == null ? [] : item._docs[id][j], item);
+ }
+ break;
+ }
+ }
+ }
+}
+
+/*!
+ * Init helper.
+ *
+ * @param {Object} self document instance
+ * @param {Object} obj raw mongodb doc
+ * @param {Object} doc object we are initializing
+ * @api private
+ */
+
+function init(self, obj, doc, opts, prefix) {
+ prefix = prefix || '';
+
+ const keys = Object.keys(obj);
+ const len = keys.length;
+ let schema;
+ let path;
+ let i;
+ let index = 0;
+
+ while (index < len) {
+ _init(index++);
+ }
+
+ function _init(index) {
+ i = keys[index];
+ path = prefix + i;
+ schema = self.schema.path(path);
+
+ // Should still work if not a model-level discriminator, but should not be
+ // necessary. This is *only* to catch the case where we queried using the
+ // base model and the discriminated model has a projection
+ if (self.schema.$isRootDiscriminator && !self.isSelected(path)) {
+ return;
+ }
+
+ if (!schema && utils.isPOJO(obj[i])) {
+ // assume nested object
+ if (!doc[i]) {
+ doc[i] = {};
+ }
+ init(self, obj[i], doc[i], opts, path + '.');
+ } else if (!schema) {
+ doc[i] = obj[i];
+ } else {
+ if (obj[i] === null) {
+ doc[i] = schema._castNullish(null);
+ } else if (obj[i] !== undefined) {
+ const intCache = obj[i].$__ || {};
+ const wasPopulated = intCache.wasPopulated || null;
+
+ if (schema && !wasPopulated) {
+ try {
+ doc[i] = schema.cast(obj[i], self, true);
+ } catch (e) {
+ self.invalidate(e.path, new ValidatorError({
+ path: e.path,
+ message: e.message,
+ type: 'cast',
+ value: e.value,
+ reason: e
+ }));
+ }
+ } else {
+ doc[i] = obj[i];
+ }
+ }
+ // mark as hydrated
+ if (!self.isModified(path)) {
+ self.$__.activePaths.init(path);
+ }
+ }
+ }
+}
+
+/**
+ * Sends an update command with this document `_id` as the query selector.
+ *
+ * ####Example:
+ *
+ * weirdCar.update({$inc: {wheels:1}}, { w: 1 }, callback);
+ *
+ * ####Valid options:
+ *
+ * - same as in [Model.update](#model_Model.update)
+ *
+ * @see Model.update #model_Model.update
+ * @param {Object} doc
+ * @param {Object} options
+ * @param {Function} callback
+ * @return {Query}
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.update = function update() {
+ const args = utils.args(arguments);
+ args.unshift({ _id: this._id });
+ const query = this.constructor.update.apply(this.constructor, args);
+
+ if (this.$session() != null) {
+ if (!('session' in query.options)) {
+ query.options.session = this.$session();
+ }
+ }
+
+ return query;
+};
+
+/**
+ * Sends an updateOne command with this document `_id` as the query selector.
+ *
+ * ####Example:
+ *
+ * weirdCar.updateOne({$inc: {wheels:1}}, { w: 1 }, callback);
+ *
+ * ####Valid options:
+ *
+ * - same as in [Model.updateOne](#model_Model.updateOne)
+ *
+ * @see Model.updateOne #model_Model.updateOne
+ * @param {Object} doc
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and the [Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Function} callback
+ * @return {Query}
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.updateOne = function updateOne(doc, options, callback) {
+ const query = this.constructor.updateOne({ _id: this._id }, doc, options);
+ query._pre(cb => {
+ this.constructor._middleware.execPre('updateOne', this, [this], cb);
+ });
+ query._post(cb => {
+ this.constructor._middleware.execPost('updateOne', this, [this], {}, cb);
+ });
+
+ if (this.$session() != null) {
+ if (!('session' in query.options)) {
+ query.options.session = this.$session();
+ }
+ }
+
+ if (callback != null) {
+ return query.exec(callback);
+ }
+
+ return query;
+};
+
+/**
+ * Sends a replaceOne command with this document `_id` as the query selector.
+ *
+ * ####Valid options:
+ *
+ * - same as in [Model.replaceOne](#model_Model.replaceOne)
+ *
+ * @see Model.replaceOne #model_Model.replaceOne
+ * @param {Object} doc
+ * @param {Object} options
+ * @param {Function} callback
+ * @return {Query}
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.replaceOne = function replaceOne() {
+ const args = utils.args(arguments);
+ args.unshift({ _id: this._id });
+ return this.constructor.replaceOne.apply(this.constructor, args);
+};
+
+/**
+ * Getter/setter around the session associated with this document. Used to
+ * automatically set `session` if you `save()` a doc that you got from a
+ * query with an associated session.
+ *
+ * ####Example:
+ *
+ * const session = MyModel.startSession();
+ * const doc = await MyModel.findOne().session(session);
+ * doc.$session() === session; // true
+ * doc.$session(null);
+ * doc.$session() === null; // true
+ *
+ * If this is a top-level document, setting the session propagates to all child
+ * docs.
+ *
+ * @param {ClientSession} [session] overwrite the current session
+ * @return {ClientSession}
+ * @method $session
+ * @api public
+ * @memberOf Document
+ */
+
+Document.prototype.$session = function $session(session) {
+ if (arguments.length === 0) {
+ return this.$__.session;
+ }
+ this.$__.session = session;
+
+ if (!this.ownerDocument) {
+ const subdocs = this.$__getAllSubdocs();
+ for (const child of subdocs) {
+ child.$session(session);
+ }
+ }
+
+ return session;
+};
+
+/**
+ * Overwrite all values in this document with the values of `obj`, except
+ * for immutable properties. Behaves similarly to `set()`, except for it
+ * unsets all properties that aren't in `obj`.
+ *
+ * @param {Object} obj the object to overwrite this document with
+ * @method overwrite
+ * @name overwrite
+ * @memberOf Document
+ * @instance
+ * @api public
+ */
+
+Document.prototype.overwrite = function overwrite(obj) {
+ const keys = Array.from(new Set(Object.keys(this._doc).concat(Object.keys(obj))));
+
+ for (const key of keys) {
+ if (key === '_id') {
+ continue;
+ }
+ // Explicitly skip version key
+ if (this.schema.options.versionKey && key === this.schema.options.versionKey) {
+ continue;
+ }
+ if (this.schema.options.discriminatorKey && key === this.schema.options.discriminatorKey) {
+ continue;
+ }
+ this.$set(key, obj[key]);
+ }
+
+ return this;
+};
+
+/**
+ * Alias for `set()`, used internally to avoid conflicts
+ *
+ * @param {String|Object} path path or object of key/vals to set
+ * @param {Any} val the value to set
+ * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for "on-the-fly" attributes
+ * @param {Object} [options] optionally specify options that modify the behavior of the set
+ * @method $set
+ * @name $set
+ * @memberOf Document
+ * @instance
+ * @api public
+ */
+
+Document.prototype.$set = function $set(path, val, type, options) {
+ if (utils.isPOJO(type)) {
+ options = type;
+ type = undefined;
+ }
+
+ options = options || {};
+ const merge = options.merge;
+ const adhoc = type && type !== true;
+ const constructing = type === true;
+ let adhocs;
+ let keys;
+ let i = 0;
+ let pathtype;
+ let key;
+ let prefix;
+
+ const strict = 'strict' in options
+ ? options.strict
+ : this.$__.strictMode;
+
+ if (adhoc) {
+ adhocs = this.$__.adhocPaths || (this.$__.adhocPaths = {});
+ adhocs[path] = this.schema.interpretAsType(path, type, this.schema.options);
+ }
+
+ if (typeof path !== 'string') {
+ // new Document({ key: val })
+ if (path instanceof Document) {
+ if (path.$__isNested) {
+ path = path.toObject();
+ } else {
+ path = path._doc;
+ }
+ }
+
+ if (path == null) {
+ const _ = path;
+ path = val;
+ val = _;
+ } else {
+ prefix = val ? val + '.' : '';
+
+ keys = Object.keys(path);
+ const len = keys.length;
+
+ // `_skipMinimizeTopLevel` is because we may have deleted the top-level
+ // nested key to ensure key order.
+ const _skipMinimizeTopLevel = get(options, '_skipMinimizeTopLevel', false);
+ if (len === 0 && _skipMinimizeTopLevel) {
+ delete options._skipMinimizeTopLevel;
+ if (val) {
+ this.$set(val, {});
+ }
+ return this;
+ }
+
+ while (i < len) {
+ _handleIndex.call(this, i++);
+ }
+
+ return this;
+ }
+ } else {
+ this.$__.$setCalled.add(path);
+ }
+
+ function _handleIndex(i) {
+ key = keys[i];
+ const pathName = prefix + key;
+ pathtype = this.schema.pathType(pathName);
+
+ // On initial set, delete any nested keys if we're going to overwrite
+ // them to ensure we keep the user's key order.
+ if (type === true &&
+ !prefix &&
+ path[key] != null &&
+ pathtype === 'nested' &&
+ this._doc[key] != null &&
+ Object.keys(this._doc[key]).length === 0) {
+ delete this._doc[key];
+ // Make sure we set `{}` back even if we minimize re: gh-8565
+ options = Object.assign({}, options, { _skipMinimizeTopLevel: true });
+ }
+
+ if (typeof path[key] === 'object' &&
+ !utils.isNativeObject(path[key]) &&
+ !utils.isMongooseType(path[key]) &&
+ path[key] != null &&
+ pathtype !== 'virtual' &&
+ pathtype !== 'real' &&
+ pathtype !== 'adhocOrUndefined' &&
+ !(this.$__path(pathName) instanceof MixedSchema) &&
+ !(this.schema.paths[pathName] &&
+ this.schema.paths[pathName].options &&
+ this.schema.paths[pathName].options.ref)) {
+ this.$__.$setCalled.add(prefix + key);
+ this.$set(path[key], prefix + key, constructing, options);
+ } else if (strict) {
+ // Don't overwrite defaults with undefined keys (gh-3981) (gh-9039)
+ if (constructing && path[key] === void 0 &&
+ this.get(pathName) !== void 0) {
+ return;
+ }
+
+ if (pathtype === 'adhocOrUndefined') {
+ pathtype = getEmbeddedDiscriminatorPath(this, pathName, { typeOnly: true });
+ }
+
+ if (pathtype === 'real' || pathtype === 'virtual') {
+ // Check for setting single embedded schema to document (gh-3535)
+ let p = path[key];
+ if (this.schema.paths[pathName] &&
+ this.schema.paths[pathName].$isSingleNested &&
+ path[key] instanceof Document) {
+ p = p.toObject({ virtuals: false, transform: false });
+ }
+ this.$set(prefix + key, p, constructing, options);
+ } else if (pathtype === 'nested' && path[key] instanceof Document) {
+ this.$set(prefix + key,
+ path[key].toObject({ transform: false }), constructing, options);
+ } else if (strict === 'throw') {
+ if (pathtype === 'nested') {
+ throw new ObjectExpectedError(key, path[key]);
+ } else {
+ throw new StrictModeError(key);
+ }
+ }
+ } else if (path[key] !== void 0) {
+ this.$set(prefix + key, path[key], constructing, options);
+ }
+ }
+
+ let pathType = this.schema.pathType(path);
+ if (pathType === 'adhocOrUndefined') {
+ pathType = getEmbeddedDiscriminatorPath(this, path, { typeOnly: true });
+ }
+
+ // Assume this is a Mongoose document that was copied into a POJO using
+ // `Object.assign()` or `{...doc}`
+ val = handleSpreadDoc(val);
+
+ if (pathType === 'nested' && val) {
+ if (typeof val === 'object' && val != null) {
+ if (!merge) {
+ this.$__setValue(path, null);
+ cleanModifiedSubpaths(this, path);
+ } else {
+ return this.$set(val, path, constructing);
+ }
+
+ const keys = Object.keys(val);
+ this.$__setValue(path, {});
+ for (const key of keys) {
+ this.$set(path + '.' + key, val[key], constructing);
+ }
+ this.markModified(path);
+ cleanModifiedSubpaths(this, path, { skipDocArrays: true });
+ return this;
+ }
+ this.invalidate(path, new MongooseError.CastError('Object', val, path));
+ return this;
+ }
+
+ let schema;
+ const parts = path.indexOf('.') === -1 ? [path] : path.split('.');
+
+ // Might need to change path for top-level alias
+ if (typeof this.schema.aliases[parts[0]] == 'string') {
+ parts[0] = this.schema.aliases[parts[0]];
+ }
+
+ if (pathType === 'adhocOrUndefined' && strict) {
+ // check for roots that are Mixed types
+ let mixed;
+
+ for (i = 0; i < parts.length; ++i) {
+ const subpath = parts.slice(0, i + 1).join('.');
+
+ // If path is underneath a virtual, bypass everything and just set it.
+ if (i + 1 < parts.length && this.schema.pathType(subpath) === 'virtual') {
+ mpath.set(path, val, this);
+ return this;
+ }
+
+ schema = this.schema.path(subpath);
+ if (schema == null) {
+ continue;
+ }
+
+ if (schema instanceof MixedSchema) {
+ // allow changes to sub paths of mixed types
+ mixed = true;
+ break;
+ }
+ }
+
+ if (schema == null) {
+ // Check for embedded discriminators
+ schema = getEmbeddedDiscriminatorPath(this, path);
+ }
+
+ if (!mixed && !schema) {
+ if (strict === 'throw') {
+ throw new StrictModeError(path);
+ }
+ return this;
+ }
+ } else if (pathType === 'virtual') {
+ schema = this.schema.virtualpath(path);
+ schema.applySetters(val, this);
+ return this;
+ } else {
+ schema = this.$__path(path);
+ }
+
+ // gh-4578, if setting a deeply nested path that doesn't exist yet, create it
+ let cur = this._doc;
+ let curPath = '';
+ for (i = 0; i < parts.length - 1; ++i) {
+ cur = cur[parts[i]];
+ curPath += (curPath.length > 0 ? '.' : '') + parts[i];
+ if (!cur) {
+ this.$set(curPath, {});
+ // Hack re: gh-5800. If nested field is not selected, it probably exists
+ // so `MongoError: cannot use the part (nested of nested.num) to
+ // traverse the element ({nested: null})` is not likely. If user gets
+ // that error, its their fault for now. We should reconsider disallowing
+ // modifying not selected paths for 6.x
+ if (!this.isSelected(curPath)) {
+ this.unmarkModified(curPath);
+ }
+ cur = this.$__getValue(curPath);
+ }
+ }
+
+ let pathToMark;
+
+ // When using the $set operator the path to the field must already exist.
+ // Else mongodb throws: "LEFT_SUBFIELD only supports Object"
+
+ if (parts.length <= 1) {
+ pathToMark = path;
+ } else {
+ for (i = 0; i < parts.length; ++i) {
+ const subpath = parts.slice(0, i + 1).join('.');
+ if (this.get(subpath, null, { getters: false }) === null) {
+ pathToMark = subpath;
+ break;
+ }
+ }
+
+ if (!pathToMark) {
+ pathToMark = path;
+ }
+ }
+
+ // if this doc is being constructed we should not trigger getters
+ const priorVal = (() => {
+ if (this.$__.$options.priorDoc != null) {
+ return this.$__.$options.priorDoc.$__getValue(path);
+ }
+ if (constructing) {
+ return void 0;
+ }
+ return this.$__getValue(path);
+ })();
+
+ if (!schema) {
+ this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
+ return this;
+ }
+
+ // If overwriting a subdocument path, make sure to clear out
+ // any errors _before_ setting, so new errors that happen
+ // get persisted. Re: #9080
+ if (schema.$isSingleNested || schema.$isMongooseArray) {
+ _markValidSubpaths(this, path);
+ }
+
+ if (schema.$isSingleNested && val != null && merge) {
+ if (val instanceof Document) {
+ val = val.toObject({ virtuals: false, transform: false });
+ }
+ const keys = Object.keys(val);
+ for (const key of keys) {
+ this.$set(path + '.' + key, val[key], constructing, options);
+ }
+
+ return this;
+ }
+
+ let shouldSet = true;
+ try {
+ // If the user is trying to set a ref path to a document with
+ // the correct model name, treat it as populated
+ const refMatches = (() => {
+ if (schema.options == null) {
+ return false;
+ }
+ if (!(val instanceof Document)) {
+ return false;
+ }
+ const model = val.constructor;
+
+ // Check ref
+ const ref = schema.options.ref;
+ if (ref != null && (ref === model.modelName || ref === model.baseModelName)) {
+ return true;
+ }
+
+ // Check refPath
+ const refPath = schema.options.refPath;
+ if (refPath == null) {
+ return false;
+ }
+ const modelName = val.get(refPath);
+ return modelName === model.modelName || modelName === model.baseModelName;
+ })();
+
+ let didPopulate = false;
+ if (refMatches && val instanceof Document) {
+ this.populated(path, val._id, { [populateModelSymbol]: val.constructor });
+ didPopulate = true;
+ }
+
+ let popOpts;
+ if (schema.options &&
+ Array.isArray(schema.options[this.schema.options.typeKey]) &&
+ schema.options[this.schema.options.typeKey].length &&
+ schema.options[this.schema.options.typeKey][0].ref &&
+ _isManuallyPopulatedArray(val, schema.options[this.schema.options.typeKey][0].ref)) {
+ if (this.ownerDocument) {
+ popOpts = { [populateModelSymbol]: val[0].constructor };
+ this.ownerDocument().populated(this.$__fullPath(path),
+ val.map(function(v) { return v._id; }), popOpts);
+ } else {
+ popOpts = { [populateModelSymbol]: val[0].constructor };
+ this.populated(path, val.map(function(v) { return v._id; }), popOpts);
+ }
+ didPopulate = true;
+ }
+
+ if (this.schema.singleNestedPaths[path] == null) {
+ // If this path is underneath a single nested schema, we'll call the setter
+ // later in `$__set()` because we don't take `_doc` when we iterate through
+ // a single nested doc. That's to make sure we get the correct context.
+ // Otherwise we would double-call the setter, see gh-7196.
+ val = schema.applySetters(val, this, false, priorVal);
+ }
+
+ if (schema.$isMongooseDocumentArray &&
+ Array.isArray(val) &&
+ val.length > 0 &&
+ val[0] != null &&
+ val[0].$__ != null &&
+ val[0].$__.populated != null) {
+ const populatedPaths = Object.keys(val[0].$__.populated);
+ for (const populatedPath of populatedPaths) {
+ this.populated(path + '.' + populatedPath,
+ val.map(v => v.populated(populatedPath)),
+ val[0].$__.populated[populatedPath].options);
+ }
+ didPopulate = true;
+ }
+
+ if (!didPopulate && this.$__.populated) {
+ // If this array partially contains populated documents, convert them
+ // all to ObjectIds re: #8443
+ if (Array.isArray(val) && this.$__.populated[path]) {
+ for (let i = 0; i < val.length; ++i) {
+ if (val[i] instanceof Document) {
+ val[i] = val[i]._id;
+ }
+ }
+ }
+ delete this.$__.populated[path];
+ }
+
+ if (schema.$isSingleNested && val != null) {
+ _checkImmutableSubpaths(val, schema, priorVal);
+ }
+
+ this.$markValid(path);
+ } catch (e) {
+ if (e instanceof MongooseError.StrictModeError && e.isImmutableError) {
+ this.invalidate(path, e);
+ } else if (e instanceof MongooseError.CastError) {
+ this.invalidate(e.path, e);
+ if (e.$originalErrorPath) {
+ this.invalidate(path,
+ new MongooseError.CastError(schema.instance, val, path, e.$originalErrorPath));
+ }
+ } else {
+ this.invalidate(path,
+ new MongooseError.CastError(schema.instance, val, path, e));
+ }
+ shouldSet = false;
+ }
+
+ if (shouldSet) {
+ this.$__set(pathToMark, path, constructing, parts, schema, val, priorVal);
+ }
+
+ if (schema.$isSingleNested && (this.isDirectModified(path) || val == null)) {
+ cleanModifiedSubpaths(this, path);
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+function _isManuallyPopulatedArray(val, ref) {
+ if (!Array.isArray(val)) {
+ return false;
+ }
+ if (val.length === 0) {
+ return false;
+ }
+
+ for (const el of val) {
+ if (!(el instanceof Document)) {
+ return false;
+ }
+ const modelName = el.constructor.modelName;
+ if (modelName == null) {
+ return false;
+ }
+ if (el.constructor.modelName != ref && el.constructor.baseModelName != ref) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/**
+ * Sets the value of a path, or many paths.
+ *
+ * ####Example:
+ *
+ * // path, value
+ * doc.set(path, value)
+ *
+ * // object
+ * doc.set({
+ * path : value
+ * , path2 : {
+ * path : value
+ * }
+ * })
+ *
+ * // on-the-fly cast to number
+ * doc.set(path, value, Number)
+ *
+ * // on-the-fly cast to string
+ * doc.set(path, value, String)
+ *
+ * // changing strict mode behavior
+ * doc.set(path, value, { strict: false });
+ *
+ * @param {String|Object} path path or object of key/vals to set
+ * @param {Any} val the value to set
+ * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for "on-the-fly" attributes
+ * @param {Object} [options] optionally specify options that modify the behavior of the set
+ * @api public
+ * @method set
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.set = Document.prototype.$set;
+
+/**
+ * Determine if we should mark this change as modified.
+ *
+ * @return {Boolean}
+ * @api private
+ * @method $__shouldModify
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__shouldModify = function(pathToMark, path, constructing, parts, schema, val, priorVal) {
+ if (this.isNew) {
+ return true;
+ }
+
+ // Re: the note about gh-7196, `val` is the raw value without casting or
+ // setters if the full path is under a single nested subdoc because we don't
+ // want to double run setters. So don't set it as modified. See gh-7264.
+ if (this.schema.singleNestedPaths[path] != null) {
+ return false;
+ }
+
+ if (val === void 0 && !this.isSelected(path)) {
+ // when a path is not selected in a query, its initial
+ // value will be undefined.
+ return true;
+ }
+
+ if (val === void 0 && path in this.$__.activePaths.states.default) {
+ // we're just unsetting the default value which was never saved
+ return false;
+ }
+
+ // gh-3992: if setting a populated field to a doc, don't mark modified
+ // if they have the same _id
+ if (this.populated(path) &&
+ val instanceof Document &&
+ deepEqual(val._id, priorVal)) {
+ return false;
+ }
+
+ if (!deepEqual(val, priorVal || utils.getValue(path, this))) {
+ return true;
+ }
+
+ if (!constructing &&
+ val !== null &&
+ val !== undefined &&
+ path in this.$__.activePaths.states.default &&
+ deepEqual(val, schema.getDefault(this, constructing))) {
+ // a path with a default was $unset on the server
+ // and the user is setting it to the same value again
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Handles the actual setting of the value and marking the path modified if appropriate.
+ *
+ * @api private
+ * @method $__set
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__set = function(pathToMark, path, constructing, parts, schema, val, priorVal) {
+ Embedded = Embedded || require('./types/embedded');
+
+ const shouldModify = this.$__shouldModify(pathToMark, path, constructing, parts,
+ schema, val, priorVal);
+ const _this = this;
+
+ if (shouldModify) {
+ this.markModified(pathToMark);
+
+ // handle directly setting arrays (gh-1126)
+ MongooseArray || (MongooseArray = require('./types/array'));
+ if (val && val.isMongooseArray) {
+ val._registerAtomic('$set', val);
+
+ // Update embedded document parent references (gh-5189)
+ if (val.isMongooseDocumentArray) {
+ val.forEach(function(item) {
+ item && item.__parentArray && (item.__parentArray = val);
+ });
+ }
+
+ // Small hack for gh-1638: if we're overwriting the entire array, ignore
+ // paths that were modified before the array overwrite
+ this.$__.activePaths.forEach(function(modifiedPath) {
+ if (modifiedPath.startsWith(path + '.')) {
+ _this.$__.activePaths.ignore(modifiedPath);
+ }
+ });
+ }
+ }
+
+ let obj = this._doc;
+ let i = 0;
+ const l = parts.length;
+ let cur = '';
+
+ for (; i < l; i++) {
+ const next = i + 1;
+ const last = next === l;
+ cur += (cur ? '.' + parts[i] : parts[i]);
+ if (specialProperties.has(parts[i])) {
+ return;
+ }
+
+ if (last) {
+ if (obj instanceof Map) {
+ obj.set(parts[i], val);
+ } else {
+ obj[parts[i]] = val;
+ }
+ } else {
+ if (utils.isPOJO(obj[parts[i]])) {
+ obj = obj[parts[i]];
+ } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
+ obj = obj[parts[i]];
+ } else if (obj[parts[i]] && obj[parts[i]].$isSingleNested) {
+ obj = obj[parts[i]];
+ } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
+ obj = obj[parts[i]];
+ } else {
+ obj[parts[i]] = obj[parts[i]] || {};
+ obj = obj[parts[i]];
+ }
+ }
+ }
+};
+
+/**
+ * Gets a raw value from a path (no getters)
+ *
+ * @param {String} path
+ * @api private
+ */
+
+Document.prototype.$__getValue = function(path) {
+ return utils.getValue(path, this._doc);
+};
+
+/**
+ * Sets a raw value for a path (no casting, setters, transformations)
+ *
+ * @param {String} path
+ * @param {Object} value
+ * @api private
+ */
+
+Document.prototype.$__setValue = function(path, val) {
+ utils.setValue(path, val, this._doc);
+ return this;
+};
+
+/**
+ * Returns the value of a path.
+ *
+ * ####Example
+ *
+ * // path
+ * doc.get('age') // 47
+ *
+ * // dynamic casting to a string
+ * doc.get('age', String) // "47"
+ *
+ * @param {String} path
+ * @param {Schema|String|Number|Buffer|*} [type] optionally specify a type for on-the-fly attributes
+ * @param {Object} [options]
+ * @param {Boolean} [options.virtuals=false] Apply virtuals before getting this path
+ * @param {Boolean} [options.getters=true] If false, skip applying getters and just get the raw value
+ * @api public
+ */
+
+Document.prototype.get = function(path, type, options) {
+ let adhoc;
+ options = options || {};
+ if (type) {
+ adhoc = this.schema.interpretAsType(path, type, this.schema.options);
+ }
+
+ let schema = this.$__path(path);
+ if (schema == null) {
+ schema = this.schema.virtualpath(path);
+ }
+ if (schema instanceof MixedSchema) {
+ const virtual = this.schema.virtualpath(path);
+ if (virtual != null) {
+ schema = virtual;
+ }
+ }
+ const pieces = path.split('.');
+ let obj = this._doc;
+
+ if (schema instanceof VirtualType) {
+ if (schema.getters.length === 0) {
+ return void 0;
+ }
+ return schema.applyGetters(null, this);
+ }
+
+ // Might need to change path for top-level alias
+ if (typeof this.schema.aliases[pieces[0]] == 'string') {
+ pieces[0] = this.schema.aliases[pieces[0]];
+ }
+
+ for (let i = 0, l = pieces.length; i < l; i++) {
+ if (obj && obj._doc) {
+ obj = obj._doc;
+ }
+
+ if (obj == null) {
+ obj = void 0;
+ } else if (obj instanceof Map) {
+ obj = obj.get(pieces[i], { getters: false });
+ } else if (i === l - 1) {
+ obj = utils.getValue(pieces[i], obj);
+ } else {
+ obj = obj[pieces[i]];
+ }
+ }
+
+ if (adhoc) {
+ obj = adhoc.cast(obj);
+ }
+
+ if (schema != null && options.getters !== false) {
+ obj = schema.applyGetters(obj, this);
+ } else if (this.schema.nested[path] && options.virtuals) {
+ // Might need to apply virtuals if this is a nested path
+ return applyVirtuals(this, utils.clone(obj) || {}, { path: path });
+ }
+
+ return obj;
+};
+
+/*!
+ * ignore
+ */
+
+Document.prototype[getSymbol] = Document.prototype.get;
+
+/**
+ * Returns the schematype for the given `path`.
+ *
+ * @param {String} path
+ * @api private
+ * @method $__path
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__path = function(path) {
+ const adhocs = this.$__.adhocPaths;
+ const adhocType = adhocs && adhocs.hasOwnProperty(path) ? adhocs[path] : null;
+
+ if (adhocType) {
+ return adhocType;
+ }
+ return this.schema.path(path);
+};
+
+/**
+ * Marks the path as having pending changes to write to the db.
+ *
+ * _Very helpful when using [Mixed](./schematypes.html#mixed) types._
+ *
+ * ####Example:
+ *
+ * doc.mixed.type = 'changed';
+ * doc.markModified('mixed.type');
+ * doc.save() // changes to mixed.type are now persisted
+ *
+ * @param {String} path the path to mark modified
+ * @param {Document} [scope] the scope to run validators with
+ * @api public
+ */
+
+Document.prototype.markModified = function(path, scope) {
+ this.$__.activePaths.modify(path);
+ if (scope != null && !this.ownerDocument) {
+ this.$__.pathsToScopes[path] = scope;
+ }
+};
+
+/**
+ * Clears the modified state on the specified path.
+ *
+ * ####Example:
+ *
+ * doc.foo = 'bar';
+ * doc.unmarkModified('foo');
+ * doc.save(); // changes to foo will not be persisted
+ *
+ * @param {String} path the path to unmark modified
+ * @api public
+ */
+
+Document.prototype.unmarkModified = function(path) {
+ this.$__.activePaths.init(path);
+ delete this.$__.pathsToScopes[path];
+};
+
+/**
+ * Don't run validation on this path or persist changes to this path.
+ *
+ * ####Example:
+ *
+ * doc.foo = null;
+ * doc.$ignore('foo');
+ * doc.save(); // changes to foo will not be persisted and validators won't be run
+ *
+ * @memberOf Document
+ * @instance
+ * @method $ignore
+ * @param {String} path the path to ignore
+ * @api public
+ */
+
+Document.prototype.$ignore = function(path) {
+ this.$__.activePaths.ignore(path);
+};
+
+/**
+ * Returns the list of paths that have been directly modified. A direct
+ * modified path is a path that you explicitly set, whether via `doc.foo = 'bar'`,
+ * `Object.assign(doc, { foo: 'bar' })`, or `doc.set('foo', 'bar')`.
+ *
+ * A path `a` may be in `modifiedPaths()` but not in `directModifiedPaths()`
+ * because a child of `a` was directly modified.
+ *
+ * ####Example
+ * const schema = new Schema({ foo: String, nested: { bar: String } });
+ * const Model = mongoose.model('Test', schema);
+ * await Model.create({ foo: 'original', nested: { bar: 'original' } });
+ *
+ * const doc = await Model.findOne();
+ * doc.nested.bar = 'modified';
+ * doc.directModifiedPaths(); // ['nested.bar']
+ * doc.modifiedPaths(); // ['nested', 'nested.bar']
+ *
+ * @return {Array}
+ * @api public
+ */
+
+Document.prototype.directModifiedPaths = function() {
+ return Object.keys(this.$__.activePaths.states.modify);
+};
+
+/**
+ * Returns true if the given path is nullish or only contains empty objects.
+ * Useful for determining whether this subdoc will get stripped out by the
+ * [minimize option](/docs/guide.html#minimize).
+ *
+ * ####Example:
+ * const schema = new Schema({ nested: { foo: String } });
+ * const Model = mongoose.model('Test', schema);
+ * const doc = new Model({});
+ * doc.$isEmpty('nested'); // true
+ * doc.nested.$isEmpty(); // true
+ *
+ * doc.nested.foo = 'bar';
+ * doc.$isEmpty('nested'); // false
+ * doc.nested.$isEmpty(); // false
+ *
+ * @memberOf Document
+ * @instance
+ * @api public
+ * @method $isEmpty
+ * @return {Boolean}
+ */
+
+Document.prototype.$isEmpty = function(path) {
+ const isEmptyOptions = {
+ minimize: true,
+ virtuals: false,
+ getters: false,
+ transform: false
+ };
+
+ if (arguments.length > 0) {
+ const v = this.get(path);
+ if (v == null) {
+ return true;
+ }
+ if (typeof v !== 'object') {
+ return false;
+ }
+ if (utils.isPOJO(v)) {
+ return _isEmpty(v);
+ }
+ return Object.keys(v.toObject(isEmptyOptions)).length === 0;
+ }
+
+ return Object.keys(this.toObject(isEmptyOptions)).length === 0;
+};
+
+function _isEmpty(v) {
+ if (v == null) {
+ return true;
+ }
+ if (typeof v !== 'object' || Array.isArray(v)) {
+ return false;
+ }
+ for (const key of Object.keys(v)) {
+ if (!_isEmpty(v[key])) {
+ return false;
+ }
+ }
+ return true;
+}
+
+/**
+ * Returns the list of paths that have been modified.
+ *
+ * @param {Object} [options]
+ * @param {Boolean} [options.includeChildren=false] if true, returns children of modified paths as well. For example, if false, the list of modified paths for `doc.colors = { primary: 'blue' };` will **not** contain `colors.primary`. If true, `modifiedPaths()` will return an array that contains `colors.primary`.
+ * @return {Array}
+ * @api public
+ */
+
+Document.prototype.modifiedPaths = function(options) {
+ options = options || {};
+ const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
+ const _this = this;
+ return directModifiedPaths.reduce(function(list, path) {
+ const parts = path.split('.');
+ list = list.concat(parts.reduce(function(chains, part, i) {
+ return chains.concat(parts.slice(0, i).concat(part).join('.'));
+ }, []).filter(function(chain) {
+ return (list.indexOf(chain) === -1);
+ }));
+
+ if (!options.includeChildren) {
+ return list;
+ }
+
+ let cur = _this.get(path);
+ if (cur != null && typeof cur === 'object') {
+ if (cur._doc) {
+ cur = cur._doc;
+ }
+ if (Array.isArray(cur)) {
+ const len = cur.length;
+ for (let i = 0; i < len; ++i) {
+ if (list.indexOf(path + '.' + i) === -1) {
+ list.push(path + '.' + i);
+ if (cur[i] != null && cur[i].$__) {
+ const modified = cur[i].modifiedPaths();
+ for (const childPath of modified) {
+ list.push(path + '.' + i + '.' + childPath);
+ }
+ }
+ }
+ }
+ } else {
+ Object.keys(cur).
+ filter(function(key) {
+ return list.indexOf(path + '.' + key) === -1;
+ }).
+ forEach(function(key) {
+ list.push(path + '.' + key);
+ });
+ }
+ }
+
+ return list;
+ }, []);
+};
+
+Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
+
+/**
+ * Returns true if this document was modified, else false.
+ *
+ * If `path` is given, checks if a path or any full path containing `path` as part of its path chain has been modified.
+ *
+ * ####Example
+ *
+ * doc.set('documents.0.title', 'changed');
+ * doc.isModified() // true
+ * doc.isModified('documents') // true
+ * doc.isModified('documents.0.title') // true
+ * doc.isModified('documents otherProp') // true
+ * doc.isDirectModified('documents') // false
+ *
+ * @param {String} [path] optional
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isModified = function(paths, modifiedPaths) {
+ if (paths) {
+ if (!Array.isArray(paths)) {
+ paths = paths.split(' ');
+ }
+ const modified = modifiedPaths || this[documentModifiedPaths]();
+ const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
+ const isModifiedChild = paths.some(function(path) {
+ return !!~modified.indexOf(path);
+ });
+
+ return isModifiedChild || paths.some(function(path) {
+ return directModifiedPaths.some(function(mod) {
+ return mod === path || path.startsWith(mod + '.');
+ });
+ });
+ }
+
+ return this.$__.activePaths.some('modify');
+};
+
+Document.prototype[documentIsModified] = Document.prototype.isModified;
+
+/**
+ * Checks if a path is set to its default.
+ *
+ * ####Example
+ *
+ * MyModel = mongoose.model('test', { name: { type: String, default: 'Val '} });
+ * const m = new MyModel();
+ * m.$isDefault('name'); // true
+ *
+ * @memberOf Document
+ * @instance
+ * @method $isDefault
+ * @param {String} [path]
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.$isDefault = function(path) {
+ return (path in this.$__.activePaths.states.default);
+};
+
+/**
+ * Getter/setter, determines whether the document was removed or not.
+ *
+ * ####Example:
+ * product.remove(function (err, product) {
+ * product.$isDeleted(); // true
+ * product.remove(); // no-op, doesn't send anything to the db
+ *
+ * product.$isDeleted(false);
+ * product.$isDeleted(); // false
+ * product.remove(); // will execute a remove against the db
+ * })
+ *
+ * @param {Boolean} [val] optional, overrides whether mongoose thinks the doc is deleted
+ * @return {Boolean} whether mongoose thinks this doc is deleted.
+ * @method $isDeleted
+ * @memberOf Document
+ * @instance
+ * @api public
+ */
+
+Document.prototype.$isDeleted = function(val) {
+ if (arguments.length === 0) {
+ return !!this.$__.isDeleted;
+ }
+
+ this.$__.isDeleted = !!val;
+ return this;
+};
+
+/**
+ * Returns true if `path` was directly set and modified, else false.
+ *
+ * ####Example
+ *
+ * doc.set('documents.0.title', 'changed');
+ * doc.isDirectModified('documents.0.title') // true
+ * doc.isDirectModified('documents') // false
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isDirectModified = function(path) {
+ return (path in this.$__.activePaths.states.modify);
+};
+
+/**
+ * Checks if `path` was initialized.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isInit = function(path) {
+ return (path in this.$__.activePaths.states.init);
+};
+
+/**
+ * Checks if `path` was selected in the source query which initialized this document.
+ *
+ * ####Example
+ *
+ * Thing.findOne().select('name').exec(function (err, doc) {
+ * doc.isSelected('name') // true
+ * doc.isSelected('age') // false
+ * })
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isSelected = function isSelected(path) {
+ if (this.$__.selected) {
+ if (path === '_id') {
+ return this.$__.selected._id !== 0;
+ }
+
+ const paths = Object.keys(this.$__.selected);
+ let i = paths.length;
+ let inclusive = null;
+ let cur;
+
+ if (i === 1 && paths[0] === '_id') {
+ // only _id was selected.
+ return this.$__.selected._id === 0;
+ }
+
+ while (i--) {
+ cur = paths[i];
+ if (cur === '_id') {
+ continue;
+ }
+ if (!isDefiningProjection(this.$__.selected[cur])) {
+ continue;
+ }
+ inclusive = !!this.$__.selected[cur];
+ break;
+ }
+
+ if (inclusive === null) {
+ return true;
+ }
+
+ if (path in this.$__.selected) {
+ return inclusive;
+ }
+
+ i = paths.length;
+ const pathDot = path + '.';
+
+ while (i--) {
+ cur = paths[i];
+ if (cur === '_id') {
+ continue;
+ }
+
+ if (cur.startsWith(pathDot)) {
+ return inclusive || cur !== pathDot;
+ }
+
+ if (pathDot.startsWith(cur + '.')) {
+ return inclusive;
+ }
+ }
+
+ return !inclusive;
+ }
+
+ return true;
+};
+
+Document.prototype[documentIsSelected] = Document.prototype.isSelected;
+
+/**
+ * Checks if `path` was explicitly selected. If no projection, always returns
+ * true.
+ *
+ * ####Example
+ *
+ * Thing.findOne().select('nested.name').exec(function (err, doc) {
+ * doc.isDirectSelected('nested.name') // true
+ * doc.isDirectSelected('nested.otherName') // false
+ * doc.isDirectSelected('nested') // false
+ * })
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api public
+ */
+
+Document.prototype.isDirectSelected = function isDirectSelected(path) {
+ if (this.$__.selected) {
+ if (path === '_id') {
+ return this.$__.selected._id !== 0;
+ }
+
+ const paths = Object.keys(this.$__.selected);
+ let i = paths.length;
+ let inclusive = null;
+ let cur;
+
+ if (i === 1 && paths[0] === '_id') {
+ // only _id was selected.
+ return this.$__.selected._id === 0;
+ }
+
+ while (i--) {
+ cur = paths[i];
+ if (cur === '_id') {
+ continue;
+ }
+ if (!isDefiningProjection(this.$__.selected[cur])) {
+ continue;
+ }
+ inclusive = !!this.$__.selected[cur];
+ break;
+ }
+
+ if (inclusive === null) {
+ return true;
+ }
+
+ if (path in this.$__.selected) {
+ return inclusive;
+ }
+
+ return !inclusive;
+ }
+
+ return true;
+};
+
+/**
+ * Executes registered validation rules for this document.
+ *
+ * ####Note:
+ *
+ * This method is called `pre` save and if a validation rule is violated, [save](#model_Model-save) is aborted and the error is returned to your `callback`.
+ *
+ * ####Example:
+ *
+ * doc.validate(function (err) {
+ * if (err) handleError(err);
+ * else // validation passed
+ * });
+ *
+ * @param {Array|String} [pathsToValidate] list of paths to validate. If set, Mongoose will validate only the modified paths that are in the given list.
+ * @param {Object} [options] internal options
+ * @param {Boolean} [options.validateModifiedOnly=false] if `true` mongoose validates only modified paths.
+ * @param {Function} [callback] optional callback called after validation completes, passing an error if one occurred
+ * @return {Promise} Promise
+ * @api public
+ */
+
+Document.prototype.validate = function(pathsToValidate, options, callback) {
+ let parallelValidate;
+ this.$op = 'validate';
+
+ if (this.ownerDocument != null) {
+ // Skip parallel validate check for subdocuments
+ } else if (this.$__.validating) {
+ parallelValidate = new ParallelValidateError(this, {
+ parentStack: options && options.parentStack,
+ conflictStack: this.$__.validating.stack
+ });
+ } else {
+ this.$__.validating = new ParallelValidateError(this, { parentStack: options && options.parentStack });
+ }
+
+ if (typeof pathsToValidate === 'function') {
+ callback = pathsToValidate;
+ options = null;
+ pathsToValidate = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = pathsToValidate;
+ pathsToValidate = null;
+ }
+
+ return promiseOrCallback(callback, cb => {
+ if (parallelValidate != null) {
+ return cb(parallelValidate);
+ }
+
+ this.$__validate(pathsToValidate, options, (error) => {
+ this.$op = null;
+ cb(error);
+ });
+ }, this.constructor.events);
+};
+
+/*!
+ * ignore
+ */
+
+function _evaluateRequiredFunctions(doc) {
+ Object.keys(doc.$__.activePaths.states.require).forEach(path => {
+ const p = doc.schema.path(path);
+
+ if (p != null && typeof p.originalRequiredValue === 'function') {
+ doc.$__.cachedRequired[path] = p.originalRequiredValue.call(doc, doc);
+ }
+ });
+}
+
+/*!
+ * ignore
+ */
+
+function _getPathsToValidate(doc) {
+ const skipSchemaValidators = {};
+
+ _evaluateRequiredFunctions(doc);
+
+ // only validate required fields when necessary
+ let paths = new Set(Object.keys(doc.$__.activePaths.states.require).filter(function(path) {
+ if (!doc.isSelected(path) && !doc.isModified(path)) {
+ return false;
+ }
+ if (path in doc.$__.cachedRequired) {
+ return doc.$__.cachedRequired[path];
+ }
+ return true;
+ }));
+
+
+ Object.keys(doc.$__.activePaths.states.init).forEach(addToPaths);
+ Object.keys(doc.$__.activePaths.states.modify).forEach(addToPaths);
+ Object.keys(doc.$__.activePaths.states.default).forEach(addToPaths);
+ function addToPaths(p) { paths.add(p); }
+
+ const subdocs = doc.$__getAllSubdocs();
+ const modifiedPaths = doc.modifiedPaths();
+ for (const subdoc of subdocs) {
+ if (subdoc.$basePath) {
+ // Remove child paths for now, because we'll be validating the whole
+ // subdoc
+ for (const p of paths) {
+ if (p === null || p.startsWith(subdoc.$basePath + '.')) {
+ paths.delete(p);
+ }
+ }
+
+ if (doc.isModified(subdoc.$basePath, modifiedPaths) &&
+ !doc.isDirectModified(subdoc.$basePath) &&
+ !doc.$isDefault(subdoc.$basePath)) {
+ paths.add(subdoc.$basePath);
+
+ skipSchemaValidators[subdoc.$basePath] = true;
+ }
+ }
+ }
+
+ // from here on we're not removing items from paths
+
+ // gh-661: if a whole array is modified, make sure to run validation on all
+ // the children as well
+ for (const path of paths) {
+ const _pathType = doc.schema.path(path);
+ if (!_pathType ||
+ !_pathType.$isMongooseArray ||
+ // To avoid potential performance issues, skip doc arrays whose children
+ // are not required. `getPositionalPathType()` may be slow, so avoid
+ // it unless we have a case of #6364
+ (_pathType.$isMongooseDocumentArray && !get(_pathType, 'schemaOptions.required'))) {
+ continue;
+ }
+
+ const val = doc.$__getValue(path);
+ _pushNestedArrayPaths(val, paths, path);
+ }
+
+ function _pushNestedArrayPaths(val, paths, path) {
+ if (val != null) {
+ const numElements = val.length;
+ for (let j = 0; j < numElements; ++j) {
+ if (Array.isArray(val[j])) {
+ _pushNestedArrayPaths(val[j], paths, path + '.' + j);
+ } else {
+ paths.add(path + '.' + j);
+ }
+ }
+ }
+ }
+
+ const flattenOptions = { skipArrays: true };
+ for (const pathToCheck of paths) {
+ if (doc.schema.nested[pathToCheck]) {
+ let _v = doc.$__getValue(pathToCheck);
+ if (isMongooseObject(_v)) {
+ _v = _v.toObject({ transform: false });
+ }
+ const flat = flatten(_v, pathToCheck, flattenOptions, doc.schema);
+ Object.keys(flat).forEach(addToPaths);
+ }
+ }
+
+
+ for (const path of paths) {
+ // Single nested paths (paths embedded under single nested subdocs) will
+ // be validated on their own when we call `validate()` on the subdoc itself.
+ // Re: gh-8468
+ if (doc.schema.singleNestedPaths.hasOwnProperty(path)) {
+ paths.delete(path);
+ continue;
+ }
+ const _pathType = doc.schema.path(path);
+ if (!_pathType || !_pathType.$isSchemaMap) {
+ continue;
+ }
+
+ const val = doc.$__getValue(path);
+ if (val == null) {
+ continue;
+ }
+ for (const key of val.keys()) {
+ paths.add(path + '.' + key);
+ }
+ }
+
+ paths = Array.from(paths);
+ return [paths, skipSchemaValidators];
+}
+
+/*!
+ * ignore
+ */
+
+Document.prototype.$__validate = function(pathsToValidate, options, callback) {
+ if (typeof pathsToValidate === 'function') {
+ callback = pathsToValidate;
+ options = null;
+ pathsToValidate = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const hasValidateModifiedOnlyOption = options &&
+ (typeof options === 'object') &&
+ ('validateModifiedOnly' in options);
+
+ let shouldValidateModifiedOnly;
+ if (hasValidateModifiedOnlyOption) {
+ shouldValidateModifiedOnly = !!options.validateModifiedOnly;
+ } else {
+ shouldValidateModifiedOnly = this.schema.options.validateModifiedOnly;
+ }
+
+ const _this = this;
+ const _complete = () => {
+ let validationError = this.$__.validationError;
+ this.$__.validationError = undefined;
+
+ if (shouldValidateModifiedOnly && validationError != null) {
+ // Remove any validation errors that aren't from modified paths
+ const errors = Object.keys(validationError.errors);
+ for (const errPath of errors) {
+ if (!this.isModified(errPath)) {
+ delete validationError.errors[errPath];
+ }
+ }
+ if (Object.keys(validationError.errors).length === 0) {
+ validationError = void 0;
+ }
+ }
+
+ this.$__.cachedRequired = {};
+ this.emit('validate', _this);
+ this.constructor.emit('validate', _this);
+
+ this.$__.validating = null;
+ if (validationError) {
+ for (const key in validationError.errors) {
+ // Make sure cast errors persist
+ if (!this[documentArrayParent] &&
+ validationError.errors[key] instanceof MongooseError.CastError) {
+ this.invalidate(key, validationError.errors[key]);
+ }
+ }
+
+ return validationError;
+ }
+ };
+
+ // only validate required fields when necessary
+ const pathDetails = _getPathsToValidate(this);
+ let paths = shouldValidateModifiedOnly ?
+ pathDetails[0].filter((path) => this.isModified(path)) :
+ pathDetails[0];
+ const skipSchemaValidators = pathDetails[1];
+
+ if (Array.isArray(pathsToValidate)) {
+ paths = _handlePathsToValidate(paths, pathsToValidate);
+ }
+
+ if (paths.length === 0) {
+ return process.nextTick(function() {
+ const error = _complete();
+ if (error) {
+ return _this.schema.s.hooks.execPost('validate:error', _this, [_this], { error: error }, function(error) {
+ callback(error);
+ });
+ }
+ callback(null, _this);
+ });
+ }
+
+ const validated = {};
+ let total = 0;
+
+ const complete = function() {
+ const error = _complete();
+ if (error) {
+ return _this.schema.s.hooks.execPost('validate:error', _this, [_this], { error: error }, function(error) {
+ callback(error);
+ });
+ }
+ callback(null, _this);
+ };
+
+ const validatePath = function(path) {
+ if (path == null || validated[path]) {
+ return;
+ }
+
+ validated[path] = true;
+ total++;
+
+ process.nextTick(function() {
+ const schemaType = _this.schema.path(path);
+
+ if (!schemaType) {
+ return --total || complete();
+ }
+
+ // If user marked as invalid or there was a cast error, don't validate
+ if (!_this.$isValid(path)) {
+ --total || complete();
+ return;
+ }
+
+ let val = _this.$__getValue(path);
+
+ // If you `populate()` and get back a null value, required validators
+ // shouldn't fail (gh-8018). We should always fall back to the populated
+ // value.
+ let pop;
+ if (val == null && (pop = _this.populated(path))) {
+ val = pop;
+ }
+ const scope = path in _this.$__.pathsToScopes ?
+ _this.$__.pathsToScopes[path] :
+ _this;
+
+ const doValidateOptions = {
+ skipSchemaValidators: skipSchemaValidators[path],
+ path: path
+ };
+ schemaType.doValidate(val, function(err) {
+ if (err && (!schemaType.$isMongooseDocumentArray || err.$isArrayValidatorError)) {
+ if (schemaType.$isSingleNested &&
+ err instanceof ValidationError &&
+ schemaType.schema.options.storeSubdocValidationError === false) {
+ return --total || complete();
+ }
+ _this.invalidate(path, err, undefined, true);
+ }
+ --total || complete();
+ }, scope, doValidateOptions);
+ });
+ };
+
+ const numPaths = paths.length;
+ for (let i = 0; i < numPaths; ++i) {
+ validatePath(paths[i]);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function _handlePathsToValidate(paths, pathsToValidate) {
+ const _pathsToValidate = new Set(pathsToValidate);
+ const parentPaths = new Map([]);
+ for (const path of pathsToValidate) {
+ if (path.indexOf('.') === -1) {
+ continue;
+ }
+ const pieces = path.split('.');
+ let cur = pieces[0];
+ for (let i = 1; i < pieces.length; ++i) {
+ // Since we skip subpaths under single nested subdocs to
+ // avoid double validation, we need to add back the
+ // single nested subpath if the user asked for it (gh-8626)
+ parentPaths.set(cur, path);
+ cur = cur + '.' + pieces[i];
+ }
+ }
+
+ const ret = [];
+ for (const path of paths) {
+ if (_pathsToValidate.has(path)) {
+ ret.push(path);
+ } else if (parentPaths.has(path)) {
+ ret.push(parentPaths.get(path));
+ }
+ }
+ return ret;
+}
+
+/**
+ * Executes registered validation rules (skipping asynchronous validators) for this document.
+ *
+ * ####Note:
+ *
+ * This method is useful if you need synchronous validation.
+ *
+ * ####Example:
+ *
+ * const err = doc.validateSync();
+ * if (err) {
+ * handleError(err);
+ * } else {
+ * // validation passed
+ * }
+ *
+ * @param {Array|string} pathsToValidate only validate the given paths
+ * @param {Object} [options] options for validation
+ * @param {Boolean} [options.validateModifiedOnly=false] If `true`, Mongoose will only validate modified paths, as opposed to modified paths and `required` paths.
+ * @return {ValidationError|undefined} ValidationError if there are errors during validation, or undefined if there is no error.
+ * @api public
+ */
+
+Document.prototype.validateSync = function(pathsToValidate, options) {
+ const _this = this;
+
+ const hasValidateModifiedOnlyOption = options &&
+ (typeof options === 'object') &&
+ ('validateModifiedOnly' in options);
+
+ let shouldValidateModifiedOnly;
+ if (hasValidateModifiedOnlyOption) {
+ shouldValidateModifiedOnly = !!options.validateModifiedOnly;
+ } else {
+ shouldValidateModifiedOnly = this.schema.options.validateModifiedOnly;
+ }
+
+ if (typeof pathsToValidate === 'string') {
+ pathsToValidate = pathsToValidate.split(' ');
+ }
+
+ // only validate required fields when necessary
+ const pathDetails = _getPathsToValidate(this);
+ let paths = shouldValidateModifiedOnly ?
+ pathDetails[0].filter((path) => this.isModified(path)) :
+ pathDetails[0];
+ const skipSchemaValidators = pathDetails[1];
+
+ if (Array.isArray(pathsToValidate)) {
+ paths = _handlePathsToValidate(paths, pathsToValidate);
+ }
+
+ const validating = {};
+
+ paths.forEach(function(path) {
+ if (validating[path]) {
+ return;
+ }
+
+ validating[path] = true;
+
+ const p = _this.schema.path(path);
+ if (!p) {
+ return;
+ }
+ if (!_this.$isValid(path)) {
+ return;
+ }
+
+ const val = _this.$__getValue(path);
+ const err = p.doValidateSync(val, _this, {
+ skipSchemaValidators: skipSchemaValidators[path],
+ path: path
+ });
+ if (err && (!p.$isMongooseDocumentArray || err.$isArrayValidatorError)) {
+ if (p.$isSingleNested &&
+ err instanceof ValidationError &&
+ p.schema.options.storeSubdocValidationError === false) {
+ return;
+ }
+ _this.invalidate(path, err, undefined, true);
+ }
+ });
+
+ const err = _this.$__.validationError;
+ _this.$__.validationError = undefined;
+ _this.emit('validate', _this);
+ _this.constructor.emit('validate', _this);
+
+ if (err) {
+ for (const key in err.errors) {
+ // Make sure cast errors persist
+ if (err.errors[key] instanceof MongooseError.CastError) {
+ _this.invalidate(key, err.errors[key]);
+ }
+ }
+ }
+
+ return err;
+};
+
+/**
+ * Marks a path as invalid, causing validation to fail.
+ *
+ * The `errorMsg` argument will become the message of the `ValidationError`.
+ *
+ * The `value` argument (if passed) will be available through the `ValidationError.value` property.
+ *
+ * doc.invalidate('size', 'must be less than 20', 14);
+
+ * doc.validate(function (err) {
+ * console.log(err)
+ * // prints
+ * { message: 'Validation failed',
+ * name: 'ValidationError',
+ * errors:
+ * { size:
+ * { message: 'must be less than 20',
+ * name: 'ValidatorError',
+ * path: 'size',
+ * type: 'user defined',
+ * value: 14 } } }
+ * })
+ *
+ * @param {String} path the field to invalidate. For array elements, use the `array.i.field` syntax, where `i` is the 0-based index in the array.
+ * @param {String|Error} errorMsg the error which states the reason `path` was invalid
+ * @param {Object|String|Number|any} value optional invalid value
+ * @param {String} [kind] optional `kind` property for the error
+ * @return {ValidationError} the current ValidationError, with all currently invalidated paths
+ * @api public
+ */
+
+Document.prototype.invalidate = function(path, err, val, kind) {
+ if (!this.$__.validationError) {
+ this.$__.validationError = new ValidationError(this);
+ }
+
+ if (this.$__.validationError.errors[path]) {
+ return;
+ }
+
+ if (!err || typeof err === 'string') {
+ err = new ValidatorError({
+ path: path,
+ message: err,
+ type: kind || 'user defined',
+ value: val
+ });
+ }
+
+ if (this.$__.validationError === err) {
+ return this.$__.validationError;
+ }
+
+ this.$__.validationError.addError(path, err);
+ return this.$__.validationError;
+};
+
+/**
+ * Marks a path as valid, removing existing validation errors.
+ *
+ * @param {String} path the field to mark as valid
+ * @api public
+ * @memberOf Document
+ * @instance
+ * @method $markValid
+ */
+
+Document.prototype.$markValid = function(path) {
+ if (!this.$__.validationError || !this.$__.validationError.errors[path]) {
+ return;
+ }
+
+ delete this.$__.validationError.errors[path];
+ if (Object.keys(this.$__.validationError.errors).length === 0) {
+ this.$__.validationError = null;
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function _markValidSubpaths(doc, path) {
+ if (!doc.$__.validationError) {
+ return;
+ }
+
+ const keys = Object.keys(doc.$__.validationError.errors);
+ for (const key of keys) {
+ if (key.startsWith(path + '.')) {
+ delete doc.$__.validationError.errors[key];
+ }
+ }
+ if (Object.keys(doc.$__.validationError.errors).length === 0) {
+ doc.$__.validationError = null;
+ }
+}
+
+/*!
+ * ignore
+ */
+
+function _checkImmutableSubpaths(subdoc, schematype, priorVal) {
+ const schema = schematype.schema;
+ if (schema == null) {
+ return;
+ }
+
+ for (const key of Object.keys(schema.paths)) {
+ const path = schema.paths[key];
+ if (path.$immutableSetter == null) {
+ continue;
+ }
+ const oldVal = priorVal == null ? void 0 : priorVal.$__getValue(key);
+ // Calling immutableSetter with `oldVal` even though it expects `newVal`
+ // is intentional. That's because `$immutableSetter` compares its param
+ // to the current value.
+ path.$immutableSetter.call(subdoc, oldVal);
+ }
+}
+
+/**
+ * Saves this document by inserting a new document into the database if [document.isNew](/docs/api.html#document_Document-isNew) is `true`,
+ * or sends an [updateOne](/docs/api.html#document_Document-updateOne) operation **only** with the modifications to the database, it does not replace the whole document in the latter case.
+ *
+ * ####Example:
+ *
+ * product.sold = Date.now();
+ * product = await product.save();
+ *
+ * If save is successful, the returned promise will fulfill with the document
+ * saved.
+ *
+ * ####Example:
+ *
+ * const newProduct = await product.save();
+ * newProduct === product; // true
+ *
+ * @param {Object} [options] options optional options
+ * @param {Session} [options.session=null] the [session](https://docs.mongodb.com/manual/reference/server-sessions/) associated with this save operation. If not specified, defaults to the [document's associated session](api.html#document_Document-$session).
+ * @param {Object} [options.safe] (DEPRECATED) overrides [schema's safe option](http://mongoosejs.com//docs/guide.html#safe). Use the `w` option instead.
+ * @param {Boolean} [options.validateBeforeSave] set to false to save without validating.
+ * @param {Boolean} [options.validateModifiedOnly=false] If `true`, Mongoose will only validate modified paths, as opposed to modified paths and `required` paths.
+ * @param {Number|String} [options.w] set the [write concern](https://docs.mongodb.com/manual/reference/write-concern/#w-option). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.j] set to true for MongoDB to wait until this `save()` has been [journaled before resolving the returned promise](https://docs.mongodb.com/manual/reference/write-concern/#j-option). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern)
+ * @param {Number} [options.wtimeout] sets a [timeout for the write concern](https://docs.mongodb.com/manual/reference/write-concern/#wtimeout). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern).
+ * @param {Boolean} [options.checkKeys=true] the MongoDB driver prevents you from saving keys that start with '$' or contain '.' by default. Set this option to `false` to skip that check. See [restrictions on field names](https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names)
+ * @param {Boolean} [options.timestamps=true] if `false` and [timestamps](./guide.html#timestamps) are enabled, skip timestamps for this `save()`.
+ * @param {Function} [fn] optional callback
+ * @method save
+ * @memberOf Document
+ * @instance
+ * @throws {DocumentNotFoundError} if this [save updates an existing document](api.html#document_Document-isNew) but the document doesn't exist in the database. For example, you will get this error if the document is [deleted between when you retrieved the document and when you saved it](documents.html#updating).
+ * @return {Promise|undefined} Returns undefined if used with callback or a Promise otherwise.
+ * @api public
+ * @see middleware http://mongoosejs.com/docs/middleware.html
+ */
+
+/**
+ * Checks if a path is invalid
+ *
+ * @param {String} path the field to check
+ * @method $isValid
+ * @memberOf Document
+ * @instance
+ * @api private
+ */
+
+Document.prototype.$isValid = function(path) {
+ return !this.$__.validationError || !this.$__.validationError.errors[path];
+};
+
+/**
+ * Resets the internal modified state of this document.
+ *
+ * @api private
+ * @return {Document}
+ * @method $__reset
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__reset = function reset() {
+ let _this = this;
+ DocumentArray || (DocumentArray = require('./types/documentarray'));
+
+ this.$__.activePaths
+ .map('init', 'modify', function(i) {
+ return _this.$__getValue(i);
+ })
+ .filter(function(val) {
+ return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
+ })
+ .forEach(function(array) {
+ let i = array.length;
+ while (i--) {
+ const doc = array[i];
+ if (!doc) {
+ continue;
+ }
+ doc.$__reset();
+ }
+
+ _this.$__.activePaths.init(array.$path());
+
+ array[arrayAtomicsBackupSymbol] = array[arrayAtomicsSymbol];
+ array[arrayAtomicsSymbol] = {};
+ });
+
+ this.$__.activePaths.
+ map('init', 'modify', function(i) {
+ return _this.$__getValue(i);
+ }).
+ filter(function(val) {
+ return val && val.$isSingleNested;
+ }).
+ forEach(function(doc) {
+ doc.$__reset();
+ _this.$__.activePaths.init(doc.$basePath);
+ });
+
+ // clear atomics
+ this.$__dirty().forEach(function(dirt) {
+ const type = dirt.value;
+
+ if (type && type[arrayAtomicsSymbol]) {
+ type[arrayAtomicsBackupSymbol] = type[arrayAtomicsSymbol];
+ type[arrayAtomicsSymbol] = {};
+ }
+ });
+
+ this.$__.backup = {};
+ this.$__.backup.activePaths = {
+ modify: Object.assign({}, this.$__.activePaths.states.modify),
+ default: Object.assign({}, this.$__.activePaths.states.default)
+ };
+ this.$__.backup.validationError = this.$__.validationError;
+ this.$__.backup.errors = this.errors;
+
+ // Clear 'dirty' cache
+ this.$__.activePaths.clear('modify');
+ this.$__.activePaths.clear('default');
+ this.$__.validationError = undefined;
+ this.errors = undefined;
+ _this = this;
+ this.schema.requiredPaths().forEach(function(path) {
+ _this.$__.activePaths.require(path);
+ });
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Document.prototype.$__undoReset = function $__undoReset() {
+ if (this.$__.backup == null || this.$__.backup.activePaths == null) {
+ return;
+ }
+
+ this.$__.activePaths.states.modify = this.$__.backup.activePaths.modify;
+ this.$__.activePaths.states.default = this.$__.backup.activePaths.default;
+
+ this.$__.validationError = this.$__.backup.validationError;
+ this.errors = this.$__.backup.errors;
+
+ for (const dirt of this.$__dirty()) {
+ const type = dirt.value;
+
+ if (type && type[arrayAtomicsSymbol] && type[arrayAtomicsBackupSymbol]) {
+ type[arrayAtomicsSymbol] = type[arrayAtomicsBackupSymbol];
+ }
+ }
+
+ for (const subdoc of this.$__getAllSubdocs()) {
+ subdoc.$__undoReset();
+ }
+};
+
+/**
+ * Returns this documents dirty paths / vals.
+ *
+ * @api private
+ * @method $__dirty
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__dirty = function() {
+ const _this = this;
+
+ let all = this.$__.activePaths.map('modify', function(path) {
+ return {
+ path: path,
+ value: _this.$__getValue(path),
+ schema: _this.$__path(path)
+ };
+ });
+
+ // gh-2558: if we had to set a default and the value is not undefined,
+ // we have to save as well
+ all = all.concat(this.$__.activePaths.map('default', function(path) {
+ if (path === '_id' || _this.$__getValue(path) == null) {
+ return;
+ }
+ return {
+ path: path,
+ value: _this.$__getValue(path),
+ schema: _this.$__path(path)
+ };
+ }));
+
+ // Sort dirty paths in a flat hierarchy.
+ all.sort(function(a, b) {
+ return (a.path < b.path ? -1 : (a.path > b.path ? 1 : 0));
+ });
+
+ // Ignore "foo.a" if "foo" is dirty already.
+ const minimal = [];
+ let lastPath;
+ let top;
+
+ all.forEach(function(item) {
+ if (!item) {
+ return;
+ }
+ if (lastPath == null || item.path.indexOf(lastPath) !== 0) {
+ lastPath = item.path + '.';
+ minimal.push(item);
+ top = item;
+ } else if (top != null &&
+ top.value != null &&
+ top.value[arrayAtomicsSymbol] != null &&
+ top.value.hasAtomics()) {
+ // special case for top level MongooseArrays
+ // the `top` array itself and a sub path of `top` are being modified.
+ // the only way to honor all of both modifications is through a $set
+ // of entire array.
+ top.value[arrayAtomicsSymbol] = {};
+ top.value[arrayAtomicsSymbol].$set = top.value;
+ }
+ });
+
+ top = lastPath = null;
+ return minimal;
+};
+
+/**
+ * Assigns/compiles `schema` into this documents prototype.
+ *
+ * @param {Schema} schema
+ * @api private
+ * @method $__setSchema
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__setSchema = function(schema) {
+ schema.plugin(idGetter, { deduplicate: true });
+ compile(schema.tree, this, undefined, schema.options);
+
+ // Apply default getters if virtual doesn't have any (gh-6262)
+ for (const key of Object.keys(schema.virtuals)) {
+ schema.virtuals[key]._applyDefaultGetters();
+ }
+
+ this.schema = schema;
+ this[documentSchemaSymbol] = schema;
+};
+
+
+/**
+ * Get active path that were changed and are arrays
+ *
+ * @api private
+ * @method $__getArrayPathsToValidate
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__getArrayPathsToValidate = function() {
+ DocumentArray || (DocumentArray = require('./types/documentarray'));
+
+ // validate all document arrays.
+ return this.$__.activePaths
+ .map('init', 'modify', function(i) {
+ return this.$__getValue(i);
+ }.bind(this))
+ .filter(function(val) {
+ return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
+ }).reduce(function(seed, array) {
+ return seed.concat(array);
+ }, [])
+ .filter(function(doc) {
+ return doc;
+ });
+};
+
+
+/**
+ * Get all subdocs (by bfs)
+ *
+ * @api private
+ * @method $__getAllSubdocs
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__getAllSubdocs = function() {
+ DocumentArray || (DocumentArray = require('./types/documentarray'));
+ Embedded = Embedded || require('./types/embedded');
+
+ function docReducer(doc, seed, path) {
+ let val = doc;
+ if (path) {
+ if (doc instanceof Document && doc[documentSchemaSymbol].paths[path]) {
+ val = doc._doc[path];
+ } else {
+ val = doc[path];
+ }
+ }
+ if (val instanceof Embedded) {
+ seed.push(val);
+ } else if (val instanceof Map) {
+ seed = Array.from(val.keys()).reduce(function(seed, path) {
+ return docReducer(val.get(path), seed, null);
+ }, seed);
+ } else if (val && val.$isSingleNested) {
+ seed = Object.keys(val._doc).reduce(function(seed, path) {
+ return docReducer(val._doc, seed, path);
+ }, seed);
+ seed.push(val);
+ } else if (val && val.isMongooseDocumentArray) {
+ val.forEach(function _docReduce(doc) {
+ if (!doc || !doc._doc) {
+ return;
+ }
+ seed = Object.keys(doc._doc).reduce(function(seed, path) {
+ return docReducer(doc._doc, seed, path);
+ }, seed);
+ if (doc instanceof Embedded) {
+ seed.push(doc);
+ }
+ });
+ } else if (val instanceof Document && val.$__isNested) {
+ seed = Object.keys(val).reduce(function(seed, path) {
+ return docReducer(val, seed, path);
+ }, seed);
+ }
+ return seed;
+ }
+
+ const _this = this;
+ const subDocs = Object.keys(this._doc).reduce(function(seed, path) {
+ return docReducer(_this, seed, path);
+ }, []);
+
+ return subDocs;
+};
+
+/*!
+ * Runs queued functions
+ */
+
+function applyQueue(doc) {
+ const q = doc.schema && doc.schema.callQueue;
+ if (!q.length) {
+ return;
+ }
+
+ for (const pair of q) {
+ if (pair[0] !== 'pre' && pair[0] !== 'post' && pair[0] !== 'on') {
+ doc[pair[0]].apply(doc, pair[1]);
+ }
+ }
+}
+
+/*!
+ * ignore
+ */
+
+Document.prototype.$__handleReject = function handleReject(err) {
+ // emit on the Model if listening
+ if (this.listeners('error').length) {
+ this.emit('error', err);
+ } else if (this.constructor.listeners && this.constructor.listeners('error').length) {
+ this.constructor.emit('error', err);
+ }
+};
+
+/**
+ * Internal helper for toObject() and toJSON() that doesn't manipulate options
+ *
+ * @api private
+ * @method $toObject
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$toObject = function(options, json) {
+ let defaultOptions = {
+ transform: true,
+ flattenDecimals: true
+ };
+
+ const path = json ? 'toJSON' : 'toObject';
+ const baseOptions = get(this, 'constructor.base.options.' + path, {});
+ const schemaOptions = get(this, 'schema.options', {});
+ // merge base default options with Schema's set default options if available.
+ // `clone` is necessary here because `utils.options` directly modifies the second input.
+ defaultOptions = utils.options(defaultOptions, clone(baseOptions));
+ defaultOptions = utils.options(defaultOptions, clone(schemaOptions[path] || {}));
+
+ // If options do not exist or is not an object, set it to empty object
+ options = utils.isPOJO(options) ? clone(options) : {};
+ options._calledWithOptions = options._calledWithOptions || clone(options);
+
+ if (!('flattenMaps' in options)) {
+ options.flattenMaps = defaultOptions.flattenMaps;
+ }
+
+ let _minimize;
+ if (options._calledWithOptions.minimize != null) {
+ _minimize = options.minimize;
+ } else if (defaultOptions.minimize != null) {
+ _minimize = defaultOptions.minimize;
+ } else {
+ _minimize = schemaOptions.minimize;
+ }
+
+ // The original options that will be passed to `clone()`. Important because
+ // `clone()` will recursively call `$toObject()` on embedded docs, so we
+ // need the original options the user passed in, plus `_isNested` and
+ // `_parentOptions` for checking whether we need to depopulate.
+ const cloneOptions = Object.assign(utils.clone(options), {
+ _isNested: true,
+ json: json,
+ minimize: _minimize
+ });
+
+ if (utils.hasUserDefinedProperty(options, 'getters')) {
+ cloneOptions.getters = options.getters;
+ }
+ if (utils.hasUserDefinedProperty(options, 'virtuals')) {
+ cloneOptions.virtuals = options.virtuals;
+ }
+
+ const depopulate = options.depopulate ||
+ get(options, '_parentOptions.depopulate', false);
+ // _isNested will only be true if this is not the top level document, we
+ // should never depopulate
+ if (depopulate && options._isNested && this.$__.wasPopulated) {
+ // populated paths that we set to a document
+ return clone(this._id, cloneOptions);
+ }
+
+ // merge default options with input options.
+ options = utils.options(defaultOptions, options);
+ options._isNested = true;
+ options.json = json;
+ options.minimize = _minimize;
+
+ cloneOptions._parentOptions = options;
+ cloneOptions._skipSingleNestedGetters = true;
+
+ const gettersOptions = Object.assign({}, cloneOptions);
+ gettersOptions._skipSingleNestedGetters = false;
+
+ // remember the root transform function
+ // to save it from being overwritten by sub-transform functions
+ const originalTransform = options.transform;
+
+ let ret = clone(this._doc, cloneOptions) || {};
+
+ if (options.getters) {
+ applyGetters(this, ret, gettersOptions);
+
+ if (options.minimize) {
+ ret = minimize(ret) || {};
+ }
+ }
+
+ if (options.virtuals || (options.getters && options.virtuals !== false)) {
+ applyVirtuals(this, ret, gettersOptions, options);
+ }
+
+ if (options.versionKey === false && this.schema.options.versionKey) {
+ delete ret[this.schema.options.versionKey];
+ }
+
+ let transform = options.transform;
+
+ // In the case where a subdocument has its own transform function, we need to
+ // check and see if the parent has a transform (options.transform) and if the
+ // child schema has a transform (this.schema.options.toObject) In this case,
+ // we need to adjust options.transform to be the child schema's transform and
+ // not the parent schema's
+ if (transform) {
+ applySchemaTypeTransforms(this, ret);
+ }
+
+ if (options.useProjection) {
+ omitDeselectedFields(this, ret);
+ }
+
+ if (transform === true || (schemaOptions.toObject && transform)) {
+ const opts = options.json ? schemaOptions.toJSON : schemaOptions.toObject;
+
+ if (opts) {
+ transform = (typeof options.transform === 'function' ? options.transform : opts.transform);
+ }
+ } else {
+ options.transform = originalTransform;
+ }
+
+ if (typeof transform === 'function') {
+ const xformed = transform(this, ret, options);
+ if (typeof xformed !== 'undefined') {
+ ret = xformed;
+ }
+ }
+
+ return ret;
+};
+
+/**
+ * Converts this document into a plain javascript object, ready for storage in MongoDB.
+ *
+ * Buffers are converted to instances of [mongodb.Binary](http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html) for proper storage.
+ *
+ * ####Options:
+ *
+ * - `getters` apply all getters (path and virtual getters), defaults to false
+ * - `aliases` apply all aliases if `virtuals=true`, defaults to true
+ * - `virtuals` apply virtual getters (can override `getters` option), defaults to false
+ * - `minimize` remove empty objects, defaults to true
+ * - `transform` a transform function to apply to the resulting document before returning
+ * - `depopulate` depopulate any populated paths, replacing them with their original refs, defaults to false
+ * - `versionKey` whether to include the version key, defaults to true
+ * - `flattenMaps` convert Maps to POJOs. Useful if you want to JSON.stringify() the result of toObject(), defaults to false
+ * - `useProjection` set to `true` to omit fields that are excluded in this document's projection. Unless you specified a projection, this will omit any field that has `select: false` in the schema.
+ *
+ * ####Getters/Virtuals
+ *
+ * Example of only applying path getters
+ *
+ * doc.toObject({ getters: true, virtuals: false })
+ *
+ * Example of only applying virtual getters
+ *
+ * doc.toObject({ virtuals: true })
+ *
+ * Example of applying both path and virtual getters
+ *
+ * doc.toObject({ getters: true })
+ *
+ * To apply these options to every document of your schema by default, set your [schemas](#schema_Schema) `toObject` option to the same argument.
+ *
+ * schema.set('toObject', { virtuals: true })
+ *
+ * ####Transform
+ *
+ * We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional `transform` function.
+ *
+ * Transform functions receive three arguments
+ *
+ * function (doc, ret, options) {}
+ *
+ * - `doc` The mongoose document which is being converted
+ * - `ret` The plain object representation which has been converted
+ * - `options` The options in use (either schema options or the options passed inline)
+ *
+ * ####Example
+ *
+ * // specify the transform schema option
+ * if (!schema.options.toObject) schema.options.toObject = {};
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * // remove the _id of every document before returning the result
+ * delete ret._id;
+ * return ret;
+ * }
+ *
+ * // without the transformation in the schema
+ * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
+ *
+ * // with the transformation
+ * doc.toObject(); // { name: 'Wreck-it Ralph' }
+ *
+ * With transformations we can do a lot more than remove properties. We can even return completely new customized objects:
+ *
+ * if (!schema.options.toObject) schema.options.toObject = {};
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * return { movie: ret.name }
+ * }
+ *
+ * // without the transformation in the schema
+ * doc.toObject(); // { _id: 'anId', name: 'Wreck-it Ralph' }
+ *
+ * // with the transformation
+ * doc.toObject(); // { movie: 'Wreck-it Ralph' }
+ *
+ * _Note: if a transform function returns `undefined`, the return value will be ignored._
+ *
+ * Transformations may also be applied inline, overridding any transform set in the options:
+ *
+ * function xform (doc, ret, options) {
+ * return { inline: ret.name, custom: true }
+ * }
+ *
+ * // pass the transform as an inline option
+ * doc.toObject({ transform: xform }); // { inline: 'Wreck-it Ralph', custom: true }
+ *
+ * If you want to skip transformations, use `transform: false`:
+ *
+ * schema.options.toObject.hide = '_id';
+ * schema.options.toObject.transform = function (doc, ret, options) {
+ * if (options.hide) {
+ * options.hide.split(' ').forEach(function (prop) {
+ * delete ret[prop];
+ * });
+ * }
+ * return ret;
+ * }
+ *
+ * const doc = new Doc({ _id: 'anId', secret: 47, name: 'Wreck-it Ralph' });
+ * doc.toObject(); // { secret: 47, name: 'Wreck-it Ralph' }
+ * doc.toObject({ hide: 'secret _id', transform: false });// { _id: 'anId', secret: 47, name: 'Wreck-it Ralph' }
+ * doc.toObject({ hide: 'secret _id', transform: true }); // { name: 'Wreck-it Ralph' }
+ *
+ * If you pass a transform in `toObject()` options, Mongoose will apply the transform
+ * to [subdocuments](/docs/subdocs.html) in addition to the top-level document.
+ * Similarly, `transform: false` skips transforms for all subdocuments.
+ * Note that this is behavior is different for transforms defined in the schema:
+ * if you define a transform in `schema.options.toObject.transform`, that transform
+ * will **not** apply to subdocuments.
+ *
+ * const memberSchema = new Schema({ name: String, email: String });
+ * const groupSchema = new Schema({ members: [memberSchema], name: String, email });
+ * const Group = mongoose.model('Group', groupSchema);
+ *
+ * const doc = new Group({
+ * name: 'Engineering',
+ * email: 'dev@mongoosejs.io',
+ * members: [{ name: 'Val', email: 'val@mongoosejs.io' }]
+ * });
+ *
+ * // Removes `email` from both top-level document **and** array elements
+ * // { name: 'Engineering', members: [{ name: 'Val' }] }
+ * doc.toObject({ transform: (doc, ret) => { delete ret.email; return ret; } });
+ *
+ * Transforms, like all of these options, are also available for `toJSON`. See [this guide to `JSON.stringify()`](https://thecodebarbarian.com/the-80-20-guide-to-json-stringify-in-javascript.html) to learn why `toJSON()` and `toObject()` are separate functions.
+ *
+ * See [schema options](/docs/guide.html#toObject) for some more details.
+ *
+ * _During save, no custom options are applied to the document before being sent to the database._
+ *
+ * @param {Object} [options]
+ * @param {Boolean} [options.getters=false] if true, apply all getters, including virtuals
+ * @param {Boolean} [options.virtuals=false] if true, apply virtuals, including aliases. Use `{ getters: true, virtuals: false }` to just apply getters, not virtuals
+ * @param {Boolean} [options.aliases=true] if `options.virtuals = true`, you can set `options.aliases = false` to skip applying aliases. This option is a no-op if `options.virtuals = false`.
+ * @param {Boolean} [options.minimize=true] if true, omit any empty objects from the output
+ * @param {Function|null} [options.transform=null] if set, mongoose will call this function to allow you to transform the returned object
+ * @param {Boolean} [options.depopulate=false] if true, replace any conventionally populated paths with the original id in the output. Has no affect on virtual populated paths.
+ * @param {Boolean} [options.versionKey=true] if false, exclude the version key (`__v` by default) from the output
+ * @param {Boolean} [options.flattenMaps=false] if true, convert Maps to POJOs. Useful if you want to `JSON.stringify()` the result of `toObject()`.
+ * @param {Boolean} [options.useProjection=false] - If true, omits fields that are excluded in this document's projection. Unless you specified a projection, this will omit any field that has `select: false` in the schema.
+ * @return {Object} js object
+ * @see mongodb.Binary http://mongodb.github.com/node-mongodb-native/api-bson-generated/binary.html
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.toObject = function(options) {
+ return this.$toObject(options);
+};
+
+/*!
+ * Minimizes an object, removing undefined values and empty objects
+ *
+ * @param {Object} object to minimize
+ * @return {Object}
+ */
+
+function minimize(obj) {
+ const keys = Object.keys(obj);
+ let i = keys.length;
+ let hasKeys;
+ let key;
+ let val;
+
+ while (i--) {
+ key = keys[i];
+ val = obj[key];
+
+ if (utils.isObject(val) && !Buffer.isBuffer(val)) {
+ obj[key] = minimize(val);
+ }
+
+ if (undefined === obj[key]) {
+ delete obj[key];
+ continue;
+ }
+
+ hasKeys = true;
+ }
+
+ return hasKeys
+ ? obj
+ : undefined;
+}
+
+/*!
+ * Applies virtuals properties to `json`.
+ */
+
+function applyVirtuals(self, json, options, toObjectOptions) {
+ const schema = self.schema;
+ const paths = Object.keys(schema.virtuals);
+ let i = paths.length;
+ const numPaths = i;
+ let path;
+ let assignPath;
+ let cur = self._doc;
+ let v;
+ const aliases = get(toObjectOptions, 'aliases', true);
+
+ if (!cur) {
+ return json;
+ }
+
+ options = options || {};
+ for (i = 0; i < numPaths; ++i) {
+ path = paths[i];
+
+ // Allow skipping aliases with `toObject({ virtuals: true, aliases: false })`
+ if (!aliases && schema.aliases.hasOwnProperty(path)) {
+ continue;
+ }
+
+ // We may be applying virtuals to a nested object, for example if calling
+ // `doc.nestedProp.toJSON()`. If so, the path we assign to, `assignPath`,
+ // will be a trailing substring of the `path`.
+ assignPath = path;
+ if (options.path != null) {
+ if (!path.startsWith(options.path + '.')) {
+ continue;
+ }
+ assignPath = path.substr(options.path.length + 1);
+ }
+ const parts = assignPath.split('.');
+ v = clone(self.get(path), options);
+ if (v === void 0) {
+ continue;
+ }
+ const plen = parts.length;
+ cur = json;
+ for (let j = 0; j < plen - 1; ++j) {
+ cur[parts[j]] = cur[parts[j]] || {};
+ cur = cur[parts[j]];
+ }
+ cur[parts[plen - 1]] = v;
+ }
+
+ return json;
+}
+
+/*!
+ * Applies virtuals properties to `json`.
+ *
+ * @param {Document} self
+ * @param {Object} json
+ * @return {Object} `json`
+ */
+
+function applyGetters(self, json, options) {
+ const schema = self.schema;
+ const paths = Object.keys(schema.paths);
+ let i = paths.length;
+ let path;
+ let cur = self._doc;
+ let v;
+
+ if (!cur) {
+ return json;
+ }
+
+ while (i--) {
+ path = paths[i];
+
+ const parts = path.split('.');
+ const plen = parts.length;
+ const last = plen - 1;
+ let branch = json;
+ let part;
+ cur = self._doc;
+
+ if (!self.isSelected(path)) {
+ continue;
+ }
+
+ for (let ii = 0; ii < plen; ++ii) {
+ part = parts[ii];
+ v = cur[part];
+ if (ii === last) {
+ const val = self.get(path);
+ branch[part] = clone(val, options);
+ } else if (v == null) {
+ if (part in cur) {
+ branch[part] = v;
+ }
+ break;
+ } else {
+ branch = branch[part] || (branch[part] = {});
+ }
+ cur = v;
+ }
+ }
+
+ return json;
+}
+
+/*!
+ * Applies schema type transforms to `json`.
+ *
+ * @param {Document} self
+ * @param {Object} json
+ * @return {Object} `json`
+ */
+
+function applySchemaTypeTransforms(self, json) {
+ const schema = self.schema;
+ const paths = Object.keys(schema.paths || {});
+ const cur = self._doc;
+
+ if (!cur) {
+ return json;
+ }
+
+ for (const path of paths) {
+ const schematype = schema.paths[path];
+ if (typeof schematype.options.transform === 'function') {
+ const val = self.get(path);
+ const transformedValue = schematype.options.transform.call(self, val);
+ throwErrorIfPromise(path, transformedValue);
+ json[path] = transformedValue;
+ } else if (schematype.$embeddedSchemaType != null &&
+ typeof schematype.$embeddedSchemaType.options.transform === 'function') {
+ const vals = [].concat(self.get(path));
+ const transform = schematype.$embeddedSchemaType.options.transform;
+ for (let i = 0; i < vals.length; ++i) {
+ const transformedValue = transform.call(self, vals[i]);
+ vals[i] = transformedValue;
+ throwErrorIfPromise(path, transformedValue);
+ }
+
+ json[path] = vals;
+ }
+ }
+
+ return json;
+}
+
+function throwErrorIfPromise(path, transformedValue) {
+ if (isPromise(transformedValue)) {
+ throw new Error('`transform` function must be synchronous, but the transform on path `' + path + '` returned a promise.');
+ }
+}
+
+/*!
+ * ignore
+ */
+
+function omitDeselectedFields(self, json) {
+ const schema = self.schema;
+ const paths = Object.keys(schema.paths || {});
+ const cur = self._doc;
+
+ if (!cur) {
+ return json;
+ }
+
+ let selected = self.$__.selected;
+ if (selected === void 0) {
+ selected = {};
+ queryhelpers.applyPaths(selected, schema);
+ }
+ if (selected == null || Object.keys(selected).length === 0) {
+ return json;
+ }
+
+ for (const path of paths) {
+ if (selected[path] != null && !selected[path]) {
+ delete json[path];
+ }
+ }
+
+ return json;
+}
+
+/**
+ * The return value of this method is used in calls to JSON.stringify(doc).
+ *
+ * This method accepts the same options as [Document#toObject](#document_Document-toObject). To apply the options to every document of your schema by default, set your [schemas](#schema_Schema) `toJSON` option to the same argument.
+ *
+ * schema.set('toJSON', { virtuals: true })
+ *
+ * See [schema options](/docs/guide.html#toJSON) for details.
+ *
+ * @param {Object} options
+ * @return {Object}
+ * @see Document#toObject #document_Document-toObject
+ * @see JSON.stringify() in JavaScript https://thecodebarbarian.com/the-80-20-guide-to-json-stringify-in-javascript.html
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.toJSON = function(options) {
+ return this.$toObject(options, true);
+};
+
+/**
+ * If this document is a subdocument or populated document, returns the document's
+ * parent. Returns `undefined` otherwise.
+ *
+ * @api public
+ * @method parent
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.parent = function() {
+ return this.$__.parent;
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ * @method inspect
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.inspect = function(options) {
+ const isPOJO = utils.isPOJO(options);
+ let opts;
+ if (isPOJO) {
+ opts = options;
+ opts.minimize = false;
+ }
+ const ret = this.toObject(opts);
+
+ if (ret == null) {
+ // If `toObject()` returns null, `this` is still an object, so if `inspect()`
+ // prints out null this can cause some serious confusion. See gh-7942.
+ return 'MongooseDocument { ' + ret + ' }';
+ }
+
+ return ret;
+};
+
+if (inspect.custom) {
+ /*!
+ * Avoid Node deprecation warning DEP0079
+ */
+
+ Document.prototype[inspect.custom] = Document.prototype.inspect;
+}
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ * @method toString
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.toString = function() {
+ const ret = this.inspect();
+ if (typeof ret === 'string') {
+ return ret;
+ }
+ return inspect(ret);
+};
+
+/**
+ * Returns true if the Document stores the same data as doc.
+ *
+ * Documents are considered equal when they have matching `_id`s, unless neither
+ * document has an `_id`, in which case this function falls back to using
+ * `deepEqual()`.
+ *
+ * @param {Document} doc a document to compare
+ * @return {Boolean}
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.equals = function(doc) {
+ if (!doc) {
+ return false;
+ }
+
+ const tid = this.$__getValue('_id');
+ const docid = doc.$__ != null ? doc.$__getValue('_id') : doc;
+ if (!tid && !docid) {
+ return deepEqual(this, doc);
+ }
+ return tid && tid.equals
+ ? tid.equals(docid)
+ : tid === docid;
+};
+
+/**
+ * Populates document references, executing the `callback` when complete.
+ * If you want to use promises instead, use this function with
+ * [`execPopulate()`](#document_Document-execPopulate)
+ *
+ * ####Example:
+ *
+ * doc
+ * .populate('company')
+ * .populate({
+ * path: 'notes',
+ * match: /airline/,
+ * select: 'text',
+ * model: 'modelName'
+ * options: opts
+ * }, function (err, user) {
+ * assert(doc._id === user._id) // the document itself is passed
+ * })
+ *
+ * // summary
+ * doc.populate(path) // not executed
+ * doc.populate(options); // not executed
+ * doc.populate(path, callback) // executed
+ * doc.populate(options, callback); // executed
+ * doc.populate(callback); // executed
+ * doc.populate(options).execPopulate() // executed, returns promise
+ *
+ *
+ * ####NOTE:
+ *
+ * Population does not occur unless a `callback` is passed *or* you explicitly
+ * call `execPopulate()`.
+ * Passing the same path a second time will overwrite the previous path options.
+ * See [Model.populate()](#model_Model.populate) for explaination of options.
+ *
+ * @see Model.populate #model_Model.populate
+ * @see Document.execPopulate #document_Document-execPopulate
+ * @param {String|Object} [path] The path to populate or an options object
+ * @param {Function} [callback] When passed, population is invoked
+ * @api public
+ * @return {Document} this
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.populate = function populate() {
+ if (arguments.length === 0) {
+ return this;
+ }
+
+ const pop = this.$__.populate || (this.$__.populate = {});
+ const args = utils.args(arguments);
+ let fn;
+
+ if (typeof args[args.length - 1] === 'function') {
+ fn = args.pop();
+ }
+
+ // allow `doc.populate(callback)`
+ if (args.length) {
+ // use hash to remove duplicate paths
+ const res = utils.populate.apply(null, args);
+ for (const populateOptions of res) {
+ pop[populateOptions.path] = populateOptions;
+ }
+ }
+
+ if (fn) {
+ const paths = utils.object.vals(pop);
+ this.$__.populate = undefined;
+ let topLevelModel = this.constructor;
+ if (this.$__isNested) {
+ topLevelModel = this.$__[scopeSymbol].constructor;
+ const nestedPath = this.$__.nestedPath;
+ paths.forEach(function(populateOptions) {
+ populateOptions.path = nestedPath + '.' + populateOptions.path;
+ });
+ }
+
+ // Use `$session()` by default if the document has an associated session
+ // See gh-6754
+ if (this.$session() != null) {
+ const session = this.$session();
+ paths.forEach(path => {
+ if (path.options == null) {
+ path.options = { session: session };
+ return;
+ }
+ if (!('session' in path.options)) {
+ path.options.session = session;
+ }
+ });
+ }
+
+ topLevelModel.populate(this, paths, fn);
+ }
+
+ return this;
+};
+
+/**
+ * Explicitly executes population and returns a promise. Useful for ES2015
+ * integration.
+ *
+ * ####Example:
+ *
+ * const promise = doc.
+ * populate('company').
+ * populate({
+ * path: 'notes',
+ * match: /airline/,
+ * select: 'text',
+ * model: 'modelName'
+ * options: opts
+ * }).
+ * execPopulate();
+ *
+ * // summary
+ * doc.execPopulate().then(resolve, reject);
+ *
+ * // you can also use doc.execPopulate(options) as a shorthand for
+ * // doc.populate(options).execPopulate()
+ *
+ *
+ * ####Example:
+ * const promise = doc.execPopulate({ path: 'company', select: 'employees' });
+ *
+ * // summary
+ * promise.then(resolve,reject);
+ *
+ * @see Document.populate #document_Document-populate
+ * @api public
+ * @param {Function} [callback] optional callback. If specified, a promise will **not** be returned
+ * @return {Promise} promise that resolves to the document when population is done
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.execPopulate = function(callback) {
+ const isUsingShorthand = callback != null && typeof callback !== 'function';
+ if (isUsingShorthand) {
+ return this.populate.apply(this, arguments).execPopulate();
+ }
+
+ return promiseOrCallback(callback, cb => {
+ this.populate(cb);
+ }, this.constructor.events);
+};
+
+/**
+ * Gets _id(s) used during population of the given `path`.
+ *
+ * ####Example:
+ *
+ * Model.findOne().populate('author').exec(function (err, doc) {
+ * console.log(doc.author.name) // Dr.Seuss
+ * console.log(doc.populated('author')) // '5144cf8050f071d979c118a7'
+ * })
+ *
+ * If the path was not populated, undefined is returned.
+ *
+ * @param {String} path
+ * @return {Array|ObjectId|Number|Buffer|String|undefined}
+ * @memberOf Document
+ * @instance
+ * @api public
+ */
+
+Document.prototype.populated = function(path, val, options) {
+ // val and options are internal
+ if (val === null || val === void 0) {
+ if (!this.$__.populated) {
+ return undefined;
+ }
+ const v = this.$__.populated[path];
+ if (v) {
+ return v.value;
+ }
+ return undefined;
+ }
+
+ // internal
+ if (val === true) {
+ if (!this.$__.populated) {
+ return undefined;
+ }
+ return this.$__.populated[path];
+ }
+
+ this.$__.populated || (this.$__.populated = {});
+ this.$__.populated[path] = { value: val, options: options };
+
+ // If this was a nested populate, make sure each populated doc knows
+ // about its populated children (gh-7685)
+ const pieces = path.split('.');
+ for (let i = 0; i < pieces.length - 1; ++i) {
+ const subpath = pieces.slice(0, i + 1).join('.');
+ const subdoc = this.get(subpath);
+ if (subdoc != null && subdoc.$__ != null && this.populated(subpath)) {
+ const rest = pieces.slice(i + 1).join('.');
+ subdoc.populated(rest, val, options);
+ // No need to continue because the above recursion should take care of
+ // marking the rest of the docs as populated
+ break;
+ }
+ }
+
+ return val;
+};
+
+/**
+ * Takes a populated field and returns it to its unpopulated state.
+ *
+ * ####Example:
+ *
+ * Model.findOne().populate('author').exec(function (err, doc) {
+ * console.log(doc.author.name); // Dr.Seuss
+ * console.log(doc.depopulate('author'));
+ * console.log(doc.author); // '5144cf8050f071d979c118a7'
+ * })
+ *
+ * If the path was not populated, this is a no-op.
+ *
+ * @param {String} path
+ * @return {Document} this
+ * @see Document.populate #document_Document-populate
+ * @api public
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.depopulate = function(path) {
+ if (typeof path === 'string') {
+ path = path.split(' ');
+ }
+
+ let populatedIds;
+ const virtualKeys = this.$$populatedVirtuals ? Object.keys(this.$$populatedVirtuals) : [];
+ const populated = get(this, '$__.populated', {});
+
+ if (arguments.length === 0) {
+ // Depopulate all
+ for (const virtualKey of virtualKeys) {
+ delete this.$$populatedVirtuals[virtualKey];
+ delete this._doc[virtualKey];
+ delete populated[virtualKey];
+ }
+
+ const keys = Object.keys(populated);
+
+ for (const key of keys) {
+ populatedIds = this.populated(key);
+ if (!populatedIds) {
+ continue;
+ }
+ delete populated[key];
+ this.$set(key, populatedIds);
+ }
+ return this;
+ }
+
+ for (const singlePath of path) {
+ populatedIds = this.populated(singlePath);
+ delete populated[singlePath];
+
+ if (virtualKeys.indexOf(singlePath) !== -1) {
+ delete this.$$populatedVirtuals[singlePath];
+ delete this._doc[singlePath];
+ } else if (populatedIds) {
+ this.$set(singlePath, populatedIds);
+ }
+ }
+ return this;
+};
+
+
+/**
+ * Returns the full path to this document.
+ *
+ * @param {String} [path]
+ * @return {String}
+ * @api private
+ * @method $__fullPath
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.$__fullPath = function(path) {
+ // overridden in SubDocuments
+ return path || '';
+};
+
+/**
+ * Returns the changes that happened to the document
+ * in the format that will be sent to MongoDB.
+ *
+ * #### Example:
+ *
+ * const userSchema = new Schema({
+ * name: String,
+ * age: Number,
+ * country: String
+ * });
+ * const User = mongoose.model('User', userSchema);
+ * const user = await User.create({
+ * name: 'Hafez',
+ * age: 25,
+ * country: 'Egypt'
+ * });
+ *
+ * // returns an empty object, no changes happened yet
+ * user.getChanges(); // { }
+ *
+ * user.country = undefined;
+ * user.age = 26;
+ *
+ * user.getChanges(); // { $set: { age: 26 }, { $unset: { country: 1 } } }
+ *
+ * await user.save();
+ *
+ * user.getChanges(); // { }
+ *
+ * Modifying the object that `getChanges()` returns does not affect the document's
+ * change tracking state. Even if you `delete user.getChanges().$set`, Mongoose
+ * will still send a `$set` to the server.
+ *
+ * @return {Object}
+ * @api public
+ * @method getChanges
+ * @memberOf Document
+ * @instance
+ */
+
+Document.prototype.getChanges = function() {
+ const delta = this.$__delta();
+
+ const changes = delta ? delta[1] : {};
+ return changes;
+};
+
+/*!
+ * Module exports.
+ */
+
+Document.ValidationError = ValidationError;
+module.exports = exports = Document;
diff --git a/node_modules/mongoose/lib/document_provider.js b/node_modules/mongoose/lib/document_provider.js
new file mode 100644
index 0000000..1ace61f
--- /dev/null
+++ b/node_modules/mongoose/lib/document_provider.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/* eslint-env browser */
+
+/*!
+ * Module dependencies.
+ */
+const Document = require('./document.js');
+const BrowserDocument = require('./browserDocument.js');
+
+let isBrowser = false;
+
+/**
+ * Returns the Document constructor for the current context
+ *
+ * @api private
+ */
+module.exports = function() {
+ if (isBrowser) {
+ return BrowserDocument;
+ }
+ return Document;
+};
+
+/*!
+ * ignore
+ */
+module.exports.setBrowser = function(flag) {
+ isBrowser = flag;
+};
diff --git a/node_modules/mongoose/lib/driver.js b/node_modules/mongoose/lib/driver.js
new file mode 100644
index 0000000..cf7ca3d
--- /dev/null
+++ b/node_modules/mongoose/lib/driver.js
@@ -0,0 +1,15 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+let driver = null;
+
+module.exports.get = function() {
+ return driver;
+};
+
+module.exports.set = function(v) {
+ driver = v;
+};
diff --git a/node_modules/mongoose/lib/drivers/SPEC.md b/node_modules/mongoose/lib/drivers/SPEC.md
new file mode 100644
index 0000000..6464693
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/SPEC.md
@@ -0,0 +1,4 @@
+
+# Driver Spec
+
+TODO
diff --git a/node_modules/mongoose/lib/drivers/browser/ReadPreference.js b/node_modules/mongoose/lib/drivers/browser/ReadPreference.js
new file mode 100644
index 0000000..1363570
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/browser/ReadPreference.js
@@ -0,0 +1,7 @@
+/*!
+ * ignore
+ */
+
+'use strict';
+
+module.exports = function() {};
diff --git a/node_modules/mongoose/lib/drivers/browser/binary.js b/node_modules/mongoose/lib/drivers/browser/binary.js
new file mode 100644
index 0000000..4658f7b
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/browser/binary.js
@@ -0,0 +1,14 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const Binary = require('bson').Binary;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = Binary;
diff --git a/node_modules/mongoose/lib/drivers/browser/decimal128.js b/node_modules/mongoose/lib/drivers/browser/decimal128.js
new file mode 100644
index 0000000..5668182
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/browser/decimal128.js
@@ -0,0 +1,7 @@
+/*!
+ * ignore
+ */
+
+'use strict';
+
+module.exports = require('bson').Decimal128;
diff --git a/node_modules/mongoose/lib/drivers/browser/index.js b/node_modules/mongoose/lib/drivers/browser/index.js
new file mode 100644
index 0000000..56d0b8a
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/browser/index.js
@@ -0,0 +1,13 @@
+/*!
+ * Module exports.
+ */
+
+'use strict';
+
+exports.Binary = require('./binary');
+exports.Collection = function() {
+ throw new Error('Cannot create a collection from browser library');
+};
+exports.Decimal128 = require('./decimal128');
+exports.ObjectId = require('./objectid');
+exports.ReadPreference = require('./ReadPreference');
diff --git a/node_modules/mongoose/lib/drivers/browser/objectid.js b/node_modules/mongoose/lib/drivers/browser/objectid.js
new file mode 100644
index 0000000..b1e603d
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/browser/objectid.js
@@ -0,0 +1,28 @@
+
+/*!
+ * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId
+ * @constructor NodeMongoDbObjectId
+ * @see ObjectId
+ */
+
+'use strict';
+
+const ObjectId = require('bson').ObjectID;
+
+/*!
+ * Getter for convenience with populate, see gh-6115
+ */
+
+Object.defineProperty(ObjectId.prototype, '_id', {
+ enumerable: false,
+ configurable: true,
+ get: function() {
+ return this;
+ }
+});
+
+/*!
+ * ignore
+ */
+
+module.exports = exports = ObjectId;
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/ReadPreference.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/ReadPreference.js
new file mode 100644
index 0000000..024ee18
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/ReadPreference.js
@@ -0,0 +1,47 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const mongodb = require('mongodb');
+const ReadPref = mongodb.ReadPreference;
+
+/*!
+ * Converts arguments to ReadPrefs the driver
+ * can understand.
+ *
+ * @param {String|Array} pref
+ * @param {Array} [tags]
+ */
+
+module.exports = function readPref(pref, tags) {
+ if (Array.isArray(pref)) {
+ tags = pref[1];
+ pref = pref[0];
+ }
+
+ if (pref instanceof ReadPref) {
+ return pref;
+ }
+
+ switch (pref) {
+ case 'p':
+ pref = 'primary';
+ break;
+ case 'pp':
+ pref = 'primaryPreferred';
+ break;
+ case 's':
+ pref = 'secondary';
+ break;
+ case 'sp':
+ pref = 'secondaryPreferred';
+ break;
+ case 'n':
+ pref = 'nearest';
+ break;
+ }
+
+ return new ReadPref(pref, tags);
+};
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
new file mode 100644
index 0000000..4e3c86f
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/binary.js
@@ -0,0 +1,10 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const Binary = require('mongodb').Binary;
+
+module.exports = exports = Binary;
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
new file mode 100644
index 0000000..d660c7d
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js
@@ -0,0 +1,368 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseCollection = require('../../collection');
+const MongooseError = require('../../error/mongooseError');
+const Collection = require('mongodb').Collection;
+const get = require('../../helpers/get');
+const sliced = require('sliced');
+const stream = require('stream');
+const util = require('util');
+
+/**
+ * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) collection implementation.
+ *
+ * All methods methods from the [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver are copied and wrapped in queue management.
+ *
+ * @inherits Collection
+ * @api private
+ */
+
+function NativeCollection(name, options) {
+ this.collection = null;
+ this.Promise = options.Promise || Promise;
+ this._closed = false;
+ MongooseCollection.apply(this, arguments);
+}
+
+/*!
+ * Inherit from abstract Collection.
+ */
+
+NativeCollection.prototype.__proto__ = MongooseCollection.prototype;
+
+/**
+ * Called when the connection opens.
+ *
+ * @api private
+ */
+
+NativeCollection.prototype.onOpen = function() {
+ const _this = this;
+
+ // always get a new collection in case the user changed host:port
+ // of parent db instance when re-opening the connection.
+
+ if (!_this.opts.capped.size) {
+ // non-capped
+ callback(null, _this.conn.db.collection(_this.name));
+ return _this.collection;
+ }
+
+ if (_this.opts.autoCreate === false) {
+ _this.collection = _this.conn.db.collection(_this.name);
+ return _this.collection;
+ }
+
+ // capped
+ return _this.conn.db.collection(_this.name, function(err, c) {
+ if (err) return callback(err);
+
+ // discover if this collection exists and if it is capped
+ _this.conn.db.listCollections({ name: _this.name }).toArray(function(err, docs) {
+ if (err) {
+ return callback(err);
+ }
+ const doc = docs[0];
+ const exists = !!doc;
+
+ if (exists) {
+ if (doc.options && doc.options.capped) {
+ callback(null, c);
+ } else {
+ const msg = 'A non-capped collection exists with the name: ' + _this.name + '\n\n'
+ + ' To use this collection as a capped collection, please '
+ + 'first convert it.\n'
+ + ' http://www.mongodb.org/display/DOCS/Capped+Collections#CappedCollections-Convertingacollectiontocapped';
+ err = new Error(msg);
+ callback(err);
+ }
+ } else {
+ // create
+ const opts = Object.assign({}, _this.opts.capped);
+ opts.capped = true;
+ _this.conn.db.createCollection(_this.name, opts, callback);
+ }
+ });
+ });
+
+ function callback(err, collection) {
+ if (err) {
+ // likely a strict mode error
+ _this.conn.emit('error', err);
+ } else {
+ _this.collection = collection;
+ MongooseCollection.prototype.onOpen.call(_this);
+ }
+ }
+};
+
+/**
+ * Called when the connection closes
+ *
+ * @api private
+ */
+
+NativeCollection.prototype.onClose = function(force) {
+ MongooseCollection.prototype.onClose.call(this, force);
+};
+
+/*!
+ * ignore
+ */
+
+const syncCollectionMethods = { watch: true };
+
+/*!
+ * Copy the collection methods and make them subject to queues
+ */
+
+function iter(i) {
+ NativeCollection.prototype[i] = function() {
+ const collection = this.collection;
+ const args = Array.from(arguments);
+ const _this = this;
+ const debug = get(_this, 'conn.base.options.debug');
+ const lastArg = arguments[arguments.length - 1];
+
+ // If user force closed, queueing will hang forever. See #5664
+ if (this.conn.$wasForceClosed) {
+ const error = new MongooseError('Connection was force closed');
+ if (args.length > 0 &&
+ typeof args[args.length - 1] === 'function') {
+ args[args.length - 1](error);
+ return;
+ } else {
+ throw error;
+ }
+ }
+
+ if (this._shouldBufferCommands() && this.buffer) {
+ if (syncCollectionMethods[i]) {
+ throw new Error('Collection method ' + i + ' is synchronous');
+ }
+ if (typeof lastArg === 'function') {
+ this.addQueue(i, args);
+ return;
+ }
+
+ this.conn.emit('buffer', { method: i, args: args });
+
+ return new this.Promise((resolve, reject) => {
+ this.addQueue(i, [].concat(args).concat([(err, res) => {
+ if (err != null) {
+ return reject(err);
+ }
+ resolve(res);
+ }]));
+ });
+ }
+
+ if (debug) {
+ if (typeof debug === 'function') {
+ debug.apply(_this,
+ [_this.name, i].concat(sliced(args, 0, args.length - 1)));
+ } 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);
+ }
+ }
+
+ try {
+ if (collection == null) {
+ throw new MongooseError('Cannot call `' + this.name + '.' + i + '()` before initial connection is complete if `bufferCommands = false`. Make sure you `await mongoose.connect()` if you have `bufferCommands = false`.');
+ }
+
+ return collection[i].apply(collection, args);
+ } 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);
+ } else {
+ throw error;
+ }
+ }
+ };
+}
+
+for (const key of Object.keys(Collection.prototype)) {
+ // Janky hack to work around gh-3005 until we can get rid of the mongoose
+ // collection abstraction
+ const descriptor = Object.getOwnPropertyDescriptor(Collection.prototype, key);
+ // Skip properties with getters because they may throw errors (gh-8528)
+ if (descriptor.get !== undefined) {
+ continue;
+ }
+ if (typeof Collection.prototype[key] !== 'function') {
+ continue;
+ }
+
+ iter(key);
+}
+
+/**
+ * Debug print helper
+ *
+ * @api public
+ * @method $print
+ */
+
+NativeCollection.prototype.$print = function(name, i, args, color) {
+ 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));
+ }
+ }
+ const params = '(' + _args.join(', ') + ')';
+
+ console.info(moduleName + functionCall + params);
+};
+
+/**
+ * Debug print helper
+ *
+ * @api public
+ * @method $print
+ */
+
+NativeCollection.prototype.$printToStream = function(name, i, args, stream) {
+ 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]));
+ }
+ }
+ const params = '(' + _args.join(', ') + ')';
+
+ stream.write(functionCall + params, 'utf8');
+};
+
+/**
+ * Formatter for debug print args
+ *
+ * @api public
+ * @method $format
+ */
+
+NativeCollection.prototype.$format = function(arg, color) {
+ const type = typeof arg;
+ if (type === 'function' || type === 'undefined') return '';
+ return format(arg, false, color);
+};
+
+/*!
+ * Debug print helper
+ */
+
+function inspectable(representation) {
+ const ret = {
+ inspect: function() { return representation; }
+ };
+ if (util.inspect.custom) {
+ ret[util.inspect.custom] = ret.inspect;
+ }
+ return ret;
+}
+function map(o) {
+ return format(o, true);
+}
+function formatObjectId(x, key) {
+ x[key] = inspectable('ObjectId("' + x[key].toHexString() + '")');
+}
+function formatDate(x, key) {
+ x[key] = inspectable('new Date("' + x[key].toUTCString() + '")');
+}
+function format(obj, sub, color) {
+ if (obj && typeof obj.toBSON === 'function') {
+ obj = obj.toBSON();
+ }
+ if (obj == null) {
+ return obj;
+ }
+
+ const clone = require('../../helpers/clone');
+ let x = clone(obj, { transform: false });
+
+ if (x.constructor.name === 'Binary') {
+ x = 'BinData(' + x.sub_type + ', "' + x.toString('base64') + '")';
+ } else if (x.constructor.name === 'ObjectID') {
+ x = inspectable('ObjectId("' + x.toHexString() + '")');
+ } else if (x.constructor.name === 'Date') {
+ x = inspectable('new Date("' + x.toUTCString() + '")');
+ } else if (x.constructor.name === 'Object') {
+ const keys = Object.keys(x);
+ const numKeys = keys.length;
+ let key;
+ for (let i = 0; i < numKeys; ++i) {
+ key = keys[i];
+ if (x[key]) {
+ let error;
+ if (typeof x[key].toBSON === 'function') {
+ try {
+ // `session.toBSON()` throws an error. This means we throw errors
+ // in debug mode when using transactions, see gh-6712. As a
+ // workaround, catch `toBSON()` errors, try to serialize without
+ // `toBSON()`, and rethrow if serialization still fails.
+ x[key] = x[key].toBSON();
+ } catch (_error) {
+ error = _error;
+ }
+ }
+ if (x[key].constructor.name === 'Binary') {
+ x[key] = 'BinData(' + x[key].sub_type + ', "' +
+ x[key].buffer.toString('base64') + '")';
+ } else if (x[key].constructor.name === 'Object') {
+ x[key] = format(x[key], true);
+ } else if (x[key].constructor.name === 'ObjectID') {
+ formatObjectId(x, key);
+ } else if (x[key].constructor.name === 'Date') {
+ formatDate(x, key);
+ } else if (x[key].constructor.name === 'ClientSession') {
+ x[key] = inspectable('ClientSession("' +
+ get(x[key], 'id.id.buffer', '').toString('hex') + '")');
+ } else if (Array.isArray(x[key])) {
+ x[key] = x[key].map(map);
+ } else if (error != null) {
+ // If there was an error with `toBSON()` and the object wasn't
+ // already converted to a string representation, rethrow it.
+ // Open to better ideas on how to handle this.
+ throw error;
+ }
+ }
+ }
+ }
+ if (sub) {
+ return x;
+ }
+
+ return util.
+ inspect(x, false, 10, color).
+ replace(/\n/g, '').
+ replace(/\s{2,}/g, ' ');
+}
+
+/**
+ * Retrieves information about this collections indexes.
+ *
+ * @param {Function} callback
+ * @method getIndexes
+ * @api public
+ */
+
+NativeCollection.prototype.getIndexes = NativeCollection.prototype.indexInformation;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = NativeCollection;
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
new file mode 100644
index 0000000..8041a88
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js
@@ -0,0 +1,185 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseConnection = require('../../connection');
+const STATES = require('../../connectionstate');
+
+/**
+ * A [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) connection implementation.
+ *
+ * @inherits Connection
+ * @api private
+ */
+
+function NativeConnection() {
+ MongooseConnection.apply(this, arguments);
+ this._listening = false;
+}
+
+/**
+ * Expose the possible connection states.
+ * @api public
+ */
+
+NativeConnection.STATES = STATES;
+
+/*!
+ * Inherits from Connection.
+ */
+
+NativeConnection.prototype.__proto__ = MongooseConnection.prototype;
+
+/**
+ * Switches to a different database using the same connection pool.
+ *
+ * Returns a new connection object, with the new db. If you set the `useCache`
+ * option, `useDb()` will cache connections by `name`.
+ *
+ * @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.
+ * @return {Connection} New Connection Object
+ * @api public
+ */
+
+NativeConnection.prototype.useDb = function(name, options) {
+ // Return immediately if cached
+ if (options && options.useCache && this.relatedDbs[name]) {
+ return this.relatedDbs[name];
+ }
+
+ // we have to manually copy all of the attributes...
+ const newConn = new this.constructor();
+ newConn.name = name;
+ newConn.base = this.base;
+ newConn.collections = {};
+ newConn.models = {};
+ newConn.replica = this.replica;
+ newConn.config = Object.assign({}, this.base.connection.config, newConn.config);
+ newConn.name = this.name;
+ newConn.options = this.options;
+ newConn._readyState = this._readyState;
+ newConn._closeCalled = this._closeCalled;
+ newConn._hasOpened = this._hasOpened;
+ newConn._listening = false;
+
+ newConn.host = this.host;
+ newConn.port = this.port;
+ newConn.user = this.user;
+ newConn.pass = this.pass;
+
+ // First, when we create another db object, we are not guaranteed to have a
+ // db object to work with. So, in the case where we have a db object and it
+ // is connected, we can just proceed with setting everything up. However, if
+ // we do not have a db or the state is not connected, then we need to wait on
+ // the 'open' event of the connection before doing the rest of the setup
+ // the 'connected' event is the first time we'll have access to the db object
+
+ const _this = this;
+
+ newConn.client = _this.client;
+
+ if (this.db && this._readyState === STATES.connected) {
+ wireup();
+ } else {
+ this.once('connected', wireup);
+ }
+
+ function wireup() {
+ newConn.client = _this.client;
+ newConn.db = _this.client.db(name);
+ newConn.onOpen();
+ // setup the events appropriately
+ listen(newConn);
+ }
+
+ newConn.name = name;
+
+ // push onto the otherDbs stack, this is used when state changes
+ this.otherDbs.push(newConn);
+ newConn.otherDbs.push(this);
+
+ // push onto the relatedDbs cache, this is used when state changes
+ if (options && options.useCache) {
+ this.relatedDbs[newConn.name] = newConn;
+ newConn.relatedDbs = this.relatedDbs;
+ }
+
+ return newConn;
+};
+
+/*!
+ * Register listeners for important events and bubble appropriately.
+ */
+
+function listen(conn) {
+ if (conn.db._listening) {
+ return;
+ }
+ conn.db._listening = true;
+
+ conn.db.on('close', function(force) {
+ if (conn._closeCalled) return;
+
+ // the driver never emits an `open` event. auto_reconnect still
+ // emits a `close` event but since we never get another
+ // `open` we can't emit close
+ if (conn.db.serverConfig.autoReconnect) {
+ conn.readyState = STATES.disconnected;
+ conn.emit('close');
+ return;
+ }
+ conn.onClose(force);
+ });
+ conn.db.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) {
+ conn.readyState = STATES.connected;
+ conn.emit('reconnect');
+ conn.emit('reconnected');
+ }
+ });
+ conn.db.on('parseError', function(err) {
+ conn.emit('parseError', err);
+ });
+}
+
+/**
+ * Closes the connection
+ *
+ * @param {Boolean} [force]
+ * @param {Function} [fn]
+ * @return {Connection} this
+ * @api private
+ */
+
+NativeConnection.prototype.doClose = function(force, fn) {
+ 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.
+ // If there's queued operations, you may still get some background work
+ // after the callback is called.
+ setTimeout(() => fn(err, res), 1);
+ });
+ return this;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = NativeConnection;
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/decimal128.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/decimal128.js
new file mode 100644
index 0000000..c895f17
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/decimal128.js
@@ -0,0 +1,7 @@
+/*!
+ * ignore
+ */
+
+'use strict';
+
+module.exports = require('mongodb').Decimal128;
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/index.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/index.js
new file mode 100644
index 0000000..2cd749e
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/index.js
@@ -0,0 +1,11 @@
+/*!
+ * Module exports.
+ */
+
+'use strict';
+
+exports.Binary = require('./binary');
+exports.Collection = require('./collection');
+exports.Decimal128 = require('./decimal128');
+exports.ObjectId = require('./objectid');
+exports.ReadPreference = require('./ReadPreference'); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js b/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
new file mode 100644
index 0000000..6f432b7
--- /dev/null
+++ b/node_modules/mongoose/lib/drivers/node-mongodb-native/objectid.js
@@ -0,0 +1,16 @@
+
+/*!
+ * [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) ObjectId
+ * @constructor NodeMongoDbObjectId
+ * @see ObjectId
+ */
+
+'use strict';
+
+const ObjectId = require('mongodb').ObjectId;
+
+/*!
+ * ignore
+ */
+
+module.exports = exports = ObjectId;
diff --git a/node_modules/mongoose/lib/error/browserMissingSchema.js b/node_modules/mongoose/lib/error/browserMissingSchema.js
new file mode 100644
index 0000000..fe492d5
--- /dev/null
+++ b/node_modules/mongoose/lib/error/browserMissingSchema.js
@@ -0,0 +1,28 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+class MissingSchemaError extends MongooseError {
+ /*!
+ * MissingSchema Error constructor.
+ */
+ constructor() {
+ super('Schema hasn\'t been registered for document.\n'
+ + 'Use mongoose.Document(name, schema)');
+ }
+}
+
+Object.defineProperty(MissingSchemaError.prototype, 'name', {
+ value: 'MongooseError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = MissingSchemaError;
diff --git a/node_modules/mongoose/lib/error/cast.js b/node_modules/mongoose/lib/error/cast.js
new file mode 100644
index 0000000..c6ff277
--- /dev/null
+++ b/node_modules/mongoose/lib/error/cast.js
@@ -0,0 +1,120 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./mongooseError');
+const get = require('../helpers/get');
+const util = require('util');
+
+/**
+ * Casting Error constructor.
+ *
+ * @param {String} type
+ * @param {String} value
+ * @inherits MongooseError
+ * @api private
+ */
+
+class CastError extends MongooseError {
+ constructor(type, value, path, reason, schemaType) {
+ // If no args, assume we'll `init()` later.
+ if (arguments.length > 0) {
+ const stringValue = getStringValue(value);
+ const messageFormat = getMessageFormat(schemaType);
+ const msg = formatMessage(null, type, stringValue, path, messageFormat);
+ super(msg);
+ this.init(type, value, path, reason, schemaType);
+ } else {
+ super(formatMessage());
+ }
+ }
+
+ /*!
+ * ignore
+ */
+ init(type, value, path, reason, schemaType) {
+ this.stringValue = getStringValue(value);
+ this.messageFormat = getMessageFormat(schemaType);
+ this.kind = type;
+ this.value = value;
+ this.path = path;
+ this.reason = reason;
+ }
+
+ /*!
+ * ignore
+ * @param {Readonly<CastError>} other
+ */
+ copy(other) {
+ this.messageFormat = other.messageFormat;
+ this.stringValue = other.stringValue;
+ this.kind = other.kind;
+ this.value = other.value;
+ this.path = other.path;
+ this.reason = other.reason;
+ this.message = other.message;
+ }
+
+ /*!
+ * ignore
+ */
+ setModel(model) {
+ this.model = model;
+ this.message = formatMessage(model, this.kind, this.stringValue, this.path,
+ this.messageFormat);
+ }
+}
+
+Object.defineProperty(CastError.prototype, 'name', {
+ value: 'CastError'
+});
+
+function getStringValue(value) {
+ let stringValue = util.inspect(value);
+ stringValue = stringValue.replace(/^'|'$/g, '"');
+ if (!stringValue.startsWith('"')) {
+ stringValue = '"' + stringValue + '"';
+ }
+ return stringValue;
+}
+
+function getMessageFormat(schemaType) {
+ const messageFormat = get(schemaType, 'options.cast', null);
+ if (typeof messageFormat === 'string') {
+ return messageFormat;
+ }
+}
+
+/*!
+ * ignore
+ */
+
+function formatMessage(model, kind, stringValue, path, messageFormat) {
+ if (messageFormat != null) {
+ let ret = messageFormat.
+ replace('{KIND}', kind).
+ replace('{VALUE}', stringValue).
+ replace('{PATH}', path);
+ if (model != null) {
+ ret = ret.replace('{MODEL}', model.modelName);
+ }
+
+ return ret;
+ } else {
+ let ret = 'Cast to ' + kind + ' failed for value ' +
+ stringValue + ' at path "' + path + '"';
+ if (model != null) {
+ ret += ' for model "' + model.modelName + '"';
+ }
+
+ return ret;
+ }
+}
+
+/*!
+ * exports
+ */
+
+module.exports = CastError;
diff --git a/node_modules/mongoose/lib/error/disconnected.js b/node_modules/mongoose/lib/error/disconnected.js
new file mode 100644
index 0000000..777a1de
--- /dev/null
+++ b/node_modules/mongoose/lib/error/disconnected.js
@@ -0,0 +1,34 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+/**
+ * The connection failed to reconnect and will never successfully reconnect to
+ * MongoDB without manual intervention.
+ * @api private
+ */
+class DisconnectedError extends MongooseError {
+ /**
+ * @param {String} connectionString
+ */
+ constructor(connectionString) {
+ super('Ran out of retries trying to reconnect to "' +
+ connectionString + '". Try setting `server.reconnectTries` and ' +
+ '`server.reconnectInterval` to something higher.');
+ }
+}
+
+Object.defineProperty(DisconnectedError.prototype, 'name', {
+ value: 'DisconnectedError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = DisconnectedError;
diff --git a/node_modules/mongoose/lib/error/divergentArray.js b/node_modules/mongoose/lib/error/divergentArray.js
new file mode 100644
index 0000000..ed86caf
--- /dev/null
+++ b/node_modules/mongoose/lib/error/divergentArray.js
@@ -0,0 +1,37 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+class DivergentArrayError extends MongooseError {
+ /*!
+ * DivergentArrayError constructor.
+ * @param {Array<String>} paths
+ */
+ constructor(paths) {
+ const msg = 'For your own good, using `document.save()` to update an array '
+ + 'which was selected using an $elemMatch projection OR '
+ + 'populated using skip, limit, query conditions, or exclusion of '
+ + 'the _id field when the operation results in a $pop or $set of '
+ + 'the entire array is not supported. The following '
+ + 'path(s) would have been modified unsafely:\n'
+ + ' ' + paths.join('\n ') + '\n'
+ + 'Use Model.update() to update these arrays instead.';
+ // TODO write up a docs page (FAQ) and link to it
+ super(msg);
+ }
+}
+
+Object.defineProperty(DivergentArrayError.prototype, 'name', {
+ value: 'DivergentArrayError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = DivergentArrayError;
diff --git a/node_modules/mongoose/lib/error/index.js b/node_modules/mongoose/lib/error/index.js
new file mode 100644
index 0000000..ec4188d
--- /dev/null
+++ b/node_modules/mongoose/lib/error/index.js
@@ -0,0 +1,205 @@
+'use strict';
+
+/**
+ * MongooseError constructor. MongooseError is the base class for all
+ * Mongoose-specific errors.
+ *
+ * ####Example:
+ * const Model = mongoose.model('Test', new Schema({ answer: Number }));
+ * const doc = new Model({ answer: 'not a number' });
+ * const err = doc.validateSync();
+ *
+ * err instanceof mongoose.Error; // true
+ *
+ * @constructor Error
+ * @param {String} msg Error message
+ * @inherits Error https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error
+ */
+
+const MongooseError = require('./mongooseError');
+
+/**
+ * The name of the error. The name uniquely identifies this Mongoose error. The
+ * possible values are:
+ *
+ * - `MongooseError`: general Mongoose error
+ * - `CastError`: Mongoose could not convert a value to the type defined in the schema path. May be in a `ValidationError` class' `errors` property.
+ * - `DisconnectedError`: This [connection](connections.html) timed out in trying to reconnect to MongoDB and will not successfully reconnect to MongoDB unless you explicitly reconnect.
+ * - `DivergentArrayError`: You attempted to `save()` an array that was modified after you loaded it with a `$elemMatch` or similar projection
+ * - `MissingSchemaError`: You tried to access a model with [`mongoose.model()`](api.html#mongoose_Mongoose-model) that was not defined
+ * - `DocumentNotFoundError`: The document you tried to [`save()`](api.html#document_Document-save) was not found
+ * - `ValidatorError`: error from an individual schema path's validator
+ * - `ValidationError`: error returned from [`validate()`](api.html#document_Document-validate) or [`validateSync()`](api.html#document_Document-validateSync). Contains zero or more `ValidatorError` instances in `.errors` property.
+ * - `MissingSchemaError`: You called `mongoose.Document()` without a schema
+ * - `ObjectExpectedError`: Thrown when you set a nested path to a non-object value with [strict mode set](guide.html#strict).
+ * - `ObjectParameterError`: Thrown when you pass a non-object value to a function which expects an object as a paramter
+ * - `OverwriteModelError`: Thrown when you call [`mongoose.model()`](api.html#mongoose_Mongoose-model) to re-define a model that was already defined.
+ * - `ParallelSaveError`: Thrown when you call [`save()`](api.html#model_Model-save) on a document when the same document instance is already saving.
+ * - `StrictModeError`: Thrown when you set a path that isn't the schema and [strict mode](guide.html#strict) is set to `throw`.
+ * - `VersionError`: Thrown when the [document is out of sync](guide.html#versionKey)
+ *
+ * @api public
+ * @property {String} name
+ * @memberOf Error
+ * @instance
+ */
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = MongooseError;
+
+/**
+ * The default built-in validator error messages.
+ *
+ * @see Error.messages #error_messages_MongooseError-messages
+ * @api public
+ * @memberOf Error
+ * @static messages
+ */
+
+MongooseError.messages = require('./messages');
+
+// backward compat
+MongooseError.Messages = MongooseError.messages;
+
+/**
+ * An instance of this error class will be returned when `save()` fails
+ * because the underlying
+ * document was not found. The constructor takes one parameter, the
+ * conditions that mongoose passed to `update()` when trying to update
+ * the document.
+ *
+ * @api public
+ * @memberOf Error
+ * @static DocumentNotFoundError
+ */
+
+MongooseError.DocumentNotFoundError = require('./notFound');
+
+/**
+ * An instance of this error class will be returned when mongoose failed to
+ * cast a value.
+ *
+ * @api public
+ * @memberOf Error
+ * @static CastError
+ */
+
+MongooseError.CastError = require('./cast');
+
+/**
+ * An instance of this error class will be returned when [validation](/docs/validation.html) failed.
+ * The `errors` property contains an object whose keys are the paths that failed and whose values are
+ * instances of CastError or ValidationError.
+ *
+ * @api public
+ * @memberOf Error
+ * @static ValidationError
+ */
+
+MongooseError.ValidationError = require('./validation');
+
+/**
+ * A `ValidationError` has a hash of `errors` that contain individual
+ * `ValidatorError` instances.
+ *
+ * ####Example:
+ *
+ * const schema = Schema({ name: { type: String, required: true } });
+ * const Model = mongoose.model('Test', schema);
+ * const doc = new Model({});
+ *
+ * // Top-level error is a ValidationError, **not** a ValidatorError
+ * const err = doc.validateSync();
+ * err instanceof mongoose.Error.ValidationError; // true
+ *
+ * // A ValidationError `err` has 0 or more ValidatorErrors keyed by the
+ * // path in the `err.errors` property.
+ * err.errors['name'] instanceof mongoose.Error.ValidatorError;
+ *
+ * err.errors['name'].kind; // 'required'
+ * err.errors['name'].path; // 'name'
+ * err.errors['name'].value; // undefined
+ *
+ * Instances of `ValidatorError` have the following properties:
+ *
+ * - `kind`: The validator's `type`, like `'required'` or `'regexp'`
+ * - `path`: The path that failed validation
+ * - `value`: The value that failed validation
+ *
+ * @api public
+ * @memberOf Error
+ * @static ValidatorError
+ */
+
+MongooseError.ValidatorError = require('./validator');
+
+/**
+ * An instance of this error class will be returned when you call `save()` after
+ * the document in the database was changed in a potentially unsafe way. See
+ * the [`versionKey` option](/docs/guide.html#versionKey) for more information.
+ *
+ * @api public
+ * @memberOf Error
+ * @static VersionError
+ */
+
+MongooseError.VersionError = require('./version');
+
+/**
+ * An instance of this error class will be returned when you call `save()` multiple
+ * times on the same document in parallel. See the [FAQ](/docs/faq.html) for more
+ * information.
+ *
+ * @api public
+ * @memberOf Error
+ * @static ParallelSaveError
+ */
+
+MongooseError.ParallelSaveError = require('./parallelSave');
+
+/**
+ * Thrown when a model with the given name was already registered on the connection.
+ * See [the FAQ about `OverwriteModelError`](/docs/faq.html#overwrite-model-error).
+ *
+ * @api public
+ * @memberOf Error
+ * @static OverwriteModelError
+ */
+
+MongooseError.OverwriteModelError = require('./overwriteModel');
+
+/**
+ * Thrown when you try to access a model that has not been registered yet
+ *
+ * @api public
+ * @memberOf Error
+ * @static MissingSchemaError
+ */
+
+MongooseError.MissingSchemaError = require('./missingSchema');
+
+/**
+ * An instance of this error will be returned if you used an array projection
+ * and then modified the array in an unsafe way.
+ *
+ * @api public
+ * @memberOf Error
+ * @static DivergentArrayError
+ */
+
+MongooseError.DivergentArrayError = require('./divergentArray');
+
+/**
+ * Thrown when your try to pass values to model contrtuctor that
+ * were not specified in schema or change immutable properties when
+ * `strict` mode is `"throw"`
+ *
+ * @api public
+ * @memberOf Error
+ * @static StrictModeError
+ */
+
+MongooseError.StrictModeError = require('./strict');
diff --git a/node_modules/mongoose/lib/error/messages.js b/node_modules/mongoose/lib/error/messages.js
new file mode 100644
index 0000000..ac0294a
--- /dev/null
+++ b/node_modules/mongoose/lib/error/messages.js
@@ -0,0 +1,47 @@
+
+/**
+ * The default built-in validator error messages. These may be customized.
+ *
+ * // customize within each schema or globally like so
+ * const mongoose = require('mongoose');
+ * mongoose.Error.messages.String.enum = "Your custom message for {PATH}.";
+ *
+ * As you might have noticed, error messages support basic templating
+ *
+ * - `{PATH}` is replaced with the invalid document path
+ * - `{VALUE}` is replaced with the invalid value
+ * - `{TYPE}` is replaced with the validator type such as "regexp", "min", or "user defined"
+ * - `{MIN}` is replaced with the declared min value for the Number.min validator
+ * - `{MAX}` is replaced with the declared max value for the Number.max validator
+ *
+ * Click the "show code" link below to see all defaults.
+ *
+ * @static messages
+ * @receiver MongooseError
+ * @api public
+ */
+
+'use strict';
+
+const msg = module.exports = exports = {};
+
+msg.DocumentNotFoundError = null;
+
+msg.general = {};
+msg.general.default = 'Validator failed for path `{PATH}` with value `{VALUE}`';
+msg.general.required = 'Path `{PATH}` is required.';
+
+msg.Number = {};
+msg.Number.min = 'Path `{PATH}` ({VALUE}) is less than minimum allowed value ({MIN}).';
+msg.Number.max = 'Path `{PATH}` ({VALUE}) is more than maximum allowed value ({MAX}).';
+msg.Number.enum = '`{VALUE}` is not a valid enum value for path `{PATH}`.';
+
+msg.Date = {};
+msg.Date.min = 'Path `{PATH}` ({VALUE}) is before minimum allowed value ({MIN}).';
+msg.Date.max = 'Path `{PATH}` ({VALUE}) is after maximum allowed value ({MAX}).';
+
+msg.String = {};
+msg.String.enum = '`{VALUE}` is not a valid enum value for path `{PATH}`.';
+msg.String.match = 'Path `{PATH}` is invalid ({VALUE}).';
+msg.String.minlength = 'Path `{PATH}` (`{VALUE}`) is shorter than the minimum allowed length ({MINLENGTH}).';
+msg.String.maxlength = 'Path `{PATH}` (`{VALUE}`) is longer than the maximum allowed length ({MAXLENGTH}).';
diff --git a/node_modules/mongoose/lib/error/missingSchema.js b/node_modules/mongoose/lib/error/missingSchema.js
new file mode 100644
index 0000000..ca306b7
--- /dev/null
+++ b/node_modules/mongoose/lib/error/missingSchema.js
@@ -0,0 +1,30 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+class MissingSchemaError extends MongooseError {
+ /*!
+ * MissingSchema Error constructor.
+ * @param {String} name
+ */
+ constructor(name) {
+ const msg = 'Schema hasn\'t been registered for model "' + name + '".\n'
+ + 'Use mongoose.model(name, schema)';
+ super(msg);
+ }
+}
+
+Object.defineProperty(MissingSchemaError.prototype, 'name', {
+ value: 'MissingSchemaError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = MissingSchemaError;
diff --git a/node_modules/mongoose/lib/error/mongooseError.js b/node_modules/mongoose/lib/error/mongooseError.js
new file mode 100644
index 0000000..5505105
--- /dev/null
+++ b/node_modules/mongoose/lib/error/mongooseError.js
@@ -0,0 +1,13 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+class MongooseError extends Error { }
+
+Object.defineProperty(MongooseError.prototype, 'name', {
+ value: 'MongooseError'
+});
+
+module.exports = MongooseError;
diff --git a/node_modules/mongoose/lib/error/notFound.js b/node_modules/mongoose/lib/error/notFound.js
new file mode 100644
index 0000000..0e8386b
--- /dev/null
+++ b/node_modules/mongoose/lib/error/notFound.js
@@ -0,0 +1,44 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./');
+const util = require('util');
+
+class DocumentNotFoundError extends MongooseError {
+ /*!
+ * OverwriteModel Error constructor.
+ */
+ constructor(filter, model, numAffected, result) {
+ let msg;
+ const messages = MongooseError.messages;
+ if (messages.DocumentNotFoundError != null) {
+ msg = typeof messages.DocumentNotFoundError === 'function' ?
+ messages.DocumentNotFoundError(filter, model) :
+ messages.DocumentNotFoundError;
+ } else {
+ msg = 'No document found for query "' + util.inspect(filter) +
+ '" on model "' + model + '"';
+ }
+
+ super(msg);
+
+ this.result = result;
+ this.numAffected = numAffected;
+ this.filter = filter;
+ // Backwards compat
+ this.query = filter;
+ }
+}
+
+Object.defineProperty(DocumentNotFoundError.prototype, 'name', {
+ value: 'DocumentNotFoundError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = DocumentNotFoundError;
diff --git a/node_modules/mongoose/lib/error/objectExpected.js b/node_modules/mongoose/lib/error/objectExpected.js
new file mode 100644
index 0000000..3b02bb4
--- /dev/null
+++ b/node_modules/mongoose/lib/error/objectExpected.js
@@ -0,0 +1,30 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+class ObjectExpectedError extends MongooseError {
+ /**
+ * Strict mode error constructor
+ *
+ * @param {string} type
+ * @param {string} value
+ * @api private
+ */
+ constructor(path, val) {
+ const typeDescription = Array.isArray(val) ? 'array' : 'primitive value';
+ super('Tried to set nested object field `' + path +
+ `\` to ${typeDescription} \`` + val + '` and strict mode is set to throw.');
+ this.path = path;
+ }
+}
+
+Object.defineProperty(ObjectExpectedError.prototype, 'name', {
+ value: 'ObjectExpectedError'
+});
+
+module.exports = ObjectExpectedError;
diff --git a/node_modules/mongoose/lib/error/objectParameter.js b/node_modules/mongoose/lib/error/objectParameter.js
new file mode 100644
index 0000000..5881a48
--- /dev/null
+++ b/node_modules/mongoose/lib/error/objectParameter.js
@@ -0,0 +1,30 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+class ObjectParameterError extends MongooseError {
+ /**
+ * Constructor for errors that happen when a parameter that's expected to be
+ * an object isn't an object
+ *
+ * @param {Any} value
+ * @param {String} paramName
+ * @param {String} fnName
+ * @api private
+ */
+ constructor(value, paramName, fnName) {
+ super('Parameter "' + paramName + '" to ' + fnName +
+ '() must be an object, got ' + value.toString());
+ }
+}
+
+
+Object.defineProperty(ObjectParameterError.prototype, 'name', {
+ value: 'ObjectParameterError'
+});
+
+module.exports = ObjectParameterError;
diff --git a/node_modules/mongoose/lib/error/overwriteModel.js b/node_modules/mongoose/lib/error/overwriteModel.js
new file mode 100644
index 0000000..d509e19
--- /dev/null
+++ b/node_modules/mongoose/lib/error/overwriteModel.js
@@ -0,0 +1,29 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+class OverwriteModelError extends MongooseError {
+ /*!
+ * OverwriteModel Error constructor.
+ * @param {String} name
+ */
+ constructor(name) {
+ super('Cannot overwrite `' + name + '` model once compiled.');
+ }
+}
+
+Object.defineProperty(OverwriteModelError.prototype, 'name', {
+ value: 'OverwriteModelError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = OverwriteModelError;
diff --git a/node_modules/mongoose/lib/error/parallelSave.js b/node_modules/mongoose/lib/error/parallelSave.js
new file mode 100644
index 0000000..e062857
--- /dev/null
+++ b/node_modules/mongoose/lib/error/parallelSave.js
@@ -0,0 +1,30 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./');
+
+class ParallelSaveError extends MongooseError {
+ /**
+ * ParallelSave Error constructor.
+ *
+ * @param {Document} doc
+ * @api private
+ */
+ constructor(doc) {
+ const msg = 'Can\'t save() the same doc multiple times in parallel. Document: ';
+ super(msg + doc._id);
+ }
+}
+
+Object.defineProperty(ParallelSaveError.prototype, 'name', {
+ value: 'ParallelSaveError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = ParallelSaveError;
diff --git a/node_modules/mongoose/lib/error/parallelValidate.js b/node_modules/mongoose/lib/error/parallelValidate.js
new file mode 100644
index 0000000..18697b6
--- /dev/null
+++ b/node_modules/mongoose/lib/error/parallelValidate.js
@@ -0,0 +1,31 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./mongooseError');
+
+
+class ParallelValidateError extends MongooseError {
+ /**
+ * ParallelValidate Error constructor.
+ *
+ * @param {Document} doc
+ * @api private
+ */
+ constructor(doc) {
+ const msg = 'Can\'t validate() the same doc multiple times in parallel. Document: ';
+ super(msg + doc._id);
+ }
+}
+
+Object.defineProperty(ParallelValidateError.prototype, 'name', {
+ value: 'ParallelValidateError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = ParallelValidateError; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/error/serverSelection.js b/node_modules/mongoose/lib/error/serverSelection.js
new file mode 100644
index 0000000..162e2fc
--- /dev/null
+++ b/node_modules/mongoose/lib/error/serverSelection.js
@@ -0,0 +1,61 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./mongooseError');
+const allServersUnknown = require('../helpers/topology/allServersUnknown');
+const isAtlas = require('../helpers/topology/isAtlas');
+const isSSLError = require('../helpers/topology/isSSLError');
+
+/*!
+ * ignore
+ */
+
+const atlasMessage = 'Could not connect to any servers in your MongoDB Atlas cluster. ' +
+ 'One common reason is that you\'re trying to access the database from ' +
+ '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
+ *
+ * @api private
+ */
+ assimilateError(err) {
+ const reason = err.reason;
+ // 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 &&
+ 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];
+ }
+ }
+
+ return this;
+ }
+}
+
+Object.defineProperty(MongooseServerSelectionError.prototype, 'name', {
+ value: 'MongooseServerSelectionError'
+});
+
+module.exports = MongooseServerSelectionError;
diff --git a/node_modules/mongoose/lib/error/strict.js b/node_modules/mongoose/lib/error/strict.js
new file mode 100644
index 0000000..393ca6e
--- /dev/null
+++ b/node_modules/mongoose/lib/error/strict.js
@@ -0,0 +1,33 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+class StrictModeError extends MongooseError {
+ /**
+ * Strict mode error constructor
+ *
+ * @param {String} path
+ * @param {String} [msg]
+ * @param {Boolean} [immutable]
+ * @inherits MongooseError
+ * @api private
+ */
+ constructor(path, msg, immutable) {
+ msg = msg || 'Field `' + path + '` is not in schema and strict ' +
+ 'mode is set to throw.';
+ super(msg);
+ this.isImmutableError = !!immutable;
+ this.path = path;
+ }
+}
+
+Object.defineProperty(StrictModeError.prototype, 'name', {
+ value: 'StrictModeError'
+});
+
+module.exports = StrictModeError;
diff --git a/node_modules/mongoose/lib/error/validation.js b/node_modules/mongoose/lib/error/validation.js
new file mode 100644
index 0000000..ccae07a
--- /dev/null
+++ b/node_modules/mongoose/lib/error/validation.js
@@ -0,0 +1,110 @@
+/*!
+ * Module requirements
+ */
+
+'use strict';
+
+const MongooseError = require('./mongooseError');
+const util = require('util');
+
+class ValidationError extends MongooseError {
+ /**
+ * Document Validation Error
+ *
+ * @api private
+ * @param {Document} [instance]
+ * @inherits MongooseError
+ */
+ constructor(instance) {
+ let _message;
+ if (instance && instance.constructor.name === 'model') {
+ _message = instance.constructor.modelName + ' validation failed';
+ } else {
+ _message = 'Validation failed';
+ }
+
+ super(_message);
+
+ this.errors = {};
+ this._message = _message;
+
+ if (instance) {
+ instance.errors = this.errors;
+ }
+ }
+
+ /**
+ * Console.log helper
+ */
+ toString() {
+ return this.name + ': ' + _generateMessage(this);
+ }
+
+ /*!
+ * inspect helper
+ */
+ inspect() {
+ return Object.assign(new Error(this.message), this);
+ }
+
+ /*!
+ * add message
+ */
+ addError(path, error) {
+ this.errors[path] = error;
+ this.message = this._message + ': ' + _generateMessage(this);
+ }
+}
+
+
+if (util.inspect.custom) {
+ /*!
+ * Avoid Node deprecation warning DEP0079
+ */
+
+ ValidationError.prototype[util.inspect.custom] = ValidationError.prototype.inspect;
+}
+
+/*!
+ * Helper for JSON.stringify
+ */
+Object.defineProperty(ValidationError.prototype, 'toJSON', {
+ enumerable: false,
+ writable: false,
+ configurable: true,
+ value: function() {
+ return Object.assign({}, this, { message: this.message });
+ }
+});
+
+
+Object.defineProperty(ValidationError.prototype, 'name', {
+ value: 'ValidationError'
+});
+
+/*!
+ * ignore
+ */
+
+function _generateMessage(err) {
+ const keys = Object.keys(err.errors || {});
+ const len = keys.length;
+ const msgs = [];
+ let key;
+
+ for (let i = 0; i < len; ++i) {
+ key = keys[i];
+ if (err === err.errors[key]) {
+ continue;
+ }
+ msgs.push(key + ': ' + err.errors[key].message);
+ }
+
+ return msgs.join(', ');
+}
+
+/*!
+ * Module exports
+ */
+
+module.exports = ValidationError;
diff --git a/node_modules/mongoose/lib/error/validator.js b/node_modules/mongoose/lib/error/validator.js
new file mode 100644
index 0000000..f880e2b
--- /dev/null
+++ b/node_modules/mongoose/lib/error/validator.js
@@ -0,0 +1,94 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseError = require('./');
+
+
+class ValidatorError extends MongooseError {
+ /**
+ * Schema validator error
+ *
+ * @param {Object} properties
+ * @api private
+ */
+ constructor(properties) {
+ let msg = properties.message;
+ if (!msg) {
+ msg = MongooseError.messages.general.default;
+ }
+
+ const message = formatMessage(msg, properties);
+ super(message);
+
+ properties = Object.assign({}, properties, { message: message });
+ this.properties = properties;
+ this.kind = properties.type;
+ this.path = properties.path;
+ this.value = properties.value;
+ this.reason = properties.reason;
+ }
+
+ /*!
+ * toString helper
+ * TODO remove? This defaults to `${this.name}: ${this.message}`
+ */
+ 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);
+ }
+}
+
+
+Object.defineProperty(ValidatorError.prototype, 'name', {
+ value: 'ValidatorError'
+});
+
+/*!
+ * The object used to define this validator. Not enumerable to hide
+ * it from `require('util').inspect()` output re: gh-3925
+ */
+
+Object.defineProperty(ValidatorError.prototype, 'properties', {
+ enumerable: false,
+ writable: true,
+ value: null
+});
+
+// Exposed for testing
+ValidatorError.prototype.formatMessage = formatMessage;
+
+/*!
+ * Formats error messages
+ */
+
+function formatMessage(msg, properties) {
+ if (typeof msg === 'function') {
+ return msg(properties);
+ }
+
+ const propertyNames = Object.keys(properties);
+ for (const propertyName of propertyNames) {
+ if (propertyName === 'message') {
+ continue;
+ }
+ msg = msg.replace('{' + propertyName.toUpperCase() + '}', properties[propertyName]);
+ }
+
+ return msg;
+}
+
+/*!
+ * exports
+ */
+
+module.exports = ValidatorError;
diff --git a/node_modules/mongoose/lib/error/version.js b/node_modules/mongoose/lib/error/version.js
new file mode 100644
index 0000000..b357fb1
--- /dev/null
+++ b/node_modules/mongoose/lib/error/version.js
@@ -0,0 +1,36 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./');
+
+class VersionError extends MongooseError {
+ /**
+ * Version Error constructor.
+ *
+ * @param {Document} doc
+ * @param {Number} currentVersion
+ * @param {Array<String>} modifiedPaths
+ * @api private
+ */
+ constructor(doc, currentVersion, modifiedPaths) {
+ const modifiedPathsStr = modifiedPaths.join(', ');
+ super('No matching document found for id "' + doc._id +
+ '" version ' + currentVersion + ' modifiedPaths "' + modifiedPathsStr + '"');
+ this.version = currentVersion;
+ this.modifiedPaths = modifiedPaths;
+ }
+}
+
+
+Object.defineProperty(VersionError.prototype, 'name', {
+ value: 'VersionError'
+});
+
+/*!
+ * exports
+ */
+
+module.exports = VersionError;
diff --git a/node_modules/mongoose/lib/helpers/aggregate/stringifyAccumulatorOptions.js b/node_modules/mongoose/lib/helpers/aggregate/stringifyAccumulatorOptions.js
new file mode 100644
index 0000000..7362514
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/aggregate/stringifyAccumulatorOptions.js
@@ -0,0 +1,38 @@
+'use strict';
+
+module.exports = function stringifyAccumulatorOptions(pipeline) {
+ if (!Array.isArray(pipeline)) {
+ return;
+ }
+
+ for (const stage of pipeline) {
+ if (stage == null) {
+ continue;
+ }
+
+ const canHaveAccumulator = stage.$group || stage.$bucket || stage.$bucketAuto;
+ if (canHaveAccumulator != null) {
+ for (const key of Object.keys(canHaveAccumulator)) {
+ handleAccumulator(canHaveAccumulator[key]);
+ }
+ }
+
+ if (stage.$facet != null) {
+ for (const key of Object.keys(stage.$facet)) {
+ stringifyAccumulatorOptions(stage.$facet[key]);
+ }
+ }
+ }
+};
+
+function handleAccumulator(operator) {
+ if (operator == null || operator.$accumulator == null) {
+ return;
+ }
+
+ for (const key of ['init', 'accumulate', 'merge', 'finalize']) {
+ if (typeof operator.$accumulator[key] === 'function') {
+ operator.$accumulator[key] = String(operator.$accumulator[key]);
+ }
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/arrayDepth.js b/node_modules/mongoose/lib/helpers/arrayDepth.js
new file mode 100644
index 0000000..2c6f2e5
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/arrayDepth.js
@@ -0,0 +1,30 @@
+'use strict';
+
+module.exports = arrayDepth;
+
+function arrayDepth(arr) {
+ if (!Array.isArray(arr)) {
+ return { min: 0, max: 0, containsNonArrayItem: true };
+ }
+ if (arr.length === 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) {
+ res.min = _res.min;
+ }
+ if (_res.max > res.max) {
+ res.max = _res.max;
+ }
+ res.containsNonArrayItem = res.containsNonArrayItem || _res.containsNonArrayItem;
+ }
+
+ res.min = res.min + 1;
+ res.max = res.max + 1;
+
+ return res;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/clone.js b/node_modules/mongoose/lib/helpers/clone.js
new file mode 100644
index 0000000..5f0b2c9
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/clone.js
@@ -0,0 +1,143 @@
+'use strict';
+
+
+const cloneRegExp = require('regexp-clone');
+const Decimal = require('../types/decimal128');
+const ObjectId = require('../types/objectid');
+const specialProperties = require('./specialProperties');
+const isMongooseObject = require('./isMongooseObject');
+const getFunctionName = require('./getFunctionName');
+const isBsonType = require('./isBsonType');
+const isObject = require('./isObject');
+const symbols = require('./symbols');
+const utils = require('../utils');
+
+
+/*!
+ * Object clone with Mongoose natives support.
+ *
+ * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
+ *
+ * Functions are never cloned.
+ *
+ * @param {Object} obj the object to clone
+ * @param {Object} options
+ * @param {Boolean} isArrayChild true if cloning immediately underneath an array. Special case for minimize.
+ * @return {Object} the cloned object
+ * @api private
+ */
+
+function clone(obj, options, isArrayChild) {
+ if (obj == null) {
+ return obj;
+ }
+
+ if (Array.isArray(obj)) {
+ return cloneArray(obj, options);
+ }
+
+ if (isMongooseObject(obj)) {
+ // Single nested subdocs should apply getters later in `applyGetters()`
+ // when calling `toObject()`. See gh-7442, gh-8295
+ 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);
+ }
+ return obj.toObject(options);
+ }
+
+ if (obj.constructor) {
+ switch (getFunctionName(obj.constructor)) {
+ case 'Object':
+ return cloneObject(obj, options, isArrayChild);
+ case 'Date':
+ return new obj.constructor(+obj);
+ case 'RegExp':
+ return cloneRegExp(obj);
+ default:
+ // ignore
+ break;
+ }
+ }
+
+ if (obj instanceof ObjectId) {
+ return new ObjectId(obj.id);
+ }
+
+ if (isBsonType(obj, 'Decimal128')) {
+ if (options && options.flattenDecimals) {
+ return obj.toJSON();
+ }
+ return Decimal.fromString(obj.toString());
+ }
+
+ if (!obj.constructor && isObject(obj)) {
+ // object created with Object.create(null)
+ return cloneObject(obj, options, isArrayChild);
+ }
+
+ if (obj[symbols.schemaTypeSymbol]) {
+ return obj.clone();
+ }
+
+ // If we're cloning this object to go into a MongoDB command,
+ // and there's a `toBSON()` function, assume this object will be
+ // stored as a primitive in MongoDB and doesn't need to be cloned.
+ if (options && options.bson && typeof obj.toBSON === 'function') {
+ return obj;
+ }
+
+ if (obj.valueOf != null) {
+ return obj.valueOf();
+ }
+
+ return cloneObject(obj, options, isArrayChild);
+}
+module.exports = clone;
+
+/*!
+ * ignore
+ */
+
+function cloneObject(obj, options, isArrayChild) {
+ const minimize = options && options.minimize;
+ const ret = {};
+ let hasKeys;
+
+ for (const k in obj) {
+ if (specialProperties.has(k)) {
+ continue;
+ }
+
+ // Don't pass `isArrayChild` down
+ const val = clone(obj[k], options);
+
+ if (!minimize || (typeof val !== 'undefined')) {
+ if (minimize === false && typeof val === 'undefined') {
+ delete ret[k];
+ } else {
+ hasKeys || (hasKeys = true);
+ ret[k] = val;
+ }
+ }
+ }
+
+ return minimize && !isArrayChild ? hasKeys && ret : ret;
+}
+
+function cloneArray(arr, options) {
+ const ret = [];
+
+ for (const item of arr) {
+ ret.push(clone(item, options, true));
+ }
+
+ return ret;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/common.js b/node_modules/mongoose/lib/helpers/common.js
new file mode 100644
index 0000000..ed7dc42
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/common.js
@@ -0,0 +1,106 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const Binary = require('../driver').get().Binary;
+const Decimal128 = require('../types/decimal128');
+const ObjectId = require('../types/objectid');
+const isMongooseObject = require('./isMongooseObject');
+
+exports.flatten = flatten;
+exports.modifiedPaths = modifiedPaths;
+
+/*!
+ * ignore
+ */
+
+function flatten(update, path, options, schema) {
+ let keys;
+ if (update && isMongooseObject(update) && !Buffer.isBuffer(update)) {
+ keys = Object.keys(update.toObject({ transform: false, virtuals: false }));
+ } else {
+ keys = Object.keys(update || {});
+ }
+
+ const numKeys = keys.length;
+ const result = {};
+ path = path ? path + '.' : '';
+
+ for (let i = 0; i < numKeys; ++i) {
+ const key = keys[i];
+ const val = update[key];
+ result[path + key] = val;
+
+ // Avoid going into mixed paths if schema is specified
+ const keySchema = schema && schema.path && schema.path(path + key);
+ const isNested = schema && schema.nested && schema.nested[path + key];
+ if (keySchema && keySchema.instance === 'Mixed') continue;
+
+ if (shouldFlatten(val)) {
+ if (options && options.skipArrays && Array.isArray(val)) {
+ continue;
+ }
+ const flat = flatten(val, path + key, options, schema);
+ for (const k in flat) {
+ result[k] = flat[k];
+ }
+ if (Array.isArray(val)) {
+ result[path + key] = val;
+ }
+ }
+
+ if (isNested) {
+ const paths = Object.keys(schema.paths);
+ for (const p of paths) {
+ if (p.startsWith(path + key + '.') && !result.hasOwnProperty(p)) {
+ result[p] = void 0;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * ignore
+ */
+
+function modifiedPaths(update, path, result) {
+ const keys = Object.keys(update || {});
+ const numKeys = keys.length;
+ result = result || {};
+ path = path ? path + '.' : '';
+
+ for (let i = 0; i < numKeys; ++i) {
+ const key = keys[i];
+ let val = update[key];
+
+ result[path + key] = true;
+ if (isMongooseObject(val) && !Buffer.isBuffer(val)) {
+ val = val.toObject({ transform: false, virtuals: false });
+ }
+ if (shouldFlatten(val)) {
+ modifiedPaths(val, path + key, result);
+ }
+ }
+
+ return result;
+}
+
+/*!
+ * ignore
+ */
+
+function shouldFlatten(val) {
+ return val &&
+ typeof val === 'object' &&
+ !(val instanceof Date) &&
+ !(val instanceof ObjectId) &&
+ (!Array.isArray(val) || val.length > 0) &&
+ !(val instanceof Buffer) &&
+ !(val instanceof Decimal128) &&
+ !(val instanceof Binary);
+}
diff --git a/node_modules/mongoose/lib/helpers/cursor/eachAsync.js b/node_modules/mongoose/lib/helpers/cursor/eachAsync.js
new file mode 100644
index 0000000..4afff03
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/cursor/eachAsync.js
@@ -0,0 +1,121 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const promiseOrCallback = require('../promiseOrCallback');
+
+/**
+ * Execute `fn` for every document in the cursor. If `fn` returns a promise,
+ * will wait for the promise to resolve before iterating on to the next one.
+ * Returns a promise that resolves when done.
+ *
+ * @param {Function} next the thunk to call to get the next document
+ * @param {Function} fn
+ * @param {Object} options
+ * @param {Function} [callback] executed when all docs have been processed
+ * @return {Promise}
+ * @api public
+ * @method eachAsync
+ */
+
+module.exports = function eachAsync(next, fn, options, callback) {
+ const parallel = options.parallel || 1;
+ const enqueue = asyncQueue();
+
+ return promiseOrCallback(callback, cb => {
+ iterate(cb);
+ });
+
+ function iterate(finalCallback) {
+ let drained = false;
+ let handleResultsInProgress = 0;
+ let currentDocumentIndex = 0;
+
+ let error = null;
+ for (let i = 0; i < parallel; ++i) {
+ enqueue(fetch);
+ }
+
+ function fetch(done) {
+ if (drained || error) {
+ return done();
+ }
+
+ next(function(err, doc) {
+ if (drained || error != null) {
+ return done();
+ }
+ if (err != null) {
+ error = err;
+ finalCallback(err);
+ return done();
+ }
+ if (doc == null) {
+ drained = true;
+ if (handleResultsInProgress <= 0) {
+ finalCallback(null);
+ }
+ return done();
+ }
+
+ ++handleResultsInProgress;
+
+ // 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());
+
+ handleNextResult(doc, currentDocumentIndex++, function(err) {
+ --handleResultsInProgress;
+ if (err != null) {
+ error = err;
+ return finalCallback(err);
+ }
+ if (drained && handleResultsInProgress <= 0) {
+ return finalCallback(null);
+ }
+
+ setTimeout(() => enqueue(fetch), 0);
+ });
+ });
+ }
+ }
+
+ function handleNextResult(doc, i, callback) {
+ const promise = fn(doc, i);
+ if (promise && typeof promise.then === 'function') {
+ promise.then(
+ function() { callback(null); },
+ function(error) { callback(error || new Error('`eachAsync()` promise rejected without error')); });
+ } else {
+ callback(null);
+ }
+ }
+};
+
+// `next()` can only execute one at a time, so make sure we always execute
+// `next()` in series, while still allowing multiple `fn()` instances to run
+// in parallel.
+function asyncQueue() {
+ const _queue = [];
+ let inProgress = null;
+ let id = 0;
+
+ return function enqueue(fn) {
+ if (_queue.length === 0 && inProgress == null) {
+ inProgress = id++;
+ return fn(_step);
+ }
+ _queue.push(fn);
+ };
+
+ function _step() {
+ inProgress = null;
+ if (_queue.length > 0) {
+ inProgress = id++;
+ const fn = _queue.shift();
+ fn(_step);
+ }
+ }
+}
diff --git a/node_modules/mongoose/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js b/node_modules/mongoose/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js
new file mode 100644
index 0000000..755de88
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js
@@ -0,0 +1,12 @@
+'use strict';
+
+module.exports = function checkEmbeddedDiscriminatorKeyProjection(userProjection, path, schema, selected, addedPaths) {
+ const userProjectedInPath = Object.keys(userProjection).
+ reduce((cur, key) => cur || key.startsWith(path + '.'), false);
+ const _discriminatorKey = path + '.' + schema.options.discriminatorKey;
+ if (!userProjectedInPath &&
+ addedPaths.length === 1 &&
+ addedPaths[0] === _discriminatorKey) {
+ selected.splice(selected.indexOf(_discriminatorKey), 1);
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/discriminator/getConstructor.js b/node_modules/mongoose/lib/helpers/discriminator/getConstructor.js
new file mode 100644
index 0000000..04a3ded
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/discriminator/getConstructor.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const getDiscriminatorByValue = require('./getDiscriminatorByValue');
+
+/*!
+ * Find the correct constructor, taking into account discriminators
+ */
+
+module.exports = function getConstructor(Constructor, value) {
+ const discriminatorKey = Constructor.schema.options.discriminatorKey;
+ if (value != null &&
+ Constructor.discriminators &&
+ value[discriminatorKey] != null) {
+ if (Constructor.discriminators[value[discriminatorKey]]) {
+ Constructor = Constructor.discriminators[value[discriminatorKey]];
+ } else {
+ const constructorByValue = getDiscriminatorByValue(Constructor, value[discriminatorKey]);
+ if (constructorByValue) {
+ Constructor = constructorByValue;
+ }
+ }
+ }
+
+ return Constructor;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js b/node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js
new file mode 100644
index 0000000..a107a91
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/discriminator/getDiscriminatorByValue.js
@@ -0,0 +1,27 @@
+'use strict';
+
+/*!
+* returns discriminator by discriminatorMapping.value
+*
+* @param {Model} model
+* @param {string} value
+*/
+
+module.exports = function getDiscriminatorByValue(model, value) {
+ let discriminator = null;
+ if (!model.discriminators) {
+ return discriminator;
+ }
+ for (const name in model.discriminators) {
+ const it = model.discriminators[name];
+ if (
+ it.schema &&
+ it.schema.discriminatorMapping &&
+ it.schema.discriminatorMapping.value == value
+ ) {
+ discriminator = it;
+ break;
+ }
+ }
+ return discriminator;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js b/node_modules/mongoose/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js
new file mode 100644
index 0000000..f3e71a0
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js
@@ -0,0 +1,24 @@
+'use strict';
+
+/*!
+* returns discriminator by discriminatorMapping.value
+*
+* @param {Schema} schema
+* @param {string} value
+*/
+
+module.exports = function getSchemaDiscriminatorByValue(schema, value) {
+ if (schema == null || schema.discriminators == null) {
+ return null;
+ }
+ for (const key of Object.keys(schema.discriminators)) {
+ const discriminatorSchema = schema.discriminators[key];
+ if (discriminatorSchema.discriminatorMapping == null) {
+ continue;
+ }
+ if (discriminatorSchema.discriminatorMapping.value === value) {
+ return discriminatorSchema;
+ }
+ }
+ return null;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js b/node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js
new file mode 100644
index 0000000..252d348
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/document/cleanModifiedSubpaths.js
@@ -0,0 +1,28 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function cleanModifiedSubpaths(doc, path, options) {
+ options = options || {};
+ const skipDocArrays = options.skipDocArrays;
+
+ let deleted = 0;
+ if (!doc) {
+ return deleted;
+ }
+ for (const modifiedPath of Object.keys(doc.$__.activePaths.states.modify)) {
+ if (skipDocArrays) {
+ const schemaType = doc.schema.path(modifiedPath);
+ if (schemaType && schemaType.$isMongooseDocumentArray) {
+ continue;
+ }
+ }
+ if (modifiedPath.startsWith(path + '.')) {
+ delete doc.$__.activePaths.states.modify[modifiedPath];
+ ++deleted;
+ }
+ }
+ return deleted;
+};
diff --git a/node_modules/mongoose/lib/helpers/document/compile.js b/node_modules/mongoose/lib/helpers/document/compile.js
new file mode 100644
index 0000000..def45e6
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/document/compile.js
@@ -0,0 +1,204 @@
+'use strict';
+
+const documentSchemaSymbol = require('../../helpers/symbols').documentSchemaSymbol;
+const get = require('../../helpers/get');
+const internalToObjectOptions = require('../../options').internalToObjectOptions;
+const utils = require('../../utils');
+
+let Document;
+const getSymbol = require('../../helpers/symbols').getSymbol;
+const scopeSymbol = require('../../helpers/symbols').scopeSymbol;
+
+/*!
+ * exports
+ */
+
+exports.compile = compile;
+exports.defineKey = defineKey;
+
+/*!
+ * Compiles schemas.
+ */
+
+function compile(tree, proto, prefix, options) {
+ Document = Document || require('../../document');
+ const keys = Object.keys(tree);
+ const len = keys.length;
+ let limb;
+ let key;
+
+ for (let i = 0; i < len; ++i) {
+ key = keys[i];
+ limb = tree[key];
+
+ const hasSubprops = utils.isPOJO(limb) && Object.keys(limb).length &&
+ (!limb[options.typeKey] || (options.typeKey === 'type' && limb.type.type));
+ const subprops = hasSubprops ? limb : null;
+
+ defineKey(key, subprops, proto, prefix, keys, options);
+ }
+}
+
+/*!
+ * Defines the accessor named prop on the incoming prototype.
+ */
+
+function defineKey(prop, subprops, prototype, prefix, keys, options) {
+ Document = Document || require('../../document');
+ const path = (prefix ? prefix + '.' : '') + prop;
+ prefix = prefix || '';
+
+ if (subprops) {
+ Object.defineProperty(prototype, prop, {
+ enumerable: true,
+ configurable: true,
+ get: function() {
+ const _this = this;
+ if (!this.$__.getters) {
+ this.$__.getters = {};
+ }
+
+ if (!this.$__.getters[path]) {
+ const nested = Object.create(Document.prototype, getOwnPropertyDescriptors(this));
+
+ // save scope for nested getters/setters
+ if (!prefix) {
+ nested.$__[scopeSymbol] = this;
+ }
+ nested.$__.nestedPath = path;
+
+ Object.defineProperty(nested, 'schema', {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: prototype.schema
+ });
+
+ Object.defineProperty(nested, documentSchemaSymbol, {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: prototype.schema
+ });
+
+ Object.defineProperty(nested, 'toObject', {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: function() {
+ return utils.clone(_this.get(path, null, {
+ virtuals: get(this, 'schema.options.toObject.virtuals', null)
+ }));
+ }
+ });
+
+ 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,
+ writable: false,
+ value: function() {
+ return _this.get(path, null, {
+ virtuals: get(_this, 'schema.options.toJSON.virtuals', null)
+ });
+ }
+ });
+
+ Object.defineProperty(nested, '$__isNested', {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: true
+ });
+
+ const _isEmptyOptions = Object.freeze({
+ minimize: true,
+ virtuals: false,
+ getters: false,
+ transform: false
+ });
+ Object.defineProperty(nested, '$isEmpty', {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: function() {
+ return Object.keys(this.get(path, null, _isEmptyOptions) || {}).length === 0;
+ }
+ });
+
+ Object.defineProperty(nested, '$__parent', {
+ enumerable: false,
+ configurable: true,
+ writable: false,
+ value: this
+ });
+
+ compile(subprops, nested, path, options);
+ this.$__.getters[path] = nested;
+ }
+
+ return this.$__.getters[path];
+ },
+ set: function(v) {
+ 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);
+ }
+ });
+ } else {
+ Object.defineProperty(prototype, prop, {
+ enumerable: true,
+ configurable: true,
+ get: function() {
+ return this[getSymbol].call(this.$__[scopeSymbol] || this, path);
+ },
+ set: function(v) {
+ this.$set.call(this.$__[scopeSymbol] || this, path, v);
+ }
+ });
+ }
+}
+
+// gets descriptors for all properties of `object`
+// makes all properties non-enumerable to match previous behavior to #2211
+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 = [
+ 'isNew',
+ '$__',
+ 'errors',
+ '_doc',
+ '$locals',
+ '$op',
+ '__parentArray',
+ '__index',
+ '$isDocumentArrayElement'
+ ].indexOf(key) === -1;
+ });
+
+ return result;
+}
diff --git a/node_modules/mongoose/lib/helpers/document/getEmbeddedDiscriminatorPath.js b/node_modules/mongoose/lib/helpers/document/getEmbeddedDiscriminatorPath.js
new file mode 100644
index 0000000..a2784e3
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/document/getEmbeddedDiscriminatorPath.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const get = require('../get');
+
+/*!
+ * Like `schema.path()`, except with a document, because impossible to
+ * determine path type without knowing the embedded discriminator key.
+ */
+
+module.exports = function getEmbeddedDiscriminatorPath(doc, path, options) {
+ options = options || {};
+ const typeOnly = options.typeOnly;
+ const parts = path.split('.');
+ let schema = null;
+ let type = 'adhocOrUndefined';
+
+ for (let i = 0; i < parts.length; ++i) {
+ const subpath = parts.slice(0, i + 1).join('.');
+ schema = doc.schema.path(subpath);
+ if (schema == null) {
+ type = 'adhocOrUndefined';
+ continue;
+ }
+ if (schema.instance === 'Mixed') {
+ return typeOnly ? 'real' : schema;
+ }
+ type = doc.schema.pathType(subpath);
+ if ((schema.$isSingleNested || schema.$isMongooseDocumentArrayElement) &&
+ schema.schema.discriminators != null) {
+ const discriminators = schema.schema.discriminators;
+ const discriminatorKey = doc.get(subpath + '.' +
+ get(schema, 'schema.options.discriminatorKey'));
+ if (discriminatorKey == null || discriminators[discriminatorKey] == null) {
+ continue;
+ }
+ const rest = parts.slice(i + 1).join('.');
+ return getEmbeddedDiscriminatorPath(doc.get(subpath), rest, options);
+ }
+ }
+
+ // Are we getting the whole schema or just the type, 'real', 'nested', etc.
+ return typeOnly ? type : schema;
+};
diff --git a/node_modules/mongoose/lib/helpers/document/handleSpreadDoc.js b/node_modules/mongoose/lib/helpers/document/handleSpreadDoc.js
new file mode 100644
index 0000000..d3075e4
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/document/handleSpreadDoc.js
@@ -0,0 +1,17 @@
+'use strict';
+
+const utils = require('../../utils');
+
+/**
+ * Using spread operator on a Mongoose document gives you a
+ * POJO that has a tendency to cause infinite recursion. So
+ * we use this function on `set()` to prevent that.
+ */
+
+module.exports = function handleSpreadDoc(v) {
+ if (utils.isPOJO(v) && v.$__ != null && v._doc != null) {
+ return v._doc;
+ }
+
+ return v;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/each.js b/node_modules/mongoose/lib/helpers/each.js
new file mode 100644
index 0000000..fe70069
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/each.js
@@ -0,0 +1,25 @@
+'use strict';
+
+module.exports = function each(arr, cb, done) {
+ if (arr.length === 0) {
+ return done();
+ }
+
+ let remaining = arr.length;
+ let err = null;
+ for (const v of arr) {
+ cb(v, function(_err) {
+ if (err != null) {
+ return;
+ }
+ if (_err != null) {
+ err = _err;
+ return done(err);
+ }
+
+ if (--remaining <= 0) {
+ return done();
+ }
+ });
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/get.js b/node_modules/mongoose/lib/helpers/get.js
new file mode 100644
index 0000000..dcb3881
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/get.js
@@ -0,0 +1,39 @@
+'use strict';
+
+/*!
+ * Simplified lodash.get to work around the annoying null quirk. See:
+ * https://github.com/lodash/lodash/issues/3659
+ */
+
+module.exports = function get(obj, path, def) {
+ const parts = path.split('.');
+ let rest = path;
+ let cur = obj;
+ for (const part of parts) {
+ if (cur == null) {
+ return def;
+ }
+
+ // `lib/cast.js` depends on being able to get dotted paths in updates,
+ // like `{ $set: { 'a.b': 42 } }`
+ if (cur[rest] != null) {
+ return cur[rest];
+ }
+
+ cur = getProperty(cur, part);
+
+ rest = rest.substr(part.length + 1);
+ }
+
+ return cur == null ? def : cur;
+};
+
+function getProperty(obj, prop) {
+ if (obj == null) {
+ return obj;
+ }
+ if (obj instanceof Map) {
+ return obj.get(prop);
+ }
+ return obj[prop];
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/getDefaultBulkwriteResult.js b/node_modules/mongoose/lib/helpers/getDefaultBulkwriteResult.js
new file mode 100644
index 0000000..7d10f17
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/getDefaultBulkwriteResult.js
@@ -0,0 +1,27 @@
+'use strict';
+function getDefaultBulkwriteResult() {
+ return {
+ result: {
+ ok: 1,
+ writeErrors: [],
+ writeConcernErrors: [],
+ insertedIds: [],
+ nInserted: 0,
+ nUpserted: 0,
+ nMatched: 0,
+ nModified: 0,
+ nRemoved: 0,
+ upserted: []
+ },
+ insertedCount: 0,
+ matchedCount: 0,
+ modifiedCount: 0,
+ deletedCount: 0,
+ upsertedCount: 0,
+ upsertedIds: {},
+ insertedIds: {},
+ n: 0
+ };
+}
+
+module.exports = getDefaultBulkwriteResult; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/getFunctionName.js b/node_modules/mongoose/lib/helpers/getFunctionName.js
new file mode 100644
index 0000000..87a2c69
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/getFunctionName.js
@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = function(fn) {
+ if (fn.name) {
+ return fn.name;
+ }
+ return (fn.toString().trim().match(/^function\s*([^\s(]+)/) || [])[1];
+};
diff --git a/node_modules/mongoose/lib/helpers/immediate.js b/node_modules/mongoose/lib/helpers/immediate.js
new file mode 100644
index 0000000..ddb7060
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/immediate.js
@@ -0,0 +1,12 @@
+/*!
+ * Centralize this so we can more easily work around issues with people
+ * stubbing out `process.nextTick()` in tests using sinon:
+ * https://github.com/sinonjs/lolex#automatically-incrementing-mocked-time
+ * See gh-6074
+ */
+
+'use strict';
+
+module.exports = function immediate(cb) {
+ return process.nextTick(cb);
+};
diff --git a/node_modules/mongoose/lib/helpers/indexes/isDefaultIdIndex.js b/node_modules/mongoose/lib/helpers/indexes/isDefaultIdIndex.js
new file mode 100644
index 0000000..c975dcf
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/indexes/isDefaultIdIndex.js
@@ -0,0 +1,18 @@
+'use strict';
+
+const get = require('../get');
+
+module.exports = function isDefaultIdIndex(index) {
+ if (Array.isArray(index)) {
+ // Mongoose syntax
+ const keys = Object.keys(index[0]);
+ return keys.length === 1 && keys[0] === '_id' && index[0]._id !== 'hashed';
+ }
+
+ if (typeof index !== 'object') {
+ return false;
+ }
+
+ const key = get(index, 'key', {});
+ return Object.keys(key).length === 1 && key.hasOwnProperty('_id');
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js b/node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js
new file mode 100644
index 0000000..d59d734
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/indexes/isIndexEqual.js
@@ -0,0 +1,95 @@
+'use strict';
+
+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) {
+ // 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',
+ 'sparse',
+ 'expireAfterSeconds',
+ 'collation'
+ ];
+ for (const key of optionKeys) {
+ if (!(key in options) && !(key in 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;
+ for (const opt of definedKeys) {
+ if (get(schemaCollation, opt) !== get(dbCollation, opt)) {
+ return false;
+ }
+ }
+ } else if (!utils.deepEqual(options[key], dbIndex[key])) {
+ return false;
+ }
+ }
+
+ const schemaIndexKeys = Object.keys(key);
+ const dbIndexKeys = Object.keys(dbIndex.key);
+ if (schemaIndexKeys.length !== dbIndexKeys.length) {
+ return false;
+ }
+ for (let i = 0; i < schemaIndexKeys.length; ++i) {
+ if (schemaIndexKeys[i] !== dbIndexKeys[i]) {
+ return false;
+ }
+ if (!utils.deepEqual(key[schemaIndexKeys[i]], dbIndex.key[dbIndexKeys[i]])) {
+ return false;
+ }
+ }
+
+ return true;
+};
diff --git a/node_modules/mongoose/lib/helpers/isBsonType.js b/node_modules/mongoose/lib/helpers/isBsonType.js
new file mode 100644
index 0000000..01435d3
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/isBsonType.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const get = require('./get');
+
+/*!
+ * Get the bson type, if it exists
+ */
+
+function isBsonType(obj, typename) {
+ return get(obj, '_bsontype', void 0) === typename;
+}
+
+module.exports = isBsonType;
diff --git a/node_modules/mongoose/lib/helpers/isMongooseObject.js b/node_modules/mongoose/lib/helpers/isMongooseObject.js
new file mode 100644
index 0000000..016f9e6
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/isMongooseObject.js
@@ -0,0 +1,21 @@
+'use strict';
+
+/*!
+ * Returns if `v` is a mongoose object that has a `toObject()` method we can use.
+ *
+ * This is for compatibility with libs like Date.js which do foolish things to Natives.
+ *
+ * @param {any} v
+ * @api private
+ */
+
+module.exports = function(v) {
+ if (v == null) {
+ return false;
+ }
+
+ return v.$__ != null || // Document
+ v.isMongooseArray || // Array or Document Array
+ v.isMongooseBuffer || // Buffer
+ v.$isMongooseMap; // Map
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/isObject.js b/node_modules/mongoose/lib/helpers/isObject.js
new file mode 100644
index 0000000..f8ac313
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/isObject.js
@@ -0,0 +1,16 @@
+'use strict';
+
+/*!
+ * Determines if `arg` is an object.
+ *
+ * @param {Object|Array|String|Function|RegExp|any} arg
+ * @api private
+ * @return {Boolean}
+ */
+
+module.exports = function(arg) {
+ if (Buffer.isBuffer(arg)) {
+ return true;
+ }
+ return Object.prototype.toString.call(arg) === '[object Object]';
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/isPromise.js b/node_modules/mongoose/lib/helpers/isPromise.js
new file mode 100644
index 0000000..d6db260
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/isPromise.js
@@ -0,0 +1,6 @@
+'use strict';
+function isPromise(val) {
+ return !!val && (typeof val === 'object' || typeof val === 'function') && typeof val.then === 'function';
+}
+
+module.exports = isPromise; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/model/applyHooks.js b/node_modules/mongoose/lib/helpers/model/applyHooks.js
new file mode 100644
index 0000000..9570a36
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/applyHooks.js
@@ -0,0 +1,135 @@
+'use strict';
+
+const symbols = require('../../schema/symbols');
+const promiseOrCallback = require('../promiseOrCallback');
+
+/*!
+ * ignore
+ */
+
+module.exports = applyHooks;
+
+/*!
+ * ignore
+ */
+
+applyHooks.middlewareFunctions = [
+ 'deleteOne',
+ 'save',
+ 'validate',
+ 'remove',
+ 'updateOne',
+ 'init'
+];
+
+/*!
+ * Register hooks for this model
+ *
+ * @param {Model} model
+ * @param {Schema} schema
+ */
+
+function applyHooks(model, schema, options) {
+ options = options || {};
+
+ const kareemOptions = {
+ useErrorHandlers: true,
+ numCallbackParams: 1,
+ nullResultByDefault: true,
+ contextParameter: true
+ };
+ const objToDecorate = options.decorateDoc ? model : model.prototype;
+
+ model.$appliedHooks = true;
+ for (const key of Object.keys(schema.paths)) {
+ const type = schema.paths[key];
+ let childModel = null;
+ if (type.$isSingleNested) {
+ childModel = type.caster;
+ } else if (type.$isMongooseDocumentArray) {
+ childModel = type.Constructor;
+ } else {
+ continue;
+ }
+
+ if (childModel.$appliedHooks) {
+ continue;
+ }
+
+ applyHooks(childModel, type.schema, options);
+ if (childModel.discriminators != null) {
+ const keys = Object.keys(childModel.discriminators);
+ for (const key of keys) {
+ applyHooks(childModel.discriminators[key],
+ childModel.discriminators[key].schema, options);
+ }
+ }
+ }
+
+ // Built-in hooks rely on hooking internal functions in order to support
+ // promises and make it so that `doc.save.toString()` provides meaningful
+ // information.
+
+ const middleware = schema.s.hooks.
+ filter(hook => {
+ if (hook.name === 'updateOne' || hook.name === 'deleteOne') {
+ return !!hook['document'];
+ }
+ if (hook.name === 'remove' || hook.name === 'init') {
+ return hook['document'] == null || !!hook['document'];
+ }
+ return true;
+ }).
+ filter(hook => {
+ // If user has overwritten the method, don't apply built-in middleware
+ if (schema.methods[hook.name]) {
+ return !hook.fn[symbols.builtInMiddleware];
+ }
+
+ return true;
+ });
+
+ model._middleware = middleware;
+
+ objToDecorate.$__originalValidate = objToDecorate.$__originalValidate || objToDecorate.$__validate;
+
+ for (const method of ['save', 'validate', 'remove', 'deleteOne']) {
+ const toWrap = method === 'validate' ? '$__originalValidate' : `$__${method}`;
+ const wrapped = middleware.
+ createWrapper(method, objToDecorate[toWrap], null, kareemOptions);
+ objToDecorate[`$__${method}`] = wrapped;
+ }
+ objToDecorate.$__init = middleware.
+ createWrapperSync('init', objToDecorate.$__init, null, kareemOptions);
+
+ // Support hooks for custom methods
+ const customMethods = Object.keys(schema.methods);
+ const customMethodOptions = Object.assign({}, kareemOptions, {
+ // Only use `checkForPromise` for custom methods, because mongoose
+ // query thunks are not as consistent as I would like about returning
+ // a nullish value rather than the query. If a query thunk returns
+ // a query, `checkForPromise` causes infinite recursion
+ checkForPromise: true
+ });
+ for (const method of customMethods) {
+ if (!middleware.hasHooks(method)) {
+ // Don't wrap if there are no hooks for the custom method to avoid
+ // surprises. Also, `createWrapper()` enforces consistent async,
+ // so wrapping a sync method would break it.
+ continue;
+ }
+ const originalMethod = objToDecorate[method];
+ objToDecorate[method] = function() {
+ const args = Array.prototype.slice.call(arguments);
+ const cb = args.slice(-1).pop();
+ const argsWithoutCallback = typeof cb === 'function' ?
+ args.slice(0, args.length - 1) : args;
+ return promiseOrCallback(cb, callback => {
+ return this[`$__${method}`].apply(this,
+ argsWithoutCallback.concat([callback]));
+ }, model.events);
+ };
+ objToDecorate[`$__${method}`] = middleware.
+ createWrapper(method, originalMethod, null, customMethodOptions);
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/model/applyMethods.js b/node_modules/mongoose/lib/helpers/model/applyMethods.js
new file mode 100644
index 0000000..912f3aa
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/applyMethods.js
@@ -0,0 +1,56 @@
+'use strict';
+
+const get = require('../get');
+
+/*!
+ * Register methods for this model
+ *
+ * @param {Model} model
+ * @param {Schema} schema
+ */
+
+module.exports = function applyMethods(model, schema) {
+ function apply(method, schema) {
+ Object.defineProperty(model.prototype, method, {
+ get: function() {
+ const h = {};
+ for (const k in schema.methods[method]) {
+ h[k] = schema.methods[method][k].bind(this);
+ }
+ return h;
+ },
+ configurable: true
+ });
+ }
+ for (const method of Object.keys(schema.methods)) {
+ const fn = schema.methods[method];
+ if (schema.tree.hasOwnProperty(method)) {
+ throw new Error('You have a method and a property in your schema both ' +
+ 'named "' + method + '"');
+ }
+ if (schema.reserved[method] &&
+ !get(schema, `methodOptions.${method}.suppressWarning`, false)) {
+ console.warn(`mongoose: the method name "${method}" is used by mongoose ` +
+ 'internally, overwriting it may cause bugs. If you\'re sure you know ' +
+ 'what you\'re doing, you can suppress this error by using ' +
+ `\`schema.method('${method}', fn, { suppressWarning: true })\`.`);
+ }
+ if (typeof fn === 'function') {
+ model.prototype[method] = fn;
+ } else {
+ apply(method, schema);
+ }
+ }
+
+ // Recursively call `applyMethods()` on child schemas
+ model.$appliedMethods = true;
+ for (const key of Object.keys(schema.paths)) {
+ const type = schema.paths[key];
+ if (type.$isSingleNested && !type.caster.$appliedMethods) {
+ applyMethods(type.caster, type.schema);
+ }
+ if (type.$isMongooseDocumentArray && !type.Constructor.$appliedMethods) {
+ applyMethods(type.Constructor, type.schema);
+ }
+ }
+};
diff --git a/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js b/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js
new file mode 100644
index 0000000..219e289
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/applyStaticHooks.js
@@ -0,0 +1,71 @@
+'use strict';
+
+const middlewareFunctions = require('../query/applyQueryMiddleware').middlewareFunctions;
+const promiseOrCallback = require('../promiseOrCallback');
+
+module.exports = function applyStaticHooks(model, hooks, statics) {
+ const kareemOptions = {
+ useErrorHandlers: true,
+ numCallbackParams: 1
+ };
+
+ hooks = hooks.filter(hook => {
+ // If the custom static overwrites an existing query middleware, don't apply
+ // middleware to it by default. This avoids a potential backwards breaking
+ // change with plugins like `mongoose-delete` that use statics to overwrite
+ // built-in Mongoose functions.
+ if (middlewareFunctions.indexOf(hook.name) !== -1) {
+ return !!hook.model;
+ }
+ return hook.model !== false;
+ });
+
+ model.$__insertMany = hooks.createWrapper('insertMany',
+ model.$__insertMany, model, kareemOptions);
+
+ for (const key of Object.keys(statics)) {
+ if (hooks.hasHooks(key)) {
+ const original = model[key];
+
+ model[key] = function() {
+ const numArgs = arguments.length;
+ const lastArg = numArgs > 0 ? arguments[numArgs - 1] : null;
+ const cb = typeof lastArg === 'function' ? lastArg : null;
+ const args = Array.prototype.slice.
+ call(arguments, 0, cb == null ? numArgs : numArgs - 1);
+ // Special case: can't use `Kareem#wrap()` because it doesn't currently
+ // support wrapped functions that return a promise.
+ return promiseOrCallback(cb, callback => {
+ hooks.execPre(key, model, args, function(err) {
+ if (err != null) {
+ return callback(err);
+ }
+
+ let postCalled = 0;
+ const ret = original.apply(model, args.concat(post));
+ if (ret != null && typeof ret.then === 'function') {
+ ret.then(res => post(null, res), err => post(err));
+ }
+
+ function post(error, res) {
+ if (postCalled++ > 0) {
+ return;
+ }
+
+ if (error != null) {
+ return callback(error);
+ }
+
+ hooks.execPost(key, model, [res], function(error) {
+ if (error != null) {
+ return callback(error);
+ }
+ callback(null, res);
+ });
+ }
+ });
+ }, model.events);
+ };
+ }
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/model/applyStatics.js b/node_modules/mongoose/lib/helpers/model/applyStatics.js
new file mode 100644
index 0000000..3b9501e
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/applyStatics.js
@@ -0,0 +1,12 @@
+'use strict';
+
+/*!
+ * Register statics for this model
+ * @param {Model} model
+ * @param {Schema} schema
+ */
+module.exports = function applyStatics(model, schema) {
+ for (const i in schema.statics) {
+ model[i] = schema.statics[i];
+ }
+};
diff --git a/node_modules/mongoose/lib/helpers/model/castBulkWrite.js b/node_modules/mongoose/lib/helpers/model/castBulkWrite.js
new file mode 100644
index 0000000..6e7a830
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/castBulkWrite.js
@@ -0,0 +1,224 @@
+'use strict';
+
+const getDiscriminatorByValue = require('../../helpers/discriminator/getDiscriminatorByValue');
+const applyTimestampsToChildren = require('../update/applyTimestampsToChildren');
+const applyTimestampsToUpdate = require('../update/applyTimestampsToUpdate');
+const cast = require('../../cast');
+const castUpdate = require('../query/castUpdate');
+const setDefaultsOnInsert = require('../setDefaultsOnInsert');
+
+/*!
+ * Given a model and a bulkWrite op, return a thunk that handles casting and
+ * validating the individual op.
+ */
+
+module.exports = function castBulkWrite(originalModel, op, options) {
+ const now = originalModel.base.now();
+
+ if (op['insertOne']) {
+ return (callback) => {
+ const model = decideModelByObject(originalModel, op['insertOne']['document']);
+
+ const doc = new model(op['insertOne']['document']);
+ if (model.schema.options.timestamps != null) {
+ doc.initializeTimestamps();
+ }
+ if (options.session != null) {
+ doc.$session(options.session);
+ }
+ op['insertOne']['document'] = doc;
+ op['insertOne']['document'].validate({ __noPromise: true }, function(error) {
+ if (error) {
+ return callback(error, null);
+ }
+ callback(null);
+ });
+ };
+ } 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.');
+ }
+
+ const model = decideModelByObject(originalModel, op['updateOne']['filter']);
+ const schema = model.schema;
+ const strict = options.strict != null ? options.strict : model.schema.options.strict;
+
+ _addDiscriminatorToObject(schema, op['updateOne']['filter']);
+
+ if (model.schema.$timestamps != null && op['updateOne'].timestamps !== false) {
+ const createdAt = model.schema.$timestamps.createdAt;
+ const updatedAt = model.schema.$timestamps.updatedAt;
+ applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateOne']['update'], {});
+ }
+
+ applyTimestampsToChildren(now, op['updateOne']['update'], model.schema);
+
+ if (op['updateOne'].setDefaultsOnInsert) {
+ setDefaultsOnInsert(op['updateOne']['filter'], model.schema, op['updateOne']['update'], {
+ setDefaultsOnInsert: true,
+ upsert: op['updateOne'].upsert
+ });
+ }
+
+ op['updateOne']['filter'] = cast(model.schema, op['updateOne']['filter'], {
+ strict: strict,
+ upsert: op['updateOne'].upsert
+ });
+
+ op['updateOne']['update'] = castUpdate(model.schema, op['updateOne']['update'], {
+ strict: strict,
+ overwrite: false,
+ upsert: op['updateOne'].upsert
+ }, model, op['updateOne']['filter']);
+ } catch (error) {
+ return callback(error, null);
+ }
+
+ callback(null);
+ };
+ } 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.');
+ }
+
+ const model = decideModelByObject(originalModel, op['updateMany']['filter']);
+ const schema = model.schema;
+ const strict = options.strict != null ? options.strict : model.schema.options.strict;
+
+ if (op['updateMany'].setDefaultsOnInsert) {
+ setDefaultsOnInsert(op['updateMany']['filter'], model.schema, op['updateMany']['update'], {
+ setDefaultsOnInsert: true,
+ upsert: op['updateMany'].upsert
+ });
+ }
+
+ if (model.schema.$timestamps != null && op['updateMany'].timestamps !== false) {
+ const createdAt = model.schema.$timestamps.createdAt;
+ const updatedAt = model.schema.$timestamps.updatedAt;
+ applyTimestampsToUpdate(now, createdAt, updatedAt, op['updateMany']['update'], {});
+ }
+
+ applyTimestampsToChildren(now, op['updateMany']['update'], model.schema);
+
+ _addDiscriminatorToObject(schema, op['updateMany']['filter']);
+
+ op['updateMany']['filter'] = cast(model.schema, op['updateMany']['filter'], {
+ strict: strict,
+ upsert: op['updateMany'].upsert
+ });
+
+ op['updateMany']['update'] = castUpdate(model.schema, op['updateMany']['update'], {
+ strict: strict,
+ overwrite: false,
+ upsert: op['updateMany'].upsert
+ }, model, op['updateMany']['filter']);
+
+ } catch (error) {
+ return callback(error, null);
+ }
+
+ callback(null);
+ };
+ } else if (op['replaceOne']) {
+ return (callback) => {
+ const model = decideModelByObject(originalModel, op['replaceOne']['filter']);
+ const schema = model.schema;
+ const strict = options.strict != null ? options.strict : model.schema.options.strict;
+
+ _addDiscriminatorToObject(schema, op['replaceOne']['filter']);
+ try {
+ op['replaceOne']['filter'] = cast(model.schema, op['replaceOne']['filter'], {
+ strict: strict,
+ upsert: op['replaceOne'].upsert
+ });
+ } catch (error) {
+ return callback(error, null);
+ }
+
+ // 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) {
+ doc.initializeTimestamps();
+ }
+ if (options.session != null) {
+ doc.$session(options.session);
+ }
+ op['replaceOne']['replacement'] = doc;
+
+ op['replaceOne']['replacement'].validate({ __noPromise: true }, function(error) {
+ if (error) {
+ return callback(error, null);
+ }
+ op['replaceOne']['replacement'] = op['replaceOne']['replacement'].toBSON();
+ callback(null);
+ });
+ };
+ } else if (op['deleteOne']) {
+ return (callback) => {
+ const model = decideModelByObject(originalModel, op['deleteOne']['filter']);
+ const schema = model.schema;
+
+ _addDiscriminatorToObject(schema, op['deleteOne']['filter']);
+
+ try {
+ op['deleteOne']['filter'] = cast(model.schema,
+ op['deleteOne']['filter']);
+ } catch (error) {
+ return callback(error, null);
+ }
+
+ callback(null);
+ };
+ } else if (op['deleteMany']) {
+ return (callback) => {
+ const model = decideModelByObject(originalModel, op['deleteMany']['filter']);
+ const schema = model.schema;
+
+ _addDiscriminatorToObject(schema, op['deleteMany']['filter']);
+
+ try {
+ op['deleteMany']['filter'] = cast(model.schema,
+ op['deleteMany']['filter']);
+ } catch (error) {
+ return callback(error, null);
+ }
+
+ callback(null);
+ };
+ } else {
+ return (callback) => {
+ callback(new Error('Invalid op passed to `bulkWrite()`'), null);
+ };
+ }
+};
+
+function _addDiscriminatorToObject(schema, obj) {
+ if (schema == null) {
+ return;
+ }
+ if (schema.discriminatorMapping && !schema.discriminatorMapping.isRoot) {
+ obj[schema.discriminatorMapping.key] = schema.discriminatorMapping.value;
+ }
+}
+
+/*!
+ * gets discriminator model if discriminator key is present in object
+ */
+
+function decideModelByObject(model, object) {
+ const discriminatorKey = model.schema.options.discriminatorKey;
+ if (object != null && object.hasOwnProperty(discriminatorKey)) {
+ model = getDiscriminatorByValue(model, object[discriminatorKey]) || model;
+ }
+ return model;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/model/discriminator.js b/node_modules/mongoose/lib/helpers/model/discriminator.js
new file mode 100644
index 0000000..2ad4c5e
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/model/discriminator.js
@@ -0,0 +1,205 @@
+'use strict';
+
+const Mixed = require('../../schema/mixed');
+const defineKey = require('../document/compile').defineKey;
+const get = require('../get');
+const utils = require('../../utils');
+
+const CUSTOMIZABLE_DISCRIMINATOR_OPTIONS = {
+ toJSON: true,
+ toObject: true,
+ _id: true,
+ id: true
+};
+
+/*!
+ * ignore
+ */
+
+module.exports = function discriminator(model, name, schema, tiedValue, applyPlugins) {
+ if (!(schema && schema.instanceOfSchema)) {
+ throw new Error('You must pass a valid discriminator Schema');
+ }
+
+ if (model.schema.discriminatorMapping &&
+ !model.schema.discriminatorMapping.isRoot) {
+ throw new Error('Discriminator "' + name +
+ '" can only be a discriminator of the root model');
+ }
+
+ if (applyPlugins) {
+ const applyPluginsToDiscriminators = get(model.base,
+ 'options.applyPluginsToDiscriminators', false);
+ // Even if `applyPluginsToDiscriminators` isn't set, we should still apply
+ // global plugins to schemas embedded in the discriminator schema (gh-7370)
+ model.base._applyPlugins(schema, {
+ skipTopLevel: !applyPluginsToDiscriminators
+ });
+ }
+
+ const key = model.schema.options.discriminatorKey;
+
+ const existingPath = model.schema.path(key);
+ if (existingPath != null) {
+ if (!utils.hasUserDefinedProperty(existingPath.options, 'select')) {
+ existingPath.options.select = true;
+ }
+ existingPath.options.$skipDiscriminatorCheck = true;
+ } else {
+ const baseSchemaAddition = {};
+ baseSchemaAddition[key] = {
+ default: void 0,
+ select: true,
+ $skipDiscriminatorCheck: true
+ };
+ baseSchemaAddition[key][model.schema.options.typeKey] = String;
+ model.schema.add(baseSchemaAddition);
+ defineKey(key, null, model.prototype, null, [key], model.schema.options);
+ }
+
+ if (schema.path(key) && schema.path(key).options.$skipDiscriminatorCheck !== true) {
+ throw new Error('Discriminator "' + name +
+ '" cannot have field with name "' + key + '"');
+ }
+
+ let value = name;
+ if (typeof tiedValue == 'string' && tiedValue.length) {
+ value = tiedValue;
+ }
+
+ function merge(schema, baseSchema) {
+ // Retain original schema before merging base schema
+ schema._baseSchema = baseSchema;
+ if (baseSchema.paths._id &&
+ baseSchema.paths._id.options &&
+ !baseSchema.paths._id.options.auto) {
+ schema.remove('_id');
+ }
+
+ // Find conflicting paths: if something is a path in the base schema
+ // and a nested path in the child schema, overwrite the base schema path.
+ // See gh-6076
+ const baseSchemaPaths = Object.keys(baseSchema.paths);
+ const conflictingPaths = [];
+
+ for (const path of baseSchemaPaths) {
+ if (schema.nested[path]) {
+ conflictingPaths.push(path);
+ continue;
+ }
+
+ if (path.indexOf('.') === -1) {
+ continue;
+ }
+ const sp = path.split('.').slice(0, -1);
+ let cur = '';
+ for (const piece of sp) {
+ cur += (cur.length ? '.' : '') + piece;
+ 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;
+ return cur;
+ }, {})
+ });
+
+ // Clean up conflicting paths _after_ merging re: gh-6076
+ for (const conflictingPath of conflictingPaths) {
+ delete schema.paths[conflictingPath];
+ }
+
+ // Rebuild schema models because schemas may have been merged re: #7884
+ schema.childSchemas.forEach(obj => {
+ obj.model.prototype.$__setSchema(obj.schema);
+ });
+
+ const obj = {};
+ obj[key] = {
+ default: value,
+ select: true,
+ set: function(newName) {
+ if (newName === value) {
+ return value;
+ }
+ throw new Error('Can\'t set discriminator key "' + key + '"');
+ },
+ $skipDiscriminatorCheck: true
+ };
+ obj[key][schema.options.typeKey] = existingPath ?
+ existingPath.instance :
+ String;
+ schema.add(obj);
+ schema.discriminatorMapping = { key: key, value: value, isRoot: false };
+
+ if (baseSchema.options.collection) {
+ schema.options.collection = baseSchema.options.collection;
+ }
+
+ const toJSON = schema.options.toJSON;
+ const toObject = schema.options.toObject;
+ const _id = schema.options._id;
+ const id = schema.options.id;
+
+ const keys = Object.keys(schema.options);
+ schema.options.discriminatorKey = baseSchema.options.discriminatorKey;
+
+ 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(', ') +
+ ')');
+ }
+ }
+ }
+ schema.options = utils.clone(baseSchema.options);
+ if (toJSON) schema.options.toJSON = toJSON;
+ if (toObject) schema.options.toObject = toObject;
+ if (typeof _id !== 'undefined') {
+ schema.options._id = _id;
+ }
+ schema.options.id = id;
+ schema.s.hooks = model.schema.s.hooks.merge(schema.s.hooks);
+
+ schema.plugins = Array.prototype.slice.call(baseSchema.plugins);
+ schema.callQueue = baseSchema.callQueue.concat(schema.callQueue);
+ delete schema._requiredpaths; // reset just in case Schema#requiredPaths() was called on either schema
+ }
+
+ // merges base schema into new discriminator schema and sets new type field.
+ merge(schema, model.schema);
+
+ if (!model.discriminators) {
+ model.discriminators = {};
+ }
+
+ if (!model.schema.discriminatorMapping) {
+ model.schema.discriminatorMapping = { key: key, value: null, isRoot: true };
+ }
+ if (!model.schema.discriminators) {
+ model.schema.discriminators = {};
+ }
+
+ model.schema.discriminators[name] = schema;
+
+ if (model.discriminators[name]) {
+ throw new Error('Discriminator with name "' + name + '" already exists');
+ }
+
+ return schema;
+};
diff --git a/node_modules/mongoose/lib/helpers/once.js b/node_modules/mongoose/lib/helpers/once.js
new file mode 100644
index 0000000..0267579
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/once.js
@@ -0,0 +1,12 @@
+'use strict';
+
+module.exports = function once(fn) {
+ let called = false;
+ return function() {
+ if (called) {
+ return;
+ }
+ called = true;
+ return fn.apply(null, arguments);
+ };
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/parallelLimit.js b/node_modules/mongoose/lib/helpers/parallelLimit.js
new file mode 100644
index 0000000..9b07c02
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/parallelLimit.js
@@ -0,0 +1,55 @@
+'use strict';
+
+module.exports = parallelLimit;
+
+/*!
+ * ignore
+ */
+
+function parallelLimit(fns, limit, callback) {
+ let numInProgress = 0;
+ let numFinished = 0;
+ let error = null;
+
+ if (limit <= 0) {
+ throw new Error('Limit must be positive');
+ }
+
+ if (fns.length === 0) {
+ return callback(null, []);
+ }
+
+ for (let i = 0; i < fns.length && i < limit; ++i) {
+ _start();
+ }
+
+ function _start() {
+ fns[numFinished + numInProgress](_done(numFinished + numInProgress));
+ ++numInProgress;
+ }
+
+ const results = [];
+
+ function _done(index) {
+ return (err, res) => {
+ --numInProgress;
+ ++numFinished;
+
+ if (error != null) {
+ return;
+ }
+ if (err != null) {
+ error = err;
+ return callback(error);
+ }
+
+ results[index] = res;
+
+ if (numFinished === fns.length) {
+ return callback(null, results);
+ } else if (numFinished + numInProgress < fns.length) {
+ _start();
+ }
+ };
+ }
+}
diff --git a/node_modules/mongoose/lib/helpers/populate/SkipPopulateValue.js b/node_modules/mongoose/lib/helpers/populate/SkipPopulateValue.js
new file mode 100644
index 0000000..5d46cfd
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/SkipPopulateValue.js
@@ -0,0 +1,10 @@
+'use strict';
+
+module.exports = function SkipPopulateValue(val) {
+ if (!(this instanceof SkipPopulateValue)) {
+ return new SkipPopulateValue(val);
+ }
+
+ this.val = val;
+ return this;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js b/node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
new file mode 100644
index 0000000..843c148
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/assignRawDocsToIdStructure.js
@@ -0,0 +1,98 @@
+'use strict';
+
+const leanPopulateMap = require('./leanPopulateMap');
+const modelSymbol = require('../symbols').modelSymbol;
+const utils = require('../../utils');
+
+module.exports = assignRawDocsToIdStructure;
+
+/*!
+ * Assign `vals` returned by mongo query to the `rawIds`
+ * structure returned from utils.getVals() honoring
+ * query sort order if specified by user.
+ *
+ * This can be optimized.
+ *
+ * Rules:
+ *
+ * if the value of the path is not an array, use findOne rules, else find.
+ * for findOne the results are assigned directly to doc path (including null results).
+ * for find, if user specified sort order, results are assigned directly
+ * else documents are put back in original order of array if found in results
+ *
+ * @param {Array} rawIds
+ * @param {Array} vals
+ * @param {Boolean} sort
+ * @api private
+ */
+
+function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, recursed) {
+ // honor user specified sort order
+ const newOrder = [];
+ const sorting = options.sort && rawIds.length > 1;
+ const nullIfNotFound = options.$nullIfNotFound;
+ let doc;
+ let sid;
+ let id;
+
+ for (let i = 0; i < rawIds.length; ++i) {
+ id = rawIds[i];
+
+ if (Array.isArray(id)) {
+ // handle [ [id0, id2], [id3] ]
+ assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true);
+ newOrder.push(id);
+ continue;
+ }
+
+ if (id === null && !sorting) {
+ // keep nulls for findOne unless sorting, which always
+ // removes them (backward compat)
+ newOrder.push(id);
+ continue;
+ }
+
+ sid = String(id);
+
+ doc = resultDocs[sid];
+ // If user wants separate copies of same doc, use this option
+ if (options.clone && doc != null) {
+ if (options.lean) {
+ const _model = leanPopulateMap.get(doc);
+ doc = utils.clone(doc);
+ leanPopulateMap.set(doc, _model);
+ } else {
+ doc = doc.constructor.hydrate(doc._doc);
+ }
+ }
+
+ if (recursed) {
+ if (doc) {
+ if (sorting) {
+ newOrder[resultOrder[sid]] = doc;
+ } else {
+ newOrder.push(doc);
+ }
+ } else if (id != null && id[modelSymbol] != null) {
+ newOrder.push(id);
+ } else {
+ newOrder.push(options.retainNullValues || nullIfNotFound ? null : id);
+ }
+ } else {
+ // apply findOne behavior - if document in results, assign, else assign null
+ newOrder[i] = doc || null;
+ }
+ }
+
+ rawIds.length = 0;
+ if (newOrder.length) {
+ // reassign the documents based on corrected order
+
+ // forEach skips over sparse entries in arrays so we
+ // can safely use this to our advantage dealing with sorted
+ // result sets too.
+ newOrder.forEach(function(doc, i) {
+ rawIds[i] = doc;
+ });
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/assignVals.js b/node_modules/mongoose/lib/helpers/populate/assignVals.js
new file mode 100644
index 0000000..9fd51d8
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/assignVals.js
@@ -0,0 +1,274 @@
+'use strict';
+
+const SkipPopulateValue = require('./SkipPopulateValue');
+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');
+ // `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
+ assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);
+
+ // now update the original documents being populated using the
+ // result structure that contains real documents.
+ const docs = o.docs;
+ const rawIds = o.rawIds;
+ const options = o.options;
+ const count = o.count && o.isVirtual;
+
+ function setValue(val) {
+ if (count) {
+ return val;
+ }
+ if (val instanceof SkipPopulateValue) {
+ return val.val;
+ }
+
+ 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, populatedModel);
+ } else if (o.justOne === false && !Array.isArray(val)) {
+ return valueFilter([val], options, populateOptions, populatedModel);
+ }
+ return valueFilter(val, options, populateOptions, populatedModel);
+ }
+
+ for (let i = 0; i < docs.length; ++i) {
+ const existingVal = mpath.get(o.path, docs[i], lookupLocalFields);
+ if (existingVal == null && !getVirtual(o.originalModel.schema, o.path)) {
+ continue;
+ }
+
+ let valueToSet;
+ if (count) {
+ 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];
+ } else {
+ valueToSet = rawIds[i];
+ }
+
+ // If we're populating a map, the existing value will be an object, so
+ // we need to transform again
+ const originalSchema = o.originalModel.schema;
+ const isDoc = get(docs[i], '$__', null) != null;
+ let isMap = isDoc ?
+ existingVal instanceof Map :
+ 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');
+ if (!o.isVirtual && isMap) {
+ const _keys = existingVal instanceof Map ?
+ Array.from(existingVal.keys()) :
+ Object.keys(existingVal);
+ valueToSet = valueToSet.reduce((cur, v, i) => {
+ cur.set(_keys[i], v);
+ return cur;
+ }, 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);
+ // 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);
+ continue;
+ }
+
+ const parts = o.path.split('.');
+ let cur = docs[i];
+ const curPath = parts[0];
+ for (let j = 0; j < parts.length - 1; ++j) {
+ // If we get to an array with a dotted path, like `arr.foo`, don't set
+ // `foo` on the array.
+ if (Array.isArray(cur) && !utils.isArrayIndex(parts[j])) {
+ 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;
+ }
+ cur[parts[j]] = {};
+ }
+ cur = cur[parts[j]];
+ // 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;
+ }
+ }
+ if (docs[i].$__) {
+ docs[i].populated(o.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
+ mpath.set(o.path, valueToSet, docs[i], lookupLocalFields, setValue, false);
+ }
+};
+
+function numDocs(v) {
+ if (Array.isArray(v)) {
+ // If setting underneath an array of populated subdocs, we may have an
+ // array of arrays. See gh-7573
+ if (v.some(el => Array.isArray(el))) {
+ return v.map(el => numDocs(el));
+ }
+ return v.length;
+ }
+ return v == null ? 0 : 1;
+}
+
+/*!
+ * 1) Apply backwards compatible find/findOne behavior to sub documents
+ *
+ * find logic:
+ * a) filter out non-documents
+ * b) remove _id from sub docs when user specified
+ *
+ * findOne
+ * a) if no doc found, set to null
+ * b) remove _id from sub docs when user specified
+ *
+ * 2) Remove _ids when specified by users query.
+ *
+ * background:
+ * _ids are left in the query even when user excludes them so
+ * that population mapping can occur.
+ */
+
+function valueFilter(val, assignmentOpts, populateOptions) {
+ 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)) {
+ continue;
+ }
+ maybeRemoveId(subdoc, assignmentOpts);
+ ret.push(subdoc);
+ if (assignmentOpts.originalLimit &&
+ ret.length >= assignmentOpts.originalLimit) {
+ break;
+ }
+ }
+
+ // 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 val;
+ }
+
+ // findOne
+ if (isPopulatedObject(val)) {
+ maybeRemoveId(val, assignmentOpts);
+ return val;
+ }
+
+ if (val instanceof Map) {
+ return val;
+ }
+
+ if (populateOptions.justOne === true) {
+ return (val == null ? val : null);
+ }
+ if (populateOptions.justOne === false) {
+ return [];
+ }
+ return val;
+}
+
+/*!
+ * Remove _id from `subdoc` if user specified "lean" query option
+ */
+
+function maybeRemoveId(subdoc, assignmentOpts) {
+ if (subdoc != null && assignmentOpts.excludeId) {
+ if (typeof subdoc.$__setValue === 'function') {
+ delete subdoc._doc._id;
+ } else {
+ delete subdoc._id;
+ }
+ }
+}
+
+/*!
+ * Determine if `obj` is something we can set a populated path to. Can be a
+ * document, a lean document, or an array/map that contains docs.
+ */
+
+function isPopulatedObject(obj) {
+ if (obj == null) {
+ return false;
+ }
+
+ return Array.isArray(obj) ||
+ obj.$isMongooseMap ||
+ obj.$__ != null ||
+ leanPopulateMap.has(obj);
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js b/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
new file mode 100644
index 0000000..66baf19
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/getModelsMapForPopulate.js
@@ -0,0 +1,522 @@
+'use strict';
+
+const MongooseError = require('../../error/index');
+const SkipPopulateValue = require('./SkipPopulateValue');
+const get = require('../get');
+const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
+const isPathExcluded = require('../projection/isPathExcluded');
+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');
+
+const modelSymbol = require('../symbols').modelSymbol;
+const populateModelSymbol = require('../symbols').populateModelSymbol;
+const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
+
+module.exports = function getModelsMapForPopulate(model, docs, options) {
+ let i;
+ let doc;
+ const len = docs.length;
+ const available = {};
+ const map = [];
+ const modelNameFromQuery = options.model && options.model.modelName || options.model;
+ let schema;
+ let refPath;
+ let Model;
+ let currentOptions;
+ let modelNames;
+ let modelName;
+ let modelForFindSchema;
+
+ const originalModel = options.model;
+ let isVirtual = false;
+ const modelSchema = model.schema;
+
+ let allSchemaTypes = getSchemaTypes(modelSchema, null, options.path);
+ allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);
+ const _firstWithRefPath = allSchemaTypes.find(schematype => get(schematype, 'options.refPath', null) != null);
+
+ 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
+ if (schema != null &&
+ schema.$isMongooseDocumentArray &&
+ schema.options.ref == null &&
+ schema.options.refPath == null) {
+ continue;
+ }
+ // 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]) {
+ continue;
+ }
+ const isUnderneathDocArray = schema && schema.$isUnderneathDocArray;
+ if (isUnderneathDocArray && get(options, 'options.sort') != null) {
+ return new MongooseError('Cannot populate with `sort` on path ' + options.path +
+ ' because it is a subproperty of a document array');
+ }
+
+ modelNames = null;
+ let isRefPath = !!_firstWithRefPath;
+ let normalizedRefPath = _firstWithRefPath ? get(_firstWithRefPath, 'options.refPath', null) : null;
+
+ if (Array.isArray(schema)) {
+ const schemasArray = schema;
+ for (const _schema of schemasArray) {
+ let _modelNames;
+ let res;
+ try {
+ res = _getModelNames(doc, _schema);
+ _modelNames = res.modelNames;
+ isRefPath = isRefPath || res.isRefPath;
+ normalizedRefPath = normalizeRefPath(normalizedRefPath, doc, options.path) ||
+ res.refPath;
+ justOne = res.justOne;
+ } catch (error) {
+ return error;
+ }
+
+ if (isRefPath && !res.isRefPath) {
+ continue;
+ }
+ if (!_modelNames) {
+ continue;
+ }
+ modelNames = modelNames || [];
+ for (const modelName of _modelNames) {
+ if (modelNames.indexOf(modelName) === -1) {
+ modelNames.push(modelName);
+ }
+ }
+ }
+ } else {
+ try {
+ const res = _getModelNames(doc, schema);
+ modelNames = res.modelNames;
+ isRefPath = res.isRefPath;
+ normalizedRefPath = res.refPath;
+ justOne = res.justOne;
+ } catch (error) {
+ return error;
+ }
+
+ if (!modelNames) {
+ continue;
+ }
+ }
+
+ const _virtualRes = getVirtual(model.schema, options.path);
+ const virtual = _virtualRes == null ? null : _virtualRes.virtual;
+
+ let localField;
+ let count = false;
+ if (virtual && virtual.options) {
+ const virtualPrefix = _virtualRes.nestedSchemaPath ?
+ _virtualRes.nestedSchemaPath + '.' : '';
+ if (typeof virtual.options.localField === 'function') {
+ localField = virtualPrefix + virtual.options.localField.call(doc, doc);
+ } else {
+ localField = virtualPrefix + virtual.options.localField;
+ }
+ count = virtual.options.count;
+
+ if (virtual.options.skip != null && !options.hasOwnProperty('skip')) {
+ options.skip = virtual.options.skip;
+ }
+ if (virtual.options.limit != null && !options.hasOwnProperty('limit')) {
+ options.limit = virtual.options.limit;
+ }
+ if (virtual.options.perDocumentLimit != null && !options.hasOwnProperty('perDocumentLimit')) {
+ options.perDocumentLimit = virtual.options.perDocumentLimit;
+ }
+ } else {
+ localField = options.path;
+ }
+ let foreignField = virtual && virtual.options ?
+ virtual.options.foreignField :
+ '_id';
+
+ // `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()`
+ if ('justOne' in options && options.justOne !== void 0) {
+ justOne = options.justOne;
+ } else if (virtual && virtual.options && virtual.options.refPath) {
+ const normalizedRefPath =
+ normalizeRefPath(virtual.options.refPath, doc, options.path);
+ justOne = !!virtual.options.justOne;
+ isVirtual = true;
+ const refValue = utils.getValue(normalizedRefPath, doc);
+ modelNames = Array.isArray(refValue) ? refValue : [refValue];
+ } else if (virtual && virtual.options && virtual.options.ref) {
+ let normalizedRef;
+ if (typeof virtual.options.ref === 'function') {
+ normalizedRef = virtual.options.ref.call(doc, doc);
+ } else {
+ normalizedRef = virtual.options.ref;
+ }
+ justOne = !!virtual.options.justOne;
+ isVirtual = true;
+ if (!modelNames) {
+ modelNames = [].concat(normalizedRef);
+ }
+ } 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 (!modelNames) {
+ continue;
+ }
+
+ if (virtual && (!localField || !foreignField)) {
+ return new MongooseError('If you are populating a virtual, you must set the ' +
+ 'localField and foreignField options');
+ }
+
+ options.isVirtual = isVirtual;
+ options.virtual = virtual;
+ if (typeof localField === 'function') {
+ localField = localField.call(doc, doc);
+ }
+ if (typeof foreignField === 'function') {
+ foreignField = foreignField.call(doc);
+ }
+
+ const localFieldPathType = modelSchema._getPathType(localField);
+ const localFieldPath = localFieldPathType === 'real' ? modelSchema.path(localField) : localFieldPathType.schema;
+ const localFieldGetters = localFieldPath && localFieldPath.getters ? localFieldPath.getters : [];
+ let ret;
+
+ const _populateOptions = get(options, 'options', {});
+
+ const getters = 'getters' in _populateOptions ?
+ _populateOptions.getters :
+ options.isVirtual && get(virtual, 'options.getters', false);
+ if (localFieldGetters.length > 0 && getters) {
+ const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
+ const localFieldValue = mpath.get(localField, doc, lookupLocalFields);
+ if (Array.isArray(localFieldValue)) {
+ 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(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.
+ if (isRefPath && normalizedRefPath != null) {
+ const pieces = normalizedRefPath.split('.');
+ let cur = '';
+ for (let j = 0; j < pieces.length; ++j) {
+ const piece = pieces[j];
+ cur = cur + (cur.length === 0 ? '' : '.') + piece;
+ const schematype = modelSchema.path(cur);
+ if (schematype != null &&
+ schematype.$isMongooseArray &&
+ schematype.caster.discriminators != null &&
+ Object.keys(schematype.caster.discriminators).length > 0) {
+ const subdocs = utils.getValue(cur, doc);
+ const remnant = options.path.substr(cur.length + 1);
+ const discriminatorKey = schematype.caster.schema.options.discriminatorKey;
+ modelNames = [];
+ for (const subdoc of subdocs) {
+ const discriminatorName = utils.getValue(discriminatorKey, subdoc);
+ const discriminator = schematype.caster.discriminators[discriminatorName];
+ const discriminatorSchema = discriminator && discriminator.schema;
+ if (discriminatorSchema == null) {
+ continue;
+ }
+ const _path = discriminatorSchema.path(remnant);
+ if (_path == null || _path.options.refPath == null) {
+ const docValue = utils.getValue(localField.substr(cur.length + 1), subdoc);
+ ret = ret.map(v => v === docValue ? SkipPopulateValue(v) : v);
+ continue;
+ }
+ const modelName = utils.getValue(pieces.slice(j + 1).join('.'), subdoc);
+ modelNames.push(modelName);
+ }
+ }
+ }
+ }
+
+ let k = modelNames.length;
+ while (k--) {
+ modelName = modelNames[k];
+ if (modelName == null) {
+ continue;
+ }
+
+ // `PopulateOptions#connection`: if the model is passed as a string, the
+ // connection matters because different connections have different models.
+ const connection = options.connection != null ? options.connection : model.db;
+
+ try {
+ Model = originalModel && originalModel[modelSymbol] ?
+ originalModel :
+ modelName[modelSymbol] ? modelName : connection.model(modelName);
+ } catch (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;
+ const flat = Array.isArray(ret) ? utils.array.flatten(ret) : [];
+
+ if (isRefPath && Array.isArray(ret) && flat.length === modelNames.length) {
+ ids = flat.filter((val, i) => modelNames[i] === modelName);
+ }
+
+ 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);
+ }
+ utils.merge(currentOptions, options);
+
+ // Used internally for checking what model was used to populate this
+ // path.
+ options[populateModelSymbol] = Model;
+
+ available[modelName] = {
+ model: Model,
+ options: currentOptions,
+ match: hasMatchFunction ? [match] : match,
+ docs: [doc],
+ ids: [ids],
+ allIds: [ret],
+ localField: new Set([localField]),
+ foreignField: new Set([foreignField]),
+ justOne: justOne,
+ isVirtual: isVirtual,
+ virtual: virtual,
+ count: count,
+ [populateModelSymbol]: Model
+ };
+ map.push(available[modelName]);
+ } else {
+ available[modelName].localField.add(localField);
+ available[modelName].foreignField.add(foreignField);
+ available[modelName].docs.push(doc);
+ available[modelName].ids.push(ids);
+ available[modelName].allIds.push(ret);
+ if (hasMatchFunction) {
+ available[modelName].match.push(match);
+ }
+ }
+ }
+ }
+
+ return map;
+
+ function _getModelNames(doc, schema) {
+ let modelNames;
+ let discriminatorKey;
+ let isRefPath = false;
+ let justOne = null;
+
+ if (schema && schema.caster) {
+ schema = schema.caster;
+ }
+ if (schema && schema.$isSchemaMap) {
+ schema = schema.$__schemaType;
+ }
+
+ if (!schema && model.discriminators) {
+ discriminatorKey = model.schema.discriminatorMapping.key;
+ }
+
+ refPath = schema && schema.options && schema.options.refPath;
+
+ const normalizedRefPath = normalizeRefPath(refPath, doc, options.path);
+
+ if (modelNameFromQuery) {
+ modelNames = [modelNameFromQuery]; // query options
+ } else if (normalizedRefPath) {
+ if (options._queryProjection != null && isPathExcluded(options._queryProjection, normalizedRefPath)) {
+ throw new MongooseError('refPath `' + normalizedRefPath +
+ '` must not be excluded in projection, got ' +
+ util.inspect(options._queryProjection));
+ }
+
+ if (modelSchema.virtuals.hasOwnProperty(normalizedRefPath) && doc.$__ == null) {
+ modelNames = [modelSchema.virtuals[normalizedRefPath].applyGetters(void 0, doc)];
+ } else {
+ modelNames = utils.getValue(normalizedRefPath, doc);
+ }
+
+ if (Array.isArray(modelNames)) {
+ modelNames = utils.array.flatten(modelNames);
+ }
+
+ isRefPath = true;
+ } else {
+ let modelForCurrentDoc = model;
+ let schemaForCurrentDoc;
+
+ 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;
+ }
+ }
+
+ schemaForCurrentDoc = modelForCurrentDoc.schema._getSchema(options.path);
+
+ if (schemaForCurrentDoc && schemaForCurrentDoc.caster) {
+ schemaForCurrentDoc = schemaForCurrentDoc.caster;
+ }
+ }
+ } else {
+ schemaForCurrentDoc = schema;
+ }
+ 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;
+
+ if ((ref = get(schemaForCurrentDoc, 'options.ref')) != null) {
+ ref = handleRefFunction(ref, doc);
+ modelNames = [ref];
+ } else if ((ref = get(virtual, 'options.ref')) != null) {
+ ref = handleRefFunction(ref, doc);
+
+ // When referencing nested arrays, the ref should be an Array
+ // of modelNames.
+ if (Array.isArray(ref)) {
+ modelNames = ref;
+ } else {
+ modelNames = [ref];
+ }
+
+ isVirtual = true;
+ } else if ((refPath = get(schemaForCurrentDoc, 'options.refPath')) != null) {
+ isRefPath = true;
+ refPath = normalizeRefPath(refPath, doc, options.path);
+ modelNames = utils.getValue(refPath, doc);
+ if (Array.isArray(modelNames)) {
+ modelNames = utils.array.flatten(modelNames);
+ }
+ } else {
+ // We may have a discriminator, in which case we don't want to
+ // populate using the base model by default
+ modelNames = discriminatorKey ? null : [model.modelName];
+ }
+ }
+
+ if (!modelNames) {
+ return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
+ }
+
+ if (!Array.isArray(modelNames)) {
+ modelNames = [modelNames];
+ }
+
+ return { modelNames: modelNames, isRefPath: isRefPath, refPath: normalizedRefPath, justOne: justOne };
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function handleRefFunction(ref, doc) {
+ if (typeof ref === 'function' && !ref[modelSymbol]) {
+ return ref.call(doc, doc);
+ }
+ return ref;
+}
+
+/*!
+ * Retrieve the _id of `val` if a Document or Array of Documents.
+ *
+ * @param {Array|Document|Any} val
+ * @return {Array|Document|Any}
+ */
+
+function convertTo_id(val, schema) {
+ if (val != null && val.$__ != null) return val._id;
+
+ if (Array.isArray(val)) {
+ for (let i = 0; i < val.length; ++i) {
+ if (val[i] != null && val[i].$__ != null) {
+ val[i] = val[i]._id;
+ }
+ }
+ if (val.isMongooseArray && val.$schema()) {
+ return val.$schema().cast(val, val.$parent());
+ }
+
+ return [].concat(val);
+ }
+
+ // `populate('map')` may be an object if populating on a doc that hasn't
+ // been hydrated yet
+ if (val != null &&
+ val.constructor.name === '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)) {
+ const ret = [];
+ for (const key of Object.keys(val)) {
+ ret.push(val[key]);
+ }
+ return ret;
+ }
+ // If doc has already been hydrated, e.g. `doc.populate('map').execPopulate()`
+ // then `val` will already be a map
+ if (val instanceof Map) {
+ return Array.from(val.values());
+ }
+
+ return val;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js b/node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
new file mode 100644
index 0000000..15660df
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/getSchemaTypes.js
@@ -0,0 +1,198 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+const Mixed = require('../../schema/mixed');
+const get = require('../get');
+const leanPopulateMap = require('./leanPopulateMap');
+const mpath = require('mpath');
+
+const populateModelSymbol = require('../symbols').populateModelSymbol;
+
+/*!
+ * @param {Schema} schema
+ * @param {Object} doc POJO
+ * @param {string} path
+ */
+
+module.exports = function getSchemaTypes(schema, doc, path) {
+ const pathschema = schema.path(path);
+ const topLevelDoc = doc;
+
+ if (pathschema) {
+ return pathschema;
+ }
+
+ function search(parts, schema, subdoc, nestedPath) {
+ let p = parts.length + 1;
+ let foundschema;
+ let trypath;
+
+ while (p--) {
+ trypath = parts.slice(0, p).join('.');
+ foundschema = schema.path(trypath);
+
+ if (foundschema == null) {
+ continue;
+ }
+
+ if (foundschema.caster) {
+ // array of Mixed?
+ if (foundschema.caster instanceof Mixed) {
+ return foundschema.caster;
+ }
+
+ let schemas = null;
+ if (foundschema.schema != null && foundschema.schema.discriminators != null) {
+ const discriminators = foundschema.schema.discriminators;
+ const discriminatorKeyPath = trypath + '.' +
+ foundschema.schema.options.discriminatorKey;
+ const keys = subdoc ? mpath.get(discriminatorKeyPath, subdoc) || [] : [];
+ schemas = Object.keys(discriminators).
+ reduce(function(cur, discriminator) {
+ if (doc == null || keys.indexOf(discriminator) !== -1) {
+ cur.push(discriminators[discriminator]);
+ }
+ return cur;
+ }, []);
+ }
+
+ // Now that we found the array, we need to check if there
+ // are remaining document paths to look up for casting.
+ // Also we need to handle array.$.path since schema.path
+ // doesn't work for that.
+ // If there is no foundschema.schema we are dealing with
+ // a path like array.$
+ if (p !== parts.length && foundschema.schema) {
+ let ret;
+ if (parts[p] === '$') {
+ if (p + 1 === parts.length) {
+ // comments.$
+ return foundschema;
+ }
+ // comments.$.comments.$.title
+ ret = search(
+ parts.slice(p + 1),
+ schema,
+ subdoc ? mpath.get(trypath, subdoc) : null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+ if (ret) {
+ ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
+ !foundschema.schema.$isSingleNested;
+ }
+ return ret;
+ }
+
+ if (schemas != null && schemas.length > 0) {
+ ret = [];
+ for (const schema of schemas) {
+ const _ret = search(
+ parts.slice(p),
+ schema,
+ subdoc ? mpath.get(trypath, subdoc) : null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+ if (_ret != null) {
+ _ret.$isUnderneathDocArray = _ret.$isUnderneathDocArray ||
+ !foundschema.schema.$isSingleNested;
+ if (_ret.$isUnderneathDocArray) {
+ ret.$isUnderneathDocArray = true;
+ }
+ ret.push(_ret);
+ }
+ }
+ return ret;
+ } else {
+ ret = search(
+ parts.slice(p),
+ foundschema.schema,
+ subdoc ? mpath.get(trypath, subdoc) : null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+
+ if (ret) {
+ 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(
+ parts.slice(p),
+ type.schema,
+ null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+ }
+ }
+
+ const fullPath = nestedPath.concat([trypath]).join('.');
+ if (topLevelDoc != null && topLevelDoc.$__ && topLevelDoc.populated(fullPath) && p < parts.length) {
+ const model = doc.$__.populated[fullPath].options[populateModelSymbol];
+ if (model != null) {
+ const ret = search(
+ parts.slice(p),
+ model.schema,
+ subdoc ? mpath.get(trypath, subdoc) : null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+
+ if (ret) {
+ ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
+ !model.schema.$isSingleNested;
+ }
+
+ return ret;
+ }
+ }
+
+ const _val = get(topLevelDoc, trypath);
+ if (_val != null) {
+ const model = Array.isArray(_val) && _val.length > 0 ?
+ leanPopulateMap.get(_val[0]) :
+ leanPopulateMap.get(_val);
+ // Populated using lean, `leanPopulateMap` value is the foreign model
+ const schema = model != null ? model.schema : null;
+ if (schema != null) {
+ const ret = search(
+ parts.slice(p),
+ schema,
+ subdoc ? mpath.get(trypath, subdoc) : null,
+ nestedPath.concat(parts.slice(0, p))
+ );
+
+ if (ret) {
+ ret.$isUnderneathDocArray = ret.$isUnderneathDocArray ||
+ !schema.$isSingleNested;
+ }
+
+ return ret;
+ }
+ }
+
+ return foundschema;
+ }
+ }
+
+ // look for arrays
+ const parts = path.split('.');
+ for (let i = 0; i < parts.length; ++i) {
+ if (parts[i] === '$') {
+ // Re: gh-5628, because `schema.path()` doesn't take $ into account.
+ parts[i] = '0';
+ }
+ }
+ return search(parts, schema, doc, []);
+};
diff --git a/node_modules/mongoose/lib/helpers/populate/getVirtual.js b/node_modules/mongoose/lib/helpers/populate/getVirtual.js
new file mode 100644
index 0000000..fc1641d
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/getVirtual.js
@@ -0,0 +1,72 @@
+'use strict';
+
+module.exports = getVirtual;
+
+/*!
+ * ignore
+ */
+
+function getVirtual(schema, name) {
+ if (schema.virtuals[name]) {
+ return { virtual: schema.virtuals[name], path: void 0 };
+ }
+
+ const parts = name.split('.');
+ let cur = '';
+ let nestedSchemaPath = '';
+ for (let i = 0; i < parts.length; ++i) {
+ cur += (cur.length > 0 ? '.' : '') + parts[i];
+ if (schema.virtuals[cur]) {
+ if (i === parts.length - 1) {
+ return { virtual: schema.virtuals[cur], path: nestedSchemaPath };
+ }
+ continue;
+ }
+
+ if (schema.nested[cur]) {
+ continue;
+ }
+
+ if (schema.paths[cur] && schema.paths[cur].schema) {
+ schema = schema.paths[cur].schema;
+ const rest = parts.slice(i + 1).join('.');
+
+ if (schema.virtuals[rest]) {
+ if (i === parts.length - 2) {
+ return {
+ virtual: schema.virtuals[rest],
+ nestedSchemaPath: [nestedSchemaPath, cur].filter(v => !!v).join('.')
+ };
+ }
+ continue;
+ }
+
+ if (i + 1 < parts.length && schema.discriminators) {
+ for (const key of Object.keys(schema.discriminators)) {
+ const res = getVirtual(schema.discriminators[key], rest);
+ if (res != null) {
+ const _path = [nestedSchemaPath, cur, res.nestedSchemaPath].
+ filter(v => !!v).join('.');
+ return {
+ virtual: res.virtual,
+ nestedSchemaPath: _path
+ };
+ }
+ }
+ }
+
+ nestedSchemaPath += (nestedSchemaPath.length > 0 ? '.' : '') + cur;
+ cur = '';
+ continue;
+ }
+
+ if (schema.discriminators) {
+ for (const discriminatorKey of Object.keys(schema.discriminators)) {
+ const virtualFromDiscriminator = getVirtual(schema.discriminators[discriminatorKey], name);
+ if (virtualFromDiscriminator) return virtualFromDiscriminator;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/node_modules/mongoose/lib/helpers/populate/leanPopulateMap.js b/node_modules/mongoose/lib/helpers/populate/leanPopulateMap.js
new file mode 100644
index 0000000..a333124
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/leanPopulateMap.js
@@ -0,0 +1,7 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = new WeakMap(); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/lookupLocalFields.js b/node_modules/mongoose/lib/helpers/populate/lookupLocalFields.js
new file mode 100644
index 0000000..08ed763
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/lookupLocalFields.js
@@ -0,0 +1,26 @@
+'use strict';
+
+module.exports = function lookupLocalFields(cur, path, val) {
+ if (cur == null) {
+ return cur;
+ }
+
+ if (cur._doc != null) {
+ cur = cur._doc;
+ }
+
+ if (arguments.length >= 3) {
+ cur[path] = val;
+ return val;
+ }
+
+
+ // Support populating paths under maps using `map.$*.subpath`
+ if (path === '$*') {
+ return cur instanceof Map ?
+ Array.from(cur.values()) :
+ Object.keys(cur).map(key => cur[key]);
+ }
+
+ return cur[path];
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/normalizeRefPath.js b/node_modules/mongoose/lib/helpers/populate/normalizeRefPath.js
new file mode 100644
index 0000000..233b741
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/normalizeRefPath.js
@@ -0,0 +1,45 @@
+'use strict';
+
+module.exports = function normalizeRefPath(refPath, doc, populatedPath) {
+ if (refPath == null) {
+ return refPath;
+ }
+
+ if (typeof refPath === 'function') {
+ refPath = refPath.call(doc, doc, populatedPath);
+ }
+
+ // If populated path has numerics, the end `refPath` should too. For example,
+ // if populating `a.0.b` instead of `a.b` and `b` has `refPath = a.c`, we
+ // should return `a.0.c` for the refPath.
+ const hasNumericProp = /(\.\d+$|\.\d+\.)/g;
+
+ if (hasNumericProp.test(populatedPath)) {
+ const chunks = populatedPath.split(hasNumericProp);
+
+ if (chunks[chunks.length - 1] === '') {
+ throw new Error('Can\'t populate individual element in an array');
+ }
+
+ let _refPath = '';
+ let _remaining = refPath;
+ // 2nd, 4th, etc. will be numeric props. For example: `[ 'a', '.0.', 'b' ]`
+ for (let i = 0; i < chunks.length; i += 2) {
+ const chunk = chunks[i];
+ if (_remaining.startsWith(chunk + '.')) {
+ _refPath += _remaining.substr(0, chunk.length) + chunks[i + 1];
+ _remaining = _remaining.substr(chunk.length + 1);
+ } else if (i === chunks.length - 1) {
+ _refPath += _remaining;
+ _remaining = '';
+ break;
+ } else {
+ throw new Error('Could not normalize ref path, chunk ' + chunk + ' not in populated path');
+ }
+ }
+
+ return _refPath;
+ }
+
+ return refPath;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/removeDeselectedForeignField.js b/node_modules/mongoose/lib/helpers/populate/removeDeselectedForeignField.js
new file mode 100644
index 0000000..39b893a
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/removeDeselectedForeignField.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const get = require('../get');
+const mpath = require('mpath');
+const parseProjection = require('../projection/parseProjection');
+
+/*!
+ * ignore
+ */
+
+module.exports = function removeDeselectedForeignField(foreignFields, options, docs) {
+ const projection = parseProjection(get(options, 'select', null), true) ||
+ parseProjection(get(options, 'options.select', null), true);
+
+ if (projection == null) {
+ return;
+ }
+ for (const foreignField of foreignFields) {
+ if (!projection.hasOwnProperty('-' + foreignField)) {
+ continue;
+ }
+
+ for (const val of docs) {
+ if (val.$__ != null) {
+ mpath.unset(foreignField, val._doc);
+ } else {
+ mpath.unset(foreignField, val);
+ }
+ }
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/populate/validateRef.js b/node_modules/mongoose/lib/helpers/populate/validateRef.js
new file mode 100644
index 0000000..9dc2b6f
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/populate/validateRef.js
@@ -0,0 +1,19 @@
+'use strict';
+
+const MongooseError = require('../../error/mongooseError');
+const util = require('util');
+
+module.exports = validateRef;
+
+function validateRef(ref, path) {
+ if (typeof ref === 'string') {
+ return;
+ }
+
+ if (typeof ref === 'function') {
+ return;
+ }
+
+ throw new MongooseError('Invalid ref at path "' + path + '". Got ' +
+ util.inspect(ref, { depth: 0 }));
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/printJestWarning.js b/node_modules/mongoose/lib/helpers/printJestWarning.js
new file mode 100644
index 0000000..eb3a8eb
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/printJestWarning.js
@@ -0,0 +1,8 @@
+'use strict';
+
+if (typeof jest !== 'undefined' && typeof window !== 'undefined') {
+ console.warn('Mongoose: looks like you\'re trying to test a Mongoose app ' +
+ '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');
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/projection/isDefiningProjection.js b/node_modules/mongoose/lib/helpers/projection/isDefiningProjection.js
new file mode 100644
index 0000000..67dfb39
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/isDefiningProjection.js
@@ -0,0 +1,18 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function isDefiningProjection(val) {
+ if (val == null) {
+ // `undefined` or `null` become exclusive projections
+ return true;
+ }
+ if (typeof val === 'object') {
+ // Only cases where a value does **not** define whether the whole projection
+ // is inclusive or exclusive are `$meta` and `$slice`.
+ return !('$meta' in val) && !('$slice' in val);
+ }
+ return true;
+};
diff --git a/node_modules/mongoose/lib/helpers/projection/isExclusive.js b/node_modules/mongoose/lib/helpers/projection/isExclusive.js
new file mode 100644
index 0000000..8c64bc5
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/isExclusive.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const isDefiningProjection = require('./isDefiningProjection');
+
+/*!
+ * ignore
+ */
+
+module.exports = function isExclusive(projection) {
+ const keys = Object.keys(projection);
+ let ki = keys.length;
+ let exclude = null;
+
+ if (ki === 1 && keys[0] === '_id') {
+ exclude = !!projection[keys[ki]];
+ } else {
+ while (ki--) {
+ // Does this projection explicitly define inclusion/exclusion?
+ // Explicitly avoid `$meta` and `$slice`
+ if (keys[ki] !== '_id' && isDefiningProjection(projection[keys[ki]])) {
+ exclude = !projection[keys[ki]];
+ break;
+ }
+ }
+ }
+
+ return exclude;
+};
diff --git a/node_modules/mongoose/lib/helpers/projection/isInclusive.js b/node_modules/mongoose/lib/helpers/projection/isInclusive.js
new file mode 100644
index 0000000..098309f
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/isInclusive.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const isDefiningProjection = require('./isDefiningProjection');
+
+/*!
+ * ignore
+ */
+
+module.exports = function isInclusive(projection) {
+ if (projection == null) {
+ return false;
+ }
+
+ const props = Object.keys(projection);
+ const numProps = props.length;
+ if (numProps === 0) {
+ return false;
+ }
+
+ for (let i = 0; i < numProps; ++i) {
+ const prop = props[i];
+ // Plus paths can't define the projection (see gh-7050)
+ if (prop.startsWith('+')) {
+ continue;
+ }
+ // If field is truthy (1, true, etc.) and not an object, then this
+ // projection must be inclusive. If object, assume its $meta, $slice, etc.
+ if (isDefiningProjection(projection[prop]) && !!projection[prop]) {
+ return true;
+ }
+ }
+
+ return false;
+};
diff --git a/node_modules/mongoose/lib/helpers/projection/isPathExcluded.js b/node_modules/mongoose/lib/helpers/projection/isPathExcluded.js
new file mode 100644
index 0000000..fc2592c
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/isPathExcluded.js
@@ -0,0 +1,35 @@
+'use strict';
+
+const isDefiningProjection = require('./isDefiningProjection');
+
+/*!
+ * Determines if `path` is excluded by `projection`
+ *
+ * @param {Object} projection
+ * @param {string} path
+ * @return {Boolean}
+ */
+
+module.exports = function isPathExcluded(projection, path) {
+ if (path === '_id') {
+ return projection._id === 0;
+ }
+
+ const paths = Object.keys(projection);
+ let type = null;
+
+ for (const _path of paths) {
+ if (isDefiningProjection(projection[_path])) {
+ type = projection[path] === 1 ? 'inclusive' : 'exclusive';
+ break;
+ }
+ }
+
+ if (type === 'inclusive') {
+ return projection[path] !== 1;
+ }
+ if (type === 'exclusive') {
+ return projection[path] === 0;
+ }
+ return false;
+};
diff --git a/node_modules/mongoose/lib/helpers/projection/isPathSelectedInclusive.js b/node_modules/mongoose/lib/helpers/projection/isPathSelectedInclusive.js
new file mode 100644
index 0000000..8a05fc9
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/isPathSelectedInclusive.js
@@ -0,0 +1,28 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function isPathSelectedInclusive(fields, path) {
+ const chunks = path.split('.');
+ let cur = '';
+ let j;
+ let keys;
+ let numKeys;
+ for (let i = 0; i < chunks.length; ++i) {
+ cur += cur.length ? '.' : '' + chunks[i];
+ if (fields[cur]) {
+ keys = Object.keys(fields);
+ numKeys = keys.length;
+ for (j = 0; j < numKeys; ++j) {
+ if (keys[i].indexOf(cur + '.') === 0 && keys[i].indexOf(path) !== 0) {
+ continue;
+ }
+ }
+ return true;
+ }
+ }
+
+ return false;
+};
diff --git a/node_modules/mongoose/lib/helpers/projection/parseProjection.js b/node_modules/mongoose/lib/helpers/projection/parseProjection.js
new file mode 100644
index 0000000..d2a44b1
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/projection/parseProjection.js
@@ -0,0 +1,33 @@
+'use strict';
+
+/**
+ * Convert a string or array into a projection object, retaining all
+ * `-` and `+` paths.
+ */
+
+module.exports = function parseProjection(v, retainMinusPaths) {
+ const type = typeof v;
+
+ if (type === 'string') {
+ v = v.split(/\s+/);
+ }
+ if (!Array.isArray(v) && Object.prototype.toString.call(v) !== '[object Arguments]') {
+ return v;
+ }
+
+ const len = v.length;
+ const ret = {};
+ for (let i = 0; i < len; ++i) {
+ let field = v[i];
+ if (!field) {
+ continue;
+ }
+ const include = '-' == field[0] ? 0 : 1;
+ if (!retainMinusPaths && include === 0) {
+ field = field.substring(1);
+ }
+ ret[field] = include;
+ }
+
+ return ret;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/promiseOrCallback.js b/node_modules/mongoose/lib/helpers/promiseOrCallback.js
new file mode 100644
index 0000000..a1aff55
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/promiseOrCallback.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const PromiseProvider = require('../promise_provider');
+
+const emittedSymbol = Symbol.for('mongoose:emitted');
+
+module.exports = function promiseOrCallback(callback, fn, ee) {
+ if (typeof callback === 'function') {
+ return fn(function(error) {
+ if (error != null) {
+ if (ee != null && ee.listeners('error').length > 0 && !error[emittedSymbol]) {
+ error[emittedSymbol] = true;
+ ee.emit('error', error);
+ }
+ try {
+ callback(error);
+ } catch (error) {
+ return process.nextTick(() => {
+ throw error;
+ });
+ }
+ return;
+ }
+ callback.apply(this, arguments);
+ });
+ }
+
+ const 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]) {
+ error[emittedSymbol] = true;
+ ee.emit('error', error);
+ }
+ return reject(error);
+ }
+ if (arguments.length > 2) {
+ return resolve(Array.prototype.slice.call(arguments, 1));
+ }
+ resolve(res);
+ });
+ });
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/query/applyGlobalMaxTimeMS.js b/node_modules/mongoose/lib/helpers/query/applyGlobalMaxTimeMS.js
new file mode 100644
index 0000000..cb49260
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/applyGlobalMaxTimeMS.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const utils = require('../../utils');
+
+module.exports = function applyGlobalMaxTimeMS(options, model) {
+ if (utils.hasUserDefinedProperty(options, 'maxTimeMS')) {
+ return;
+ }
+
+ if (utils.hasUserDefinedProperty(model.db.options, 'maxTimeMS')) {
+ options.maxTimeMS = model.db.options.maxTimeMS;
+ } else if (utils.hasUserDefinedProperty(model.base.options, 'maxTimeMS')) {
+ options.maxTimeMS = model.base.options.maxTimeMS;
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js b/node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js
new file mode 100644
index 0000000..a08baf8
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/applyQueryMiddleware.js
@@ -0,0 +1,90 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = applyQueryMiddleware;
+
+/*!
+ * ignore
+ */
+
+applyQueryMiddleware.middlewareFunctions = [
+ 'count',
+ 'countDocuments',
+ 'deleteMany',
+ 'deleteOne',
+ 'distinct',
+ 'estimatedDocumentCount',
+ 'find',
+ 'findOne',
+ 'findOneAndDelete',
+ 'findOneAndRemove',
+ 'findOneAndReplace',
+ 'findOneAndUpdate',
+ 'remove',
+ 'replaceOne',
+ 'update',
+ 'updateMany',
+ 'updateOne',
+ 'validate'
+];
+
+/*!
+ * Apply query middleware
+ *
+ * @param {Query} query constructor
+ * @param {Model} model
+ */
+
+function applyQueryMiddleware(Query, model) {
+ const kareemOptions = {
+ useErrorHandlers: true,
+ numCallbackParams: 1,
+ nullResultByDefault: true
+ };
+
+ const middleware = model.hooks.filter(hook => {
+ const contexts = _getContexts(hook);
+ if (hook.name === 'updateOne') {
+ return contexts.query == null || !!contexts.query;
+ }
+ if (hook.name === 'deleteOne') {
+ return !!contexts.query || Object.keys(contexts).length === 0;
+ }
+ if (hook.name === 'validate' || hook.name === 'remove') {
+ return !!contexts.query;
+ }
+ return true;
+ });
+
+ // `update()` thunk has a different name because `_update` was already taken
+ Query.prototype._execUpdate = middleware.createWrapper('update',
+ Query.prototype._execUpdate, null, kareemOptions);
+ // `distinct()` thunk has a different name because `_distinct` was already taken
+ Query.prototype.__distinct = middleware.createWrapper('distinct',
+ Query.prototype.__distinct, null, kareemOptions);
+
+ // `validate()` doesn't have a thunk because it doesn't execute a query.
+ Query.prototype.validate = middleware.createWrapper('validate',
+ Query.prototype.validate, null, kareemOptions);
+
+ applyQueryMiddleware.middlewareFunctions.
+ filter(v => v !== 'update' && v !== 'distinct' && v !== 'validate').
+ forEach(fn => {
+ Query.prototype[`_${fn}`] = middleware.createWrapper(fn,
+ Query.prototype[`_${fn}`], null, kareemOptions);
+ });
+}
+
+function _getContexts(hook) {
+ const ret = {};
+ if (hook.hasOwnProperty('query')) {
+ ret.query = hook.query;
+ }
+ if (hook.hasOwnProperty('document')) {
+ ret.document = hook.document;
+ }
+ return ret;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/query/castFilterPath.js b/node_modules/mongoose/lib/helpers/query/castFilterPath.js
new file mode 100644
index 0000000..74ff1c2
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/castFilterPath.js
@@ -0,0 +1,55 @@
+'use strict';
+
+const isOperator = require('./isOperator');
+
+module.exports = function castFilterPath(query, schematype, val) {
+ const ctx = query;
+ const any$conditionals = Object.keys(val).some(isOperator);
+
+ if (!any$conditionals) {
+ return schematype.castForQueryWrapper({
+ val: val,
+ context: ctx
+ });
+ }
+
+ const ks = Object.keys(val);
+
+ let k = ks.length;
+
+ while (k--) {
+ const $cond = ks[k];
+ const nested = val[$cond];
+
+ if ($cond === '$not') {
+ if (nested && schematype && !schematype.caster) {
+ const _keys = Object.keys(nested);
+ if (_keys.length && isOperator(_keys[0])) {
+ for (const key in nested) {
+ nested[key] = schematype.castForQueryWrapper({
+ $conditional: key,
+ val: nested[key],
+ context: ctx
+ });
+ }
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: ctx
+ });
+ }
+ continue;
+ }
+ // cast(schematype.caster ? schematype.caster.schema : schema, nested, options, context);
+ } else {
+ val[$cond] = schematype.castForQueryWrapper({
+ $conditional: $cond,
+ val: nested,
+ context: ctx
+ });
+ }
+ }
+
+ return val;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/query/castUpdate.js b/node_modules/mongoose/lib/helpers/query/castUpdate.js
new file mode 100644
index 0000000..bf60e5d
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/castUpdate.js
@@ -0,0 +1,538 @@
+'use strict';
+
+const CastError = require('../../error/cast');
+const MongooseError = require('../../error/mongooseError');
+const StrictModeError = require('../../error/strict');
+const ValidationError = require('../../error/validation');
+const castNumber = require('../../cast/number');
+const cast = require('../../cast');
+const getEmbeddedDiscriminatorPath = require('./getEmbeddedDiscriminatorPath');
+const handleImmutable = require('./handleImmutable');
+const moveImmutableProperties = require('../update/moveImmutableProperties');
+const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
+const utils = require('../../utils');
+
+/*!
+ * Casts an update op based on the given schema
+ *
+ * @param {Schema} schema
+ * @param {Object} obj
+ * @param {Object} options
+ * @param {Boolean} [options.overwrite] defaults to false
+ * @param {Boolean|String} [options.strict] defaults to true
+ * @param {Query} context passed to setters
+ * @return {Boolean} true iff the update is non-empty
+ */
+
+module.exports = function castUpdate(schema, obj, options, context, filter) {
+ if (obj == null) {
+ return undefined;
+ }
+ options = options || {};
+
+ // Update pipeline
+ if (Array.isArray(obj)) {
+ const len = obj.length;
+ for (let i = 0; i < len; ++i) {
+ const ops = Object.keys(obj[i]);
+ for (const op of ops) {
+ obj[i][op] = castPipelineOperator(op, obj[i][op]);
+ }
+ }
+ return obj;
+ }
+
+ if (options.upsert) {
+ moveImmutableProperties(schema, obj, context);
+ }
+
+ const ops = Object.keys(obj);
+ let i = ops.length;
+ const ret = {};
+ let val;
+ let hasDollarKey = false;
+ const overwrite = options.overwrite;
+
+ filter = filter || {};
+
+ while (i--) {
+ const op = ops[i];
+ // if overwrite is set, don't do any of the special $set stuff
+ if (op[0] !== '$' && !overwrite) {
+ // fix up $set sugar
+ if (!ret.$set) {
+ if (obj.$set) {
+ ret.$set = obj.$set;
+ } else {
+ ret.$set = {};
+ }
+ }
+ ret.$set[op] = obj[op];
+ ops.splice(i, 1);
+ if (!~ops.indexOf('$set')) ops.push('$set');
+ } else if (op === '$set') {
+ if (!ret.$set) {
+ ret[op] = obj[op];
+ }
+ } else {
+ ret[op] = obj[op];
+ }
+ }
+
+ // cast each value
+ i = ops.length;
+
+ while (i--) {
+ const op = ops[i];
+ val = ret[op];
+ hasDollarKey = hasDollarKey || op.startsWith('$');
+
+ if (val &&
+ typeof val === 'object' &&
+ !Buffer.isBuffer(val) &&
+ (!overwrite || hasDollarKey)) {
+ walkUpdatePath(schema, val, op, options, context, filter);
+ } else if (overwrite && ret && typeof ret === 'object') {
+ walkUpdatePath(schema, ret, '$set', options, context, filter);
+ } else {
+ const msg = 'Invalid atomic update value for ' + op + '. '
+ + 'Expected an object, received ' + typeof val;
+ throw new Error(msg);
+ }
+
+ if (op.startsWith('$') && utils.isEmptyObject(val)) {
+ delete ret[op];
+ }
+ }
+
+ 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;
+};
+
+/*!
+ * ignore
+ */
+
+function castPipelineOperator(op, val) {
+ if (op === '$unset') {
+ if (!Array.isArray(val) || val.find(v => typeof v !== 'string')) {
+ throw new MongooseError('Invalid $unset in pipeline, must be ' +
+ 'an array of strings');
+ }
+ return val;
+ }
+ if (op === '$project') {
+ if (val == null || typeof val !== 'object') {
+ throw new MongooseError('Invalid $project in pipeline, must be an object');
+ }
+ return val;
+ }
+ if (op === '$addFields' || op === '$set') {
+ if (val == null || typeof val !== 'object') {
+ throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
+ }
+ return val;
+ } else if (op === '$replaceRoot' || op === '$replaceWith') {
+ if (val == null || typeof val !== 'object') {
+ throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
+ }
+ return val;
+ }
+
+ throw new MongooseError('Invalid update pipeline operator: "' + op + '"');
+}
+
+/*!
+ * Walk each path of obj and cast its values
+ * according to its schema.
+ *
+ * @param {Schema} schema
+ * @param {Object} obj - part of a query
+ * @param {String} op - the atomic operator ($pull, $set, etc)
+ * @param {Object} options
+ * @param {Boolean|String} [options.strict]
+ * @param {Boolean} [options.omitUndefined]
+ * @param {Query} context
+ * @param {String} pref - path prefix (internal only)
+ * @return {Bool} true if this path has keys to update
+ * @api private
+ */
+
+function walkUpdatePath(schema, obj, op, options, context, filter, pref) {
+ const strict = options.strict;
+ const prefix = pref ? pref + '.' : '';
+ const keys = Object.keys(obj);
+ let i = keys.length;
+ let hasKeys = false;
+ let schematype;
+ let key;
+ let val;
+
+ let aggregatedError = null;
+
+ let useNestedStrict;
+ if (options.useNestedStrict === undefined) {
+ useNestedStrict = schema.options.useNestedStrict;
+ } else {
+ useNestedStrict = options.useNestedStrict;
+ }
+
+ while (i--) {
+ key = keys[i];
+ val = obj[key];
+
+ // `$pull` is special because we need to cast the RHS as a query, not as
+ // an update.
+ if (op === '$pull') {
+ schematype = schema._getSchema(prefix + key);
+ if (schematype != null && schematype.schema != null) {
+ obj[key] = cast(schematype.schema, obj[key], options, context);
+ hasKeys = true;
+ continue;
+ }
+ }
+
+ if (val && val.constructor.name === 'Object') {
+ // watch for embedded doc schemas
+ schematype = schema._getSchema(prefix + key);
+
+ if (op !== '$setOnInsert' &&
+ handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
+ continue;
+ }
+
+ if (schematype && schematype.caster && op in castOps) {
+ // embedded doc schema
+ if ('$each' in val) {
+ hasKeys = true;
+ try {
+ obj[key] = {
+ $each: castUpdateVal(schematype, val.$each, op, key, context, prefix + key)
+ };
+ } catch (error) {
+ aggregatedError = _handleCastError(error, context, key, aggregatedError);
+ }
+
+ if (val.$slice != null) {
+ obj[key].$slice = val.$slice | 0;
+ }
+
+ if (val.$sort) {
+ obj[key].$sort = val.$sort;
+ }
+
+ if (val.$position != null) {
+ obj[key].$position = castNumber(val.$position);
+ }
+ } else {
+ if (schematype != null && schematype.$isSingleNested) {
+ // Special case to make sure `strict` bubbles down correctly to
+ // single nested re: gh-8735
+ let _strict = strict;
+ if (useNestedStrict !== false && schematype.schema.options.hasOwnProperty('strict')) {
+ _strict = schematype.schema.options.strict;
+ } else if (useNestedStrict === false) {
+ _strict = schema.options.strict;
+ }
+ try {
+ obj[key] = schematype.castForQuery(val, context, { strict: _strict });
+ } catch (error) {
+ aggregatedError = _handleCastError(error, context, key, aggregatedError);
+ }
+ } else {
+ try {
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
+ } catch (error) {
+ aggregatedError = _handleCastError(error, context, key, aggregatedError);
+ }
+ }
+
+ if (options.omitUndefined && obj[key] === void 0) {
+ delete obj[key];
+ continue;
+ }
+
+ hasKeys = true;
+ }
+ } else if ((op === '$currentDate') || (op in castOps && schematype)) {
+ // $currentDate can take an object
+ try {
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
+ } catch (error) {
+ aggregatedError = _handleCastError(error, context, key, aggregatedError);
+ }
+
+ if (options.omitUndefined && obj[key] === void 0) {
+ delete obj[key];
+ continue;
+ }
+
+ hasKeys = true;
+ } else {
+ const pathToCheck = (prefix + key);
+ const v = schema._getPathType(pathToCheck);
+ let _strict = strict;
+ if (useNestedStrict &&
+ v &&
+ v.schema &&
+ 'strict' in v.schema.options) {
+ _strict = v.schema.options.strict;
+ }
+
+ if (v.pathType === 'undefined') {
+ if (_strict === 'throw') {
+ throw new StrictModeError(pathToCheck);
+ } else if (_strict) {
+ delete obj[key];
+ continue;
+ }
+ }
+
+ // gh-2314
+ // we should be able to set a schema-less field
+ // to an empty object literal
+ hasKeys |= walkUpdatePath(schema, val, op, options, context, filter, prefix + key) ||
+ (utils.isObject(val) && Object.keys(val).length === 0);
+ }
+ } else {
+ const checkPath = (key === '$each' || key === '$or' || key === '$and' || key === '$in') ?
+ pref : prefix + key;
+ schematype = schema._getSchema(checkPath);
+
+ // You can use `$setOnInsert` with immutable keys
+ if (op !== '$setOnInsert' &&
+ handleImmutable(schematype, strict, obj, key, prefix + key, context)) {
+ continue;
+ }
+
+ let pathDetails = schema._getPathType(checkPath);
+
+ // 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);
+ if (_res.schematype != null) {
+ schematype = _res.schematype;
+ pathDetails = _res.type;
+ }
+ }
+
+ let isStrict = strict;
+ if (useNestedStrict &&
+ pathDetails &&
+ pathDetails.schema &&
+ 'strict' in pathDetails.schema.options) {
+ isStrict = pathDetails.schema.options.strict;
+ }
+
+ const skip = isStrict &&
+ !schematype &&
+ !/real|nested/.test(pathDetails.pathType);
+
+ if (skip) {
+ // Even if strict is `throw`, avoid throwing an error because of
+ // virtuals because of #6731
+ if (isStrict === 'throw' && schema.virtuals[checkPath] == null) {
+ throw new StrictModeError(prefix + key);
+ } else {
+ delete obj[key];
+ }
+ } else {
+ // gh-1845 temporary fix: ignore $rename. See gh-3027 for tracking
+ // improving this.
+ if (op === '$rename') {
+ hasKeys = true;
+ continue;
+ }
+
+ try {
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
+ } catch (error) {
+ aggregatedError = _handleCastError(error, context, key, aggregatedError);
+ }
+
+ if (Array.isArray(obj[key]) && (op === '$addToSet' || op === '$push') && key !== '$each') {
+ if (schematype && schematype.caster && !schematype.caster.$isMongooseArray) {
+ obj[key] = { $each: obj[key] };
+ }
+ }
+
+ if (options.omitUndefined && obj[key] === void 0) {
+ delete obj[key];
+ continue;
+ }
+
+ hasKeys = true;
+ }
+ }
+ }
+
+ if (aggregatedError != null) {
+ throw aggregatedError;
+ }
+
+ return hasKeys;
+}
+
+/*!
+ * ignore
+ */
+
+function _handleCastError(error, query, key, aggregatedError) {
+ if (typeof query !== 'object' || !query.options.multipleCastError) {
+ throw error;
+ }
+ aggregatedError = aggregatedError || new ValidationError();
+ aggregatedError.addError(key, error);
+ return aggregatedError;
+}
+
+/*!
+ * These operators should be cast to numbers instead
+ * of their path schema type.
+ */
+
+const numberOps = {
+ $pop: 1,
+ $inc: 1
+};
+
+/*!
+ * These ops require no casting because the RHS doesn't do anything.
+ */
+
+const noCastOps = {
+ $unset: 1
+};
+
+/*!
+ * These operators require casting docs
+ * to real Documents for Update operations.
+ */
+
+const castOps = {
+ $push: 1,
+ $addToSet: 1,
+ $set: 1,
+ $setOnInsert: 1
+};
+
+/*!
+ * ignore
+ */
+
+const overwriteOps = {
+ $set: 1,
+ $setOnInsert: 1
+};
+
+/*!
+ * Casts `val` according to `schema` and atomic `op`.
+ *
+ * @param {SchemaType} schema
+ * @param {Object} val
+ * @param {String} op - the atomic operator ($pull, $set, etc)
+ * @param {String} $conditional
+ * @param {Query} context
+ * @api private
+ */
+
+function castUpdateVal(schema, val, op, $conditional, context, path) {
+ if (!schema) {
+ // non-existing schema path
+ if (op in numberOps) {
+ try {
+ return castNumber(val);
+ } catch (err) {
+ throw new CastError('number', val, path);
+ }
+ }
+ return val;
+ }
+
+ const cond = schema.caster && op in castOps &&
+ (utils.isObject(val) || Array.isArray(val));
+ if (cond && !overwriteOps[op]) {
+ // Cast values for ops that add data to MongoDB.
+ // Ensures embedded documents get ObjectIds etc.
+ let schemaArrayDepth = 0;
+ let cur = schema;
+ while (cur.$isMongooseArray) {
+ ++schemaArrayDepth;
+ cur = cur.caster;
+ }
+ let arrayDepth = 0;
+ let _val = val;
+ while (Array.isArray(_val)) {
+ ++arrayDepth;
+ _val = _val[0];
+ }
+
+ const additionalNesting = schemaArrayDepth - arrayDepth;
+ while (arrayDepth < schemaArrayDepth) {
+ val = [val];
+ ++arrayDepth;
+ }
+
+ let tmp = schema.applySetters(Array.isArray(val) ? val : [val], context);
+
+ for (let i = 0; i < additionalNesting; ++i) {
+ tmp = tmp[0];
+ }
+ return tmp;
+ }
+
+ if (op in noCastOps) {
+ return val;
+ }
+ if (op in numberOps) {
+ // Null and undefined not allowed for $pop, $inc
+ if (val == null) {
+ throw new CastError('number', val, schema.path);
+ }
+ if (op === '$inc') {
+ // Support `$inc` with long, int32, etc. (gh-4283)
+ return schema.castForQueryWrapper({
+ val: val,
+ context: context
+ });
+ }
+ try {
+ return castNumber(val);
+ } catch (error) {
+ throw new CastError('number', val, schema.path);
+ }
+ }
+ if (op === '$currentDate') {
+ if (typeof val === 'object') {
+ return { $type: val.$type };
+ }
+ return Boolean(val);
+ }
+
+ if (/^\$/.test($conditional)) {
+ return schema.castForQueryWrapper({
+ $conditional: $conditional,
+ val: val,
+ context: context
+ });
+ }
+
+ if (overwriteOps[op]) {
+ return schema.castForQueryWrapper({
+ val: val,
+ context: context,
+ $skipQueryCastForUpdate: val != null && schema.$isMongooseArray && schema.$fullPath != null && !schema.$fullPath.match(/\d+$/),
+ $applySetters: schema[schemaMixedSymbol] != null
+ });
+ }
+
+ return schema.castForQueryWrapper({ val: val, context: context });
+}
diff --git a/node_modules/mongoose/lib/helpers/query/completeMany.js b/node_modules/mongoose/lib/helpers/query/completeMany.js
new file mode 100644
index 0000000..aabe596
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/completeMany.js
@@ -0,0 +1,47 @@
+'use strict';
+
+const helpers = require('../../queryhelpers');
+
+module.exports = completeMany;
+
+/*!
+ * Given a model and an array of docs, hydrates all the docs to be instances
+ * of the model. Used to initialize docs returned from the db from `find()`
+ *
+ * @param {Model} model
+ * @param {Array} docs
+ * @param {Object} fields the projection used, including `select` from schemas
+ * @param {Object} userProvidedFields the user-specified projection
+ * @param {Object} opts
+ * @param {Array} [opts.populated]
+ * @param {ClientSession} [opts.session]
+ * @param {Function} callback
+ */
+
+function completeMany(model, docs, fields, userProvidedFields, opts, callback) {
+ const arr = [];
+ let count = docs.length;
+ const len = count;
+ let error = null;
+
+ function init(_error) {
+ if (_error != null) {
+ error = error || _error;
+ }
+ if (error != null) {
+ --count || process.nextTick(() => callback(error));
+ return;
+ }
+ --count || process.nextTick(() => callback(error, arr));
+ }
+
+ for (let i = 0; i < len; ++i) {
+ arr[i] = helpers.createModel(model, docs[i], fields, userProvidedFields);
+ try {
+ arr[i].init(docs[i], opts, init);
+ } catch (error) {
+ init(error);
+ }
+ arr[i].$session(opts.session);
+ }
+}
diff --git a/node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js b/node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js
new file mode 100644
index 0000000..395ea75
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/getEmbeddedDiscriminatorPath.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
+const get = require('../get');
+const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
+
+/*!
+ * 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) {
+ const parts = path.split('.');
+ let schematype = null;
+ let type = 'adhocOrUndefined';
+
+ filter = filter || {};
+ update = update || {};
+
+ for (let i = 0; i < parts.length; ++i) {
+ const subpath = cleanPositionalOperators(parts.slice(0, i + 1).join('.'));
+ schematype = schema.path(subpath);
+ if (schematype == null) {
+ continue;
+ }
+
+ type = schema.pathType(subpath);
+ if ((schematype.$isSingleNested || schematype.$isMongooseDocumentArrayElement) &&
+ schematype.schema.discriminators != null) {
+ const key = get(schematype, 'schema.options.discriminatorKey');
+ const discriminatorValuePath = subpath + '.' + key;
+ const discriminatorFilterPath =
+ discriminatorValuePath.replace(/\.\d+\./, '.');
+ let discriminatorKey = null;
+
+ if (discriminatorValuePath in filter) {
+ discriminatorKey = filter[discriminatorValuePath];
+ }
+ if (discriminatorFilterPath in filter) {
+ discriminatorKey = filter[discriminatorFilterPath];
+ }
+ const wrapperPath = subpath.replace(/\.\d+$/, '');
+ if (schematype.$isMongooseDocumentArrayElement &&
+ get(filter[wrapperPath], '$elemMatch.' + key) != null) {
+ discriminatorKey = filter[wrapperPath].$elemMatch[key];
+ }
+
+ if (discriminatorValuePath in update) {
+ discriminatorKey = update[discriminatorValuePath];
+ }
+
+ if (discriminatorKey == null) {
+ continue;
+ }
+
+ const discriminatorSchema = getDiscriminatorByValue(schematype.caster, discriminatorKey).schema;
+
+ const rest = parts.slice(i + 1).join('.');
+ schematype = discriminatorSchema.path(rest);
+ if (schematype != null) {
+ type = discriminatorSchema._getPathType(rest);
+ break;
+ }
+ }
+ }
+
+ return { type: type, schematype: schematype };
+};
diff --git a/node_modules/mongoose/lib/helpers/query/handleImmutable.js b/node_modules/mongoose/lib/helpers/query/handleImmutable.js
new file mode 100644
index 0000000..22adb3c
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/handleImmutable.js
@@ -0,0 +1,28 @@
+'use strict';
+
+const StrictModeError = require('../../error/strict');
+
+module.exports = function handleImmutable(schematype, strict, obj, key, fullPath, ctx) {
+ if (schematype == null || !schematype.options || !schematype.options.immutable) {
+ return false;
+ }
+ let immutable = schematype.options.immutable;
+
+ if (typeof immutable === 'function') {
+ immutable = immutable.call(ctx, ctx);
+ }
+ if (!immutable) {
+ return false;
+ }
+
+ if (strict === false) {
+ return false;
+ }
+ if (strict === 'throw') {
+ throw new StrictModeError(null,
+ `Field ${fullPath} is immutable and strict = 'throw'`);
+ }
+
+ delete obj[key];
+ return true;
+};
diff --git a/node_modules/mongoose/lib/helpers/query/hasDollarKeys.js b/node_modules/mongoose/lib/helpers/query/hasDollarKeys.js
new file mode 100644
index 0000000..958e1c9
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/hasDollarKeys.js
@@ -0,0 +1,19 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function(obj) {
+ if (obj == null) {
+ return false;
+ }
+ const keys = Object.keys(obj);
+ const len = keys.length;
+ for (let i = 0; i < len; ++i) {
+ if (keys[i].startsWith('$')) {
+ return true;
+ }
+ }
+ return false;
+};
diff --git a/node_modules/mongoose/lib/helpers/query/isOperator.js b/node_modules/mongoose/lib/helpers/query/isOperator.js
new file mode 100644
index 0000000..3b98139
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/isOperator.js
@@ -0,0 +1,11 @@
+'use strict';
+
+const specialKeys = new Set([
+ '$ref',
+ '$id',
+ '$db'
+]);
+
+module.exports = function isOperator(path) {
+ return path.startsWith('$') && !specialKeys.has(path);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js b/node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js
new file mode 100644
index 0000000..0653f18
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/selectPopulatedFields.js
@@ -0,0 +1,46 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function selectPopulatedFields(query) {
+ const opts = query._mongooseOptions;
+
+ 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];
+ }
+ }
+ } else if (query.selectedExclusively()) {
+ for (const path of paths) {
+ if (userProvidedFields[path] == null) {
+ delete query._fields[path];
+ }
+ }
+ }
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function isPathInFields(userProvidedFields, path) {
+ const pieces = path.split('.');
+ const len = pieces.length;
+ let cur = pieces[0];
+ for (let i = 1; i < len; ++i) {
+ if (userProvidedFields[cur] != null) {
+ return true;
+ }
+ cur += '.' + pieces[i];
+ }
+ return userProvidedFields[cur] != null;
+}
diff --git a/node_modules/mongoose/lib/helpers/query/wrapThunk.js b/node_modules/mongoose/lib/helpers/query/wrapThunk.js
new file mode 100644
index 0000000..0005c33
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/query/wrapThunk.js
@@ -0,0 +1,18 @@
+'use strict';
+
+/*!
+ * A query thunk is the function responsible for sending the query to MongoDB,
+ * like `Query#_findOne()` or `Query#_execUpdate()`. The `Query#exec()` function
+ * calls a thunk. The term "thunk" here is the traditional Node.js definition:
+ * a function that takes exactly 1 parameter, a callback.
+ *
+ * This function defines common behavior for all query thunks.
+ */
+
+module.exports = function wrapThunk(fn) {
+ return function _wrappedThunk(cb) {
+ ++this._executionCount;
+
+ fn.call(this, cb);
+ };
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/addAutoId.js b/node_modules/mongoose/lib/helpers/schema/addAutoId.js
new file mode 100644
index 0000000..11a1f23
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/addAutoId.js
@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = function addAutoId(schema) {
+ const _obj = { _id: { auto: true } };
+ _obj._id[schema.options.typeKey] = 'ObjectId';
+ schema.add(_obj);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/applyPlugins.js b/node_modules/mongoose/lib/helpers/schema/applyPlugins.js
new file mode 100644
index 0000000..f1daf40
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/applyPlugins.js
@@ -0,0 +1,44 @@
+'use strict';
+
+module.exports = function applyPlugins(schema, plugins, options, cacheKey) {
+ if (schema[cacheKey]) {
+ return;
+ }
+ schema[cacheKey] = true;
+
+ if (!options || !options.skipTopLevel) {
+ for (const plugin of plugins) {
+ schema.plugin(plugin[0], plugin[1]);
+ }
+ }
+
+ options = Object.assign({}, options);
+ delete options.skipTopLevel;
+
+ if (options.applyPluginsToChildSchemas !== false) {
+ for (const path of Object.keys(schema.paths)) {
+ const type = schema.paths[path];
+ if (type.schema != null) {
+ applyPlugins(type.schema, plugins, options, cacheKey);
+
+ // Recompile schema because plugins may have changed it, see gh-7572
+ type.caster.prototype.$__setSchema(type.schema);
+ }
+ }
+ }
+
+ const discriminators = schema.discriminators;
+ if (discriminators == null) {
+ return;
+ }
+
+ const applyPluginsToDiscriminators = options.applyPluginsToDiscriminators;
+
+ const keys = Object.keys(discriminators);
+ for (const discriminatorKey of keys) {
+ const discriminatorSchema = discriminators[discriminatorKey];
+
+ applyPlugins(discriminatorSchema, plugins,
+ { skipTopLevel: !applyPluginsToDiscriminators }, cacheKey);
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js b/node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js
new file mode 100644
index 0000000..168156d
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/applyWriteConcern.js
@@ -0,0 +1,16 @@
+'use strict';
+
+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 (!('j' in options) && writeConcern.j != null) {
+ options.j = writeConcern.j;
+ }
+ if (!('wtimeout' in options) && writeConcern.wtimeout != null) {
+ options.wtimeout = writeConcern.wtimeout;
+ }
+};
diff --git a/node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js b/node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js
new file mode 100644
index 0000000..b467be4
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/cleanPositionalOperators.js
@@ -0,0 +1,12 @@
+'use strict';
+
+/**
+ * For consistency's sake, we replace positional operator `$` and array filters
+ * `$[]` and `$[foo]` with `0` when looking up schema paths.
+ */
+
+module.exports = function cleanPositionalOperators(path) {
+ return path.
+ replace(/\.\$(\[[^\]]*\])?\./g, '.0.').
+ replace(/\.(\[[^\]]*\])?\$$/g, '.0');
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/getIndexes.js b/node_modules/mongoose/lib/helpers/schema/getIndexes.js
new file mode 100644
index 0000000..be907db
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/getIndexes.js
@@ -0,0 +1,155 @@
+'use strict';
+
+const get = require('../get');
+const helperIsObject = require('../isObject');
+
+/*!
+ * Gather all indexes defined in the schema, including single nested,
+ * document arrays, and embedded discriminators.
+ */
+
+module.exports = function getIndexes(schema) {
+ let indexes = [];
+ const schemaStack = new WeakMap();
+ const indexTypes = schema.constructor.indexTypes;
+ const indexByName = new Map();
+
+ collectIndexes(schema);
+ return indexes;
+
+ function collectIndexes(schema, prefix, baseSchema) {
+ // Ignore infinitely nested schemas, if we've already seen this schema
+ // along this path there must be a cycle
+ if (schemaStack.has(schema)) {
+ return;
+ }
+ schemaStack.set(schema, true);
+
+ prefix = prefix || '';
+ const keys = Object.keys(schema.paths);
+
+ for (const key of keys) {
+ const path = schema.paths[key];
+ if (baseSchema != null && baseSchema.paths[key]) {
+ // If looking at an embedded discriminator schema, don't look at paths
+ // that the
+ continue;
+ }
+
+ if (path.$isMongooseDocumentArray || path.$isSingleNested) {
+ if (get(path, 'options.excludeIndexes') !== true &&
+ get(path, 'schemaOptions.excludeIndexes') !== true &&
+ get(path, 'schema.options.excludeIndexes') !== true) {
+ collectIndexes(path.schema, prefix + key + '.');
+ }
+
+ if (path.schema.discriminators != null) {
+ const discriminators = path.schema.discriminators;
+ const discriminatorKeys = Object.keys(discriminators);
+ for (const discriminatorKey of discriminatorKeys) {
+ collectIndexes(discriminators[discriminatorKey],
+ prefix + key + '.', path.schema);
+ }
+ }
+
+ // Retained to minimize risk of backwards breaking changes due to
+ // gh-6113
+ if (path.$isMongooseDocumentArray) {
+ continue;
+ }
+ }
+
+ const index = path._index || (path.caster && path.caster._index);
+
+ if (index !== false && index !== null && index !== undefined) {
+ const field = {};
+ const isObject = helperIsObject(index);
+ const options = isObject ? index : {};
+ const type = typeof index === 'string' ? index :
+ isObject ? index.type :
+ false;
+
+ if (type && indexTypes.indexOf(type) !== -1) {
+ field[prefix + key] = type;
+ } else if (options.text) {
+ field[prefix + key] = 'text';
+ delete options.text;
+ } else {
+ const isDescendingIndex = Number(index) === -1;
+ field[prefix + key] = isDescendingIndex ? -1 : 1;
+ }
+
+ delete options.type;
+ if (!('background' in options)) {
+ options.background = true;
+ }
+ if (schema.options.autoIndex != null) {
+ options._autoIndex = schema.options.autoIndex;
+ }
+
+ const indexName = options && options.name;
+ if (typeof indexName === 'string') {
+ if (indexByName.has(indexName)) {
+ Object.assign(indexByName.get(indexName), field);
+ } else {
+ indexes.push([field, options]);
+ indexByName.set(indexName, field);
+ }
+ } else {
+ indexes.push([field, options]);
+ indexByName.set(indexName, field);
+ }
+ }
+ }
+
+ schemaStack.delete(schema);
+
+ if (prefix) {
+ fixSubIndexPaths(schema, prefix);
+ } else {
+ schema._indexes.forEach(function(index) {
+ if (!('background' in index[1])) {
+ index[1].background = true;
+ }
+ });
+ indexes = indexes.concat(schema._indexes);
+ }
+ }
+
+ /*!
+ * Checks for indexes added to subdocs using Schema.index().
+ * These indexes need their paths prefixed properly.
+ *
+ * schema._indexes = [ [indexObj, options], [indexObj, options] ..]
+ */
+
+ function fixSubIndexPaths(schema, prefix) {
+ const subindexes = schema._indexes;
+ const len = subindexes.length;
+ for (let i = 0; i < len; ++i) {
+ const indexObj = subindexes[i][0];
+ const indexOptions = subindexes[i][1];
+ const keys = Object.keys(indexObj);
+ const klen = keys.length;
+ const newindex = {};
+
+ // use forward iteration, order matters
+ for (let j = 0; j < klen; ++j) {
+ const key = keys[j];
+ newindex[prefix + key] = indexObj[key];
+ }
+
+ const newIndexOptions = Object.assign({}, indexOptions);
+ if (indexOptions != null && indexOptions.partialFilterExpression != null) {
+ newIndexOptions.partialFilterExpression = {};
+ const partialFilterExpression = indexOptions.partialFilterExpression;
+ for (const key of Object.keys(partialFilterExpression)) {
+ newIndexOptions.partialFilterExpression[prefix + key] =
+ partialFilterExpression[key];
+ }
+ }
+
+ indexes.push([newindex, newIndexOptions]);
+ }
+ }
+};
diff --git a/node_modules/mongoose/lib/helpers/schema/getPath.js b/node_modules/mongoose/lib/helpers/schema/getPath.js
new file mode 100644
index 0000000..ccbc67c
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/getPath.js
@@ -0,0 +1,35 @@
+'use strict';
+
+/*!
+ * Behaves like `Schema#path()`, except for it also digs into arrays without
+ * needing to put `.0.`, so `getPath(schema, 'docArr.elProp')` works.
+ */
+
+module.exports = function getPath(schema, path) {
+ let schematype = schema.path(path);
+ if (schematype != null) {
+ return schematype;
+ }
+
+ const pieces = path.split('.');
+ let cur = '';
+ let isArray = false;
+
+ for (const piece of pieces) {
+ if (/^\d+$/.test(piece) && isArray) {
+ continue;
+ }
+ cur = cur.length === 0 ? piece : cur + '.' + piece;
+
+ schematype = schema.path(cur);
+ if (schematype != null && schematype.schema) {
+ schema = schematype.schema;
+ cur = '';
+ if (schematype.$isMongooseDocumentArray) {
+ isArray = true;
+ }
+ }
+ }
+
+ return schematype;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/handleIdOption.js b/node_modules/mongoose/lib/helpers/schema/handleIdOption.js
new file mode 100644
index 0000000..569bf9f
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/handleIdOption.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const addAutoId = require('./addAutoId');
+
+module.exports = function handleIdOption(schema, options) {
+ if (options == null || options._id == null) {
+ return schema;
+ }
+
+ schema = schema.clone();
+ if (!options._id) {
+ schema.remove('_id');
+ schema.options._id = false;
+ } else if (!schema.paths['_id']) {
+ addAutoId(schema);
+ schema.options._id = true;
+ }
+
+ return schema;
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/handleTimestampOption.js b/node_modules/mongoose/lib/helpers/schema/handleTimestampOption.js
new file mode 100644
index 0000000..1551b7c
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/handleTimestampOption.js
@@ -0,0 +1,24 @@
+'use strict';
+
+module.exports = handleTimestampOption;
+
+/*!
+ * ignore
+ */
+
+function handleTimestampOption(arg, prop) {
+ if (arg == null) {
+ return null;
+ }
+
+ if (typeof arg === 'boolean') {
+ return prop;
+ }
+ if (typeof arg[prop] === 'boolean') {
+ return arg[prop] ? prop : null;
+ }
+ if (!(prop in arg)) {
+ return prop;
+ }
+ return arg[prop];
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/schema/merge.js b/node_modules/mongoose/lib/helpers/schema/merge.js
new file mode 100644
index 0000000..d206500
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schema/merge.js
@@ -0,0 +1,19 @@
+'use strict';
+
+module.exports = function merge(s1, s2) {
+ s1.add(s2.tree || {});
+
+ s1.callQueue = s1.callQueue.concat(s2.callQueue);
+ s1.method(s2.methods);
+ s1.static(s2.statics);
+
+ for (const query in s2.query) {
+ s1.query[query] = s2.query[query];
+ }
+
+ for (const virtual in s2.virtuals) {
+ s1.virtuals[virtual] = s2.virtuals[virtual].clone();
+ }
+
+ s1.s.hooks.merge(s2.s.hooks, false);
+};
diff --git a/node_modules/mongoose/lib/helpers/schematype/handleImmutable.js b/node_modules/mongoose/lib/helpers/schematype/handleImmutable.js
new file mode 100644
index 0000000..e31c4af
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/schematype/handleImmutable.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const StrictModeError = require('../../error/strict');
+
+/*!
+ * ignore
+ */
+
+module.exports = function(schematype) {
+ if (schematype.$immutable) {
+ schematype.$immutableSetter = createImmutableSetter(schematype.path,
+ schematype.options.immutable);
+ schematype.set(schematype.$immutableSetter);
+ } else if (schematype.$immutableSetter) {
+ schematype.setters = schematype.setters.
+ filter(fn => fn !== schematype.$immutableSetter);
+ delete schematype.$immutableSetter;
+ }
+};
+
+function createImmutableSetter(path, immutable) {
+ return function immutableSetter(v) {
+ if (this == null || this.$__ == null) {
+ return v;
+ }
+ if (this.isNew) {
+ return v;
+ }
+
+ const _immutable = typeof immutable === 'function' ?
+ immutable.call(this, this) :
+ immutable;
+ if (!_immutable) {
+ return v;
+ }
+
+ 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 _value;
+ };
+}
diff --git a/node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js b/node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js
new file mode 100644
index 0000000..14e3f1b
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/setDefaultsOnInsert.js
@@ -0,0 +1,127 @@
+'use strict';
+const modifiedPaths = require('./common').modifiedPaths;
+const get = require('./get');
+
+/**
+ * Applies defaults to update and findOneAndUpdate operations.
+ *
+ * @param {Object} filter
+ * @param {Schema} schema
+ * @param {Object} castedDoc
+ * @param {Object} options
+ * @method setDefaultsOnInsert
+ * @api private
+ */
+
+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 = {};
+ const numKeys = keys.length;
+ const modified = {};
+
+ let hasDollarUpdate = false;
+
+ for (let i = 0; i < numKeys; ++i) {
+ if (keys[i].startsWith('$')) {
+ modifiedPaths(castedDoc[keys[i]], '', modified);
+ hasDollarUpdate = true;
+ }
+ }
+
+ if (!hasDollarUpdate) {
+ modifiedPaths(castedDoc, '', modified);
+ }
+
+ const paths = Object.keys(filter);
+ const numPaths = paths.length;
+ for (let i = 0; i < numPaths; ++i) {
+ const path = paths[i];
+ const condition = filter[path];
+ if (condition && typeof condition === 'object') {
+ const conditionKeys = Object.keys(condition);
+ const numConditionKeys = conditionKeys.length;
+ let hasDollarKey = false;
+ for (let j = 0; j < numConditionKeys; ++j) {
+ if (conditionKeys[j].startsWith('$')) {
+ hasDollarKey = true;
+ break;
+ }
+ }
+ if (hasDollarKey) {
+ continue;
+ }
+ }
+ updatedKeys[path] = true;
+ modified[path] = true;
+ }
+
+ if (options && options.overwrite && !hasDollarUpdate) {
+ // Defaults will be set later, since we're overwriting we'll cast
+ // the whole update to a document
+ return castedDoc;
+ }
+
+ schema.eachPath(function(path, schemaType) {
+ // Skip single nested paths if underneath a map
+ const isUnderneathMap = schemaType.path.endsWith('.$*') ||
+ schemaType.path.indexOf('.$*.') !== -1;
+ if (schemaType.$isSingleNested && !isUnderneathMap) {
+ // Only handle nested schemas 1-level deep to avoid infinite
+ // recursion re: https://github.com/mongodb-js/mongoose-autopopulate/issues/11
+ schemaType.schema.eachPath(function(_path, _schemaType) {
+ if (_path === '_id' && _schemaType.auto) {
+ // Ignore _id if auto id so we don't create subdocs
+ return;
+ }
+
+ const def = _schemaType.getDefault(null, true);
+ if (!isModified(modified, path + '.' + _path) &&
+ typeof def !== 'undefined') {
+ castedDoc = castedDoc || {};
+ castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
+ castedDoc.$setOnInsert[path + '.' + _path] = def;
+ updatedValues[path + '.' + _path] = def;
+ }
+ });
+ } else {
+ const def = schemaType.getDefault(null, true);
+ if (!isModified(modified, path) && typeof def !== 'undefined') {
+ castedDoc = castedDoc || {};
+ castedDoc.$setOnInsert = castedDoc.$setOnInsert || {};
+ if (get(castedDoc, path) == null) {
+ castedDoc.$setOnInsert[path] = def;
+ }
+ updatedValues[path] = def;
+ }
+ }
+ });
+
+ return castedDoc;
+};
+
+function isModified(modified, path) {
+ if (modified[path]) {
+ return true;
+ }
+ const sp = path.split('.');
+ let cur = sp[0];
+ for (let i = 1; i < sp.length; ++i) {
+ if (modified[cur]) {
+ return true;
+ }
+ cur += '.' + sp[i];
+ }
+ return false;
+}
diff --git a/node_modules/mongoose/lib/helpers/specialProperties.js b/node_modules/mongoose/lib/helpers/specialProperties.js
new file mode 100644
index 0000000..1e1aca5
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/specialProperties.js
@@ -0,0 +1,3 @@
+'use strict';
+
+module.exports = new Set(['__proto__', 'constructor', 'prototype']); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/symbols.js b/node_modules/mongoose/lib/helpers/symbols.js
new file mode 100644
index 0000000..9d619f7
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/symbols.js
@@ -0,0 +1,19 @@
+'use strict';
+
+exports.arrayAtomicsSymbol = Symbol('mongoose#Array#_atomics');
+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'); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/timestamps/setupTimestamps.js b/node_modules/mongoose/lib/helpers/timestamps/setupTimestamps.js
new file mode 100644
index 0000000..752a565
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/timestamps/setupTimestamps.js
@@ -0,0 +1,104 @@
+'use strict';
+
+const applyTimestampsToChildren = require('../update/applyTimestampsToChildren');
+const applyTimestampsToUpdate = require('../update/applyTimestampsToUpdate');
+const get = require('../get');
+const handleTimestampOption = require('../schema/handleTimestampOption');
+const symbols = require('../../schema/symbols');
+
+module.exports = function setupTimestamps(schema, timestamps) {
+ const childHasTimestamp = schema.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 = {};
+
+ schema.$timestamps = { createdAt: createdAt, updatedAt: updatedAt };
+
+ if (updatedAt && !schema.paths[updatedAt]) {
+ schemaAdditions[updatedAt] = Date;
+ }
+
+ if (createdAt && !schema.paths[createdAt]) {
+ schemaAdditions[createdAt] = Date;
+ }
+
+ schema.add(schemaAdditions);
+
+ schema.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();
+ });
+
+ schema.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 };
+ schema.pre('findOneAndUpdate', opts, _setTimestampsOnUpdate);
+ schema.pre('replaceOne', opts, _setTimestampsOnUpdate);
+ schema.pre('update', opts, _setTimestampsOnUpdate);
+ schema.pre('updateOne', opts, _setTimestampsOnUpdate);
+ schema.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();
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/topology/allServersUnknown.js b/node_modules/mongoose/lib/helpers/topology/allServersUnknown.js
new file mode 100644
index 0000000..d3c7b4b
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/topology/allServersUnknown.js
@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = function allServersUnknown(topologyDescription) {
+ if (topologyDescription == null ||
+ topologyDescription.constructor.name !== 'TopologyDescription') {
+ return false;
+ }
+
+ const servers = Array.from(topologyDescription.servers.values());
+ return servers.length > 0 && servers.every(server => server.type === 'Unknown');
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/topology/isAtlas.js b/node_modules/mongoose/lib/helpers/topology/isAtlas.js
new file mode 100644
index 0000000..3bb8129
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/topology/isAtlas.js
@@ -0,0 +1,12 @@
+'use strict';
+
+module.exports = function isAtlas(topologyDescription) {
+ if (topologyDescription == null ||
+ topologyDescription.constructor.name !== 'TopologyDescription') {
+ return false;
+ }
+
+ const hostnames = Array.from(topologyDescription.servers.keys());
+ return hostnames.length > 0 &&
+ hostnames.every(host => host.endsWith('.mongodb.net:27017'));
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/topology/isSSLError.js b/node_modules/mongoose/lib/helpers/topology/isSSLError.js
new file mode 100644
index 0000000..61e57d1
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/topology/isSSLError.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const nonSSLMessage = 'Client network socket disconnected before secure TLS ' +
+ 'connection was established';
+
+module.exports = function isSSLError(topologyDescription) {
+ if (topologyDescription == null ||
+ topologyDescription.constructor.name !== 'TopologyDescription') {
+ return false;
+ }
+
+ const descriptions = Array.from(topologyDescription.servers.values());
+ return descriptions.length > 0 &&
+ descriptions.every(descr => descr.error && descr.error.message.indexOf(nonSSLMessage) !== -1);
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js b/node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js
new file mode 100644
index 0000000..680d692
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/applyTimestampsToChildren.js
@@ -0,0 +1,172 @@
+'use strict';
+
+const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
+const handleTimestampOption = require('../schema/handleTimestampOption');
+
+module.exports = applyTimestampsToChildren;
+
+/*!
+ * ignore
+ */
+
+function applyTimestampsToChildren(now, update, schema) {
+ if (update == null) {
+ return;
+ }
+
+ const keys = Object.keys(update);
+ const hasDollarKey = keys.some(key => key.startsWith('$'));
+
+ if (hasDollarKey) {
+ if (update.$push) {
+ for (const key of Object.keys(update.$push)) {
+ const $path = schema.path(key);
+ if (update.$push[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 (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;
+ }
+ }
+ }
+ }
+ }
+ if (update.$set != null) {
+ const keys = Object.keys(update.$set);
+ for (const key of keys) {
+ applyTimestampsToUpdateKey(schema, key, update.$set, now);
+ }
+ }
+ }
+
+ const updateKeys = Object.keys(update).filter(key => !key.startsWith('$'));
+ for (const key of updateKeys) {
+ applyTimestampsToUpdateKey(schema, key, update, now);
+ }
+}
+
+function applyTimestampsToDocumentArray(arr, schematype, now) {
+ const timestamps = schematype.schema.options.timestamps;
+
+ if (!timestamps) {
+ return;
+ }
+
+ const len = arr.length;
+
+ const createdAt = handleTimestampOption(timestamps, 'createdAt');
+ const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
+ for (let i = 0; i < len; ++i) {
+ if (updatedAt != null) {
+ arr[i][updatedAt] = now;
+ }
+ if (createdAt != null) {
+ arr[i][createdAt] = now;
+ }
+
+ applyTimestampsToChildren(now, arr[i], schematype.schema);
+ }
+}
+
+function applyTimestampsToSingleNested(subdoc, schematype, now) {
+ const timestamps = schematype.schema.options.timestamps;
+ if (!timestamps) {
+ return;
+ }
+
+ const createdAt = handleTimestampOption(timestamps, 'createdAt');
+ const updatedAt = handleTimestampOption(timestamps, 'updatedAt');
+ if (updatedAt != null) {
+ subdoc[updatedAt] = now;
+ }
+ if (createdAt != null) {
+ subdoc[createdAt] = 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;
+ }
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js b/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js
new file mode 100644
index 0000000..27d6e32
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/applyTimestampsToUpdate.js
@@ -0,0 +1,119 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+const get = require('../get');
+
+module.exports = applyTimestampsToUpdate;
+
+/*!
+ * ignore
+ */
+
+function applyTimestampsToUpdate(now, createdAt, updatedAt, currentUpdate, options) {
+ const updates = currentUpdate;
+ let _updates = updates;
+ const overwrite = get(options, 'overwrite', false);
+ const timestamps = get(options, 'timestamps', true);
+
+ // Support skipping timestamps at the query level, see gh-6980
+ if (!timestamps || updates == null) {
+ return currentUpdate;
+ }
+
+ const skipCreatedAt = timestamps != null && timestamps.createdAt === false;
+ const skipUpdatedAt = timestamps != null && timestamps.updatedAt === false;
+
+ if (overwrite) {
+ if (currentUpdate && currentUpdate.$set) {
+ currentUpdate = currentUpdate.$set;
+ updates.$set = {};
+ _updates = updates.$set;
+ }
+ if (!skipUpdatedAt && updatedAt && !currentUpdate[updatedAt]) {
+ _updates[updatedAt] = now;
+ }
+ if (!skipCreatedAt && createdAt && !currentUpdate[createdAt]) {
+ _updates[createdAt] = now;
+ }
+ return updates;
+ }
+ currentUpdate = currentUpdate || {};
+
+ if (Array.isArray(updates)) {
+ // Update with aggregation pipeline
+ updates.push({ $set: { updatedAt: now } });
+
+ return updates;
+ }
+
+ updates.$set = updates.$set || {};
+ if (!skipUpdatedAt && updatedAt &&
+ (!currentUpdate.$currentDate || !currentUpdate.$currentDate[updatedAt])) {
+ let timestampSet = false;
+ if (updatedAt.indexOf('.') !== -1) {
+ const pieces = updatedAt.split('.');
+ for (let i = 1; i < pieces.length; ++i) {
+ const remnant = pieces.slice(-i).join('.');
+ const start = pieces.slice(0, -i).join('.');
+ if (currentUpdate[start] != null) {
+ currentUpdate[start][remnant] = now;
+ timestampSet = true;
+ break;
+ } else if (currentUpdate.$set && currentUpdate.$set[start]) {
+ currentUpdate.$set[start][remnant] = now;
+ timestampSet = true;
+ break;
+ }
+ }
+ }
+
+ if (!timestampSet) {
+ updates.$set[updatedAt] = now;
+ }
+
+ if (updates.hasOwnProperty(updatedAt)) {
+ delete updates[updatedAt];
+ }
+ }
+
+ if (!skipCreatedAt && createdAt) {
+ if (currentUpdate[createdAt]) {
+ delete currentUpdate[createdAt];
+ }
+ if (currentUpdate.$set && currentUpdate.$set[createdAt]) {
+ delete currentUpdate.$set[createdAt];
+ }
+
+ let timestampSet = false;
+ if (createdAt.indexOf('.') !== -1) {
+ const pieces = createdAt.split('.');
+ for (let i = 1; i < pieces.length; ++i) {
+ const remnant = pieces.slice(-i).join('.');
+ const start = pieces.slice(0, -i).join('.');
+ if (currentUpdate[start] != null) {
+ currentUpdate[start][remnant] = now;
+ timestampSet = true;
+ break;
+ } else if (currentUpdate.$set && currentUpdate.$set[start]) {
+ currentUpdate.$set[start][remnant] = now;
+ timestampSet = true;
+ break;
+ }
+ }
+ }
+
+ if (!timestampSet) {
+ updates.$setOnInsert = updates.$setOnInsert || {};
+ updates.$setOnInsert[createdAt] = now;
+ }
+ }
+
+ if (Object.keys(updates.$set).length === 0) {
+ delete updates.$set;
+ }
+
+ return updates;
+}
diff --git a/node_modules/mongoose/lib/helpers/update/castArrayFilters.js b/node_modules/mongoose/lib/helpers/update/castArrayFilters.js
new file mode 100644
index 0000000..57018d9
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/castArrayFilters.js
@@ -0,0 +1,78 @@
+'use strict';
+
+const castFilterPath = require('../query/castFilterPath');
+const cleanPositionalOperators = require('../schema/cleanPositionalOperators');
+const getPath = require('../schema/getPath');
+const modifiedPaths = require('./modifiedPaths');
+
+module.exports = function castArrayFilters(query) {
+ const arrayFilters = query.options.arrayFilters;
+ if (!Array.isArray(arrayFilters)) {
+ return;
+ }
+
+ const update = query.getUpdate();
+ 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;
+ }, {});
+
+ for (const filter of arrayFilters) {
+ if (filter == null) {
+ throw new Error(`Got null array filter in ${arrayFilters}`);
+ }
+ for (const key in filter) {
+
+ if (filter[key] == null) {
+ continue;
+ }
+
+ const dot = key.indexOf('.');
+ let filterPath = dot === -1 ?
+ updatedPathsByFilter[key] + '.0' :
+ updatedPathsByFilter[key.substr(0, dot)] + '.0' + key.substr(dot);
+
+ if (filterPath == null) {
+ throw new Error(`Filter path not found for ${key}`);
+ }
+
+ // If there are multiple array filters in the path being updated, make sure
+ // to replace them so we can get the schema path.
+ filterPath = cleanPositionalOperators(filterPath);
+
+ const schematype = getPath(schema, filterPath);
+ if (schematype == null) {
+ if (!strictQuery) {
+ return;
+ }
+ // For now, treat `strictQuery = true` and `strictQuery = 'throw'` as
+ // equivalent for casting array filters. `strictQuery = true` doesn't
+ // quite work in this context because we never want to silently strip out
+ // array filters, even if the path isn't in the schema.
+ throw new Error(`Could not find path "${filterPath}" in schema`);
+ }
+ if (typeof filter[key] === 'object') {
+ filter[key] = castFilterPath(query, schematype, filter[key]);
+ } else {
+ filter[key] = schematype.castForQuery(filter[key]);
+ }
+ }
+ }
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/update/modifiedPaths.js b/node_modules/mongoose/lib/helpers/update/modifiedPaths.js
new file mode 100644
index 0000000..9cb567d
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/modifiedPaths.js
@@ -0,0 +1,33 @@
+'use strict';
+
+const _modifiedPaths = require('../common').modifiedPaths;
+
+/**
+ * Given an update document with potential update operators (`$set`, etc.)
+ * returns an object whose keys are the directly modified paths.
+ *
+ * If there are any top-level keys that don't start with `$`, we assume those
+ * will get wrapped in a `$set`. The Mongoose Query is responsible for wrapping
+ * top-level keys in `$set`.
+ *
+ * @param {Object} update
+ * @return {Object} modified
+ */
+
+module.exports = function modifiedPaths(update) {
+ const keys = Object.keys(update);
+ const res = {};
+
+ const withoutDollarKeys = {};
+ for (const key of keys) {
+ if (key.startsWith('$')) {
+ _modifiedPaths(update[key], '', res);
+ continue;
+ }
+ withoutDollarKeys[key] = update[key];
+ }
+
+ _modifiedPaths(withoutDollarKeys, '', res);
+
+ return res;
+};
diff --git a/node_modules/mongoose/lib/helpers/update/moveImmutableProperties.js b/node_modules/mongoose/lib/helpers/update/moveImmutableProperties.js
new file mode 100644
index 0000000..8541c5b
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/moveImmutableProperties.js
@@ -0,0 +1,53 @@
+'use strict';
+
+const get = require('../get');
+
+/**
+ * Given an update, move all $set on immutable properties to $setOnInsert.
+ * This should only be called for upserts, because $setOnInsert bypasses the
+ * strictness check for immutable properties.
+ */
+
+module.exports = function moveImmutableProperties(schema, update, ctx) {
+ if (update == null) {
+ return;
+ }
+
+ const keys = Object.keys(update);
+ for (const key of keys) {
+ const isDollarKey = key.startsWith('$');
+
+ if (key === '$set') {
+ const updatedPaths = Object.keys(update[key]);
+ for (const path of updatedPaths) {
+ _walkUpdatePath(schema, update[key], path, update, ctx);
+ }
+ } else if (!isDollarKey) {
+ _walkUpdatePath(schema, update, key, update, ctx);
+ }
+
+ }
+};
+
+function _walkUpdatePath(schema, op, path, update, ctx) {
+ const schematype = schema.path(path);
+ if (schematype == null) {
+ return;
+ }
+
+ let immutable = get(schematype, 'options.immutable', null);
+ if (immutable == null) {
+ return;
+ }
+ if (typeof immutable === 'function') {
+ immutable = immutable.call(ctx, ctx);
+ }
+
+ if (!immutable) {
+ return;
+ }
+
+ update.$setOnInsert = update.$setOnInsert || {};
+ update.$setOnInsert[path] = op[path];
+ delete op[path];
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/update/removeUnusedArrayFilters.js b/node_modules/mongoose/lib/helpers/update/removeUnusedArrayFilters.js
new file mode 100644
index 0000000..d460628
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/update/removeUnusedArrayFilters.js
@@ -0,0 +1,18 @@
+'use strict';
+
+/**
+ * MongoDB throws an error if there's unused array filters. That is, if `options.arrayFilters` defines
+ * a filter, but none of the `update` keys use it. This should be enough to filter out all unused array
+ * filters.
+ */
+
+module.exports = function removeUnusedArrayFilters(update, arrayFilters) {
+ const updateKeys = Object.keys(update).map(key => Object.keys(update[key])).reduce((cur, arr) => cur.concat(arr), []);
+ return arrayFilters.filter(obj => {
+ const firstKey = Object.keys(obj)[0];
+ const firstDot = firstKey.indexOf('.');
+ const arrayFilterKey = firstDot === -1 ? firstKey : firstKey.slice(0, firstDot);
+
+ return updateKeys.find(key => key.includes('$[' + arrayFilterKey + ']')) != null;
+ });
+}; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/helpers/updateValidators.js b/node_modules/mongoose/lib/helpers/updateValidators.js
new file mode 100644
index 0000000..aeea634
--- /dev/null
+++ b/node_modules/mongoose/lib/helpers/updateValidators.js
@@ -0,0 +1,257 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const ValidationError = require('../error/validation');
+const cleanPositionalOperators = require('./schema/cleanPositionalOperators');
+const flatten = require('./common').flatten;
+const modifiedPaths = require('./common').modifiedPaths;
+
+/**
+ * Applies validators and defaults to update and findOneAndUpdate operations,
+ * specifically passing a null doc as `this` to validators and defaults
+ *
+ * @param {Query} query
+ * @param {Schema} schema
+ * @param {Object} castedDoc
+ * @param {Object} options
+ * @method runValidatorsOnUpdate
+ * @api private
+ */
+
+module.exports = function(query, schema, castedDoc, options, callback) {
+ let _keys;
+ const keys = Object.keys(castedDoc || {});
+ let updatedKeys = {};
+ let updatedValues = {};
+ const isPull = {};
+ const arrayAtomicUpdates = {};
+ const numKeys = keys.length;
+ let hasDollarUpdate = false;
+ const modified = {};
+ let currentUpdate;
+ let key;
+ let i;
+
+ for (i = 0; i < numKeys; ++i) {
+ if (keys[i].startsWith('$')) {
+ hasDollarUpdate = true;
+ if (keys[i] === '$push' || keys[i] === '$addToSet') {
+ _keys = Object.keys(castedDoc[keys[i]]);
+ for (let ii = 0; ii < _keys.length; ++ii) {
+ currentUpdate = castedDoc[keys[i]][_keys[ii]];
+ if (currentUpdate && currentUpdate.$each) {
+ arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []).
+ concat(currentUpdate.$each);
+ } else {
+ arrayAtomicUpdates[_keys[ii]] = (arrayAtomicUpdates[_keys[ii]] || []).
+ concat([currentUpdate]);
+ }
+ }
+ continue;
+ }
+ modifiedPaths(castedDoc[keys[i]], '', modified);
+ const flat = flatten(castedDoc[keys[i]], null, null, schema);
+ const paths = Object.keys(flat);
+ const numPaths = paths.length;
+ for (let j = 0; j < numPaths; ++j) {
+ const updatedPath = cleanPositionalOperators(paths[j]);
+ key = keys[i];
+ // With `$pull` we might flatten `$in`. Skip stuff nested under `$in`
+ // for the rest of the logic, it will get handled later.
+ if (updatedPath.includes('$')) {
+ continue;
+ }
+ if (key === '$set' || key === '$setOnInsert' ||
+ key === '$pull' || key === '$pullAll') {
+ updatedValues[updatedPath] = flat[paths[j]];
+ isPull[updatedPath] = key === '$pull' || key === '$pullAll';
+ } else if (key === '$unset') {
+ updatedValues[updatedPath] = undefined;
+ }
+ updatedKeys[updatedPath] = true;
+ }
+ }
+ }
+
+ if (!hasDollarUpdate) {
+ modifiedPaths(castedDoc, '', modified);
+ updatedValues = flatten(castedDoc, null, null, schema);
+ updatedKeys = Object.keys(updatedValues);
+ }
+
+ const updates = Object.keys(updatedValues);
+ const numUpdates = updates.length;
+ const validatorsToExecute = [];
+ const validationErrors = [];
+
+ const alreadyValidated = [];
+
+ const context = options && options.context === 'query' ? query : null;
+ function iter(i, v) {
+ const schemaPath = schema._getSchema(updates[i]);
+ if (schemaPath == null) {
+ return;
+ }
+ if (schemaPath.instance === 'Mixed' && schemaPath.path !== updates[i]) {
+ return;
+ }
+
+ if (v && Array.isArray(v.$in)) {
+ v.$in.forEach((v, i) => {
+ validatorsToExecute.push(function(callback) {
+ schemaPath.doValidate(
+ v,
+ function(err) {
+ if (err) {
+ err.path = updates[i] + '.$in.' + i;
+ validationErrors.push(err);
+ }
+ callback(null);
+ },
+ context,
+ { updateValidator: true });
+ });
+ });
+ } else {
+ if (isPull[updates[i]] &&
+ schemaPath.$isMongooseArray) {
+ return;
+ }
+
+ if (schemaPath.$isMongooseDocumentArrayElement && v != null && v.$__ != null) {
+ alreadyValidated.push(updates[i]);
+ validatorsToExecute.push(function(callback) {
+ schemaPath.doValidate(v, function(err) {
+ if (err) {
+ err.path = updates[i];
+ validationErrors.push(err);
+ return callback(null);
+ }
+
+ v.validate(function(err) {
+ if (err) {
+ if (err.errors) {
+ for (const key of Object.keys(err.errors)) {
+ const _err = err.errors[key];
+ _err.path = updates[i] + '.' + key;
+ validationErrors.push(_err);
+ }
+ } else {
+ err.path = updates[i];
+ validationErrors.push(err);
+ }
+ }
+ callback(null);
+ });
+ }, context, { updateValidator: true });
+ });
+ } else {
+ validatorsToExecute.push(function(callback) {
+ for (const path of alreadyValidated) {
+ if (updates[i].startsWith(path + '.')) {
+ return callback(null);
+ }
+ }
+
+ schemaPath.doValidate(v, function(err) {
+ if (schemaPath.schema != null &&
+ schemaPath.schema.options.storeSubdocValidationError === false &&
+ err instanceof ValidationError) {
+ return callback(null);
+ }
+
+ if (err) {
+ err.path = updates[i];
+ validationErrors.push(err);
+ }
+ callback(null);
+ }, context, { updateValidator: true });
+ });
+ }
+ }
+ }
+ for (i = 0; i < numUpdates; ++i) {
+ iter(i, updatedValues[updates[i]]);
+ }
+
+ const arrayUpdates = Object.keys(arrayAtomicUpdates);
+ for (const arrayUpdate of arrayUpdates) {
+ let schemaPath = schema._getSchema(arrayUpdate);
+ if (schemaPath && schemaPath.$isMongooseDocumentArray) {
+ validatorsToExecute.push(function(callback) {
+ schemaPath.doValidate(
+ arrayAtomicUpdates[arrayUpdate],
+ getValidationCallback(arrayUpdate, validationErrors, callback),
+ options && options.context === 'query' ? query : null);
+ });
+ } else {
+ schemaPath = schema._getSchema(arrayUpdate + '.0');
+ for (const atomicUpdate of arrayAtomicUpdates[arrayUpdate]) {
+ validatorsToExecute.push(function(callback) {
+ schemaPath.doValidate(
+ atomicUpdate,
+ getValidationCallback(arrayUpdate, validationErrors, callback),
+ options && options.context === 'query' ? query : null,
+ { updateValidator: true });
+ });
+ }
+ }
+ }
+
+ if (callback != null) {
+ let numValidators = validatorsToExecute.length;
+ if (numValidators === 0) {
+ return _done(callback);
+ }
+ for (const validator of validatorsToExecute) {
+ validator(function() {
+ if (--numValidators <= 0) {
+ _done(callback);
+ }
+ });
+ }
+
+ return;
+ }
+
+ return function(callback) {
+ let numValidators = validatorsToExecute.length;
+ if (numValidators === 0) {
+ return _done(callback);
+ }
+ for (const validator of validatorsToExecute) {
+ validator(function() {
+ if (--numValidators <= 0) {
+ _done(callback);
+ }
+ });
+ }
+ };
+
+ function _done(callback) {
+ if (validationErrors.length) {
+ const err = new ValidationError(null);
+
+ for (const validationError of validationErrors) {
+ err.addError(validationError.path, validationError);
+ }
+
+ return callback(err);
+ }
+ callback(null);
+ }
+
+ function getValidationCallback(arrayUpdate, validationErrors, callback) {
+ return function(err) {
+ if (err) {
+ err.path = arrayUpdate;
+ validationErrors.push(err);
+ }
+ callback(null);
+ };
+ }
+};
+
diff --git a/node_modules/mongoose/lib/index.js b/node_modules/mongoose/lib/index.js
new file mode 100644
index 0000000..fccb625
--- /dev/null
+++ b/node_modules/mongoose/lib/index.js
@@ -0,0 +1,1132 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+if (global.MONGOOSE_DRIVER_PATH) {
+ const deprecationWarning = 'The `MONGOOSE_DRIVER_PATH` global property is ' +
+ 'deprecated. Use `mongoose.driver.set()` instead.';
+ const setDriver = require('util').deprecate(function() {
+ require('./driver').set(require(global.MONGOOSE_DRIVER_PATH));
+ }, deprecationWarning);
+ setDriver();
+} else {
+ require('./driver').set(require('./drivers/node-mongodb-native'));
+}
+
+const Document = require('./document');
+const Schema = require('./schema');
+const SchemaType = require('./schematype');
+const SchemaTypes = require('./schema/index');
+const VirtualType = require('./virtualtype');
+const STATES = require('./connectionstate');
+const VALID_OPTIONS = require('./validoptions');
+const Types = require('./types');
+const Query = require('./query');
+const Model = require('./model');
+const applyPlugins = require('./helpers/schema/applyPlugins');
+const get = require('./helpers/get');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const legacyPluralize = require('mongoose-legacy-pluralize');
+const utils = require('./utils');
+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');
+const PromiseProvider = require('./promise_provider');
+const shardingPlugin = require('./plugins/sharding');
+
+const defaultMongooseSymbol = Symbol.for('mongoose:default');
+
+require('./helpers/printJestWarning');
+
+/**
+ * Mongoose constructor.
+ *
+ * The exports object of the `mongoose` module is an instance of this class.
+ * Most apps will only use this one instance.
+ *
+ * ####Example:
+ * const mongoose = require('mongoose');
+ * mongoose instanceof mongoose.Mongoose; // true
+ *
+ * // Create a new Mongoose instance with its own `connect()`, `set()`, `model()`, etc.
+ * const m = new mongoose.Mongoose();
+ *
+ * @api public
+ * @param {Object} options see [`Mongoose#set()` docs](/docs/api/mongoose.html#mongoose_Mongoose-set)
+ */
+function Mongoose(options) {
+ this.connections = [];
+ this.models = {};
+ this.modelSchemas = {};
+ // default global options
+ this.options = Object.assign({
+ pluralization: true
+ }, options);
+ const conn = this.createConnection(); // default connection
+ conn.models = this.models;
+
+ if (this.options.pluralization) {
+ this._pluralize = legacyPluralize;
+ }
+
+ // If a user creates their own Mongoose instance, give them a separate copy
+ // of the `Schema` constructor so they get separate custom types. (gh-6933)
+ if (!options || !options[defaultMongooseSymbol]) {
+ const _this = this;
+ this.Schema = function() {
+ this.base = _this;
+ return Schema.apply(this, arguments);
+ };
+ this.Schema.prototype = Object.create(Schema.prototype);
+
+ Object.assign(this.Schema, Schema);
+ this.Schema.base = this;
+ this.Schema.Types = Object.assign({}, Schema.Types);
+ } else {
+ // Hack to work around babel's strange behavior with
+ // `import mongoose, { Schema } from 'mongoose'`. Because `Schema` is not
+ // an own property of a Mongoose global, Schema will be undefined. See gh-5648
+ for (const key of ['Schema', 'model']) {
+ this[key] = Mongoose.prototype[key];
+ }
+ }
+ this.Schema.prototype.base = this;
+
+ Object.defineProperty(this, 'plugins', {
+ configurable: false,
+ enumerable: true,
+ writable: false,
+ value: [
+ [saveSubdocs, { deduplicate: true }],
+ [validateBeforeSave, { deduplicate: true }],
+ [shardingPlugin, { deduplicate: true }],
+ [removeSubdocs, { deduplicate: true }],
+ [trackTransaction, { deduplicate: true }]
+ ]
+ });
+}
+Mongoose.prototype.cast = cast;
+/**
+ * Expose connection states for user-land
+ *
+ * @memberOf Mongoose
+ * @property STATES
+ * @api public
+ */
+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
+ * like `find()`.
+ *
+ * @memberOf Mongoose
+ * @property driver
+ * @api public
+ */
+
+Mongoose.prototype.driver = require('./driver');
+
+/**
+ * Sets mongoose options
+ *
+ * ####Example:
+ *
+ * mongoose.set('test', value) // sets the 'test' option to `value`
+ *
+ * mongoose.set('debug', true) // enable logging collection methods + arguments to the console/file
+ *
+ * mongoose.set('debug', function(collectionName, methodName, ...methodArgs) {}); // use custom function to log collection methods + arguments
+ *
+ * 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()`.
+ * - 'useNewUrlParser': false by default. Set to `true` to make all connections set the `useNewUrlParser` option by default
+ * - 'useUnifiedTopology': false by default. Set to `true` to make all connections set the `useUnifiedTopology` option by default
+ * - 'cloneSchemas': false by default. Set to `true` to `clone()` all schemas before compiling into a model.
+ * - 'applyPluginsToDiscriminators': false by default. Set to true to apply global plugins to discriminator schemas. This typically isn't necessary because plugins are applied to the base schema and discriminators copy all middleware, methods, statics, and properties from the base schema.
+ * - 'applyPluginsToChildSchemas': true by default. Set to false to skip applying global plugins to child schemas
+ * - 'objectIdGetter': true by default. Mongoose adds a getter to MongoDB ObjectId's called `_id` that returns `this` for convenience with populate. Set this to false to remove the getter.
+ * - 'runValidators': false by default. Set to true to enable [update validators](/docs/validation.html#update-validators) for all validators by default.
+ * - '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.
+ *
+ * @param {String} key
+ * @param {String|Function|Boolean} value
+ * @api public
+ */
+
+Mongoose.prototype.set = function(key, value) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ if (VALID_OPTIONS.indexOf(key) === -1) throw new Error(`\`${key}\` is an invalid option.`);
+
+ if (arguments.length === 1) {
+ return _mongoose.options[key];
+ }
+
+ _mongoose.options[key] = value;
+
+ if (key === 'objectIdGetter') {
+ if (value) {
+ Object.defineProperty(mongoose.Types.ObjectId.prototype, '_id', {
+ enumerable: false,
+ configurable: true,
+ get: function() {
+ return this;
+ }
+ });
+ } else {
+ delete mongoose.Types.ObjectId.prototype._id;
+ }
+ }
+
+ return _mongoose;
+};
+
+/**
+ * Gets mongoose options
+ *
+ * ####Example:
+ *
+ * mongoose.get('test') // returns the 'test' value
+ *
+ * @param {String} key
+ * @method get
+ * @api public
+ */
+
+Mongoose.prototype.get = Mongoose.prototype.set;
+
+/**
+ * Creates a Connection instance.
+ *
+ * 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._
+ *
+ * ####Example:
+ *
+ * // with mongodb:// URI
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port/database');
+ *
+ * // and options
+ * 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
+ * const opts = { replset: { strategy: 'ping', rs_name: 'testSet' }}
+ * db = mongoose.createConnection('mongodb://user:pass@localhost:port,anotherhost:port,yetanother:port/database', opts);
+ *
+ * // and options
+ * const opts = { server: { auto_reconnect: false }, user: 'username', pass: 'mypassword' }
+ * db = mongoose.createConnection('localhost', 'database', port, opts)
+ *
+ * // initialize now, connect later
+ * db = mongoose.createConnection();
+ * db.openUri('localhost', 'database', port, [opts]);
+ *
+ * @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.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.
+ * @param {Boolean} [options.useNewUrlParser=false] False by default. Set to `true` to make all connections set the `useNewUrlParser` option by default.
+ * @param {Boolean} [options.useUnifiedTopology=false] False by default. Set to `true` to make all connections set the `useUnifiedTopology` option by default.
+ * @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.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.
+ * @return {Connection} the created Connection object. Connections are thenable, so you can do `await mongoose.createConnection()`
+ * @api public
+ */
+
+Mongoose.prototype.createConnection = function(uri, options, callback) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ const conn = new Connection(_mongoose);
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ _mongoose.connections.push(conn);
+
+ if (arguments.length > 0) {
+ return conn.openUri(uri, options, callback);
+ }
+
+ return conn;
+};
+
+/**
+ * Opens the default mongoose connection.
+ *
+ * ####Example:
+ *
+ * mongoose.connect('mongodb://user:pass@localhost:port/database');
+ *
+ * // replica sets
+ * 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
+ * const uri = 'mongodb://nonexistent.domain:27000';
+ * mongoose.connect(uri, function(error) {
+ * // if error is truthy, the initial connection failed.
+ * })
+ *
+ * @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 {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.
+ * @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 {Boolean} [options.useUnifiedTopology=false] False by default. Set to `true` to opt in to the MongoDB driver's replica set and sharded cluster monitoring engine.
+ * @param {Number} [options.serverSelectionTimeoutMS] If `useUnifiedTopology = true`, the MongoDB driver will try to find a server to send any given operation to, and keep retrying for `serverSelectionTimeoutMS` milliseconds before erroring out. If not set, the MongoDB driver defaults to using `30000` (30 seconds).
+ * @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.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.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 {Function} [callback]
+ * @see Mongoose#createConnection #index_Mongoose-createConnection
+ * @api public
+ * @return {Promise} resolves to `this` if connection succeeded
+ */
+
+Mongoose.prototype.connect = function(uri, options, callback) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+ const conn = _mongoose.connection;
+
+ return promiseOrCallback(callback, cb => {
+ conn.openUri(uri, options, err => {
+ if (err != null) {
+ return cb(err);
+ }
+ return cb(null, _mongoose);
+ });
+ });
+};
+
+/**
+ * Runs `.close()` on all connections in parallel.
+ *
+ * @param {Function} [callback] called after all connection close, or when first error occurred.
+ * @return {Promise} resolves when all connections are closed, or rejects with the first error that occurred.
+ * @api public
+ */
+
+Mongoose.prototype.disconnect = function(callback) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ return promiseOrCallback(callback, cb => {
+ let remaining = _mongoose.connections.length;
+ if (remaining <= 0) {
+ return cb(null);
+ }
+ _mongoose.connections.forEach(conn => {
+ conn.close(function(error) {
+ if (error) {
+ return cb(error);
+ }
+ if (!--remaining) {
+ cb(null);
+ }
+ });
+ });
+ });
+};
+
+/**
+ * _Requires MongoDB >= 3.6.0._ Starts a [MongoDB session](https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions)
+ * for benefits like causal consistency, [retryable writes](https://docs.mongodb.com/manual/core/retryable-writes/),
+ * and [transactions](http://thecodebarbarian.com/a-node-js-perspective-on-mongodb-4-transactions.html).
+ *
+ * Calling `mongoose.startSession()` is equivalent to calling `mongoose.connection.startSession()`.
+ * Sessions are scoped to a connection, so calling `mongoose.startSession()`
+ * starts a session on the [default mongoose connection](/docs/api.html#mongoose_Mongoose-connection).
+ *
+ * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html#startSession)
+ * @param {Boolean} [options.causalConsistency=true] set to false to disable causal consistency
+ * @param {Function} [callback]
+ * @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
+ * @api public
+ */
+
+Mongoose.prototype.startSession = function() {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ return _mongoose.connection.startSession.apply(_mongoose.connection, arguments);
+};
+
+/**
+ * Getter/setter around function for pluralizing collection names.
+ *
+ * @param {Function|null} [fn] overwrites the function used to pluralize collection names
+ * @return {Function|null} the current function used to pluralize collection names, defaults to the legacy function from `mongoose-legacy-pluralize`.
+ * @api public
+ */
+
+Mongoose.prototype.pluralize = function(fn) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ if (arguments.length > 0) {
+ _mongoose._pluralize = fn;
+ }
+ return _mongoose._pluralize;
+};
+
+/**
+ * Defines a model or retrieves it.
+ *
+ * Models defined on the `mongoose` instance are available to all connection
+ * created by the same `mongoose` instance.
+ *
+ * If you call `mongoose.model()` with twice the same name but a different schema,
+ * you will get an `OverwriteModelError`. If you call `mongoose.model()` with
+ * the same name and same schema, you'll get the same schema back.
+ *
+ * ####Example:
+ *
+ * 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
+ * const conn = mongoose.createConnection(..);
+ *
+ * // create Actor model
+ * 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
+ *
+ * // This throws an `OverwriteModelError` because the schema is different.
+ * conn.model('Actor', new Schema({ name: String }));
+ *
+ * _When no `collection` argument is passed, Mongoose uses the model name. If you don't like this behavior, either pass a collection name, use `mongoose.pluralize()`, or set your schemas collection name option._
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String }, { collection: 'actor' });
+ *
+ * // or
+ *
+ * schema.set('collection', 'actor');
+ *
+ * // or
+ *
+ * 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)
+ * @return {Model} The model associated with `name`. Mongoose will create the model if it doesn't already exist.
+ * @api public
+ */
+
+Mongoose.prototype.model = function(name, schema, collection, skipInit) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ let model;
+ if (typeof name === 'function') {
+ model = name;
+ name = model.name;
+ if (!(model.prototype instanceof Model)) {
+ throw new _mongoose.Error('The provided class ' + name + ' must extend Model');
+ }
+ }
+
+ if (typeof schema === 'string') {
+ collection = schema;
+ schema = false;
+ }
+
+ if (utils.isObject(schema) && !(schema instanceof Schema)) {
+ schema = new Schema(schema);
+ }
+ if (schema && !(schema instanceof Schema)) {
+ throw new Error('The 2nd parameter to `mongoose.model()` should be a ' +
+ 'schema or a POJO');
+ }
+
+ if (typeof collection === 'boolean') {
+ skipInit = collection;
+ collection = null;
+ }
+
+ // handle internal options from connection.model()
+ let options;
+ if (skipInit && utils.isObject(skipInit)) {
+ options = skipInit;
+ skipInit = true;
+ } else {
+ options = {};
+ }
+
+ // look up schema for the collection.
+ if (!_mongoose.modelSchemas[name]) {
+ if (schema) {
+ // cache it so we only apply plugins once
+ _mongoose.modelSchemas[name] = schema;
+ } else {
+ throw new mongoose.Error.MissingSchemaError(name);
+ }
+ }
+
+ const originalSchema = schema;
+ if (schema) {
+ if (_mongoose.get('cloneSchemas')) {
+ schema = schema.clone();
+ }
+ _mongoose._applyPlugins(schema);
+ }
+
+ let sub;
+
+ // 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) {
+ if (originalSchema &&
+ originalSchema.instanceOfSchema &&
+ originalSchema !== _mongoose.models[name].schema) {
+ throw new _mongoose.Error.OverwriteModelError(name);
+ }
+
+ if (collection && collection !== _mongoose.models[name].collection.name) {
+ // subclass current model with alternate collection
+ model = _mongoose.models[name];
+ schema = model.prototype.schema;
+ sub = model.__subclass(_mongoose.connection, schema, collection);
+ // do not cache the sub model
+ return sub;
+ }
+
+ return _mongoose.models[name];
+ }
+
+ // ensure a schema exists
+ if (!schema) {
+ schema = this.modelSchemas[name];
+ if (!schema) {
+ throw new mongoose.Error.MissingSchemaError(name);
+ }
+ }
+
+ // Apply relevant "global" options to the schema
+ if (!('pluralization' in schema.options)) {
+ schema.options.pluralization = _mongoose.options.pluralization;
+ }
+
+ if (!collection) {
+ collection = schema.get('collection') ||
+ utils.toCollectionName(name, _mongoose.pluralize());
+ }
+
+ const connection = options.connection || _mongoose.connection;
+ model = _mongoose.Model.compile(model || name, schema, collection, connection, _mongoose);
+
+ if (!skipInit) {
+ // Errors handled internally, so safe to ignore error
+ model.init(function $modelInitNoop() {});
+ }
+
+ if (options.cache === false) {
+ return model;
+ }
+
+ _mongoose.models[name] = model;
+ return _mongoose.models[name];
+};
+
+/**
+ * Removes the model named `name` from the default connection, if it exists.
+ * You can use this function to clean up any models you created in your tests to
+ * prevent OverwriteModelErrors.
+ *
+ * Equivalent to `mongoose.connection.deleteModel(name)`.
+ *
+ * ####Example:
+ *
+ * mongoose.model('User', new Schema({ name: String }));
+ * console.log(mongoose.model('User')); // Model object
+ * mongoose.deleteModel('User');
+ * console.log(mongoose.model('User')); // undefined
+ *
+ * // Usually useful in a Mocha `afterEach()` hook
+ * afterEach(function() {
+ * mongoose.deleteModel(/.+/); // Delete every model
+ * });
+ *
+ * @api public
+ * @param {String|RegExp} name if string, the name of the model to remove. If regexp, removes all models whose name matches the regexp.
+ * @return {Mongoose} this
+ */
+
+Mongoose.prototype.deleteModel = function(name) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ _mongoose.connection.deleteModel(name);
+ return _mongoose;
+};
+
+/**
+ * Returns an array of model names created on this instance of Mongoose.
+ *
+ * ####Note:
+ *
+ * _Does not include names of models created using `connection.model()`._
+ *
+ * @api public
+ * @return {Array}
+ */
+
+Mongoose.prototype.modelNames = function() {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ const names = Object.keys(_mongoose.models);
+ return names;
+};
+
+/**
+ * Applies global plugins to `schema`.
+ *
+ * @param {Schema} schema
+ * @api private
+ */
+
+Mongoose.prototype._applyPlugins = function(schema, options) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ options = options || {};
+ options.applyPluginsToDiscriminators = get(_mongoose,
+ 'options.applyPluginsToDiscriminators', false);
+ options.applyPluginsToChildSchemas = get(_mongoose,
+ 'options.applyPluginsToChildSchemas', true);
+ applyPlugins(schema, _mongoose.plugins, options, '$globalPluginsApplied');
+};
+
+/**
+ * Declares a global plugin executed on all Schemas.
+ *
+ * Equivalent to calling `.plugin(fn)` on each Schema you create.
+ *
+ * @param {Function} fn plugin callback
+ * @param {Object} [opts] optional options
+ * @return {Mongoose} this
+ * @see plugins ./plugins.html
+ * @api public
+ */
+
+Mongoose.prototype.plugin = function(fn, opts) {
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
+
+ _mongoose.plugins.push([fn, opts]);
+ return _mongoose;
+};
+
+/**
+ * The Mongoose module's default connection. Equivalent to `mongoose.connections[0]`, see [`connections`](#mongoose_Mongoose-connections).
+ *
+ * ####Example:
+ *
+ * const mongoose = require('mongoose');
+ * mongoose.connect(...);
+ * mongoose.connection.on('error', cb);
+ *
+ * This is the connection used by default for every model created using [mongoose.model](#index_Mongoose-model).
+ *
+ * To create a new connection, use [`createConnection()`](#mongoose_Mongoose-createConnection).
+ *
+ * @memberOf Mongoose
+ * @instance
+ * @property {Connection} connection
+ * @api public
+ */
+
+Mongoose.prototype.__defineGetter__('connection', function() {
+ return this.connections[0];
+});
+
+Mongoose.prototype.__defineSetter__('connection', function(v) {
+ if (v instanceof Connection) {
+ this.connections[0] = v;
+ this.models = v.models;
+ }
+});
+
+/**
+ * An array containing all [connections](connections.html) associated with this
+ * Mongoose instance. By default, there is 1 connection. Calling
+ * [`createConnection()`](#mongoose_Mongoose-createConnection) adds a connection
+ * to this array.
+ *
+ * ####Example:
+ *
+ * const mongoose = require('mongoose');
+ * mongoose.connections.length; // 1, just the default connection
+ * mongoose.connections[0] === mongoose.connection; // true
+ *
+ * mongoose.createConnection('mongodb://localhost:27017/test');
+ * mongoose.connections.length; // 2
+ *
+ * @memberOf Mongoose
+ * @instance
+ * @property {Array} connections
+ * @api public
+ */
+
+Mongoose.prototype.connections;
+
+/*!
+ * Driver dependent APIs
+ */
+
+const driver = global.MONGOOSE_DRIVER_PATH || './drivers/node-mongodb-native';
+
+/*!
+ * Connection
+ */
+
+const Connection = require(driver + '/connection');
+
+/*!
+ * Collection
+ */
+
+const Collection = require(driver + '/collection');
+
+/**
+ * The Mongoose Aggregate constructor
+ *
+ * @method Aggregate
+ * @api public
+ */
+
+Mongoose.prototype.Aggregate = Aggregate;
+
+/**
+ * The Mongoose Collection constructor
+ *
+ * @method Collection
+ * @api public
+ */
+
+Mongoose.prototype.Collection = Collection;
+
+/**
+ * The Mongoose [Connection](#connection_Connection) constructor
+ *
+ * @memberOf Mongoose
+ * @instance
+ * @method Connection
+ * @api public
+ */
+
+Mongoose.prototype.Connection = Connection;
+
+/**
+ * The Mongoose version
+ *
+ * #### Example
+ *
+ * console.log(mongoose.version); // '5.x.x'
+ *
+ * @property version
+ * @api public
+ */
+
+Mongoose.prototype.version = pkg.version;
+
+/**
+ * The Mongoose constructor
+ *
+ * The exports of the mongoose module is an instance of this class.
+ *
+ * ####Example:
+ *
+ * const mongoose = require('mongoose');
+ * const mongoose2 = new mongoose.Mongoose();
+ *
+ * @method Mongoose
+ * @api public
+ */
+
+Mongoose.prototype.Mongoose = Mongoose;
+
+/**
+ * The Mongoose [Schema](#schema_Schema) constructor
+ *
+ * ####Example:
+ *
+ * const mongoose = require('mongoose');
+ * const Schema = mongoose.Schema;
+ * const CatSchema = new Schema(..);
+ *
+ * @method Schema
+ * @api public
+ */
+
+Mongoose.prototype.Schema = Schema;
+
+/**
+ * The Mongoose [SchemaType](#schematype_SchemaType) constructor
+ *
+ * @method SchemaType
+ * @api public
+ */
+
+Mongoose.prototype.SchemaType = SchemaType;
+
+/**
+ * The various Mongoose SchemaTypes.
+ *
+ * ####Note:
+ *
+ * _Alias of mongoose.Schema.Types for backwards compatibility._
+ *
+ * @property SchemaTypes
+ * @see Schema.SchemaTypes #schema_Schema.Types
+ * @api public
+ */
+
+Mongoose.prototype.SchemaTypes = Schema.Types;
+
+/**
+ * The Mongoose [VirtualType](#virtualtype_VirtualType) constructor
+ *
+ * @method VirtualType
+ * @api public
+ */
+
+Mongoose.prototype.VirtualType = VirtualType;
+
+/**
+ * The various Mongoose Types.
+ *
+ * ####Example:
+ *
+ * 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)
+ *
+ * Using this exposed access to the `ObjectId` type, we can construct ids on demand.
+ *
+ * const ObjectId = mongoose.Types.ObjectId;
+ * const id1 = new ObjectId;
+ *
+ * @property Types
+ * @api public
+ */
+
+Mongoose.prototype.Types = Types;
+
+/**
+ * The Mongoose [Query](#query_Query) constructor.
+ *
+ * @method Query
+ * @api public
+ */
+
+Mongoose.prototype.Query = Query;
+
+/**
+ * The Mongoose [Promise](#promise_Promise) constructor.
+ *
+ * @memberOf Mongoose
+ * @instance
+ * @property Promise
+ * @api public
+ */
+
+Object.defineProperty(Mongoose.prototype, 'Promise', {
+ get: function() {
+ return PromiseProvider.get();
+ },
+ set: function(lib) {
+ PromiseProvider.set(lib);
+ }
+});
+
+/**
+ * Storage layer for mongoose promises
+ *
+ * @method PromiseProvider
+ * @api public
+ */
+
+Mongoose.prototype.PromiseProvider = PromiseProvider;
+
+/**
+ * The Mongoose [Model](#model_Model) constructor.
+ *
+ * @method Model
+ * @api public
+ */
+
+Mongoose.prototype.Model = Model;
+
+/**
+ * The Mongoose [Document](/api/document.html) constructor.
+ *
+ * @method Document
+ * @api public
+ */
+
+Mongoose.prototype.Document = Document;
+
+/**
+ * The Mongoose DocumentProvider constructor. Mongoose users should not have to
+ * use this directly
+ *
+ * @method DocumentProvider
+ * @api public
+ */
+
+Mongoose.prototype.DocumentProvider = require('./document_provider');
+
+/**
+ * The Mongoose ObjectId [SchemaType](/docs/schematypes.html). Used for
+ * declaring paths in your schema that should be
+ * [MongoDB ObjectIds](https://docs.mongodb.com/manual/reference/method/ObjectId/).
+ * Do not use this to create a new ObjectId instance, use `mongoose.Types.ObjectId`
+ * instead.
+ *
+ * ####Example:
+ *
+ * const childSchema = new Schema({ parentId: mongoose.ObjectId });
+ *
+ * @property ObjectId
+ * @api public
+ */
+
+Mongoose.prototype.ObjectId = SchemaTypes.ObjectId;
+
+/**
+ * Returns true if Mongoose can cast the given value to an ObjectId, or
+ * false otherwise.
+ *
+ * ####Example:
+ *
+ * mongoose.isValidObjectId(new mongoose.Types.ObjectId()); // true
+ * mongoose.isValidObjectId('0123456789ab'); // true
+ * mongoose.isValidObjectId(6); // false
+ *
+ * @method isValidObjectId
+ * @api public
+ */
+
+Mongoose.prototype.isValidObjectId = function(v) {
+ if (v == null) {
+ return true;
+ }
+ const base = this || mongoose;
+ const ObjectId = base.driver.get().ObjectId;
+ if (v instanceof ObjectId) {
+ return true;
+ }
+
+ if (v._id != null) {
+ if (v._id instanceof ObjectId) {
+ return true;
+ }
+ if (v._id.toString instanceof Function) {
+ v = v._id.toString();
+ return typeof v === 'string' && (v.length === 12 || v.length === 24);
+ }
+ }
+
+ if (v.toString instanceof Function) {
+ v = v.toString();
+ }
+
+ if (typeof v === 'string' && (v.length === 12 || v.length === 24)) {
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * The Mongoose Decimal128 [SchemaType](/docs/schematypes.html). Used for
+ * declaring paths in your schema that should be
+ * [128-bit decimal floating points](http://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-decimal.html).
+ * Do not use this to create a new Decimal128 instance, use `mongoose.Types.Decimal128`
+ * instead.
+ *
+ * ####Example:
+ *
+ * const vehicleSchema = new Schema({ fuelLevel: mongoose.Decimal128 });
+ *
+ * @property Decimal128
+ * @api public
+ */
+
+Mongoose.prototype.Decimal128 = SchemaTypes.Decimal128;
+
+/**
+ * The Mongoose Mixed [SchemaType](/docs/schematypes.html). Used for
+ * declaring paths in your schema that Mongoose's change tracking, casting,
+ * and validation should ignore.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ arbitrary: mongoose.Mixed });
+ *
+ * @property Mixed
+ * @api public
+ */
+
+Mongoose.prototype.Mixed = SchemaTypes.Mixed;
+
+/**
+ * The Mongoose Date [SchemaType](/docs/schematypes.html).
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ test: Date });
+ * schema.path('test') instanceof mongoose.Date; // true
+ *
+ * @property Date
+ * @api public
+ */
+
+Mongoose.prototype.Date = SchemaTypes.Date;
+
+/**
+ * The Mongoose Number [SchemaType](/docs/schematypes.html). Used for
+ * declaring paths in your schema that Mongoose should cast to numbers.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ num: mongoose.Number });
+ * // Equivalent to:
+ * const schema = new Schema({ num: 'number' });
+ *
+ * @property Number
+ * @api public
+ */
+
+Mongoose.prototype.Number = SchemaTypes.Number;
+
+/**
+ * The [MongooseError](#error_MongooseError) constructor.
+ *
+ * @method Error
+ * @api public
+ */
+
+Mongoose.prototype.Error = require('./error/index');
+
+/**
+ * Mongoose uses this function to get the current time when setting
+ * [timestamps](/docs/guide.html#timestamps). You may stub out this function
+ * using a tool like [Sinon](https://www.npmjs.com/package/sinon) for testing.
+ *
+ * @method now
+ * @returns Date the current time
+ * @api public
+ */
+
+Mongoose.prototype.now = function now() { return new Date(); };
+
+/**
+ * The Mongoose CastError constructor
+ *
+ * @method CastError
+ * @param {String} type The name of the type
+ * @param {Any} value The value that failed to cast
+ * @param {String} path The path `a.b.c` in the doc where this cast error occurred
+ * @param {Error} [reason] The original error that was thrown
+ * @api public
+ */
+
+Mongoose.prototype.CastError = require('./error/cast');
+
+/**
+ * The constructor used for schematype options
+ *
+ * @method SchemaTypeOptions
+ * @api public
+ */
+
+Mongoose.prototype.SchemaTypeOptions = require('./options/SchemaTypeOptions');
+
+/**
+ * The [node-mongodb-native](https://github.com/mongodb/node-mongodb-native) driver Mongoose uses.
+ *
+ * @property mongo
+ * @api public
+ */
+
+Mongoose.prototype.mongo = require('mongodb');
+
+/**
+ * The [mquery](https://github.com/aheckmann/mquery) query builder Mongoose uses.
+ *
+ * @property mquery
+ * @api public
+ */
+
+Mongoose.prototype.mquery = require('mquery');
+
+/*!
+ * The exports object is an instance of Mongoose.
+ *
+ * @api public
+ */
+
+const mongoose = module.exports = exports = new Mongoose({
+ [defaultMongooseSymbol]: true
+});
diff --git a/node_modules/mongoose/lib/internal.js b/node_modules/mongoose/lib/internal.js
new file mode 100644
index 0000000..7642477
--- /dev/null
+++ b/node_modules/mongoose/lib/internal.js
@@ -0,0 +1,38 @@
+/*!
+ * Dependencies
+ */
+
+'use strict';
+
+const StateMachine = require('./statemachine');
+const ActiveRoster = StateMachine.ctor('require', 'modify', 'init', 'default', 'ignore');
+
+module.exports = exports = InternalCache;
+
+function InternalCache() {
+ this.strictMode = undefined;
+ this.selected = undefined;
+ this.shardval = undefined;
+ this.saveError = undefined;
+ this.validationError = undefined;
+ this.adhocPaths = undefined;
+ this.removing = undefined;
+ this.inserting = undefined;
+ this.saving = undefined;
+ this.version = undefined;
+ this.getters = {};
+ this._id = undefined;
+ this.populate = undefined; // what we want to populate in this doc
+ this.populated = undefined;// the _ids that have been populated
+ this.wasPopulated = false; // if this doc was the result of a population
+ this.scope = undefined;
+ this.activePaths = new ActiveRoster;
+ this.pathsToScopes = {};
+ this.cachedRequired = {};
+ this.session = null;
+ this.$setCalled = new Set();
+
+ // embedded docs
+ this.ownerDocument = undefined;
+ this.fullPath = undefined;
+}
diff --git a/node_modules/mongoose/lib/model.js b/node_modules/mongoose/lib/model.js
new file mode 100644
index 0000000..de7ab0a
--- /dev/null
+++ b/node_modules/mongoose/lib/model.js
@@ -0,0 +1,4902 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const Aggregate = require('./aggregate');
+const ChangeStream = require('./cursor/ChangeStream');
+const Document = require('./document');
+const DocumentNotFoundError = require('./error/notFound');
+const DivergentArrayError = require('./error/divergentArray');
+const EventEmitter = require('events').EventEmitter;
+const MongooseBuffer = require('./types/buffer');
+const MongooseError = require('./error/index');
+const OverwriteModelError = require('./error/overwriteModel');
+const PromiseProvider = require('./promise_provider');
+const Query = require('./query');
+const RemoveOptions = require('./options/removeOptions');
+const SaveOptions = require('./options/saveOptions');
+const Schema = require('./schema');
+const ServerSelectionError = require('./error/serverSelection');
+const SkipPopulateValue = require('./helpers/populate/SkipPopulateValue');
+const ValidationError = require('./error/validation');
+const VersionError = require('./error/version');
+const ParallelSaveError = require('./error/parallelSave');
+const applyQueryMiddleware = require('./helpers/query/applyQueryMiddleware');
+const applyHooks = require('./helpers/model/applyHooks');
+const applyMethods = require('./helpers/model/applyMethods');
+const applyStaticHooks = require('./helpers/model/applyStaticHooks');
+const applyStatics = require('./helpers/model/applyStatics');
+const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
+const assignVals = require('./helpers/populate/assignVals');
+const castBulkWrite = require('./helpers/model/castBulkWrite');
+const getDefaultBulkwriteResult = require('./helpers/getDefaultBulkwriteResult');
+const discriminator = require('./helpers/model/discriminator');
+const each = require('./helpers/each');
+const get = require('./helpers/get');
+const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
+const getModelsMapForPopulate = require('./helpers/populate/getModelsMapForPopulate');
+const immediate = require('./helpers/immediate');
+const internalToObjectOptions = require('./options').internalToObjectOptions;
+const isDefaultIdIndex = require('./helpers/indexes/isDefaultIdIndex');
+const isIndexEqual = require('./helpers/indexes/isIndexEqual');
+const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
+const leanPopulateMap = require('./helpers/populate/leanPopulateMap');
+const modifiedPaths = require('./helpers/update/modifiedPaths');
+const parallelLimit = require('./helpers/parallelLimit');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const removeDeselectedForeignField = require('./helpers/populate/removeDeselectedForeignField');
+const util = require('util');
+const utils = require('./utils');
+
+const VERSION_WHERE = 1;
+const VERSION_INC = 2;
+const VERSION_ALL = VERSION_WHERE | VERSION_INC;
+
+const arrayAtomicsSymbol = require('./helpers/symbols').arrayAtomicsSymbol;
+const modelCollectionSymbol = Symbol('mongoose#Model#collection');
+const modelDbSymbol = Symbol('mongoose#Model#db');
+const modelSymbol = require('./helpers/symbols').modelSymbol;
+const subclassedSymbol = Symbol('mongoose#Model#subclassed');
+
+const saveToObjectOptions = Object.assign({}, internalToObjectOptions, {
+ bson: true
+});
+
+/**
+ * A Model is a class that's your primary tool for interacting with MongoDB.
+ * An instance of a Model is called a [Document](./api.html#Document).
+ *
+ * In Mongoose, the term "Model" refers to subclasses of the `mongoose.Model`
+ * class. You should not use the `mongoose.Model` class directly. The
+ * [`mongoose.model()`](./api.html#mongoose_Mongoose-model) and
+ * [`connection.model()`](./api.html#connection_Connection-model) functions
+ * create subclasses of `mongoose.Model` as shown below.
+ *
+ * ####Example:
+ *
+ * // `UserModel` is a "Model", a subclass of `mongoose.Model`.
+ * const UserModel = mongoose.model('User', new Schema({ name: String }));
+ *
+ * // You can use a Model to create new documents using `new`:
+ * const userDoc = new UserModel({ name: 'Foo' });
+ * await userDoc.save();
+ *
+ * // You also use a model to create queries:
+ * const userFromDb = await UserModel.findOne({ name: 'Foo' });
+ *
+ * @param {Object} doc values for initial set
+ * @param [fields] optional object containing the fields that were selected in the query which returned this document. You do **not** need to set this parameter to ensure Mongoose handles your [query projection](./api.html#query_Query-select).
+ * @param {Boolean} [skipId=false] optional boolean. If true, mongoose doesn't add an `_id` field to the document.
+ * @inherits Document http://mongoosejs.com/docs/api/document.html
+ * @event `error`: If listening to this event, 'error' is emitted when a document was saved without passing a callback and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
+ * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
+ * @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event.
+ * @event `index-single-done`: Emitted when an individual index finishes within `Model#ensureIndexes`. If an error occurred it is passed with the event. The fields, options, and index name are also passed.
+ * @api public
+ */
+
+function Model(doc, fields, skipId) {
+ if (fields instanceof Schema) {
+ throw new TypeError('2nd argument to `Model` must be a POJO or string, ' +
+ '**not** a schema. Make sure you\'re calling `mongoose.model()`, not ' +
+ '`mongoose.Model()`.');
+ }
+ Document.call(this, doc, fields, skipId);
+}
+
+/*!
+ * Inherits from Document.
+ *
+ * All Model.prototype features are available on
+ * top level (non-sub) documents.
+ */
+
+Model.prototype.__proto__ = Document.prototype;
+Model.prototype.$isMongooseModelPrototype = true;
+
+/**
+ * Connection the model uses.
+ *
+ * @api public
+ * @property db
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.db;
+
+/**
+ * Collection the model uses.
+ *
+ * This property is read-only. Modifying this property is a no-op.
+ *
+ * @api public
+ * @property collection
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.collection;
+
+/**
+ * The name of the model
+ *
+ * @api public
+ * @property modelName
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.modelName;
+
+/**
+ * Additional properties to attach to the query when calling `save()` and
+ * `isNew` is false.
+ *
+ * @api public
+ * @property $where
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.$where;
+
+/**
+ * If this is a discriminator model, `baseModelName` is the name of
+ * the base model.
+ *
+ * @api public
+ * @property baseModelName
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.baseModelName;
+
+/**
+ * Event emitter that reports any errors that occurred. Useful for global error
+ * handling.
+ *
+ * ####Example:
+ *
+ * MyModel.events.on('error', err => console.log(err.message));
+ *
+ * // Prints a 'CastError' because of the above handler
+ * await MyModel.findOne({ _id: 'notanid' }).catch(noop);
+ *
+ * @api public
+ * @fires error whenever any query or model function errors
+ * @memberOf Model
+ * @static events
+ */
+
+Model.events;
+
+/*!
+ * Compiled middleware for this model. Set in `applyHooks()`.
+ *
+ * @api private
+ * @property _middleware
+ * @memberOf Model
+ * @static
+ */
+
+Model._middleware;
+
+/*!
+ * ignore
+ */
+
+function _applyCustomWhere(doc, where) {
+ if (doc.$where == null) {
+ return;
+ }
+
+ const keys = Object.keys(doc.$where);
+ const len = keys.length;
+ for (let i = 0; i < len; ++i) {
+ where[keys[i]] = doc.$where[keys[i]];
+ }
+}
+
+/*!
+ * ignore
+ */
+
+Model.prototype.$__handleSave = function(options, callback) {
+ const _this = this;
+ let saveOptions = {};
+
+ if ('safe' in options) {
+ _handleSafe(options);
+ }
+ applyWriteConcern(this.schema, options);
+ if ('w' in options) {
+ saveOptions.w = options.w;
+ }
+ if ('j' in options) {
+ saveOptions.j = options.j;
+ }
+ if ('wtimeout' in options) {
+ saveOptions.wtimeout = options.wtimeout;
+ }
+ if ('checkKeys' in options) {
+ saveOptions.checkKeys = options.checkKeys;
+ }
+
+ const session = this.$session();
+ if (!saveOptions.hasOwnProperty('session')) {
+ saveOptions.session = session;
+ }
+
+ if (Object.keys(saveOptions).length === 0) {
+ saveOptions = null;
+ }
+
+ if (this.isNew) {
+ // send entire doc
+ const obj = this.toObject(saveToObjectOptions);
+
+ if ((obj || {})._id === void 0) {
+ // documents must have an _id else mongoose won't know
+ // what to update later if more changes are made. the user
+ // wouldn't know what _id was generated by mongodb either
+ // nor would the ObjectId generated by mongodb necessarily
+ // match the schema definition.
+ setTimeout(function() {
+ callback(new MongooseError('document must have an _id before saving'));
+ }, 0);
+ return;
+ }
+
+ this.$__version(true, obj);
+ this[modelCollectionSymbol].insertOne(obj, saveOptions, function(err, ret) {
+ if (err) {
+ _setIsNew(_this, true);
+
+ callback(err, null);
+ return;
+ }
+
+ callback(null, ret);
+ });
+
+ this.$__reset();
+ _setIsNew(this, false);
+ // Make it possible to retry the insert
+ this.$__.inserting = true;
+ } else {
+ // Make sure we don't treat it as a new object on error,
+ // since it already exists
+ this.$__.inserting = false;
+
+ const delta = this.$__delta();
+
+ if (delta) {
+ if (delta instanceof MongooseError) {
+ callback(delta);
+ return;
+ }
+
+ const where = this.$__where(delta[0]);
+ if (where instanceof MongooseError) {
+ callback(where);
+ return;
+ }
+
+ _applyCustomWhere(this, where);
+
+ this[modelCollectionSymbol].updateOne(where, delta[1], saveOptions, (err, ret) => {
+ if (err) {
+ this.$__undoReset();
+
+ callback(err);
+ return;
+ }
+ ret.$where = where;
+ callback(null, ret);
+ });
+ } else {
+ const optionsWithCustomValues = Object.assign({}, options, saveOptions);
+ this.constructor.exists(this.$__where(), optionsWithCustomValues)
+ .then((documentExists) => {
+ if (!documentExists) {
+ throw new DocumentNotFoundError(this.$__where(), this.constructor.modelName);
+ }
+
+ callback();
+ })
+ .catch(callback);
+ return;
+ }
+
+ // store the modified paths before the document is reset
+ this.$__.modifiedPaths = this.modifiedPaths();
+
+ this.$__reset();
+
+ _setIsNew(this, false);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+Model.prototype.$__save = function(options, callback) {
+ this.$__handleSave(options, (error, result) => {
+ const hooks = this.schema.s.hooks;
+ if (error) {
+ return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
+ callback(error, this);
+ });
+ }
+
+ let numAffected = 0;
+ if (get(options, 'safe.w') !== 0 && get(options, 'w') !== 0) {
+ // Skip checking if write succeeded if writeConcern is set to
+ // unacknowledged writes, because otherwise `numAffected` will always be 0
+ if (result) {
+ if (Array.isArray(result)) {
+ numAffected = result.length;
+ } else if (result.result && result.result.n !== undefined) {
+ numAffected = result.result.n;
+ } else if (result.result && result.result.nModified !== undefined) {
+ numAffected = result.result.nModified;
+ } else {
+ numAffected = result;
+ }
+ }
+
+ // was this an update that required a version bump?
+ if (this.$__.version && !this.$__.inserting) {
+ const doIncrement = VERSION_INC === (VERSION_INC & this.$__.version);
+ this.$__.version = undefined;
+
+ const key = this.schema.options.versionKey;
+ const version = this.$__getValue(key) || 0;
+
+ if (numAffected <= 0) {
+ // the update failed. pass an error back
+ this.$__undoReset();
+ const err = this.$__.$versionError ||
+ new VersionError(this, version, this.$__.modifiedPaths);
+ return callback(err);
+ }
+
+ // increment version if was successful
+ if (doIncrement) {
+ this.$__setValue(key, version + 1);
+ }
+ }
+
+ if (result != null && numAffected <= 0) {
+ this.$__undoReset();
+ error = new DocumentNotFoundError(result.$where,
+ this.constructor.modelName, numAffected, result);
+ return hooks.execPost('save:error', this, [this], { error: error }, (error) => {
+ callback(error, this);
+ });
+ }
+ }
+ this.$__.saving = undefined;
+ this.emit('save', this, numAffected);
+ this.constructor.emit('save', this, numAffected);
+ callback(null, this);
+ });
+};
+
+/*!
+ * ignore
+ */
+
+function generateVersionError(doc, modifiedPaths) {
+ const key = doc.schema.options.versionKey;
+ if (!key) {
+ return null;
+ }
+ const version = doc.$__getValue(key) || 0;
+ return new VersionError(doc, version, modifiedPaths);
+}
+
+/**
+ * Saves this document by inserting a new document into the database if [document.isNew](/docs/api.html#document_Document-isNew) is `true`,
+ * or sends an [updateOne](/docs/api.html#document_Document-updateOne) operation **only** with the modifications to the database, it does not replace the whole document in the latter case.
+ *
+ * ####Example:
+ *
+ * product.sold = Date.now();
+ * product = await product.save();
+ *
+ * If save is successful, the returned promise will fulfill with the document
+ * saved.
+ *
+ * ####Example:
+ *
+ * const newProduct = await product.save();
+ * newProduct === product; // true
+ *
+ * @param {Object} [options] options optional options
+ * @param {Session} [options.session=null] the [session](https://docs.mongodb.com/manual/reference/server-sessions/) associated with this save operation. If not specified, defaults to the [document's associated session](api.html#document_Document-$session).
+ * @param {Object} [options.safe] (DEPRECATED) overrides [schema's safe option](http://mongoosejs.com//docs/guide.html#safe). Use the `w` option instead.
+ * @param {Boolean} [options.validateBeforeSave] set to false to save without validating.
+ * @param {Boolean} [options.validateModifiedOnly=false] if `true`, Mongoose will only validate modified paths, as opposed to modified paths and `required` paths.
+ * @param {Number|String} [options.w] set the [write concern](https://docs.mongodb.com/manual/reference/write-concern/#w-option). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.j] set to true for MongoDB to wait until this `save()` has been [journaled before resolving the returned promise](https://docs.mongodb.com/manual/reference/write-concern/#j-option). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern)
+ * @param {Number} [options.wtimeout] sets a [timeout for the write concern](https://docs.mongodb.com/manual/reference/write-concern/#wtimeout). Overrides the [schema-level `writeConcern` option](/docs/guide.html#writeConcern).
+ * @param {Boolean} [options.checkKeys=true] the MongoDB driver prevents you from saving keys that start with '$' or contain '.' by default. Set this option to `false` to skip that check. See [restrictions on field names](https://docs.mongodb.com/manual/reference/limits/#Restrictions-on-Field-Names)
+ * @param {Boolean} [options.timestamps=true] if `false` and [timestamps](./guide.html#timestamps) are enabled, skip timestamps for this `save()`.
+ * @param {Function} [fn] optional callback
+ * @throws {DocumentNotFoundError} if this [save updates an existing document](api.html#document_Document-isNew) but the document doesn't exist in the database. For example, you will get this error if the document is [deleted between when you retrieved the document and when you saved it](documents.html#updating).
+ * @return {Promise|undefined} Returns undefined if used with callback or a Promise otherwise.
+ * @api public
+ * @see middleware http://mongoosejs.com/docs/middleware.html
+ */
+
+Model.prototype.save = function(options, fn) {
+ let parallelSave;
+ this.$op = 'save';
+
+ if (this.$__.saving) {
+ parallelSave = new ParallelSaveError(this);
+ } else {
+ this.$__.saving = new ParallelSaveError(this);
+ }
+
+ if (typeof options === 'function') {
+ fn = options;
+ options = undefined;
+ }
+
+ options = new SaveOptions(options);
+ if (options.hasOwnProperty('session')) {
+ this.$session(options.session);
+ }
+
+ this.$__.$versionError = generateVersionError(this, this.modifiedPaths());
+
+ fn = this.constructor.$handleCallbackError(fn);
+
+ return promiseOrCallback(fn, cb => {
+ cb = this.constructor.$wrapCallback(cb);
+
+ if (parallelSave) {
+ this.$__handleReject(parallelSave);
+ return cb(parallelSave);
+ }
+
+ this.$__.saveOptions = options;
+
+ this.$__save(options, error => {
+ this.$__.saving = undefined;
+ delete this.$__.saveOptions;
+ delete this.$__.$versionError;
+ this.$op = null;
+
+ if (error) {
+ this.$__handleReject(error);
+ return cb(error);
+ }
+ cb(null, this);
+ });
+ }, this.constructor.events);
+};
+
+/*!
+ * Determines whether versioning should be skipped for the given path
+ *
+ * @param {Document} self
+ * @param {String} path
+ * @return {Boolean} true if versioning should be skipped for the given path
+ */
+function shouldSkipVersioning(self, path) {
+ const skipVersioning = self.schema.options.skipVersioning;
+ if (!skipVersioning) return false;
+
+ // Remove any array indexes from the path
+ path = path.replace(/\.\d+\./, '.');
+
+ return skipVersioning[path];
+}
+
+/*!
+ * Apply the operation to the delta (update) clause as
+ * well as track versioning for our where clause.
+ *
+ * @param {Document} self
+ * @param {Object} where
+ * @param {Object} delta
+ * @param {Object} data
+ * @param {Mixed} val
+ * @param {String} [operation]
+ */
+
+function operand(self, where, delta, data, val, op) {
+ // delta
+ op || (op = '$set');
+ if (!delta[op]) delta[op] = {};
+ delta[op][data.path] = val;
+
+ // disabled versioning?
+ if (self.schema.options.versionKey === false) return;
+
+ // path excluded from versioning?
+ if (shouldSkipVersioning(self, data.path)) return;
+
+ // already marked for versioning?
+ if (VERSION_ALL === (VERSION_ALL & self.$__.version)) return;
+
+ if (self.schema.options.optimisticConcurrency) {
+ self.$__.version = VERSION_ALL;
+ return;
+ }
+
+ switch (op) {
+ case '$set':
+ case '$unset':
+ case '$pop':
+ case '$pull':
+ case '$pullAll':
+ case '$push':
+ case '$addToSet':
+ break;
+ default:
+ // nothing to do
+ return;
+ }
+
+ // ensure updates sent with positional notation are
+ // editing the correct array element.
+ // only increment the version if an array position changes.
+ // modifying elements of an array is ok if position does not change.
+ if (op === '$push' || op === '$addToSet' || op === '$pullAll' || op === '$pull') {
+ self.$__.version = VERSION_INC;
+ } else if (/^\$p/.test(op)) {
+ // potentially changing array positions
+ self.increment();
+ } else if (Array.isArray(val)) {
+ // $set an array
+ self.increment();
+ } else if (/\.\d+\.|\.\d+$/.test(data.path)) {
+ // now handling $set, $unset
+ // subpath of array
+ self.$__.version = VERSION_WHERE;
+ }
+}
+
+/*!
+ * Compiles an update and where clause for a `val` with _atomics.
+ *
+ * @param {Document} self
+ * @param {Object} where
+ * @param {Object} delta
+ * @param {Object} data
+ * @param {Array} value
+ */
+
+function handleAtomics(self, where, delta, data, value) {
+ if (delta.$set && delta.$set[data.path]) {
+ // $set has precedence over other atomics
+ return;
+ }
+
+ if (typeof value.$__getAtomics === 'function') {
+ value.$__getAtomics().forEach(function(atomic) {
+ const op = atomic[0];
+ const val = atomic[1];
+ operand(self, where, delta, data, val, op);
+ });
+ return;
+ }
+
+ // legacy support for plugins
+
+ const atomics = value[arrayAtomicsSymbol];
+ const ops = Object.keys(atomics);
+ let i = ops.length;
+ let val;
+ let op;
+
+ if (i === 0) {
+ // $set
+
+ if (utils.isMongooseObject(value)) {
+ value = value.toObject({ depopulate: 1, _isNested: true });
+ } else if (value.valueOf) {
+ value = value.valueOf();
+ }
+
+ return operand(self, where, delta, data, value);
+ }
+
+ function iter(mem) {
+ return utils.isMongooseObject(mem)
+ ? mem.toObject({ depopulate: 1, _isNested: true })
+ : mem;
+ }
+
+ while (i--) {
+ op = ops[i];
+ val = atomics[op];
+
+ if (utils.isMongooseObject(val)) {
+ val = val.toObject({ depopulate: true, transform: false, _isNested: true });
+ } else if (Array.isArray(val)) {
+ val = val.map(iter);
+ } else if (val.valueOf) {
+ val = val.valueOf();
+ }
+
+ if (op === '$addToSet') {
+ val = { $each: val };
+ }
+
+ operand(self, where, delta, data, val, op);
+ }
+}
+
+/**
+ * Produces a special query document of the modified properties used in updates.
+ *
+ * @api private
+ * @method $__delta
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.$__delta = function() {
+ const dirty = this.$__dirty();
+ if (!dirty.length && VERSION_ALL !== this.$__.version) {
+ return;
+ }
+
+ const where = {};
+ const delta = {};
+ const len = dirty.length;
+ const divergent = [];
+ let d = 0;
+
+ where._id = this._doc._id;
+ // If `_id` is an object, need to depopulate, but also need to be careful
+ // because `_id` can technically be null (see gh-6406)
+ if (get(where, '_id.$__', null) != null) {
+ where._id = where._id.toObject({ transform: false, depopulate: true });
+ }
+
+ for (; d < len; ++d) {
+ const data = dirty[d];
+ let value = data.value;
+
+ const match = checkDivergentArray(this, data.path, value);
+ if (match) {
+ divergent.push(match);
+ continue;
+ }
+
+ const pop = this.populated(data.path, true);
+ if (!pop && this.$__.selected) {
+ // If any array was selected using an $elemMatch projection, we alter the path and where clause
+ // NOTE: MongoDB only supports projected $elemMatch on top level array.
+ const pathSplit = data.path.split('.');
+ const top = pathSplit[0];
+ if (this.$__.selected[top] && this.$__.selected[top].$elemMatch) {
+ // If the selected array entry was modified
+ if (pathSplit.length > 1 && pathSplit[1] == 0 && typeof where[top] === 'undefined') {
+ where[top] = this.$__.selected[top];
+ pathSplit[1] = '$';
+ data.path = pathSplit.join('.');
+ }
+ // if the selected array was modified in any other way throw an error
+ else {
+ divergent.push(data.path);
+ continue;
+ }
+ }
+ }
+
+ if (divergent.length) continue;
+
+ if (value === undefined) {
+ operand(this, where, delta, data, 1, '$unset');
+ } else if (value === null) {
+ operand(this, where, delta, data, null);
+ } else if (value.isMongooseArray && value.$path() && value[arrayAtomicsSymbol]) {
+ // arrays and other custom types (support plugins etc)
+ handleAtomics(this, where, delta, data, value);
+ } else if (value[MongooseBuffer.pathSymbol] && Buffer.isBuffer(value)) {
+ // MongooseBuffer
+ value = value.toObject();
+ operand(this, where, delta, data, value);
+ } else {
+ value = utils.clone(value, {
+ depopulate: true,
+ transform: false,
+ virtuals: false,
+ getters: false,
+ _isNested: true
+ });
+ operand(this, where, delta, data, value);
+ }
+ }
+
+ if (divergent.length) {
+ return new DivergentArrayError(divergent);
+ }
+
+ if (this.$__.version) {
+ this.$__version(where, delta);
+ }
+
+ return [where, delta];
+};
+
+/*!
+ * Determine if array was populated with some form of filter and is now
+ * being updated in a manner which could overwrite data unintentionally.
+ *
+ * @see https://github.com/Automattic/mongoose/issues/1334
+ * @param {Document} doc
+ * @param {String} path
+ * @return {String|undefined}
+ */
+
+function checkDivergentArray(doc, path, array) {
+ // see if we populated this path
+ const pop = doc.populated(path, true);
+
+ if (!pop && doc.$__.selected) {
+ // If any array was selected using an $elemMatch projection, we deny the update.
+ // NOTE: MongoDB only supports projected $elemMatch on top level array.
+ const top = path.split('.')[0];
+ if (doc.$__.selected[top + '.$']) {
+ return top;
+ }
+ }
+
+ if (!(pop && array && array.isMongooseArray)) return;
+
+ // If the array was populated using options that prevented all
+ // documents from being returned (match, skip, limit) or they
+ // deselected the _id field, $pop and $set of the array are
+ // not safe operations. If _id was deselected, we do not know
+ // how to remove elements. $pop will pop off the _id from the end
+ // of the array in the db which is not guaranteed to be the
+ // same as the last element we have here. $set of the entire array
+ // would be similarily destructive as we never received all
+ // elements of the array and potentially would overwrite data.
+ const check = pop.options.match ||
+ pop.options.options && utils.object.hasOwnProperty(pop.options.options, 'limit') || // 0 is not permitted
+ pop.options.options && pop.options.options.skip || // 0 is permitted
+ pop.options.select && // deselected _id?
+ (pop.options.select._id === 0 ||
+ /\s?-_id\s?/.test(pop.options.select));
+
+ if (check) {
+ const atomics = array[arrayAtomicsSymbol];
+ if (Object.keys(atomics).length === 0 || atomics.$set || atomics.$pop) {
+ return path;
+ }
+ }
+}
+
+/**
+ * Appends versioning to the where and update clauses.
+ *
+ * @api private
+ * @method $__version
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.$__version = function(where, delta) {
+ const key = this.schema.options.versionKey;
+
+ if (where === true) {
+ // this is an insert
+ if (key) this.$__setValue(key, delta[key] = 0);
+ return;
+ }
+
+ // updates
+
+ // only apply versioning if our versionKey was selected. else
+ // there is no way to select the correct version. we could fail
+ // fast here and force them to include the versionKey but
+ // thats a bit intrusive. can we do this automatically?
+ if (!this.isSelected(key)) {
+ return;
+ }
+
+ // $push $addToSet don't need the where clause set
+ if (VERSION_WHERE === (VERSION_WHERE & this.$__.version)) {
+ const value = this.$__getValue(key);
+ if (value != null) where[key] = value;
+ }
+
+ if (VERSION_INC === (VERSION_INC & this.$__.version)) {
+ if (get(delta.$set, key, null) != null) {
+ // Version key is getting set, means we'll increment the doc's version
+ // after a successful save, so we should set the incremented version so
+ // future saves don't fail (gh-5779)
+ ++delta.$set[key];
+ } else {
+ delta.$inc = delta.$inc || {};
+ delta.$inc[key] = 1;
+ }
+ }
+};
+
+/**
+ * Signal that we desire an increment of this documents version.
+ *
+ * ####Example:
+ *
+ * Model.findById(id, function (err, doc) {
+ * doc.increment();
+ * doc.save(function (err) { .. })
+ * })
+ *
+ * @see versionKeys http://mongoosejs.com/docs/guide.html#versionKey
+ * @api public
+ */
+
+Model.prototype.increment = function increment() {
+ this.$__.version = VERSION_ALL;
+ return this;
+};
+
+/**
+ * Returns a query object
+ *
+ * @api private
+ * @method $__where
+ * @memberOf Model
+ * @instance
+ */
+
+Model.prototype.$__where = function _where(where) {
+ where || (where = {});
+
+ if (!where._id) {
+ where._id = this._doc._id;
+ }
+
+ if (this._doc._id === void 0) {
+ return new MongooseError('No _id found on document!');
+ }
+
+ return where;
+};
+
+/**
+ * Removes this document from the db.
+ *
+ * ####Example:
+ * product.remove(function (err, product) {
+ * if (err) return handleError(err);
+ * Product.findById(product._id, function (err, product) {
+ * console.log(product) // null
+ * })
+ * })
+ *
+ *
+ * As an extra measure of flow control, remove will return a Promise (bound to `fn` if passed) so it could be chained, or hooked to recieve errors
+ *
+ * ####Example:
+ * product.remove().then(function (product) {
+ * ...
+ * }).catch(function (err) {
+ * assert.ok(err)
+ * })
+ *
+ * @param {Object} [options]
+ * @param {Session} [options.session=null] the [session](https://docs.mongodb.com/manual/reference/server-sessions/) associated with this operation. If not specified, defaults to the [document's associated session](api.html#document_Document-$session).
+ * @param {function(err,product)} [fn] optional callback
+ * @return {Promise} Promise
+ * @api public
+ */
+
+Model.prototype.remove = function remove(options, fn) {
+ if (typeof options === 'function') {
+ fn = options;
+ options = undefined;
+ }
+
+ options = new RemoveOptions(options);
+ if (options.hasOwnProperty('session')) {
+ this.$session(options.session);
+ }
+ this.$op = 'remove';
+
+ fn = this.constructor.$handleCallbackError(fn);
+
+ return promiseOrCallback(fn, cb => {
+ cb = this.constructor.$wrapCallback(cb);
+ this.$__remove(options, (err, res) => {
+ this.$op = null;
+ cb(err, res);
+ });
+ }, this.constructor.events);
+};
+
+/**
+ * Alias for remove
+ */
+
+Model.prototype.delete = Model.prototype.remove;
+
+/**
+ * Removes this document from the db. Equivalent to `.remove()`.
+ *
+ * ####Example:
+ * product = await product.deleteOne();
+ * await Product.findById(product._id); // null
+ *
+ * @param {function(err,product)} [fn] optional callback
+ * @return {Promise} Promise
+ * @api public
+ */
+
+Model.prototype.deleteOne = function deleteOne(options, fn) {
+ if (typeof options === 'function') {
+ fn = options;
+ options = undefined;
+ }
+
+ if (!options) {
+ options = {};
+ }
+
+ fn = this.constructor.$handleCallbackError(fn);
+
+ return promiseOrCallback(fn, cb => {
+ cb = this.constructor.$wrapCallback(cb);
+ this.$__deleteOne(options, cb);
+ }, this.constructor.events);
+};
+
+/*!
+ * ignore
+ */
+
+Model.prototype.$__remove = function $__remove(options, cb) {
+ if (this.$__.isDeleted) {
+ return immediate(() => cb(null, this));
+ }
+
+ const where = this.$__where();
+ if (where instanceof MongooseError) {
+ return cb(where);
+ }
+
+ _applyCustomWhere(this, where);
+
+ const session = this.$session();
+ if (!options.hasOwnProperty('session')) {
+ options.session = session;
+ }
+
+ this[modelCollectionSymbol].deleteOne(where, options, err => {
+ if (!err) {
+ this.$__.isDeleted = true;
+ this.emit('remove', this);
+ this.constructor.emit('remove', this);
+ return cb(null, this);
+ }
+ this.$__.isDeleted = false;
+ cb(err);
+ });
+};
+
+/*!
+ * ignore
+ */
+
+Model.prototype.$__deleteOne = Model.prototype.$__remove;
+
+/**
+ * Returns another Model instance.
+ *
+ * ####Example:
+ *
+ * const doc = new Tank;
+ * doc.model('User').findById(id, callback);
+ *
+ * @param {String} name model name
+ * @api public
+ */
+
+Model.prototype.model = function model(name) {
+ return this[modelDbSymbol].model(name);
+};
+
+/**
+ * Returns true if at least one document exists in the database that matches
+ * the given `filter`, and false otherwise.
+ *
+ * Under the hood, `MyModel.exists({ answer: 42 })` is equivalent to
+ * `MyModel.findOne({ answer: 42 }).select({ _id: 1 }).lean().then(doc => !!doc)`
+ *
+ * ####Example:
+ * await Character.deleteMany({});
+ * await Character.create({ name: 'Jean-Luc Picard' });
+ *
+ * await Character.exists({ name: /picard/i }); // true
+ * await Character.exists({ name: /riker/i }); // false
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOne()`
+ *
+ * @param {Object} filter
+ * @param {Function} [callback] callback
+ * @return {Promise}
+ */
+
+Model.exists = function exists(filter, options, callback) {
+ _checkContext(this, 'exists');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const query = this.findOne(filter).
+ select({ _id: 1 }).
+ lean().
+ setOptions(options);
+
+ if (typeof callback === 'function') {
+ query.exec(function(err, doc) {
+ if (err != null) {
+ return callback(err);
+ }
+ callback(null, !!doc);
+ });
+ return;
+ }
+
+ return query.then(doc => !!doc);
+};
+
+/**
+ * Adds a discriminator type.
+ *
+ * ####Example:
+ *
+ * function BaseSchema() {
+ * Schema.apply(this, arguments);
+ *
+ * this.add({
+ * name: String,
+ * createdAt: Date
+ * });
+ * }
+ * util.inherits(BaseSchema, Schema);
+ *
+ * const PersonSchema = new BaseSchema();
+ * const BossSchema = new BaseSchema({ department: String });
+ *
+ * const Person = mongoose.model('Person', PersonSchema);
+ * const Boss = Person.discriminator('Boss', BossSchema);
+ * new Boss().__t; // "Boss". `__t` is the default `discriminatorKey`
+ *
+ * const employeeSchema = new Schema({ boss: ObjectId });
+ * const Employee = Person.discriminator('Employee', employeeSchema, 'staff');
+ * new Employee().__t; // "staff" because of 3rd argument above
+ *
+ * @param {String} name discriminator model name
+ * @param {Schema} schema discriminator model schema
+ * @param {String} [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
+ * @return {Model} The newly created discriminator model
+ * @api public
+ */
+
+Model.discriminator = function(name, schema, value) {
+ let model;
+ if (typeof name === 'function') {
+ model = name;
+ name = utils.getFunctionName(model);
+ if (!(model.prototype instanceof Model)) {
+ throw new MongooseError('The provided class ' + name + ' must extend Model');
+ }
+ }
+
+ _checkContext(this, 'discriminator');
+
+ if (utils.isObject(schema) && !schema.instanceOfSchema) {
+ schema = new Schema(schema);
+ }
+
+ schema = discriminator(this, name, schema, value, true);
+ if (this.db.models[name]) {
+ throw new OverwriteModelError(name);
+ }
+
+ schema.$isRootDiscriminator = true;
+ schema.$globalPluginsApplied = true;
+
+ model = this.db.model(model || name, schema, this.collection.name);
+ this.discriminators[name] = model;
+ const d = this.discriminators[name];
+ d.prototype.__proto__ = this.prototype;
+ Object.defineProperty(d, 'baseModelName', {
+ value: this.modelName,
+ configurable: true,
+ writable: false
+ });
+
+ // apply methods and statics
+ applyMethods(d, schema);
+ applyStatics(d, schema);
+
+ if (this[subclassedSymbol] != null) {
+ for (const submodel of this[subclassedSymbol]) {
+ submodel.discriminators = submodel.discriminators || {};
+ submodel.discriminators[name] =
+ model.__subclass(model.db, schema, submodel.collection.name);
+ }
+ }
+
+ return d;
+};
+
+/*!
+ * Make sure `this` is a model
+ */
+
+function _checkContext(ctx, fnName) {
+ // Check context, because it is easy to mistakenly type
+ // `new Model.discriminator()` and get an incomprehensible error
+ if (ctx == null || ctx === global) {
+ throw new MongooseError('`Model.' + fnName + '()` cannot run without a ' +
+ 'model as `this`. Make sure you are calling `MyModel.' + fnName + '()` ' +
+ 'where `MyModel` is a Mongoose model.');
+ } else if (ctx[modelSymbol] == null) {
+ throw new MongooseError('`Model.' + fnName + '()` cannot run without a ' +
+ 'model as `this`. Make sure you are not calling ' +
+ '`new Model.' + fnName + '()`');
+ }
+}
+
+// Model (class) features
+
+/*!
+ * Give the constructor the ability to emit events.
+ */
+
+for (const i in EventEmitter.prototype) {
+ Model[i] = EventEmitter.prototype[i];
+}
+
+/**
+ * This function is responsible for building [indexes](https://docs.mongodb.com/manual/indexes/),
+ * unless [`autoIndex`](http://mongoosejs.com/docs/guide.html#autoIndex) is turned off.
+ *
+ * Mongoose calls this function automatically when a model is created using
+ * [`mongoose.model()`](/docs/api.html#mongoose_Mongoose-model) or
+ * [`connection.model()`](/docs/api.html#connection_Connection-model), so you
+ * don't need to call it. This function is also idempotent, so you may call it
+ * to get back a promise that will resolve when your indexes are finished
+ * building as an alternative to [`MyModel.on('index')`](/docs/guide.html#indexes)
+ *
+ * ####Example:
+ *
+ * const eventSchema = new Schema({ thing: { type: 'string', unique: true }})
+ * // This calls `Event.init()` implicitly, so you don't need to call
+ * // `Event.init()` on your own.
+ * const Event = mongoose.model('Event', eventSchema);
+ *
+ * Event.init().then(function(Event) {
+ * // You can also use `Event.on('index')` if you prefer event emitters
+ * // over promises.
+ * console.log('Indexes are done building!');
+ * });
+ *
+ * @api public
+ * @param {Function} [callback]
+ * @returns {Promise}
+ */
+
+Model.init = function init(callback) {
+ _checkContext(this, 'init');
+
+ this.schema.emit('init', this);
+
+ if (this.$init != null) {
+ if (callback) {
+ this.$init.then(() => callback(), err => callback(err));
+ return null;
+ }
+ return this.$init;
+ }
+
+ const Promise = PromiseProvider.get();
+ const autoIndex = utils.getOption('autoIndex',
+ this.schema.options, this.db.config, this.db.base.options);
+ const autoCreate = utils.getOption('autoCreate',
+ this.schema.options, this.db.config, this.db.base.options);
+
+ const _ensureIndexes = autoIndex ?
+ cb => this.ensureIndexes({ _automatic: true }, cb) :
+ cb => cb();
+ const _createCollection = autoCreate ?
+ cb => this.createCollection({}, cb) :
+ cb => cb();
+
+ this.$init = new Promise((resolve, reject) => {
+ _createCollection(error => {
+ if (error) {
+ return reject(error);
+ }
+ _ensureIndexes(error => {
+ if (error) {
+ return reject(error);
+ }
+ resolve(this);
+ });
+ });
+ });
+
+ if (callback) {
+ this.$init.then(() => callback(), err => callback(err));
+ this.$caught = true;
+ return null;
+ } else {
+ const _catch = this.$init.catch;
+ const _this = this;
+ this.$init.catch = function() {
+ this.$caught = true;
+ return _catch.apply(_this.$init, arguments);
+ };
+ }
+
+ return this.$init;
+};
+
+
+/**
+ * Create the collection for this model. By default, if no indexes are specified,
+ * mongoose will not create the collection for the model until any documents are
+ * created. Use this method to create the collection explicitly.
+ *
+ * Note 1: You may need to call this before starting a transaction
+ * See https://docs.mongodb.com/manual/core/transactions/#transactions-and-operations
+ *
+ * Note 2: You don't have to call this if your schema contains index or unique field.
+ * In that case, just use `Model.init()`
+ *
+ * ####Example:
+ *
+ * const userSchema = new Schema({ name: String })
+ * const User = mongoose.model('User', userSchema);
+ *
+ * User.createCollection().then(function(collection) {
+ * console.log('Collection is created!');
+ * });
+ *
+ * @api public
+ * @param {Object} [options] see [MongoDB driver docs](http://mongodb.github.io/node-mongodb-native/3.1/api/Db.html#createCollection)
+ * @param {Function} [callback]
+ * @returns {Promise}
+ */
+
+Model.createCollection = function createCollection(options, callback) {
+ _checkContext(this, 'createCollection');
+
+ if (typeof options === 'string') {
+ throw new MongooseError('You can\'t specify a new collection name in Model.createCollection.' +
+ 'This is not like Connection.createCollection. Only options are accepted here.');
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const schemaCollation = get(this, 'schema.options.collation', null);
+ if (schemaCollation != null) {
+ options = Object.assign({ collation: schemaCollation }, options);
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+
+ this.db.createCollection(this.collection.collectionName, options, utils.tick((error) => {
+ if (error != null && error.codeName !== 'NamespaceExists') {
+ return cb(error);
+ }
+ this.collection = this.db.collection(this.collection.collectionName, options);
+ cb(null, this.collection);
+ }));
+ }, this.events);
+};
+
+/**
+ * Makes the indexes in MongoDB match the indexes defined in this model's
+ * schema. This function will drop any indexes that are not defined in
+ * the model's schema except the `_id` index, and build any indexes that
+ * are in your schema but not in MongoDB.
+ *
+ * See the [introductory blog post](http://thecodebarbarian.com/whats-new-in-mongoose-5-2-syncindexes)
+ * for more information.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: { type: String, unique: true } });
+ * const Customer = mongoose.model('Customer', schema);
+ * await Customer.collection.createIndex({ age: 1 }); // Index is not in schema
+ * // Will drop the 'age' index and create an index on `name`
+ * await Customer.syncIndexes();
+ *
+ * @param {Object} [options] options to pass to `ensureIndexes()`
+ * @param {Boolean} [options.background=null] if specified, overrides each index's `background` property
+ * @param {Function} [callback] optional callback
+ * @return {Promise|undefined} Returns `undefined` if callback is specified, returns a promise if no callback.
+ * @api public
+ */
+
+Model.syncIndexes = function syncIndexes(options, callback) {
+ _checkContext(this, 'syncIndexes');
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+
+ this.createCollection(err => {
+ if (err != null && err.codeName !== 'NamespaceExists') {
+ return cb(err);
+ }
+ this.cleanIndexes((err, dropped) => {
+ if (err != null) {
+ return cb(err);
+ }
+ this.createIndexes(options, err => {
+ if (err != null) {
+ return cb(err);
+ }
+ cb(null, dropped);
+ });
+ });
+ });
+ }, this.events);
+};
+
+/**
+ * Deletes all indexes that aren't defined in this model's schema. Used by
+ * `syncIndexes()`.
+ *
+ * The returned promise resolves to a list of the dropped indexes' names as an array
+ *
+ * @param {Function} [callback] optional callback
+ * @return {Promise|undefined} Returns `undefined` if callback is specified, returns a promise if no callback.
+ * @api public
+ */
+
+Model.cleanIndexes = function cleanIndexes(callback) {
+ _checkContext(this, 'cleanIndexes');
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ const collection = this.collection;
+
+ this.listIndexes((err, indexes) => {
+ if (err != null) {
+ return cb(err);
+ }
+
+ const schemaIndexes = this.schema.indexes();
+ const toDrop = [];
+
+ for (const index of indexes) {
+ let found = false;
+ // Never try to drop `_id` index, MongoDB server doesn't allow it
+ if (isDefaultIdIndex(index)) {
+ continue;
+ }
+
+ for (const schemaIndex of schemaIndexes) {
+ const key = schemaIndex[0];
+ const options = _decorateDiscriminatorIndexOptions(this,
+ utils.clone(schemaIndex[1]));
+ if (isIndexEqual(key, options, index)) {
+ found = true;
+ }
+ }
+
+ if (!found) {
+ toDrop.push(index.name);
+ }
+ }
+
+ if (toDrop.length === 0) {
+ return cb(null, []);
+ }
+
+ dropIndexes(toDrop, cb);
+ });
+
+ function dropIndexes(toDrop, cb) {
+ let remaining = toDrop.length;
+ let error = false;
+ toDrop.forEach(indexName => {
+ collection.dropIndex(indexName, err => {
+ if (err != null) {
+ error = true;
+ return cb(err);
+ }
+ if (!error) {
+ --remaining || cb(null, toDrop);
+ }
+ });
+ });
+ }
+ });
+};
+
+/**
+ * Lists the indexes currently defined in MongoDB. This may or may not be
+ * the same as the indexes defined in your schema depending on whether you
+ * use the [`autoIndex` option](/docs/guide.html#autoIndex) and if you
+ * build indexes manually.
+ *
+ * @param {Function} [cb] optional callback
+ * @return {Promise|undefined} Returns `undefined` if callback is specified, returns a promise if no callback.
+ * @api public
+ */
+
+Model.listIndexes = function init(callback) {
+ _checkContext(this, 'listIndexes');
+
+ const _listIndexes = cb => {
+ this.collection.listIndexes().toArray(cb);
+ };
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+
+ // Buffering
+ if (this.collection.buffer) {
+ this.collection.addQueue(_listIndexes, [cb]);
+ } else {
+ _listIndexes(cb);
+ }
+ }, this.events);
+};
+
+/**
+ * Sends `createIndex` commands to mongo for each index declared in the schema.
+ * The `createIndex` commands are sent in series.
+ *
+ * ####Example:
+ *
+ * Event.ensureIndexes(function (err) {
+ * if (err) return handleError(err);
+ * });
+ *
+ * After completion, an `index` event is emitted on this `Model` passing an error if one occurred.
+ *
+ * ####Example:
+ *
+ * const eventSchema = new Schema({ thing: { type: 'string', unique: true }})
+ * const Event = mongoose.model('Event', eventSchema);
+ *
+ * Event.on('index', function (err) {
+ * if (err) console.error(err); // error occurred during index creation
+ * })
+ *
+ * _NOTE: It is not recommended that you run this in production. Index creation may impact database performance depending on your load. Use with caution._
+ *
+ * @param {Object} [options] internal options
+ * @param {Function} [cb] optional callback
+ * @return {Promise}
+ * @api public
+ */
+
+Model.ensureIndexes = function ensureIndexes(options, callback) {
+ _checkContext(this, 'ensureIndexes');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+
+ _ensureIndexes(this, options || {}, error => {
+ if (error) {
+ return cb(error);
+ }
+ cb(null);
+ });
+ }, this.events);
+};
+
+/**
+ * Similar to `ensureIndexes()`, except for it uses the [`createIndex`](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#createIndex)
+ * function.
+ *
+ * @param {Object} [options] internal options
+ * @param {Function} [cb] optional callback
+ * @return {Promise}
+ * @api public
+ */
+
+Model.createIndexes = function createIndexes(options, callback) {
+ _checkContext(this, 'createIndexes');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ options = options || {};
+ options.createIndex = true;
+ return this.ensureIndexes(options, callback);
+};
+
+/*!
+ * ignore
+ */
+
+function _ensureIndexes(model, options, callback) {
+ const indexes = model.schema.indexes();
+ let indexError;
+
+ options = options || {};
+
+ const done = function(err) {
+ if (err && !model.$caught) {
+ model.emit('error', err);
+ }
+ model.emit('index', err || indexError);
+ callback && callback(err || indexError);
+ };
+
+ for (const index of indexes) {
+ if (isDefaultIdIndex(index)) {
+ console.warn('mongoose: Cannot specify a custom index on `_id` for ' +
+ 'model name "' + model.modelName + '", ' +
+ 'MongoDB does not allow overwriting the default `_id` index. See ' +
+ 'http://bit.ly/mongodb-id-index');
+ }
+ }
+
+ if (!indexes.length) {
+ immediate(function() {
+ done();
+ });
+ return;
+ }
+ // Indexes are created one-by-one to support how MongoDB < 2.4 deals
+ // with background indexes.
+
+ const indexSingleDone = function(err, fields, options, name) {
+ model.emit('index-single-done', err, fields, options, name);
+ };
+ const indexSingleStart = function(fields, options) {
+ model.emit('index-single-start', fields, options);
+ };
+
+ const baseSchema = model.schema._baseSchema;
+ const baseSchemaIndexes = baseSchema ? baseSchema.indexes() : [];
+
+ const create = function() {
+ if (options._automatic) {
+ if (model.schema.options.autoIndex === false ||
+ (model.schema.options.autoIndex == null && model.db.config.autoIndex === false)) {
+ return done();
+ }
+ }
+
+ const index = indexes.shift();
+ if (!index) {
+ return done();
+ }
+ if (options._automatic && index[1]._autoIndex === false) {
+ return create();
+ }
+
+ if (baseSchemaIndexes.find(i => utils.deepEqual(i, index))) {
+ return create();
+ }
+
+ const indexFields = utils.clone(index[0]);
+ const indexOptions = utils.clone(index[1]);
+ delete indexOptions._autoIndex;
+
+ _decorateDiscriminatorIndexOptions(model, indexOptions);
+ if ('safe' in options) {
+ _handleSafe(options);
+ }
+ applyWriteConcern(model.schema, indexOptions);
+
+ indexSingleStart(indexFields, options);
+ let useCreateIndex = !!model.base.options.useCreateIndex;
+ if ('useCreateIndex' in model.db.config) {
+ useCreateIndex = !!model.db.config.useCreateIndex;
+ }
+ if ('createIndex' in options) {
+ useCreateIndex = !!options.createIndex;
+ }
+ if ('background' in options) {
+ indexOptions.background = options.background;
+ }
+
+ const methodName = useCreateIndex ? 'createIndex' : 'ensureIndex';
+ model.collection[methodName](indexFields, indexOptions, utils.tick(function(err, name) {
+ indexSingleDone(err, indexFields, indexOptions, name);
+ if (err) {
+ if (!indexError) {
+ indexError = err;
+ }
+ if (!model.$caught) {
+ model.emit('error', err);
+ }
+ }
+ create();
+ }));
+ };
+
+ immediate(function() {
+ // If buffering is off, do this manually.
+ if (options._automatic && !model.collection.collection) {
+ model.collection.addQueue(create, []);
+ } else {
+ create();
+ }
+ });
+}
+
+function _decorateDiscriminatorIndexOptions(model, indexOptions) {
+ // If the model is a discriminator and it has a unique index, add a
+ // partialFilterExpression by default so the unique index will only apply
+ // to that discriminator.
+ if (model.baseModelName != null && indexOptions.unique &&
+ !('partialFilterExpression' in indexOptions) &&
+ !('sparse' in indexOptions)) {
+
+ const value = (
+ model.schema.discriminatorMapping &&
+ model.schema.discriminatorMapping.value
+ ) || model.modelName;
+
+ indexOptions.partialFilterExpression = {
+ [model.schema.options.discriminatorKey]: value
+ };
+ }
+ return indexOptions;
+}
+
+const safeDeprecationWarning = 'Mongoose: the `safe` option for `save()` is ' +
+ 'deprecated. Use the `w` option instead: http://bit.ly/mongoose-save';
+
+const _handleSafe = util.deprecate(function _handleSafe(options) {
+ if (options.safe) {
+ if (typeof options.safe === 'boolean') {
+ options.w = options.safe;
+ delete options.safe;
+ }
+ if (typeof options.safe === 'object') {
+ options.w = options.safe.w;
+ options.j = options.safe.j;
+ options.wtimeout = options.safe.wtimeout;
+ delete options.safe;
+ }
+ }
+}, safeDeprecationWarning);
+
+/**
+ * Schema the model uses.
+ *
+ * @property schema
+ * @receiver Model
+ * @api public
+ * @memberOf Model
+ */
+
+Model.schema;
+
+/*!
+ * Connection instance the model uses.
+ *
+ * @property db
+ * @api public
+ * @memberOf Model
+ */
+
+Model.db;
+
+/*!
+ * Collection the model uses.
+ *
+ * @property collection
+ * @api public
+ * @memberOf Model
+ */
+
+Model.collection;
+
+/**
+ * Base Mongoose instance the model uses.
+ *
+ * @property base
+ * @api public
+ * @memberOf Model
+ */
+
+Model.base;
+
+/**
+ * Registered discriminators for this model.
+ *
+ * @property discriminators
+ * @api public
+ * @memberOf Model
+ */
+
+Model.discriminators;
+
+/**
+ * Translate any aliases fields/conditions so the final query or document object is pure
+ *
+ * ####Example:
+ *
+ * Character
+ * .find(Character.translateAliases({
+ * '名': 'Eddard Stark' // Alias for 'name'
+ * })
+ * .exec(function(err, characters) {})
+ *
+ * ####Note:
+ * Only translate arguments of object type anything else is returned raw
+ *
+ * @param {Object} raw fields/conditions that may contain aliased keys
+ * @return {Object} the translated 'pure' fields/conditions
+ */
+Model.translateAliases = function translateAliases(fields) {
+ _checkContext(this, 'translateAliases');
+
+ const translate = (key, value) => {
+ let alias;
+ const translated = [];
+ const fieldKeys = key.split('.');
+ let currentSchema = this.schema;
+ for (const i in fieldKeys) {
+ const name = fieldKeys[i];
+ if (currentSchema && currentSchema.aliases[name]) {
+ alias = currentSchema.aliases[name];
+ // Alias found,
+ translated.push(alias);
+ } else {
+ // Alias not found, so treat as un-aliased key
+ translated.push(name);
+ }
+
+ // Check if aliased path is a schema
+ if (currentSchema && currentSchema.paths[alias]) {
+ currentSchema = currentSchema.paths[alias].schema;
+ }
+ else
+ currentSchema = null;
+ }
+
+ const translatedKey = translated.join('.');
+ if (fields instanceof Map)
+ fields.set(translatedKey, value);
+ else
+ fields[translatedKey] = value;
+
+ if (translatedKey !== key) {
+ // We'll be using the translated key instead
+ if (fields instanceof Map) {
+ // Delete from map
+ fields.delete(key);
+ } else {
+ // Delete from object
+ delete fields[key]; // We'll be using the translated key instead
+ }
+ }
+ return fields;
+ };
+
+ if (typeof fields === 'object') {
+ // Fields is an object (query conditions or document fields)
+ if (fields instanceof Map) {
+ // A Map was supplied
+ for (const field of new Map(fields)) {
+ fields = translate(field[0], field[1]);
+ }
+ } else {
+ // Infer a regular object was supplied
+ for (const key of Object.keys(fields)) {
+ fields = translate(key, fields[key]);
+ if (key[0] === '$') {
+ if (Array.isArray(fields[key])) {
+ for (const i in fields[key]) {
+ // Recursively translate nested queries
+ fields[key][i] = this.translateAliases(fields[key][i]);
+ }
+ }
+ }
+ }
+ }
+
+ return fields;
+ } else {
+ // Don't know typeof fields
+ return fields;
+ }
+};
+
+/**
+ * Removes all documents that match `conditions` from the collection.
+ * To remove just the first document that matches `conditions`, set the `single`
+ * option to true.
+ *
+ * ####Example:
+ *
+ * const res = await Character.remove({ name: 'Eddard Stark' });
+ * res.deletedCount; // Number of documents removed
+ *
+ * ####Note:
+ *
+ * This method sends a remove command directly to MongoDB, no Mongoose documents
+ * are involved. Because no Mongoose documents are involved, Mongoose does
+ * not execute [document middleware](/docs/middleware.html#types-of-middleware).
+ *
+ * @param {Object} conditions
+ * @param {Object} [options]
+ * @param {Session} [options.session=null] the [session](https://docs.mongodb.com/manual/reference/server-sessions/) associated with this operation.
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.remove = function remove(conditions, options, callback) {
+ _checkContext(this, 'remove');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ // get the mongodb collection object
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.setOptions(options);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.remove(conditions, callback);
+};
+
+/**
+ * Deletes the first document that matches `conditions` from the collection.
+ * Behaves like `remove()`, but deletes at most one document regardless of the
+ * `single` option.
+ *
+ * ####Example:
+ *
+ * await Character.deleteOne({ name: 'Eddard Stark' });
+ *
+ * ####Note:
+ *
+ * This function triggers `deleteOne` query hooks. Read the
+ * [middleware docs](/docs/middleware.html#naming) to learn more.
+ *
+ * @param {Object} conditions
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.deleteOne = function deleteOne(conditions, options, callback) {
+ _checkContext(this, 'deleteOne');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ options = null;
+ }
+ else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.setOptions(options);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.deleteOne(conditions, callback);
+};
+
+/**
+ * Deletes all of the documents that match `conditions` from the collection.
+ * Behaves like `remove()`, but deletes all documents that match `conditions`
+ * regardless of the `single` option.
+ *
+ * ####Example:
+ *
+ * await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });
+ *
+ * ####Note:
+ *
+ * This function triggers `deleteMany` query hooks. Read the
+ * [middleware docs](/docs/middleware.html#naming) to learn more.
+ *
+ * @param {Object} conditions
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.deleteMany = function deleteMany(conditions, options, callback) {
+ _checkContext(this, 'deleteMany');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.setOptions(options);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.deleteMany(conditions, callback);
+};
+
+/**
+ * Finds documents.
+ *
+ * Mongoose casts the `filter` to match the model's schema before the command is sent.
+ * See our [query casting tutorial](/docs/tutorials/query_casting.html) for
+ * more information on how Mongoose casts `filter`.
+ *
+ * ####Examples:
+ *
+ * // find all documents
+ * await MyModel.find({});
+ *
+ * // find all documents named john and at least 18
+ * await MyModel.find({ name: 'john', age: { $gte: 18 } }).exec();
+ *
+ * // executes, passing results to callback
+ * MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
+ *
+ * // executes, name LIKE john and only selecting the "name" and "friends" fields
+ * await MyModel.find({ name: /john/i }, 'name friends').exec();
+ *
+ * // passing options
+ * await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
+ *
+ * @param {Object|ObjectId} filter
+ * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](http://mongoosejs.com/docs/api.html#query_Query-select)
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @see query casting /docs/tutorials/query_casting.html
+ * @api public
+ */
+
+Model.find = function find(conditions, projection, options, callback) {
+ _checkContext(this, 'find');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ projection = null;
+ options = null;
+ } else if (typeof projection === 'function') {
+ callback = projection;
+ projection = null;
+ options = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(projection);
+
+ mq.setOptions(options);
+ if (this.schema.discriminatorMapping &&
+ this.schema.discriminatorMapping.isRoot &&
+ mq.selectedInclusively()) {
+ // Need to select discriminator key because original schema doesn't have it
+ mq.select(this.schema.options.discriminatorKey);
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.find(conditions, callback);
+};
+
+/**
+ * Finds a single document by its _id field. `findById(id)` is almost*
+ * equivalent to `findOne({ _id: id })`. If you want to query by a document's
+ * `_id`, use `findById()` instead of `findOne()`.
+ *
+ * The `id` is cast based on the Schema before sending the command.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOne()`
+ *
+ * \* Except for how it treats `undefined`. If you use `findOne()`, you'll see
+ * that `findOne(undefined)` and `findOne({ _id: undefined })` are equivalent
+ * to `findOne({})` and return arbitrary documents. However, mongoose
+ * translates `findById(undefined)` into `findOne({ _id: null })`.
+ *
+ * ####Example:
+ *
+ * // Find the adventure with the given `id`, or `null` if not found
+ * await Adventure.findById(id).exec();
+ *
+ * // using callback
+ * Adventure.findById(id, function (err, adventure) {});
+ *
+ * // select only the adventures name and length
+ * await Adventure.findById(id, 'name length').exec();
+ *
+ * @param {Any} id value of `_id` to query by
+ * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @see lean queries /docs/tutorials/lean.html
+ * @see findById in Mongoose https://masteringjs.io/tutorials/mongoose/find-by-id
+ * @api public
+ */
+
+Model.findById = function findById(id, projection, options, callback) {
+ _checkContext(this, 'findById');
+
+ if (typeof id === 'undefined') {
+ id = null;
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return this.findOne({ _id: id }, projection, options, callback);
+};
+
+/**
+ * Finds one document.
+ *
+ * The `conditions` are cast to their respective SchemaTypes before the command is sent.
+ *
+ * *Note:* `conditions` is optional, and if `conditions` is null or undefined,
+ * mongoose will send an empty `findOne` command to MongoDB, which will return
+ * an arbitrary document. If you're querying by `_id`, use `findById()` instead.
+ *
+ * ####Example:
+ *
+ * // Find one adventure whose `country` is 'Croatia', otherwise `null`
+ * await Adventure.findOne({ country: 'Croatia' }).exec();
+ *
+ * // using callback
+ * Adventure.findOne({ country: 'Croatia' }, function (err, adventure) {});
+ *
+ * // select only the adventures name and length
+ * await Adventure.findOne({ country: 'Croatia' }, 'name length').exec();
+ *
+ * @param {Object} [conditions]
+ * @param {Object|String|Array<String>} [projection] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see field selection #query_Query-select
+ * @see lean queries /docs/tutorials/lean.html
+ * @api public
+ */
+
+Model.findOne = function findOne(conditions, projection, options, callback) {
+ _checkContext(this, 'findOne');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ } else if (typeof projection === 'function') {
+ callback = projection;
+ projection = null;
+ options = null;
+ } else if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ projection = null;
+ options = null;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(projection);
+
+ mq.setOptions(options);
+ if (this.schema.discriminatorMapping &&
+ this.schema.discriminatorMapping.isRoot &&
+ mq.selectedInclusively()) {
+ mq.select(this.schema.options.discriminatorKey);
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.findOne(conditions, callback);
+};
+
+/**
+ * Estimates the number of documents in the MongoDB collection. Faster than
+ * using `countDocuments()` for large collections because
+ * `estimatedDocumentCount()` uses collection metadata rather than scanning
+ * the entire collection.
+ *
+ * ####Example:
+ *
+ * const numAdventures = Adventure.estimatedDocumentCount();
+ *
+ * @param {Object} [options]
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.estimatedDocumentCount = function estimatedDocumentCount(options, callback) {
+ _checkContext(this, 'estimatedDocumentCount');
+
+ const mq = new this.Query({}, {}, this, this.collection);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.estimatedDocumentCount(options, callback);
+};
+
+/**
+ * Counts number of documents matching `filter` in a database collection.
+ *
+ * ####Example:
+ *
+ * Adventure.countDocuments({ type: 'jungle' }, function (err, count) {
+ * console.log('there are %d jungle adventures', count);
+ * });
+ *
+ * If you want to count all documents in a large collection,
+ * use the [`estimatedDocumentCount()` function](/docs/api.html#model_Model.estimatedDocumentCount)
+ * instead. If you call `countDocuments({})`, MongoDB will always execute
+ * a full collection scan and **not** use any indexes.
+ *
+ * The `countDocuments()` function is similar to `count()`, but there are a
+ * [few operators that `countDocuments()` does not support](https://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#countDocuments).
+ * Below are the operators that `count()` supports but `countDocuments()` does not,
+ * and the suggested replacement:
+ *
+ * - `$where`: [`$expr`](https://docs.mongodb.com/manual/reference/operator/query/expr/)
+ * - `$near`: [`$geoWithin`](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/) with [`$center`](https://docs.mongodb.com/manual/reference/operator/query/center/#op._S_center)
+ * - `$nearSphere`: [`$geoWithin`](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/) with [`$centerSphere`](https://docs.mongodb.com/manual/reference/operator/query/centerSphere/#op._S_centerSphere)
+ *
+ * @param {Object} filter
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.countDocuments = function countDocuments(conditions, callback) {
+ _checkContext(this, 'countDocuments');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.countDocuments(conditions, callback);
+};
+
+/**
+ * Counts number of documents that match `filter` in a database collection.
+ *
+ * This method is deprecated. If you want to count the number of documents in
+ * a collection, e.g. `count({})`, use the [`estimatedDocumentCount()` function](/docs/api.html#model_Model.estimatedDocumentCount)
+ * instead. Otherwise, use the [`countDocuments()`](/docs/api.html#model_Model.countDocuments) function instead.
+ *
+ * ####Example:
+ *
+ * Adventure.count({ type: 'jungle' }, function (err, count) {
+ * if (err) ..
+ * console.log('there are %d jungle adventures', count);
+ * });
+ *
+ * @deprecated
+ * @param {Object} filter
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.count = function count(conditions, callback) {
+ _checkContext(this, 'count');
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+
+ callback = this.$handleCallbackError(callback);
+
+ return mq.count(conditions, callback);
+};
+
+/**
+ * Creates a Query for a `distinct` operation.
+ *
+ * Passing a `callback` executes the query.
+ *
+ * ####Example
+ *
+ * Link.distinct('url', { clicks: {$gt: 100}}, function (err, result) {
+ * if (err) return handleError(err);
+ *
+ * assert(Array.isArray(result));
+ * console.log('unique urls with more than 100 clicks', result);
+ * })
+ *
+ * const query = Link.distinct('url');
+ * query.exec(callback);
+ *
+ * @param {String} field
+ * @param {Object} [conditions] optional
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.distinct = function distinct(field, conditions, callback) {
+ _checkContext(this, 'distinct');
+
+ const mq = new this.Query({}, {}, this, this.collection);
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ }
+ callback = this.$handleCallbackError(callback);
+
+ return mq.distinct(field, conditions, callback);
+};
+
+/**
+ * Creates a Query, applies the passed conditions, and returns the Query.
+ *
+ * For example, instead of writing:
+ *
+ * User.find({age: {$gte: 21, $lte: 65}}, callback);
+ *
+ * we can instead write:
+ *
+ * User.where('age').gte(21).lte(65).exec(callback);
+ *
+ * Since the Query class also supports `where` you can continue chaining
+ *
+ * User
+ * .where('age').gte(21).lte(65)
+ * .where('name', /^b/i)
+ * ... etc
+ *
+ * @param {String} path
+ * @param {Object} [val] optional value
+ * @return {Query}
+ * @api public
+ */
+
+Model.where = function where(path, val) {
+ _checkContext(this, 'where');
+
+ void val; // eslint
+ const mq = new this.Query({}, {}, this, this.collection).find({});
+ return mq.where.apply(mq, arguments);
+};
+
+/**
+ * Creates a `Query` and specifies a `$where` condition.
+ *
+ * Sometimes you need to query for things in mongodb using a JavaScript expression. You can do so via `find({ $where: javascript })`, or you can use the mongoose shortcut method $where via a Query chain or from your mongoose Model.
+ *
+ * Blog.$where('this.username.indexOf("val") !== -1').exec(function (err, docs) {});
+ *
+ * @param {String|Function} argument is a javascript string or anonymous function
+ * @method $where
+ * @memberOf Model
+ * @return {Query}
+ * @see Query.$where #query_Query-%24where
+ * @api public
+ */
+
+Model.$where = function $where() {
+ _checkContext(this, '$where');
+
+ const mq = new this.Query({}, {}, this, this.collection).find({});
+ return mq.$where.apply(mq, arguments);
+};
+
+/**
+ * Issues a mongodb findAndModify update command.
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found document (if any) to the callback. The query executes if `callback` is passed else a Query object is returned.
+ *
+ * ####Options:
+ *
+ * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `overwrite`: bool - if true, replace the entire document.
+ * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()`
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findOneAndUpdate(conditions, update, options, callback) // executes
+ * A.findOneAndUpdate(conditions, update, options) // returns Query
+ * A.findOneAndUpdate(conditions, update, callback) // executes
+ * A.findOneAndUpdate(conditions, update) // returns Query
+ * A.findOneAndUpdate() // returns Query
+ *
+ * ####Note:
+ *
+ * All top level update keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * const query = { name: 'borne' };
+ * Model.findOneAndUpdate(query, { name: 'jason bourne' }, options, callback)
+ *
+ * // is sent as
+ * Model.findOneAndUpdate(query, { $set: { name: 'jason bourne' }}, options, callback)
+ *
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
+ *
+ * ####Note:
+ *
+ * Values are cast to their appropriate types when using the findAndModify helpers.
+ * However, the below are not executed by default.
+ *
+ * - defaults. Use the `setDefaultsOnInsert` option to override.
+ *
+ * `findAndModify` helpers support limited validation. You can
+ * enable these by setting the `runValidators` options,
+ * respectively.
+ *
+ * If you need full-fledged validation, use the traditional approach of first
+ * retrieving the document.
+ *
+ * Model.findById(id, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason bourne';
+ * doc.save(callback);
+ * });
+ *
+ * @param {Object} [conditions]
+ * @param {Object} [update]
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
+ * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `update`, Mongoose will wrap `update` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`. An alternative to this would be using [Model.findOneAndReplace(conditions, update, options, callback)](https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndReplace).
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Tutorial /docs/tutorials/findoneandupdate.html
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findOneAndUpdate = function(conditions, update, options, callback) {
+ _checkContext(this, 'findOneAndUpdate');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ } else if (arguments.length === 1) {
+ if (typeof conditions === 'function') {
+ const msg = 'Model.findOneAndUpdate(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options, callback)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update, options)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(conditions, update)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate(update)\n'
+ + ' ' + this.modelName + '.findOneAndUpdate()\n';
+ throw new TypeError(msg);
+ }
+ update = conditions;
+ conditions = undefined;
+ }
+ callback = this.$handleCallbackError(callback);
+
+ let fields;
+ if (options) {
+ fields = options.fields || options.projection;
+ }
+
+ update = utils.clone(update, {
+ depopulate: true,
+ _isNested: true
+ });
+
+ _decorateUpdateWithVersionKey(update, options, this.schema.options.versionKey);
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(fields);
+
+ return mq.findOneAndUpdate(conditions, update, options, callback);
+};
+
+/*!
+ * Decorate the update with a version key, if necessary
+ */
+
+function _decorateUpdateWithVersionKey(update, options, versionKey) {
+ if (!versionKey || !get(options, 'upsert', false)) {
+ return;
+ }
+
+ const updatedPaths = modifiedPaths(update);
+ if (!updatedPaths[versionKey]) {
+ if (options.overwrite) {
+ update[versionKey] = 0;
+ } else {
+ if (!update.$setOnInsert) {
+ update.$setOnInsert = {};
+ }
+ update.$setOnInsert[versionKey] = 0;
+ }
+ }
+}
+
+/**
+ * Issues a mongodb findAndModify update command by a document's _id field.
+ * `findByIdAndUpdate(id, ...)` is equivalent to `findOneAndUpdate({ _id: id }, ...)`.
+ *
+ * Finds a matching document, updates it according to the `update` arg,
+ * passing any `options`, and returns the found document (if any) to the
+ * callback. The query executes if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndUpdate()`
+ *
+ * ####Options:
+ *
+ * - `new`: bool - true to return the modified document rather than the original. defaults to false
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findByIdAndUpdate(id, update, options, callback) // executes
+ * A.findByIdAndUpdate(id, update, options) // returns Query
+ * A.findByIdAndUpdate(id, update, callback) // executes
+ * A.findByIdAndUpdate(id, update) // returns Query
+ * A.findByIdAndUpdate() // returns Query
+ *
+ * ####Note:
+ *
+ * All top level update keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * Model.findByIdAndUpdate(id, { name: 'jason bourne' }, options, callback)
+ *
+ * // is sent as
+ * Model.findByIdAndUpdate(id, { $set: { name: 'jason bourne' }}, options, callback)
+ *
+ * This helps prevent accidentally overwriting your document with `{ name: 'jason bourne' }`.
+ *
+ * ####Note:
+ *
+ * Values are cast to their appropriate types when using the findAndModify helpers.
+ * However, the below are not executed by default.
+ *
+ * - defaults. Use the `setDefaultsOnInsert` option to override.
+ *
+ * `findAndModify` helpers support limited validation. You can
+ * enable these by setting the `runValidators` options,
+ * respectively.
+ *
+ * If you need full-fledged validation, use the traditional approach of first
+ * retrieving the document.
+ *
+ * Model.findById(id, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason bourne';
+ * doc.save(callback);
+ * });
+ *
+ * @param {Object|Number|String} id value of `_id` to query by
+ * @param {Object} [update]
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean} [options.new=false] By default, `findByIdAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
+ * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `update`, Mongoose will wrap `update` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`. An alternative to this would be using [Model.findOneAndReplace({ _id: id }, update, options, callback)](https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndReplace).
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Model.findOneAndUpdate #model_Model.findOneAndUpdate
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findByIdAndUpdate = function(id, update, options, callback) {
+ _checkContext(this, 'findByIdAndUpdate');
+
+ callback = this.$handleCallbackError(callback);
+ if (arguments.length === 1) {
+ if (typeof id === 'function') {
+ const msg = 'Model.findByIdAndUpdate(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate(id, callback)\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate(id)\n'
+ + ' ' + this.modelName + '.findByIdAndUpdate()\n';
+ throw new TypeError(msg);
+ }
+ return this.findOneAndUpdate({ _id: id }, undefined);
+ }
+
+ // if a model is passed in instead of an id
+ if (id instanceof Document) {
+ id = id._id;
+ }
+
+ return this.findOneAndUpdate.call(this, { _id: id }, update, options, callback);
+};
+
+/**
+ * Issue a MongoDB `findOneAndDelete()` command.
+ *
+ * Finds a matching document, removes it, and passes the found document
+ * (if any) to the callback.
+ *
+ * Executes the query if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndDelete()`
+ *
+ * This function differs slightly from `Model.findOneAndRemove()` in that
+ * `findOneAndRemove()` becomes a [MongoDB `findAndModify()` command](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/),
+ * as opposed to a `findOneAndDelete()` command. For most mongoose use cases,
+ * this distinction is purely pedantic. You should use `findOneAndDelete()`
+ * unless you have a good reason not to.
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `select`: sets the document fields to return, ex. `{ projection: { _id: 0 } }`
+ * - `projection`: equivalent to `select`
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findOneAndDelete(conditions, options, callback) // executes
+ * A.findOneAndDelete(conditions, options) // return Query
+ * A.findOneAndDelete(conditions, callback) // executes
+ * A.findOneAndDelete(conditions) // returns Query
+ * A.findOneAndDelete() // returns Query
+ *
+ * Values are cast to their appropriate types when using the findAndModify helpers.
+ * However, the below are not executed by default.
+ *
+ * - defaults. Use the `setDefaultsOnInsert` option to override.
+ *
+ * `findAndModify` helpers support limited validation. You can
+ * enable these by setting the `runValidators` options,
+ * respectively.
+ *
+ * If you need full-fledged validation, use the traditional approach of first
+ * retrieving the document.
+ *
+ * Model.findById(id, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason bourne';
+ * doc.save(callback);
+ * });
+ *
+ * @param {Object} conditions
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.findOneAndDelete = function(conditions, options, callback) {
+ _checkContext(this, 'findOneAndDelete');
+
+ if (arguments.length === 1 && typeof conditions === 'function') {
+ const msg = 'Model.findOneAndDelete(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndDelete(conditions, callback)\n'
+ + ' ' + this.modelName + '.findOneAndDelete(conditions)\n'
+ + ' ' + this.modelName + '.findOneAndDelete()\n';
+ throw new TypeError(msg);
+ }
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = undefined;
+ }
+ callback = this.$handleCallbackError(callback);
+
+ let fields;
+ if (options) {
+ fields = options.select;
+ options.select = undefined;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(fields);
+
+ return mq.findOneAndDelete(conditions, options, callback);
+};
+
+/**
+ * Issue a MongoDB `findOneAndDelete()` command by a document's _id field.
+ * In other words, `findByIdAndDelete(id)` is a shorthand for
+ * `findOneAndDelete({ _id: id })`.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndDelete()`
+ *
+ * @param {Object|Number|String} id value of `_id` to query by
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Model.findOneAndRemove #model_Model.findOneAndRemove
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ */
+
+Model.findByIdAndDelete = function(id, options, callback) {
+ _checkContext(this, 'findByIdAndDelete');
+
+ if (arguments.length === 1 && typeof id === 'function') {
+ const msg = 'Model.findByIdAndDelete(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findByIdAndDelete(id, callback)\n'
+ + ' ' + this.modelName + '.findByIdAndDelete(id)\n'
+ + ' ' + this.modelName + '.findByIdAndDelete()\n';
+ throw new TypeError(msg);
+ }
+ callback = this.$handleCallbackError(callback);
+
+ return this.findOneAndDelete({ _id: id }, options, callback);
+};
+
+/**
+ * Issue a MongoDB `findOneAndReplace()` command.
+ *
+ * Finds a matching document, replaces it with the provided doc, and passes the
+ * returned doc to the callback.
+ *
+ * Executes the query if `callback` is passed.
+ *
+ * This function triggers the following query middleware.
+ *
+ * - `findOneAndReplace()`
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `select`: sets the document fields to return
+ * - `projection`: like select, it determines which fields to return, ex. `{ projection: { _id: 0 } }`
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findOneAndReplace(conditions, options, callback) // executes
+ * A.findOneAndReplace(conditions, options) // return Query
+ * A.findOneAndReplace(conditions, callback) // executes
+ * A.findOneAndReplace(conditions) // returns Query
+ * A.findOneAndReplace() // returns Query
+ *
+ * Values are cast to their appropriate types when using the findAndModify helpers.
+ * However, the below are not executed by default.
+ *
+ * - defaults. Use the `setDefaultsOnInsert` option to override.
+ *
+ * @param {Object} filter Replace the first document that matches this filter
+ * @param {Object} [replacement] Replace with this document
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean} [options.new=false] By default, `findOneAndReplace()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndReplace()` will instead give you the object after `update` was applied. To change the default to `true`, use `mongoose.set('returnOriginal', false);`.
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
+ * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @api public
+ */
+
+Model.findOneAndReplace = function(filter, replacement, options, callback) {
+ _checkContext(this, 'findOneAndReplace');
+
+ if (arguments.length === 1 && typeof filter === 'function') {
+ const msg = 'Model.findOneAndReplace(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndReplace(conditions, callback)\n'
+ + ' ' + this.modelName + '.findOneAndReplace(conditions)\n'
+ + ' ' + this.modelName + '.findOneAndReplace()\n';
+ throw new TypeError(msg);
+ }
+
+ if (arguments.length === 3 && typeof options === 'function') {
+ callback = options;
+ options = replacement;
+ replacement = void 0;
+ }
+ if (arguments.length === 2 && typeof replacement === 'function') {
+ callback = replacement;
+ replacement = void 0;
+ options = void 0;
+ }
+ callback = this.$handleCallbackError(callback);
+
+ let fields;
+ if (options) {
+ fields = options.select;
+ options.select = undefined;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(fields);
+
+ return mq.findOneAndReplace(filter, replacement, options, callback);
+};
+
+/**
+ * Issue a mongodb findAndModify remove command.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to the callback.
+ *
+ * Executes the query if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndRemove()`
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `select`: sets the document fields to return
+ * - `projection`: like select, it determines which fields to return, ex. `{ projection: { _id: 0 } }`
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findOneAndRemove(conditions, options, callback) // executes
+ * A.findOneAndRemove(conditions, options) // return Query
+ * A.findOneAndRemove(conditions, callback) // executes
+ * A.findOneAndRemove(conditions) // returns Query
+ * A.findOneAndRemove() // returns Query
+ *
+ * Values are cast to their appropriate types when using the findAndModify helpers.
+ * However, the below are not executed by default.
+ *
+ * - defaults. Use the `setDefaultsOnInsert` option to override.
+ *
+ * `findAndModify` helpers support limited validation. You can
+ * enable these by setting the `runValidators` options,
+ * respectively.
+ *
+ * If you need full-fledged validation, use the traditional approach of first
+ * retrieving the document.
+ *
+ * Model.findById(id, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason bourne';
+ * doc.save(callback);
+ * });
+ *
+ * @param {Object} conditions
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Model.findOneAndRemove = function(conditions, options, callback) {
+ _checkContext(this, 'findOneAndRemove');
+
+ if (arguments.length === 1 && typeof conditions === 'function') {
+ const msg = 'Model.findOneAndRemove(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findOneAndRemove(conditions, callback)\n'
+ + ' ' + this.modelName + '.findOneAndRemove(conditions)\n'
+ + ' ' + this.modelName + '.findOneAndRemove()\n';
+ throw new TypeError(msg);
+ }
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = undefined;
+ }
+ callback = this.$handleCallbackError(callback);
+
+ let fields;
+ if (options) {
+ fields = options.select;
+ options.select = undefined;
+ }
+
+ const mq = new this.Query({}, {}, this, this.collection);
+ mq.select(fields);
+
+ return mq.findOneAndRemove(conditions, options, callback);
+};
+
+/**
+ * Issue a mongodb findAndModify remove command by a document's _id field. `findByIdAndRemove(id, ...)` is equivalent to `findOneAndRemove({ _id: id }, ...)`.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to the callback.
+ *
+ * Executes the query if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndRemove()`
+ *
+ * ####Options:
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `select`: sets the document fields to return
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `strict`: overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict) for this update
+ *
+ * ####Examples:
+ *
+ * A.findByIdAndRemove(id, options, callback) // executes
+ * A.findByIdAndRemove(id, options) // return Query
+ * A.findByIdAndRemove(id, callback) // executes
+ * A.findByIdAndRemove(id) // returns Query
+ * A.findByIdAndRemove() // returns Query
+ *
+ * @param {Object|Number|String} id value of `_id` to query by
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Object|String|Array<String>} [options.projection=null] optional fields to return, see [`Query.prototype.select()`](#query_Query-select)
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see Model.findOneAndRemove #model_Model.findOneAndRemove
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ */
+
+Model.findByIdAndRemove = function(id, options, callback) {
+ _checkContext(this, 'findByIdAndRemove');
+
+ if (arguments.length === 1 && typeof id === 'function') {
+ const msg = 'Model.findByIdAndRemove(): First argument must not be a function.\n\n'
+ + ' ' + this.modelName + '.findByIdAndRemove(id, callback)\n'
+ + ' ' + this.modelName + '.findByIdAndRemove(id)\n'
+ + ' ' + this.modelName + '.findByIdAndRemove()\n';
+ throw new TypeError(msg);
+ }
+ callback = this.$handleCallbackError(callback);
+
+ return this.findOneAndRemove({ _id: id }, options, callback);
+};
+
+/**
+ * Shortcut for saving one or more documents to the database.
+ * `MyModel.create(docs)` does `new MyModel(doc).save()` for every doc in
+ * docs.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `save()`
+ *
+ * ####Example:
+ *
+ * // Insert one new `Character` document
+ * await Character.create({ name: 'Jean-Luc Picard' });
+ *
+ * // Insert multiple new `Character` documents
+ * await Character.create([{ name: 'Will Riker' }, { name: 'Geordi LaForge' }]);
+ *
+ * // Create a new character within a transaction. Note that you **must**
+ * // pass an array as the first parameter to `create()` if you want to
+ * // specify options.
+ * await Character.create([{ name: 'Jean-Luc Picard' }], { session });
+ *
+ * @param {Array|Object} docs Documents to insert, as a spread or array
+ * @param {Object} [options] Options passed down to `save()`. To specify `options`, `docs` **must** be an array, not a spread.
+ * @param {Function} [callback] callback
+ * @return {Promise}
+ * @api public
+ */
+
+Model.create = function create(doc, options, callback) {
+ _checkContext(this, 'create');
+
+ let args;
+ let cb;
+ const discriminatorKey = this.schema.options.discriminatorKey;
+
+ if (Array.isArray(doc)) {
+ args = doc;
+ cb = typeof options === 'function' ? options : callback;
+ options = options != null && typeof options === 'object' ? options : {};
+ } else {
+ const last = arguments[arguments.length - 1];
+ options = {};
+ // Handle falsy callbacks re: #5061
+ if (typeof last === 'function' || !last) {
+ cb = last;
+ args = utils.args(arguments, 0, arguments.length - 1);
+ } else {
+ args = utils.args(arguments);
+ }
+
+ if (args.length === 2 &&
+ args[0] != null &&
+ args[1] != null &&
+ args[0].session == null &&
+ last.session != null &&
+ last.session.constructor.name === 'ClientSession' &&
+ !this.schema.path('session')) {
+ // Probably means the user is running into the common mistake of trying
+ // to use a spread to specify options, see gh-7535
+ console.warn('WARNING: to pass a `session` to `Model.create()` in ' +
+ 'Mongoose, you **must** pass an array as the first argument. See: ' +
+ 'https://mongoosejs.com/docs/api.html#model_Model.create');
+ }
+ }
+
+ return promiseOrCallback(cb, cb => {
+ cb = this.$wrapCallback(cb);
+ if (args.length === 0) {
+ return cb(null);
+ }
+
+ const toExecute = [];
+ let firstError;
+ args.forEach(doc => {
+ toExecute.push(callback => {
+ const Model = this.discriminators && doc[discriminatorKey] != null ?
+ this.discriminators[doc[discriminatorKey]] || getDiscriminatorByValue(this, doc[discriminatorKey]) :
+ this;
+ if (Model == null) {
+ throw new MongooseError(`Discriminator "${doc[discriminatorKey]}" not ` +
+ `found for model "${this.modelName}"`);
+ }
+ let toSave = doc;
+ const callbackWrapper = (error, doc) => {
+ if (error) {
+ if (!firstError) {
+ firstError = error;
+ }
+ return callback(null, { error: error });
+ }
+ callback(null, { doc: doc });
+ };
+
+ if (!(toSave instanceof Model)) {
+ try {
+ toSave = new Model(toSave);
+ } catch (error) {
+ return callbackWrapper(error);
+ }
+ }
+
+ toSave.save(options, callbackWrapper);
+ });
+ });
+
+ let numFns = toExecute.length;
+ if (numFns === 0) {
+ return cb(null, []);
+ }
+ const _done = (error, res) => {
+ const savedDocs = [];
+ const len = res.length;
+ for (let i = 0; i < len; ++i) {
+ if (res[i].doc) {
+ savedDocs.push(res[i].doc);
+ }
+ }
+
+ if (firstError) {
+ return cb(firstError, savedDocs);
+ }
+
+ if (doc instanceof Array) {
+ cb(null, savedDocs);
+ } else {
+ cb.apply(this, [null].concat(savedDocs));
+ }
+ };
+
+ const _res = [];
+ toExecute.forEach((fn, i) => {
+ fn((err, res) => {
+ _res[i] = res;
+ if (--numFns <= 0) {
+ return _done(null, _res);
+ }
+ });
+ });
+ }, this.events);
+};
+
+/**
+ * _Requires a replica set running MongoDB >= 3.6.0._ Watches the
+ * underlying collection for changes using
+ * [MongoDB change streams](https://docs.mongodb.com/manual/changeStreams/).
+ *
+ * This function does **not** trigger any middleware. In particular, it
+ * does **not** trigger aggregate middleware.
+ *
+ * The ChangeStream object is an event emitter that emits the following events:
+ *
+ * - 'change': A change occurred, see below example
+ * - 'error': An unrecoverable error occurred. In particular, change streams currently error out if they lose connection to the replica set primary. Follow [this GitHub issue](https://github.com/Automattic/mongoose/issues/6799) for updates.
+ * - 'end': Emitted if the underlying stream is closed
+ * - 'close': Emitted if the underlying stream is closed
+ *
+ * ####Example:
+ *
+ * const doc = await Person.create({ name: 'Ned Stark' });
+ * const changeStream = Person.watch().on('change', change => console.log(change));
+ * // Will print from the above `console.log()`:
+ * // { _id: { _data: ... },
+ * // operationType: 'delete',
+ * // ns: { db: 'mydb', coll: 'Person' },
+ * // documentKey: { _id: 5a51b125c5500f5aa094c7bd } }
+ * await doc.remove();
+ *
+ * @param {Array} [pipeline]
+ * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/Collection.html#watch)
+ * @return {ChangeStream} mongoose-specific change stream wrapper, inherits from EventEmitter
+ * @api public
+ */
+
+Model.watch = function(pipeline, options) {
+ _checkContext(this, 'watch');
+
+ const changeStreamThunk = cb => {
+ if (this.collection.buffer) {
+ this.collection.addQueue(() => {
+ if (this.closed) {
+ return;
+ }
+ const driverChangeStream = this.collection.watch(pipeline, options);
+ cb(null, driverChangeStream);
+ });
+ } else {
+ const driverChangeStream = this.collection.watch(pipeline, options);
+ cb(null, driverChangeStream);
+ }
+ };
+
+ return new ChangeStream(changeStreamThunk, pipeline, options);
+};
+
+/**
+ * _Requires MongoDB >= 3.6.0._ Starts a [MongoDB session](https://docs.mongodb.com/manual/release-notes/3.6/#client-sessions)
+ * for benefits like causal consistency, [retryable writes](https://docs.mongodb.com/manual/core/retryable-writes/),
+ * and [transactions](http://thecodebarbarian.com/a-node-js-perspective-on-mongodb-4-transactions.html).
+ *
+ * Calling `MyModel.startSession()` is equivalent to calling `MyModel.db.startSession()`.
+ *
+ * This function does not trigger any middleware.
+ *
+ * ####Example:
+ *
+ * const session = await Person.startSession();
+ * let doc = await Person.findOne({ name: 'Ned Stark' }, null, { session });
+ * await doc.remove();
+ * // `doc` will always be null, even if reading from a replica set
+ * // secondary. Without causal consistency, it is possible to
+ * // get a doc back from the below query if the query reads from a
+ * // secondary that is experiencing replication lag.
+ * doc = await Person.findOne({ name: 'Ned Stark' }, null, { session, readPreference: 'secondary' });
+ *
+ * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/3.0/api/MongoClient.html#startSession)
+ * @param {Boolean} [options.causalConsistency=true] set to false to disable causal consistency
+ * @param {Function} [callback]
+ * @return {Promise<ClientSession>} promise that resolves to a MongoDB driver `ClientSession`
+ * @api public
+ */
+
+Model.startSession = function() {
+ _checkContext(this, 'startSession');
+
+ return this.db.startSession.apply(this.db, arguments);
+};
+
+/**
+ * Shortcut for validating an array of documents and inserting them into
+ * MongoDB if they're all valid. This function is faster than `.create()`
+ * because it only sends one operation to the server, rather than one for each
+ * document.
+ *
+ * Mongoose always validates each document **before** sending `insertMany`
+ * to MongoDB. So if one document has a validation error, no documents will
+ * be saved, unless you set
+ * [the `ordered` option to false](https://docs.mongodb.com/manual/reference/method/db.collection.insertMany/#error-handling).
+ *
+ * This function does **not** trigger save middleware.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `insertMany()`
+ *
+ * ####Example:
+ *
+ * const arr = [{ name: 'Star Wars' }, { name: 'The Empire Strikes Back' }];
+ * Movies.insertMany(arr, function(error, docs) {});
+ *
+ * @param {Array|Object|*} doc(s)
+ * @param {Object} [options] see the [mongodb driver options](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#insertMany)
+ * @param {Boolean} [options.ordered = true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an "unordered" `insertMany()`.
+ * @param {Boolean} [options.rawResult = false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~insertWriteOpCallback) with a `mongoose` property that contains `validationErrors` if this is an unordered `insertMany`.
+ * @param {Boolean} [options.lean = false] if `true`, skips hydrating and validating the documents. This option is useful if you need the extra performance, but Mongoose won't validate the documents before inserting.
+ * @param {Number} [options.limit = null] this limits the number of documents being processed (validation/casting) by mongoose in parallel, this does **NOT** send the documents in batches to MongoDB. Use this option if you're processing a large number of documents and your app is running out of memory.
+ * @param {Function} [callback] callback
+ * @return {Promise} resolving to the raw result from the MongoDB driver if `options.rawResult` was `true`, or the documents that passed validation, otherwise
+ * @api public
+ */
+
+Model.insertMany = function(arr, options, callback) {
+ _checkContext(this, 'insertMany');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ return promiseOrCallback(callback, cb => {
+ this.$__insertMany(arr, options, cb);
+ }, this.events);
+};
+
+/*!
+ * ignore
+ */
+
+Model.$__insertMany = function(arr, options, callback) {
+ const _this = this;
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ if (callback) {
+ callback = this.$handleCallbackError(callback);
+ callback = this.$wrapCallback(callback);
+ }
+ callback = callback || utils.noop;
+ options = options || {};
+ const limit = get(options, 'limit', 1000);
+ const rawResult = get(options, 'rawResult', false);
+ const ordered = get(options, 'ordered', true);
+ const lean = get(options, 'lean', false);
+
+ if (!Array.isArray(arr)) {
+ arr = [arr];
+ }
+
+ const validationErrors = [];
+ const toExecute = arr.map(doc =>
+ callback => {
+ if (!(doc instanceof _this)) {
+ try {
+ doc = new _this(doc);
+ } catch (err) {
+ return callback(err);
+ }
+ }
+ if (options.session != null) {
+ doc.$session(options.session);
+ }
+ // If option `lean` is set to true bypass validation
+ if (lean) {
+ // we have to execute callback at the nextTick to be compatible
+ // with parallelLimit, as `results` variable has TDZ issue if we
+ // execute the callback synchronously
+ return process.nextTick(() => callback(null, doc));
+ }
+ doc.validate({ __noPromise: true }, function(error) {
+ if (error) {
+ // Option `ordered` signals that insert should be continued after reaching
+ // a failing insert. Therefore we delegate "null", meaning the validation
+ // failed. It's up to the next function to filter out all failed models
+ if (ordered === false) {
+ validationErrors.push(error);
+ return callback(null, null);
+ }
+ return callback(error);
+ }
+ callback(null, doc);
+ });
+ });
+
+ parallelLimit(toExecute, limit, function(error, docs) {
+ if (error) {
+ callback(error, null);
+ return;
+ }
+ // We filter all failed pre-validations by removing nulls
+ const docAttributes = docs.filter(function(doc) {
+ return doc != null;
+ });
+ // Quickly escape while there aren't any valid docAttributes
+ if (docAttributes.length < 1) {
+ if (rawResult) {
+ const res = {
+ mongoose: {
+ validationErrors: validationErrors
+ }
+ };
+ return callback(null, res);
+ }
+ callback(null, []);
+ return;
+ }
+ const docObjects = docAttributes.map(function(doc) {
+ if (doc.schema.options.versionKey) {
+ doc[doc.schema.options.versionKey] = 0;
+ }
+ if (doc.initializeTimestamps) {
+ return doc.initializeTimestamps().toObject(internalToObjectOptions);
+ }
+ return doc.toObject(internalToObjectOptions);
+ });
+
+ _this.collection.insertMany(docObjects, options, function(error, res) {
+ if (error) {
+ // `writeErrors` is a property reported by the MongoDB driver,
+ // just not if there's only 1 error.
+ if (error.writeErrors == null &&
+ get(error, 'result.result.writeErrors') != null) {
+ error.writeErrors = error.result.result.writeErrors;
+ }
+
+ // `insertedDocs` is a Mongoose-specific property
+ const erroredIndexes = new Set(get(error, 'writeErrors', []).map(err => err.index));
+ error.insertedDocs = docAttributes.filter((doc, i) => {
+ return !erroredIndexes.has(i);
+ });
+
+ callback(error, null);
+ return;
+ }
+
+ for (const attribute of docAttributes) {
+ attribute.$__reset();
+ _setIsNew(attribute, false);
+ }
+
+ if (rawResult) {
+ if (ordered === false) {
+ // Decorate with mongoose validation errors in case of unordered,
+ // because then still do `insertMany()`
+ res.mongoose = {
+ validationErrors: validationErrors
+ };
+ }
+ return callback(null, res);
+ }
+ callback(null, docAttributes);
+ });
+ });
+};
+
+/*!
+ * ignore
+ */
+
+function _setIsNew(doc, val) {
+ doc.isNew = val;
+ doc.emit('isNew', val);
+ doc.constructor.emit('isNew', val);
+
+ const subdocs = doc.$__getAllSubdocs();
+ for (const subdoc of subdocs) {
+ subdoc.isNew = val;
+ }
+}
+
+/**
+ * Sends multiple `insertOne`, `updateOne`, `updateMany`, `replaceOne`,
+ * `deleteOne`, and/or `deleteMany` operations to the MongoDB server in one
+ * command. This is faster than sending multiple independent operations (e.g.
+ * if you use `create()`) because with `bulkWrite()` there is only one round
+ * trip to MongoDB.
+ *
+ * Mongoose will perform casting on all operations you provide.
+ *
+ * This function does **not** trigger any middleware, neither `save()`, nor `update()`.
+ * If you need to trigger
+ * `save()` middleware for every document use [`create()`](http://mongoosejs.com/docs/api.html#model_Model.create) instead.
+ *
+ * ####Example:
+ *
+ * Character.bulkWrite([
+ * {
+ * insertOne: {
+ * document: {
+ * name: 'Eddard Stark',
+ * title: 'Warden of the North'
+ * }
+ * }
+ * },
+ * {
+ * updateOne: {
+ * filter: { name: 'Eddard Stark' },
+ * // If you were using the MongoDB driver directly, you'd need to do
+ * // `update: { $set: { title: ... } }` but mongoose adds $set for
+ * // you.
+ * update: { title: 'Hand of the King' }
+ * }
+ * },
+ * {
+ * deleteOne: {
+ * {
+ * filter: { name: 'Eddard Stark' }
+ * }
+ * }
+ * }
+ * ]).then(res => {
+ * // Prints "1 1 1"
+ * console.log(res.insertedCount, res.modifiedCount, res.deletedCount);
+ * });
+ *
+ * The [supported operations](https://docs.mongodb.com/manual/reference/method/db.collection.bulkWrite/#db.collection.bulkWrite) are:
+ *
+ * - `insertOne`
+ * - `updateOne`
+ * - `updateMany`
+ * - `deleteOne`
+ * - `deleteMany`
+ * - `replaceOne`
+ *
+ * @param {Array} ops
+ * @param {Object} [ops.insertOne.document] The document to insert
+ * @param {Object} [opts.updateOne.filter] Update the first document that matches this filter
+ * @param {Object} [opts.updateOne.update] An object containing [update operators](https://docs.mongodb.com/manual/reference/operator/update/)
+ * @param {Boolean} [opts.updateOne.upsert=false] If true, insert a doc if none match
+ * @param {Boolean} [opts.updateOne.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
+ * @param {Object} [opts.updateOne.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
+ * @param {Array} [opts.updateOne.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
+ * @param {Object} [opts.updateMany.filter] Update all the documents that match this filter
+ * @param {Object} [opts.updateMany.update] An object containing [update operators](https://docs.mongodb.com/manual/reference/operator/update/)
+ * @param {Boolean} [opts.updateMany.upsert=false] If true, insert a doc if no documents match `filter`
+ * @param {Boolean} [opts.updateMany.timestamps=true] If false, do not apply [timestamps](https://mongoosejs.com/docs/guide.html#timestamps) to the operation
+ * @param {Object} [opts.updateMany.collation] The [MongoDB collation](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-34-collations) to use
+ * @param {Array} [opts.updateMany.arrayFilters] The [array filters](https://thecodebarbarian.com/a-nodejs-perspective-on-mongodb-36-array-filters.html) used in `update`
+ * @param {Object} [opts.deleteOne.filter] Delete the first document that matches this filter
+ * @param {Object} [opts.deleteMany.filter] Delete all documents that match this filter
+ * @param {Object} [opts.replaceOne.filter] Replace the first document that matches this filter
+ * @param {Object} [opts.replaceOne.replacement] The replacement document
+ * @param {Boolean} [opts.replaceOne.upsert=false] If true, insert a doc if no documents match `filter`
+ * @param {Object} [options]
+ * @param {Boolean} [options.ordered=true] If true, execute writes in order and stop at the first error. If false, execute writes in parallel and continue until all writes have either succeeded or errored.
+ * @param {ClientSession} [options.session=null] The session associated with this bulk write. See [transactions docs](/docs/transactions.html).
+ * @param {String|number} [options.w=1] The [write concern](https://docs.mongodb.com/manual/reference/write-concern/). See [`Query#w()`](/docs/api.html#query_Query-w) for more information.
+ * @param {number} [options.wtimeout=null] The [write concern timeout](https://docs.mongodb.com/manual/reference/write-concern/#wtimeout).
+ * @param {Boolean} [options.j=true] If false, disable [journal acknowledgement](https://docs.mongodb.com/manual/reference/write-concern/#j-option)
+ * @param {Boolean} [options.bypassDocumentValidation=false] If true, disable [MongoDB server-side schema validation](https://docs.mongodb.com/manual/core/schema-validation/) for all writes in this bulk.
+ * @param {Boolean} [options.strict=null] Overwrites the [`strict` option](/docs/guide.html#strict) on schema. If false, allows filtering and writing fields not defined in the schema for all writes in this bulk.
+ * @param {Function} [callback] callback `function(error, bulkWriteOpResult) {}`
+ * @return {Promise} resolves to a [`BulkWriteOpResult`](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~BulkWriteOpResult) if the operation succeeds
+ * @api public
+ */
+
+Model.bulkWrite = function(ops, options, callback) {
+ _checkContext(this, 'bulkWrite');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+ options = options || {};
+
+ const validations = ops.map(op => castBulkWrite(this, op, options));
+
+ callback = this.$handleCallbackError(callback);
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+ each(validations, (fn, cb) => fn(cb), error => {
+ if (error) {
+ return cb(error);
+ }
+
+ if (ops.length === 0) {
+ return cb(null, getDefaultBulkwriteResult());
+ }
+
+ this.collection.bulkWrite(ops, options, (error, res) => {
+ if (error) {
+ return cb(error);
+ }
+
+ cb(null, res);
+ });
+ });
+ }, this.events);
+};
+
+/**
+ * Shortcut for creating a new Document from existing raw data, pre-saved in the DB.
+ * The document returned has no paths marked as modified initially.
+ *
+ * ####Example:
+ *
+ * // hydrate previous data into a Mongoose document
+ * const mongooseCandy = Candy.hydrate({ _id: '54108337212ffb6d459f854c', type: 'jelly bean' });
+ *
+ * @param {Object} obj
+ * @param {Object|String|Array<String>} [projection] optional projection containing which fields should be selected for this document
+ * @return {Document} document instance
+ * @api public
+ */
+
+Model.hydrate = function(obj, projection) {
+ _checkContext(this, 'hydrate');
+
+ const model = require('./queryhelpers').createModel(this, obj, projection);
+ model.init(obj);
+ return model;
+};
+
+/**
+ * Updates one document in the database without returning it.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `update()`
+ *
+ * ####Examples:
+ *
+ * MyModel.update({ age: { $gt: 18 } }, { oldEnough: true }, fn);
+ *
+ * const res = await MyModel.update({ name: 'Tobi' }, { ferret: true });
+ * res.n; // Number of documents that matched `{ name: 'Tobi' }`
+ * // Number of documents that were changed. If every doc matched already
+ * // had `ferret` set to `true`, `nModified` will be 0.
+ * res.nModified;
+ *
+ * ####Valid options:
+ *
+ * - `strict` (boolean): overrides the [schema-level `strict` option](/docs/guide.html#strict) for this update
+ * - `upsert` (boolean): whether to create the doc if it doesn't match (false)
+ * - `writeConcern` (object): sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * - `omitUndefined` (boolean): If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * - `multi` (boolean): whether multiple documents should be updated (false)
+ * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * - `setDefaultsOnInsert` (boolean): if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * - `timestamps` (boolean): If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * - `overwrite` (boolean): disables update-only mode, allowing you to overwrite the doc (false)
+ *
+ * All `update` values are cast to their appropriate SchemaTypes before being sent.
+ *
+ * The `callback` function receives `(err, rawResponse)`.
+ *
+ * - `err` is the error if any occurred
+ * - `rawResponse` is the full response from Mongo
+ *
+ * ####Note:
+ *
+ * All top level keys which are not `atomic` operation names are treated as set operations:
+ *
+ * ####Example:
+ *
+ * const query = { name: 'borne' };
+ * Model.update(query, { name: 'jason bourne' }, options, callback);
+ *
+ * // is sent as
+ * Model.update(query, { $set: { name: 'jason bourne' }}, options, function(err, res));
+ * // if overwrite option is false. If overwrite is true, sent without the $set wrapper.
+ *
+ * This helps prevent accidentally overwriting all documents in your collection with `{ name: 'jason bourne' }`.
+ *
+ * ####Note:
+ *
+ * Be careful to not use an existing model instance for the update clause (this won't work and can cause weird behavior like infinite loops). Also, ensure that the update clause does not have an _id property, which causes Mongo to return a "Mod on _id not allowed" error.
+ *
+ * ####Note:
+ *
+ * Mongoose casts values and runs setters when using update. The following
+ * features are **not** applied by default.
+ *
+ * - [defaults](/docs/defaults.html#the-setdefaultsoninsert-option)
+ * - [validators](/docs/validation.html#update-validators)
+ * - middleware
+ *
+ * If you need document middleware and fully-featured validation, load the
+ * document first and then use [`save()`](/docs/api.html#model_Model-save).
+ *
+ * Model.findOne({ name: 'borne' }, function (err, doc) {
+ * if (err) ..
+ * doc.name = 'jason bourne';
+ * doc.save(callback);
+ * })
+ *
+ * @see strict http://mongoosejs.com/docs/guide.html#strict
+ * @see response http://docs.mongodb.org/v2.6/reference/command/update/#output
+ * @param {Object} filter
+ * @param {Object} doc
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.multi=false] whether multiple documents should be updated or just the first one that matches `filter`.
+ * @param {Boolean} [options.runValidators=false] if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * @param {Boolean} [options.setDefaultsOnInsert=false] if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.overwrite=false] By default, if you don't include any [update operators](https://docs.mongodb.com/manual/reference/operator/update/) in `doc`, Mongoose will wrap `doc` in `$set` for you. This prevents you from accidentally overwriting the document. This option tells Mongoose to skip adding `$set`.
+ * @param {Function} [callback] params are (error, [updateWriteOpResult](https://mongodb.github.io/node-mongodb-native/3.6/api/Collection.html#~updateWriteOpResult))
+ * @param {Function} [callback]
+ * @return {Query}
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @see writeOpResult https://mongodb.github.io/node-mongodb-native/3.6/api/Collection.html#~updateWriteOpResult
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @api public
+ */
+
+Model.update = function update(conditions, doc, options, callback) {
+ _checkContext(this, 'update');
+
+ return _update(this, 'update', conditions, doc, options, callback);
+};
+
+/**
+ * Same as `update()`, except MongoDB will update _all_ documents that match
+ * `filter` (as opposed to just the first one) regardless of the value of
+ * the `multi` option.
+ *
+ * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')`
+ * and `post('updateMany')` instead.
+ *
+ * ####Example:
+ * const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `updateMany()`
+ *
+ * @param {Object} filter
+ * @param {Object} doc
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] `function(error, res) {}` where `res` has 3 properties: `n`, `nModified`, `ok`.
+ * @return {Query}
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @api public
+ */
+
+Model.updateMany = function updateMany(conditions, doc, options, callback) {
+ _checkContext(this, 'updateMany');
+
+ return _update(this, 'updateMany', conditions, doc, options, callback);
+};
+
+/**
+ * Same as `update()`, except it does not support the `multi` or `overwrite`
+ * options.
+ *
+ * - MongoDB will update _only_ the first document that matches `filter` regardless of the value of the `multi` option.
+ * - Use `replaceOne()` if you want to overwrite an entire document rather than using atomic operators like `$set`.
+ *
+ * ####Example:
+ * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `updateOne()`
+ *
+ * @param {Object} filter
+ * @param {Object} doc
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] params are (error, writeOpResult)
+ * @return {Query}
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @api public
+ */
+
+Model.updateOne = function updateOne(conditions, doc, options, callback) {
+ _checkContext(this, 'updateOne');
+
+ return _update(this, 'updateOne', conditions, doc, options, callback);
+};
+
+/**
+ * Same as `update()`, except MongoDB replace the existing document with the
+ * given document (no atomic operators like `$set`).
+ *
+ * ####Example:
+ * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `replaceOne()`
+ *
+ * @param {Object} filter
+ * @param {Object} doc
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] `function(error, res) {}` where `res` has 3 properties: `n`, `nModified`, `ok`.
+ * @return {Query}
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @return {Query}
+ * @api public
+ */
+
+Model.replaceOne = function replaceOne(conditions, doc, options, callback) {
+ _checkContext(this, 'replaceOne');
+
+ const versionKey = get(this, 'schema.options.versionKey', null);
+ if (versionKey && !doc[versionKey]) {
+ doc[versionKey] = 0;
+ }
+
+ return _update(this, 'replaceOne', conditions, doc, options, callback);
+};
+
+/*!
+ * Common code for `updateOne()`, `updateMany()`, `replaceOne()`, and `update()`
+ * because they need to do the same thing
+ */
+
+function _update(model, op, conditions, doc, options, callback) {
+ const mq = new model.Query({}, {}, model, model.collection);
+
+ callback = model.$handleCallbackError(callback);
+ // gh-2406
+ // make local deep copy of conditions
+ if (conditions instanceof Document) {
+ conditions = conditions.toObject();
+ } else {
+ conditions = utils.clone(conditions);
+ }
+ options = typeof options === 'function' ? options : utils.clone(options);
+
+ const versionKey = get(model, 'schema.options.versionKey', null);
+ _decorateUpdateWithVersionKey(doc, options, versionKey);
+
+ return mq[op](conditions, doc, options, callback);
+}
+
+/**
+ * Executes a mapReduce command.
+ *
+ * `o` is an object specifying all mapReduce options as well as the map and reduce functions. All options are delegated to the driver implementation. See [node-mongodb-native mapReduce() documentation](http://mongodb.github.io/node-mongodb-native/api-generated/collection.html#mapreduce) for more detail about options.
+ *
+ * This function does not trigger any middleware.
+ *
+ * ####Example:
+ *
+ * const o = {};
+ * // `map()` and `reduce()` are run on the MongoDB server, not Node.js,
+ * // these functions are converted to strings
+ * o.map = function () { emit(this.name, 1) };
+ * o.reduce = function (k, vals) { return vals.length };
+ * User.mapReduce(o, function (err, results) {
+ * console.log(results)
+ * })
+ *
+ * ####Other options:
+ *
+ * - `query` {Object} query filter object.
+ * - `sort` {Object} sort input objects using this key
+ * - `limit` {Number} max number of documents
+ * - `keeptemp` {Boolean, default:false} keep temporary data
+ * - `finalize` {Function} finalize function
+ * - `scope` {Object} scope variables exposed to map/reduce/finalize during execution
+ * - `jsMode` {Boolean, default:false} it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X
+ * - `verbose` {Boolean, default:false} provide statistics on job execution time.
+ * - `readPreference` {String}
+ * - `out*` {Object, default: {inline:1}} sets the output target for the map reduce job.
+ *
+ * ####* out options:
+ *
+ * - `{inline:1}` the results are returned in an array
+ * - `{replace: 'collectionName'}` add the results to collectionName: the results replace the collection
+ * - `{reduce: 'collectionName'}` add the results to collectionName: if dups are detected, uses the reducer / finalize functions
+ * - `{merge: 'collectionName'}` add the results to collectionName: if dups exist the new docs overwrite the old
+ *
+ * If `options.out` is set to `replace`, `merge`, or `reduce`, a Model instance is returned that can be used for further querying. Queries run against this model are all executed with the [`lean` option](/docs/tutorials/lean.html); meaning only the js object is returned and no Mongoose magic is applied (getters, setters, etc).
+ *
+ * ####Example:
+ *
+ * const o = {};
+ * // You can also define `map()` and `reduce()` as strings if your
+ * // linter complains about `emit()` not being defined
+ * o.map = 'function () { emit(this.name, 1) }';
+ * o.reduce = 'function (k, vals) { return vals.length }';
+ * o.out = { replace: 'createdCollectionNameForResults' }
+ * o.verbose = true;
+ *
+ * User.mapReduce(o, function (err, model, stats) {
+ * console.log('map reduce took %d ms', stats.processtime)
+ * model.find().where('value').gt(10).exec(function (err, docs) {
+ * console.log(docs);
+ * });
+ * })
+ *
+ * // `mapReduce()` returns a promise. However, ES6 promises can only
+ * // resolve to exactly one value,
+ * o.resolveToObject = true;
+ * const promise = User.mapReduce(o);
+ * promise.then(function (res) {
+ * const model = res.model;
+ * const stats = res.stats;
+ * console.log('map reduce took %d ms', stats.processtime)
+ * return model.find().where('value').gt(10).exec();
+ * }).then(function (docs) {
+ * console.log(docs);
+ * }).then(null, handleError).end()
+ *
+ * @param {Object} o an object specifying map-reduce options
+ * @param {Function} [callback] optional callback
+ * @see http://www.mongodb.org/display/DOCS/MapReduce
+ * @return {Promise}
+ * @api public
+ */
+
+Model.mapReduce = function mapReduce(o, callback) {
+ _checkContext(this, 'mapReduce');
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+
+ if (!Model.mapReduce.schema) {
+ const opts = { noId: true, noVirtualId: true, strict: false };
+ Model.mapReduce.schema = new Schema({}, opts);
+ }
+
+ if (!o.out) o.out = { inline: 1 };
+ if (o.verbose !== false) o.verbose = true;
+
+ o.map = String(o.map);
+ o.reduce = String(o.reduce);
+
+ if (o.query) {
+ let q = new this.Query(o.query);
+ q.cast(this);
+ o.query = q._conditions;
+ q = undefined;
+ }
+
+ this.collection.mapReduce(null, null, o, (err, res) => {
+ if (err) {
+ return cb(err);
+ }
+ if (res.collection) {
+ // returned a collection, convert to Model
+ const model = Model.compile('_mapreduce_' + res.collection.collectionName,
+ Model.mapReduce.schema, res.collection.collectionName, this.db,
+ this.base);
+
+ model._mapreduce = true;
+ res.model = model;
+
+ return cb(null, res);
+ }
+
+ cb(null, res);
+ });
+ }, this.events);
+};
+
+/**
+ * Performs [aggregations](http://docs.mongodb.org/manual/applications/aggregation/) on the models collection.
+ *
+ * If a `callback` is passed, the `aggregate` is executed and a `Promise` is returned. If a callback is not passed, the `aggregate` itself is returned.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `aggregate()`
+ *
+ * ####Example:
+ *
+ * // Find the max balance of all accounts
+ * Users.aggregate([
+ * { $group: { _id: null, maxBalance: { $max: '$balance' }}},
+ * { $project: { _id: 0, maxBalance: 1 }}
+ * ]).
+ * then(function (res) {
+ * console.log(res); // [ { maxBalance: 98000 } ]
+ * });
+ *
+ * // Or use the aggregation pipeline builder.
+ * Users.aggregate().
+ * group({ _id: null, maxBalance: { $max: '$balance' } }).
+ * project('-id maxBalance').
+ * exec(function (err, res) {
+ * if (err) return handleError(err);
+ * console.log(res); // [ { maxBalance: 98 } ]
+ * });
+ *
+ * ####NOTE:
+ *
+ * - Mongoose does **not** cast aggregation pipelines to the model's schema because `$project` and `$group` operators allow redefining the "shape" of the documents at any stage of the pipeline, which may leave documents in an incompatible format. You can use the [mongoose-cast-aggregation plugin](https://github.com/AbdelrahmanHafez/mongoose-cast-aggregation) to enable minimal casting for aggregation pipelines.
+ * - The documents returned are plain javascript objects, not mongoose documents (since any shape of document can be returned).
+ *
+ * #### More About Aggregations:
+ *
+ * - [Mongoose `Aggregate`](/docs/api/aggregate.html)
+ * - [An Introduction to Mongoose Aggregate](https://masteringjs.io/tutorials/mongoose/aggregate)
+ * - [MongoDB Aggregation docs](http://docs.mongodb.org/manual/applications/aggregation/)
+ *
+ * @see Aggregate #aggregate_Aggregate
+ * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
+ * @param {Array} [pipeline] aggregation pipeline as an array of objects
+ * @param {Function} [callback]
+ * @return {Aggregate}
+ * @api public
+ */
+
+Model.aggregate = function aggregate(pipeline, callback) {
+ _checkContext(this, 'aggregate');
+
+ if (arguments.length > 2 || get(pipeline, 'constructor.name') === 'Object') {
+ throw new MongooseError('Mongoose 5.x disallows passing a spread of operators ' +
+ 'to `Model.aggregate()`. Instead of ' +
+ '`Model.aggregate({ $match }, { $skip })`, do ' +
+ '`Model.aggregate([{ $match }, { $skip }])`');
+ }
+
+ if (typeof pipeline === 'function') {
+ callback = pipeline;
+ pipeline = [];
+ }
+
+ const aggregate = new Aggregate(pipeline || []);
+ aggregate.model(this);
+
+ if (typeof callback === 'undefined') {
+ return aggregate;
+ }
+
+ callback = this.$handleCallbackError(callback);
+ callback = this.$wrapCallback(callback);
+
+ aggregate.exec(callback);
+ return aggregate;
+};
+
+/**
+ * Casts and validates the given object against this model's schema, passing the
+ * given `context` to custom validators.
+ *
+ * ####Example:
+ *
+ * const Model = mongoose.model('Test', Schema({
+ * name: { type: String, required: true },
+ * age: { type: Number, required: true }
+ * });
+ *
+ * try {
+ * await Model.validate({ name: null }, ['name'])
+ * } catch (err) {
+ * err instanceof mongoose.Error.ValidationError; // true
+ * Object.keys(err.errors); // ['name']
+ * }
+ *
+ * @param {Object} obj
+ * @param {Array} pathsToValidate
+ * @param {Object} [context]
+ * @param {Function} [callback]
+ * @return {Promise|undefined}
+ * @api public
+ */
+
+Model.validate = function validate(obj, pathsToValidate, context, callback) {
+ return promiseOrCallback(callback, cb => {
+ const schema = this.schema;
+ let paths = Object.keys(schema.paths);
+
+ if (pathsToValidate != null) {
+ const _pathsToValidate = new Set(pathsToValidate);
+ paths = paths.filter(p => {
+ const pieces = p.split('.');
+ let cur = pieces[0];
+
+ for (const piece of pieces) {
+ if (_pathsToValidate.has(cur)) {
+ return true;
+ }
+ cur += '.' + piece;
+ }
+
+ return _pathsToValidate.has(p);
+ });
+ }
+
+ for (const path of paths) {
+ const schemaType = schema.path(path);
+ if (!schemaType || !schemaType.$isMongooseArray) {
+ continue;
+ }
+
+ const val = get(obj, path);
+ pushNestedArrayPaths(val, path);
+ }
+
+ let remaining = paths.length;
+ let error = null;
+
+ for (const path of paths) {
+ const schemaType = schema.path(path);
+ if (schemaType == null) {
+ _checkDone();
+ continue;
+ }
+
+ const pieces = path.split('.');
+ let cur = obj;
+ for (let i = 0; i < pieces.length - 1; ++i) {
+ cur = cur[pieces[i]];
+ }
+
+ let val = get(obj, path, void 0);
+
+ if (val != null) {
+ try {
+ val = schemaType.cast(val);
+ cur[pieces[pieces.length - 1]] = val;
+ } catch (err) {
+ error = error || new ValidationError();
+ error.addError(path, err);
+
+ _checkDone();
+ continue;
+ }
+ }
+
+ schemaType.doValidate(val, err => {
+ if (err) {
+ error = error || new ValidationError();
+ if (err instanceof ValidationError) {
+ for (const _err of Object.keys(err.errors)) {
+ error.addError(`${path}.${err.errors[_err].path}`, _err);
+ }
+ } else {
+ error.addError(err.path, err);
+ }
+ }
+ _checkDone();
+ }, context, { path: path });
+ }
+
+ function pushNestedArrayPaths(nestedArray, path) {
+ if (nestedArray == null) {
+ return;
+ }
+
+ for (let i = 0; i < nestedArray.length; ++i) {
+ if (Array.isArray(nestedArray[i])) {
+ pushNestedArrayPaths(nestedArray[i], path + '.' + i);
+ } else {
+ paths.push(path + '.' + i);
+ }
+ }
+ }
+
+ function _checkDone() {
+ if (--remaining <= 0) {
+ return cb(error);
+ }
+ }
+ });
+};
+
+/**
+ * Implements `$geoSearch` functionality for Mongoose
+ *
+ * This function does not trigger any middleware
+ *
+ * ####Example:
+ *
+ * const options = { near: [10, 10], maxDistance: 5 };
+ * Locations.geoSearch({ type : "house" }, options, function(err, res) {
+ * console.log(res);
+ * });
+ *
+ * ####Options:
+ * - `near` {Array} x,y point to search for
+ * - `maxDistance` {Number} the maximum distance from the point near that a result can be
+ * - `limit` {Number} The maximum number of results to return
+ * - `lean` {Object|Boolean} return the raw object instead of the Mongoose Model
+ *
+ * @param {Object} conditions an object that specifies the match condition (required)
+ * @param {Object} options for the geoSearch, some (near, maxDistance) are required
+ * @param {Object|Boolean} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and the [Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {Function} [callback] optional callback
+ * @return {Promise}
+ * @see http://docs.mongodb.org/manual/reference/command/geoSearch/
+ * @see http://docs.mongodb.org/manual/core/geohaystack/
+ * @api public
+ */
+
+Model.geoSearch = function(conditions, options, callback) {
+ _checkContext(this, 'geoSearch');
+
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+ let error;
+ if (conditions === undefined || !utils.isObject(conditions)) {
+ error = new MongooseError('Must pass conditions to geoSearch');
+ } else if (!options.near) {
+ error = new MongooseError('Must specify the near option in geoSearch');
+ } else if (!Array.isArray(options.near)) {
+ error = new MongooseError('near option must be an array [x, y]');
+ }
+
+ if (error) {
+ return cb(error);
+ }
+
+ // send the conditions in the options object
+ options.search = conditions;
+
+ this.collection.geoHaystackSearch(options.near[0], options.near[1], options, (err, res) => {
+ if (err) {
+ return cb(err);
+ }
+
+ let count = res.results.length;
+ if (options.lean || count === 0) {
+ return cb(null, res.results);
+ }
+
+ const errSeen = false;
+
+ function init(err) {
+ if (err && !errSeen) {
+ return cb(err);
+ }
+
+ if (!--count && !errSeen) {
+ cb(null, res.results);
+ }
+ }
+
+ for (let i = 0; i < res.results.length; ++i) {
+ const temp = res.results[i];
+ res.results[i] = new this();
+ res.results[i].init(temp, {}, init);
+ }
+ });
+ }, this.events);
+};
+
+/**
+ * Populates document references.
+ *
+ * ####Available top-level options:
+ *
+ * - path: space delimited path(s) to populate
+ * - select: optional fields to select
+ * - match: optional query conditions to match
+ * - model: optional name of the model to use for population
+ * - options: optional query options like sort, limit, etc
+ * - justOne: optional boolean, if true Mongoose will always set `path` to an array. Inferred from schema by default.
+ *
+ * ####Examples:
+ *
+ * // populates a single object
+ * User.findById(id, function (err, user) {
+ * const opts = [
+ * { path: 'company', match: { x: 1 }, select: 'name' },
+ * { path: 'notes', options: { limit: 10 }, model: 'override' }
+ * ];
+ *
+ * User.populate(user, opts, function (err, user) {
+ * console.log(user);
+ * });
+ * });
+ *
+ * // populates an array of objects
+ * User.find(match, function (err, users) {
+ * const opts = [{ path: 'company', match: { x: 1 }, select: 'name' }];
+ *
+ * const promise = User.populate(users, opts);
+ * promise.then(console.log).end();
+ * })
+ *
+ * // imagine a Weapon model exists with two saved documents:
+ * // { _id: 389, name: 'whip' }
+ * // { _id: 8921, name: 'boomerang' }
+ * // and this schema:
+ * // new Schema({
+ * // name: String,
+ * // weapon: { type: ObjectId, ref: 'Weapon' }
+ * // });
+ *
+ * const user = { name: 'Indiana Jones', weapon: 389 };
+ * Weapon.populate(user, { path: 'weapon', model: 'Weapon' }, function (err, user) {
+ * console.log(user.weapon.name); // whip
+ * })
+ *
+ * // populate many plain objects
+ * const users = [{ name: 'Indiana Jones', weapon: 389 }]
+ * users.push({ name: 'Batman', weapon: 8921 })
+ * Weapon.populate(users, { path: 'weapon' }, function (err, users) {
+ * users.forEach(function (user) {
+ * console.log('%s uses a %s', users.name, user.weapon.name)
+ * // Indiana Jones uses a whip
+ * // Batman uses a boomerang
+ * });
+ * });
+ * // Note that we didn't need to specify the Weapon model because
+ * // it is in the schema's ref
+ *
+ * @param {Document|Array} docs Either a single document or array of documents to populate.
+ * @param {Object|String} options Either the paths to populate or an object specifying all parameters
+ * @param {string} [options.path=null] The path to populate.
+ * @param {boolean} [options.retainNullValues=false] By default, Mongoose removes null and undefined values from populated arrays. Use this option to make `populate()` retain `null` and `undefined` array entries.
+ * @param {boolean} [options.getters=false] If true, Mongoose will call any getters defined on the `localField`. By default, Mongoose gets the raw value of `localField`. For example, you would need to set this option to `true` if you wanted to [add a `lowercase` getter to your `localField`](/docs/schematypes.html#schematype-options).
+ * @param {boolean} [options.clone=false] When you do `BlogPost.find().populate('author')`, blog posts with the same author will share 1 copy of an `author` doc. Enable this option to make Mongoose clone populated docs before assigning them.
+ * @param {Object|Function} [options.match=null] Add an additional filter to the populate query. Can be a filter object containing [MongoDB query syntax](https://docs.mongodb.com/manual/tutorial/query-documents/), or a function that returns a filter object.
+ * @param {Boolean} [options.skipInvalidIds=false] By default, Mongoose throws a cast error if `localField` and `foreignField` schemas don't line up. If you enable this option, Mongoose will instead filter out any `localField` properties that cannot be casted to `foreignField`'s schema type.
+ * @param {Number} [options.perDocumentLimit=null] For legacy reasons, `limit` with `populate()` may give incorrect results because it only executes a single query for every document being populated. If you set `perDocumentLimit`, Mongoose will ensure correct `limit` per document by executing a separate query for each document to `populate()`. For example, `.find().populate({ path: 'test', perDocumentLimit: 2 })` will execute 2 additional queries if `.find()` returns 2 documents.
+ * @param {Object} [options.options=null] Additional options like `limit` and `lean`.
+ * @param {Function} [callback(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
+ * @return {Promise}
+ * @api public
+ */
+
+Model.populate = function(docs, paths, callback) {
+ _checkContext(this, 'populate');
+
+ const _this = this;
+
+ // normalized paths
+ paths = utils.populate(paths);
+
+ // data that should persist across subPopulate calls
+ const cache = {};
+
+ callback = this.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, cb => {
+ cb = this.$wrapCallback(cb);
+ _populate(_this, docs, paths, cache, cb);
+ }, this.events);
+};
+
+/*!
+ * Populate helper
+ *
+ * @param {Model} model the model to use
+ * @param {Document|Array} docs Either a single document or array of documents to populate.
+ * @param {Object} paths
+ * @param {Function} [cb(err,doc)] Optional callback, executed upon completion. Receives `err` and the `doc(s)`.
+ * @return {Function}
+ * @api private
+ */
+
+function _populate(model, docs, paths, cache, callback) {
+ let pending = paths.length;
+
+ if (paths.length === 0) {
+ return callback(null, docs);
+ }
+
+ // each path has its own query options and must be executed separately
+ for (const path of paths) {
+ populate(model, docs, path, next);
+ }
+
+ function next(err) {
+ if (err) {
+ return callback(err, null);
+ }
+ if (--pending) {
+ return;
+ }
+ callback(null, docs);
+ }
+}
+
+/*!
+ * Populates `docs`
+ */
+const excludeIdReg = /\s?-_id\s?/;
+const excludeIdRegGlobal = /\s?-_id\s?/g;
+
+function populate(model, docs, options, callback) {
+ // normalize single / multiple docs passed
+ if (!Array.isArray(docs)) {
+ docs = [docs];
+ }
+
+ if (docs.length === 0 || docs.every(utils.isNullOrUndefined)) {
+ return callback();
+ }
+
+ const modelsMap = getModelsMapForPopulate(model, docs, options);
+
+ if (modelsMap instanceof MongooseError) {
+ return immediate(function() {
+ callback(modelsMap);
+ });
+ }
+
+ const len = modelsMap.length;
+ let vals = [];
+
+ function flatten(item) {
+ // no need to include undefined values in our query
+ return undefined !== item;
+ }
+
+ let _remaining = len;
+ let hasOne = false;
+ const params = [];
+ for (let i = 0; i < len; ++i) {
+ const mod = modelsMap[i];
+ let select = mod.options.select;
+ const match = _formatMatch(mod.match);
+
+ let ids = utils.array.flatten(mod.ids, flatten);
+ ids = utils.array.unique(ids);
+
+ const assignmentOpts = {};
+ assignmentOpts.sort = get(mod, 'options.options.sort', void 0);
+ assignmentOpts.excludeId = excludeIdReg.test(select) || (select && select._id === 0);
+
+ if (ids.length === 0 || ids.every(utils.isNullOrUndefined)) {
+ // Ensure that we set populate virtuals to 0 or empty array even
+ // if we don't actually execute a query because they don't have
+ // a value by default. See gh-7731, gh-8230
+ --_remaining;
+ if (mod.count || mod.isVirtual) {
+ _assign(model, [], mod, assignmentOpts);
+ }
+ continue;
+ }
+
+ hasOne = true;
+ if (mod.foreignField.size === 1) {
+ const foreignField = Array.from(mod.foreignField)[0];
+ const foreignSchemaType = mod.model.schema.path(foreignField);
+ if (foreignField !== '_id' || !match['_id']) {
+ ids = _filterInvalidIds(ids, foreignSchemaType, mod.options.skipInvalidIds);
+ match[foreignField] = { $in: ids };
+ }
+ } else {
+ const $or = [];
+ if (Array.isArray(match.$or)) {
+ match.$and = [{ $or: match.$or }, { $or: $or }];
+ delete match.$or;
+ } else {
+ match.$or = $or;
+ }
+ for (const foreignField of mod.foreignField) {
+ if (foreignField !== '_id' || !match['_id']) {
+ const foreignSchemaType = mod.model.schema.path(foreignField);
+ ids = _filterInvalidIds(ids, foreignSchemaType, mod.options.skipInvalidIds);
+ $or.push({ [foreignField]: { $in: ids } });
+ }
+ }
+ }
+
+ if (assignmentOpts.excludeId) {
+ // override the exclusion from the query so we can use the _id
+ // for document matching during assignment. we'll delete the
+ // _id back off before returning the result.
+ if (typeof select === 'string') {
+ select = select.replace(excludeIdRegGlobal, ' ');
+ } else {
+ // preserve original select conditions by copying
+ select = utils.object.shallowCopy(select);
+ delete select._id;
+ }
+ }
+
+ if (mod.options.options && mod.options.options.limit != null) {
+ assignmentOpts.originalLimit = mod.options.options.limit;
+ } else if (mod.options.limit != null) {
+ assignmentOpts.originalLimit = mod.options.limit;
+ }
+
+ params.push([mod, match, select, assignmentOpts, _next]);
+ }
+
+ if (!hasOne) {
+ // If no models to populate but we have a nested populate,
+ // keep trying, re: gh-8946
+ if (options.populate != null) {
+ const opts = utils.populate(options.populate).map(pop => Object.assign({}, pop, {
+ path: options.path + '.' + pop.path
+ }));
+ return model.populate(docs, opts, callback);
+ }
+ return callback();
+ }
+
+ for (const arr of params) {
+ _execPopulateQuery.apply(null, arr);
+ }
+
+ function _next(err, valsFromDb) {
+ if (err != null) {
+ return callback(err, null);
+ }
+ vals = vals.concat(valsFromDb);
+ if (--_remaining === 0) {
+ _done();
+ }
+ }
+
+ function _done() {
+ for (const arr of params) {
+ const mod = arr[0];
+ const assignmentOpts = arr[3];
+ for (const val of vals) {
+ mod.options._childDocs.push(val);
+ }
+ _assign(model, vals, mod, assignmentOpts);
+ }
+
+ for (const arr of params) {
+ removeDeselectedForeignField(arr[0].foreignField, arr[0].options, vals);
+ }
+ callback();
+ }
+}
+
+/*!
+ * ignore
+ */
+
+function _execPopulateQuery(mod, match, select, assignmentOpts, callback) {
+ const subPopulate = utils.clone(mod.options.populate);
+
+ const queryOptions = Object.assign({
+ skip: mod.options.skip,
+ limit: mod.options.limit,
+ perDocumentLimit: mod.options.perDocumentLimit
+ }, mod.options.options);
+
+ if (mod.count) {
+ delete queryOptions.skip;
+ }
+
+ if (queryOptions.perDocumentLimit != null) {
+ queryOptions.limit = queryOptions.perDocumentLimit;
+ delete queryOptions.perDocumentLimit;
+ } else if (queryOptions.limit != null) {
+ queryOptions.limit = queryOptions.limit * mod.ids.length;
+ }
+
+ const query = mod.model.find(match, select, queryOptions);
+ // If we're doing virtual populate and projection is inclusive and foreign
+ // field is not selected, automatically select it because mongoose needs it.
+ // If projection is exclusive and client explicitly unselected the foreign
+ // field, that's the client's fault.
+ for (const foreignField of mod.foreignField) {
+ if (foreignField !== '_id' && query.selectedInclusively() &&
+ !isPathSelectedInclusive(query._fields, foreignField)) {
+ query.select(foreignField);
+ }
+ }
+
+ // If using count, still need the `foreignField` so we can match counts
+ // to documents, otherwise we would need a separate `count()` for every doc.
+ if (mod.count) {
+ for (const foreignField of mod.foreignField) {
+ query.select(foreignField);
+ }
+ }
+
+ // If we need to sub-populate, call populate recursively
+ if (subPopulate) {
+ query.populate(subPopulate);
+ }
+
+ query.exec((err, docs) => {
+ if (err != null) {
+ return callback(err);
+ }
+ for (const val of docs) {
+ leanPopulateMap.set(val, mod.model);
+ }
+
+ callback(null, docs);
+ });
+}
+
+/*!
+ * ignore
+ */
+
+function _assign(model, vals, mod, assignmentOpts) {
+ const options = mod.options;
+ const isVirtual = mod.isVirtual;
+ const justOne = mod.justOne;
+ let _val;
+ const lean = get(options, 'options.lean', false);
+ const len = vals.length;
+ const rawOrder = {};
+ const rawDocs = {};
+ let key;
+ let val;
+
+ // Clone because `assignRawDocsToIdStructure` will mutate the array
+ const allIds = utils.clone(mod.allIds);
+
+ // optimization:
+ // record the document positions as returned by
+ // the query result.
+ for (let i = 0; i < len; i++) {
+ val = vals[i];
+ if (val == null) {
+ continue;
+ }
+ for (const foreignField of mod.foreignField) {
+ _val = utils.getValue(foreignField, val);
+ if (Array.isArray(_val)) {
+ _val = utils.array.flatten(_val);
+
+ for (let __val of _val) {
+ if (__val instanceof Document) {
+ __val = __val._id;
+ }
+ key = String(__val);
+ if (rawDocs[key]) {
+ if (Array.isArray(rawDocs[key])) {
+ rawDocs[key].push(val);
+ rawOrder[key].push(i);
+ } else {
+ rawDocs[key] = [rawDocs[key], val];
+ rawOrder[key] = [rawOrder[key], i];
+ }
+ } else {
+ if (isVirtual && !justOne) {
+ rawDocs[key] = [val];
+ rawOrder[key] = [i];
+ } else {
+ rawDocs[key] = val;
+ rawOrder[key] = i;
+ }
+ }
+ }
+ } else {
+ if (_val instanceof Document) {
+ _val = _val._id;
+ }
+ key = String(_val);
+ if (rawDocs[key]) {
+ if (Array.isArray(rawDocs[key])) {
+ rawDocs[key].push(val);
+ rawOrder[key].push(i);
+ } else {
+ rawDocs[key] = [rawDocs[key], val];
+ rawOrder[key] = [rawOrder[key], i];
+ }
+ } else {
+ rawDocs[key] = val;
+ rawOrder[key] = i;
+ }
+ }
+ // flag each as result of population
+ if (!lean) {
+ val.$__.wasPopulated = true;
+ }
+ }
+ }
+
+ assignVals({
+ originalModel: model,
+ // If virtual, make sure to not mutate original field
+ rawIds: mod.isVirtual ? allIds : mod.allIds,
+ allIds: allIds,
+ foreignField: mod.foreignField,
+ rawDocs: rawDocs,
+ rawOrder: rawOrder,
+ docs: mod.docs,
+ path: options.path,
+ options: assignmentOpts,
+ justOne: mod.justOne,
+ isVirtual: mod.isVirtual,
+ allOptions: mod,
+ populatedModel: mod.model,
+ lean: lean,
+ virtual: mod.virtual,
+ count: mod.count,
+ match: mod.match
+ });
+}
+
+/*!
+ * Optionally filter out invalid ids that don't conform to foreign field's schema
+ * to avoid cast errors (gh-7706)
+ */
+
+function _filterInvalidIds(ids, foreignSchemaType, skipInvalidIds) {
+ ids = ids.filter(v => !(v instanceof SkipPopulateValue));
+ if (!skipInvalidIds) {
+ return ids;
+ }
+ return ids.filter(id => {
+ try {
+ foreignSchemaType.cast(id);
+ return true;
+ } catch (err) {
+ return false;
+ }
+ });
+}
+
+/*!
+ * Format `mod.match` given that it may be an array that we need to $or if
+ * the client has multiple docs with match functions
+ */
+
+function _formatMatch(match) {
+ if (Array.isArray(match)) {
+ if (match.length > 1) {
+ return { $or: [].concat(match.map(m => Object.assign({}, m))) };
+ }
+ return Object.assign({}, match[0]);
+ }
+ return Object.assign({}, match);
+}
+
+/*!
+ * Compiler utility.
+ *
+ * @param {String|Function} name model name or class extending Model
+ * @param {Schema} schema
+ * @param {String} collectionName
+ * @param {Connection} connection
+ * @param {Mongoose} base mongoose instance
+ */
+
+Model.compile = function compile(name, schema, collectionName, connection, base) {
+ const versioningEnabled = schema.options.versionKey !== false;
+
+ if (versioningEnabled && !schema.paths[schema.options.versionKey]) {
+ // add versioning to top level documents only
+ const o = {};
+ o[schema.options.versionKey] = Number;
+ schema.add(o);
+ }
+
+ let model;
+ if (typeof name === 'function' && name.prototype instanceof Model) {
+ model = name;
+ name = model.name;
+ schema.loadClass(model, false);
+ model.prototype.$isMongooseModelPrototype = true;
+ } else {
+ // generate new class
+ model = function model(doc, fields, skipId) {
+ model.hooks.execPreSync('createModel', doc);
+ if (!(this instanceof model)) {
+ return new model(doc, fields, skipId);
+ }
+ const discriminatorKey = model.schema.options.discriminatorKey;
+
+ if (model.discriminators == null || doc == null || doc[discriminatorKey] == null) {
+ Model.call(this, doc, fields, skipId);
+ return;
+ }
+
+ // If discriminator key is set, use the discriminator instead (gh-7586)
+ const Discriminator = model.discriminators[doc[discriminatorKey]] ||
+ getDiscriminatorByValue(model, doc[discriminatorKey]);
+ if (Discriminator != null) {
+ return new Discriminator(doc, fields, skipId);
+ }
+
+ // Otherwise, just use the top-level model
+ Model.call(this, doc, fields, skipId);
+ };
+ }
+
+ model.hooks = schema.s.hooks.clone();
+ model.base = base;
+ model.modelName = name;
+
+ if (!(model.prototype instanceof Model)) {
+ model.__proto__ = Model;
+ model.prototype.__proto__ = Model.prototype;
+ }
+ model.model = function model(name) {
+ return this.db.model(name);
+ };
+ model.db = connection;
+ model.prototype.db = connection;
+ model.prototype[modelDbSymbol] = connection;
+ model.discriminators = model.prototype.discriminators = undefined;
+ model[modelSymbol] = true;
+ model.events = new EventEmitter();
+
+ model.prototype.$__setSchema(schema);
+
+ const _userProvidedOptions = schema._userProvidedOptions || {};
+
+ const collectionOptions = {
+ schemaUserProvidedOptions: _userProvidedOptions,
+ capped: schema.options.capped,
+ autoCreate: schema.options.autoCreate,
+ Promise: model.base.Promise
+ };
+
+ model.prototype.collection = connection.collection(
+ collectionName,
+ collectionOptions
+ );
+ model.prototype[modelCollectionSymbol] = model.prototype.collection;
+
+ // apply methods and statics
+ applyMethods(model, schema);
+ applyStatics(model, schema);
+ applyHooks(model, schema);
+ applyStaticHooks(model, schema.s.hooks, schema.statics);
+
+ model.schema = model.prototype.schema;
+ model.collection = model.prototype.collection;
+
+ // Create custom query constructor
+ model.Query = function() {
+ Query.apply(this, arguments);
+ };
+ model.Query.prototype = Object.create(Query.prototype);
+ model.Query.base = Query.base;
+ applyQueryMiddleware(model.Query, model);
+ applyQueryMethods(model, schema.query);
+
+ return model;
+};
+
+/*!
+ * Register custom query methods for this model
+ *
+ * @param {Model} model
+ * @param {Schema} schema
+ */
+
+function applyQueryMethods(model, methods) {
+ for (const i in methods) {
+ model.Query.prototype[i] = methods[i];
+ }
+}
+
+/*!
+ * Subclass this model with `conn`, `schema`, and `collection` settings.
+ *
+ * @param {Connection} conn
+ * @param {Schema} [schema]
+ * @param {String} [collection]
+ * @return {Model}
+ */
+
+Model.__subclass = function subclass(conn, schema, collection) {
+ // subclass model using this connection and collection name
+ const _this = this;
+
+ const Model = function Model(doc, fields, skipId) {
+ if (!(this instanceof Model)) {
+ return new Model(doc, fields, skipId);
+ }
+ _this.call(this, doc, fields, skipId);
+ };
+
+ Model.__proto__ = _this;
+ Model.prototype.__proto__ = _this.prototype;
+ Model.db = conn;
+ Model.prototype.db = conn;
+ Model.prototype[modelDbSymbol] = conn;
+
+ _this[subclassedSymbol] = _this[subclassedSymbol] || [];
+ _this[subclassedSymbol].push(Model);
+ if (_this.discriminators != null) {
+ Model.discriminators = {};
+ for (const key of Object.keys(_this.discriminators)) {
+ Model.discriminators[key] = _this.discriminators[key].
+ __subclass(_this.db, _this.discriminators[key].schema, collection);
+ }
+ }
+
+ const s = schema && typeof schema !== 'string'
+ ? schema
+ : _this.prototype.schema;
+
+ const options = s.options || {};
+ const _userProvidedOptions = s._userProvidedOptions || {};
+
+ if (!collection) {
+ collection = _this.prototype.schema.get('collection') ||
+ utils.toCollectionName(_this.modelName, this.base.pluralize());
+ }
+
+ const collectionOptions = {
+ schemaUserProvidedOptions: _userProvidedOptions,
+ capped: s && options.capped
+ };
+
+ Model.prototype.collection = conn.collection(collection, collectionOptions);
+ Model.prototype[modelCollectionSymbol] = Model.prototype.collection;
+ Model.collection = Model.prototype.collection;
+ // Errors handled internally, so ignore
+ Model.init(() => {});
+ return Model;
+};
+
+Model.$handleCallbackError = function(callback) {
+ if (callback == null) {
+ return callback;
+ }
+ if (typeof callback !== 'function') {
+ throw new MongooseError('Callback must be a function, got ' + callback);
+ }
+
+ const _this = this;
+ return function() {
+ try {
+ callback.apply(null, arguments);
+ } catch (error) {
+ _this.emit('error', error);
+ }
+ };
+};
+
+/*!
+ * ignore
+ */
+
+Model.$wrapCallback = function(callback) {
+ const serverSelectionError = new ServerSelectionError();
+ const _this = this;
+
+ return function(err) {
+ if (err != null && err.name === 'MongoServerSelectionError') {
+ arguments[0] = serverSelectionError.assimilateError(err);
+ }
+ if (err != null && err.name === 'MongoNetworkTimeoutError' && err.message.endsWith('timed out')) {
+ _this.db.emit('timeout');
+ }
+
+ return callback.apply(null, arguments);
+ };
+};
+
+/**
+ * Helper for console.log. Given a model named 'MyModel', returns the string
+ * `'Model { MyModel }'`.
+ *
+ * ####Example:
+ *
+ * const MyModel = mongoose.model('Test', Schema({ name: String }));
+ * MyModel.inspect(); // 'Model { Test }'
+ * console.log(MyModel); // Prints 'Model { Test }'
+ *
+ * @api public
+ */
+
+Model.inspect = function() {
+ return `Model { ${this.modelName} }`;
+};
+
+if (util.inspect.custom) {
+ /*!
+ * Avoid Node deprecation warning DEP0079
+ */
+
+ Model[util.inspect.custom] = Model.inspect;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = Model;
diff --git a/node_modules/mongoose/lib/options.js b/node_modules/mongoose/lib/options.js
new file mode 100644
index 0000000..8e9fc29
--- /dev/null
+++ b/node_modules/mongoose/lib/options.js
@@ -0,0 +1,14 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+exports.internalToObjectOptions = {
+ transform: false,
+ virtuals: false,
+ getters: false,
+ _skipDepopulateTopLevel: true,
+ depopulate: true,
+ flattenDecimals: false
+};
diff --git a/node_modules/mongoose/lib/options/PopulateOptions.js b/node_modules/mongoose/lib/options/PopulateOptions.js
new file mode 100644
index 0000000..5b98194
--- /dev/null
+++ b/node_modules/mongoose/lib/options/PopulateOptions.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const clone = require('../helpers/clone');
+
+class PopulateOptions {
+ constructor(obj) {
+ this._docs = {};
+ this._childDocs = [];
+
+ if (obj == null) {
+ return;
+ }
+ obj = clone(obj);
+ Object.assign(this, obj);
+ if (typeof obj.subPopulate === 'object') {
+ this.populate = obj.subPopulate;
+ }
+
+
+ if (obj.perDocumentLimit != null && obj.limit != null) {
+ throw new Error('Can not use `limit` and `perDocumentLimit` at the same time. Path: `' + obj.path + '`.');
+ }
+ }
+}
+
+/**
+ * The connection used to look up models by name. If not specified, Mongoose
+ * will default to using the connection associated with the model in
+ * `PopulateOptions#model`.
+ *
+ * @memberOf PopulateOptions
+ * @property {Connection} connection
+ * @api public
+ */
+
+module.exports = PopulateOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaArrayOptions.js b/node_modules/mongoose/lib/options/SchemaArrayOptions.js
new file mode 100644
index 0000000..ddd0b37
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaArrayOptions.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on an Array schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ tags: [String] });
+ * schema.path('tags').options; // SchemaArrayOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaArrayOptions
+ */
+
+class SchemaArrayOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If this is an array of strings, an array of allowed values for this path.
+ * Throws an error if this array isn't an array of strings.
+ *
+ * @api public
+ * @property enum
+ * @memberOf SchemaArrayOptions
+ * @type Array
+ * @instance
+ */
+
+Object.defineProperty(SchemaArrayOptions.prototype, 'enum', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaArrayOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaBufferOptions.js b/node_modules/mongoose/lib/options/SchemaBufferOptions.js
new file mode 100644
index 0000000..258130d
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaBufferOptions.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a Buffer schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ bitmap: Buffer });
+ * schema.path('bitmap').options; // SchemaBufferOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaBufferOptions
+ */
+
+class SchemaBufferOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * Set the default subtype for this buffer.
+ *
+ * @api public
+ * @property subtype
+ * @memberOf SchemaBufferOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaBufferOptions.prototype, 'subtype', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaBufferOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaDateOptions.js b/node_modules/mongoose/lib/options/SchemaDateOptions.js
new file mode 100644
index 0000000..09bf27f
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaDateOptions.js
@@ -0,0 +1,64 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a Date schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ startedAt: Date });
+ * schema.path('startedAt').options; // SchemaDateOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaDateOptions
+ */
+
+class SchemaDateOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If set, Mongoose adds a validator that checks that this path is after the
+ * given `min`.
+ *
+ * @api public
+ * @property min
+ * @memberOf SchemaDateOptions
+ * @type Date
+ * @instance
+ */
+
+Object.defineProperty(SchemaDateOptions.prototype, 'min', opts);
+
+/**
+ * If set, Mongoose adds a validator that checks that this path is before the
+ * given `max`.
+ *
+ * @api public
+ * @property max
+ * @memberOf SchemaDateOptions
+ * @type Date
+ * @instance
+ */
+
+Object.defineProperty(SchemaDateOptions.prototype, 'max', opts);
+
+/**
+ * If set, Mongoose creates a TTL index on this path.
+ *
+ * @api public
+ * @property expires
+ * @memberOf SchemaDateOptions
+ * @type Date
+ * @instance
+ */
+
+Object.defineProperty(SchemaDateOptions.prototype, 'expires', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaDateOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaDocumentArrayOptions.js b/node_modules/mongoose/lib/options/SchemaDocumentArrayOptions.js
new file mode 100644
index 0000000..f3fb7a9
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaDocumentArrayOptions.js
@@ -0,0 +1,68 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on an Document Array schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ users: [{ name: string }] });
+ * schema.path('users').options; // SchemaDocumentArrayOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaDocumentOptions
+ */
+
+class SchemaDocumentArrayOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If `true`, Mongoose will skip building any indexes defined in this array's schema.
+ * If not set, Mongoose will build all indexes defined in this array's schema.
+ *
+ * ####Example:
+ *
+ * const childSchema = Schema({ name: { type: String, index: true } });
+ * // If `excludeIndexes` is `true`, Mongoose will skip building an index
+ * // on `arr.name`. Otherwise, Mongoose will build an index on `arr.name`.
+ * const parentSchema = Schema({
+ * arr: { type: [childSchema], excludeIndexes: true }
+ * });
+ *
+ * @api public
+ * @property excludeIndexes
+ * @memberOf SchemaDocumentArrayOptions
+ * @type Array
+ * @instance
+ */
+
+Object.defineProperty(SchemaDocumentArrayOptions.prototype, 'excludeIndexes', opts);
+
+/**
+ * If set, overwrites the child schema's `_id` option.
+ *
+ * ####Example:
+ *
+ * const childSchema = Schema({ name: String });
+ * const parentSchema = Schema({
+ * child: { type: childSchema, _id: false }
+ * });
+ * parentSchema.path('child').schema.options._id; // false
+ *
+ * @api public
+ * @property _id
+ * @memberOf SchemaDocumentArrayOptions
+ * @type Array
+ * @instance
+ */
+
+Object.defineProperty(SchemaDocumentArrayOptions.prototype, '_id', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaDocumentArrayOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaMapOptions.js b/node_modules/mongoose/lib/options/SchemaMapOptions.js
new file mode 100644
index 0000000..335d84a
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaMapOptions.js
@@ -0,0 +1,43 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a Map schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ socialMediaHandles: { type: Map, of: String } });
+ * schema.path('socialMediaHandles').options; // SchemaMapOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaMapOptions
+ */
+
+class SchemaMapOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If set, specifies the type of this map's values. Mongoose will cast
+ * this map's values to the given type.
+ *
+ * If not set, Mongoose will not cast the map's values.
+ *
+ * ####Example:
+ *
+ * // Mongoose will cast `socialMediaHandles` values to strings
+ * const schema = new Schema({ socialMediaHandles: { type: Map, of: String } });
+ * schema.path('socialMediaHandles').options.of; // String
+ *
+ * @api public
+ * @property of
+ * @memberOf SchemaMapOptions
+ * @type Function|string
+ * @instance
+ */
+
+Object.defineProperty(SchemaMapOptions.prototype, 'of', opts);
+
+module.exports = SchemaMapOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaNumberOptions.js b/node_modules/mongoose/lib/options/SchemaNumberOptions.js
new file mode 100644
index 0000000..42b0a01
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaNumberOptions.js
@@ -0,0 +1,74 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a Number schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ count: Number });
+ * schema.path('count').options; // SchemaNumberOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaNumberOptions
+ */
+
+class SchemaNumberOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If set, Mongoose adds a validator that checks that this path is at least the
+ * given `min`.
+ *
+ * @api public
+ * @property min
+ * @memberOf SchemaNumberOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaNumberOptions.prototype, 'min', opts);
+
+/**
+ * If set, Mongoose adds a validator that checks that this path is less than the
+ * given `max`.
+ *
+ * @api public
+ * @property max
+ * @memberOf SchemaNumberOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaNumberOptions.prototype, 'max', opts);
+
+/**
+ * If set, Mongoose adds a validator that checks that this path is strictly
+ * equal to one of the given values.
+ *
+ * ####Example:
+ * const schema = new Schema({
+ * favoritePrime: {
+ * type: Number,
+ * enum: [3, 5, 7]
+ * }
+ * });
+ * schema.path('favoritePrime').options.enum; // [3, 5, 7]
+ *
+ * @api public
+ * @property enum
+ * @memberOf SchemaNumberOptions
+ * @type Array
+ * @instance
+ */
+
+Object.defineProperty(SchemaNumberOptions.prototype, 'enum', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaNumberOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaObjectIdOptions.js b/node_modules/mongoose/lib/options/SchemaObjectIdOptions.js
new file mode 100644
index 0000000..cf887d0
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaObjectIdOptions.js
@@ -0,0 +1,38 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on an ObjectId schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ testId: mongoose.ObjectId });
+ * schema.path('testId').options; // SchemaObjectIdOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaObjectIdOptions
+ */
+
+class SchemaObjectIdOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If truthy, uses Mongoose's default built-in ObjectId path.
+ *
+ * @api public
+ * @property auto
+ * @memberOf SchemaObjectIdOptions
+ * @type Boolean
+ * @instance
+ */
+
+Object.defineProperty(SchemaObjectIdOptions.prototype, 'auto', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaObjectIdOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaSingleNestedOptions.js b/node_modules/mongoose/lib/options/SchemaSingleNestedOptions.js
new file mode 100644
index 0000000..c916d0f
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaSingleNestedOptions.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a single nested schematype.
+ *
+ * ####Example:
+ *
+ * const schema = Schema({ child: Schema({ name: String }) });
+ * schema.path('child').options; // SchemaSingleNestedOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaSingleNestedOptions
+ */
+
+class SchemaSingleNestedOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * If set, overwrites the child schema's `_id` option.
+ *
+ * ####Example:
+ *
+ * const childSchema = Schema({ name: String });
+ * const parentSchema = Schema({
+ * child: { type: childSchema, _id: false }
+ * });
+ * parentSchema.path('child').schema.options._id; // false
+ *
+ * @api public
+ * @property of
+ * @memberOf SchemaSingleNestedOptions
+ * @type Function|string
+ * @instance
+ */
+
+Object.defineProperty(SchemaSingleNestedOptions.prototype, '_id', opts);
+
+module.exports = SchemaSingleNestedOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaStringOptions.js b/node_modules/mongoose/lib/options/SchemaStringOptions.js
new file mode 100644
index 0000000..7654993
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaStringOptions.js
@@ -0,0 +1,116 @@
+'use strict';
+
+const SchemaTypeOptions = require('./SchemaTypeOptions');
+
+/**
+ * The options defined on a string schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String });
+ * schema.path('name').options; // SchemaStringOptions instance
+ *
+ * @api public
+ * @inherits SchemaTypeOptions
+ * @constructor SchemaStringOptions
+ */
+
+class SchemaStringOptions extends SchemaTypeOptions {}
+
+const opts = require('./propertyOptions');
+
+/**
+ * Array of allowed values for this path
+ *
+ * @api public
+ * @property enum
+ * @memberOf SchemaStringOptions
+ * @type Array
+ * @instance
+ */
+
+Object.defineProperty(SchemaStringOptions.prototype, 'enum', opts);
+
+/**
+ * Attach a validator that succeeds if the data string matches the given regular
+ * expression, and fails otherwise.
+ *
+ * @api public
+ * @property match
+ * @memberOf SchemaStringOptions
+ * @type RegExp
+ * @instance
+ */
+
+Object.defineProperty(SchemaStringOptions.prototype, 'match', opts);
+
+/**
+ * If truthy, Mongoose will add a custom setter that lowercases this string
+ * using JavaScript's built-in `String#toLowerCase()`.
+ *
+ * @api public
+ * @property lowercase
+ * @memberOf SchemaStringOptions
+ * @type Boolean
+ * @instance
+ */
+
+Object.defineProperty(SchemaStringOptions.prototype, 'lowercase', opts);
+
+/**
+ * If truthy, Mongoose will add a custom setter that removes leading and trailing
+ * whitespace using JavaScript's built-in `String#trim()`.
+ *
+ * @api public
+ * @property trim
+ * @memberOf SchemaStringOptions
+ * @type Boolean
+ * @instance
+ */
+
+Object.defineProperty(SchemaStringOptions.prototype, 'trim', opts);
+
+/**
+ * If truthy, Mongoose will add a custom setter that uppercases this string
+ * using JavaScript's built-in `String#toUpperCase()`.
+ *
+ * @api public
+ * @property uppercase
+ * @memberOf SchemaStringOptions
+ * @type Boolean
+ * @instance
+ */
+
+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.
+ *
+ * @api public
+ * @property minlength
+ * @memberOf SchemaStringOptions
+ * @type Number
+ * @instance
+ */
+
+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.
+ *
+ * @api public
+ * @property maxlength
+ * @memberOf SchemaStringOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaStringOptions.prototype, 'maxlength', opts);
+
+/*!
+ * ignore
+ */
+
+module.exports = SchemaStringOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/SchemaTypeOptions.js b/node_modules/mongoose/lib/options/SchemaTypeOptions.js
new file mode 100644
index 0000000..5dc5995
--- /dev/null
+++ b/node_modules/mongoose/lib/options/SchemaTypeOptions.js
@@ -0,0 +1,232 @@
+'use strict';
+
+const clone = require('../helpers/clone');
+
+/**
+ * The options defined on a schematype.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String });
+ * schema.path('name').options instanceof mongoose.SchemaTypeOptions; // true
+ *
+ * @api public
+ * @constructor SchemaTypeOptions
+ */
+
+class SchemaTypeOptions {
+ constructor(obj) {
+ if (obj == null) {
+ return this;
+ }
+ Object.assign(this, clone(obj));
+ }
+}
+
+const opts = require('./propertyOptions');
+
+/**
+ * The type to cast this path to.
+ *
+ * @api public
+ * @property type
+ * @memberOf SchemaTypeOptions
+ * @type Function|String|Object
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'type', opts);
+
+/**
+ * Function or object describing how to validate this schematype.
+ *
+ * @api public
+ * @property validate
+ * @memberOf SchemaTypeOptions
+ * @type Function|Object
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'validate', opts);
+
+/**
+ * Allows overriding casting logic for this individual path. If a string, the
+ * given string overwrites Mongoose's default cast error message.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({
+ * num: {
+ * type: Number,
+ * cast: '{VALUE} is not a valid number'
+ * }
+ * });
+ *
+ * // Throws 'CastError: "bad" is not a valid number'
+ * schema.path('num').cast('bad');
+ *
+ * const Model = mongoose.model('Test', schema);
+ * const doc = new Model({ num: 'fail' });
+ * const err = doc.validateSync();
+ *
+ * err.errors['num']; // 'CastError: "fail" is not a valid number'
+ *
+ * @api public
+ * @property cast
+ * @memberOf SchemaTypeOptions
+ * @type String
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'cast', opts);
+
+/**
+ * If true, attach a required validator to this path, which ensures this path
+ * path cannot be set to a nullish value. If a function, Mongoose calls the
+ * function and only checks for nullish values if the function returns a truthy value.
+ *
+ * @api public
+ * @property required
+ * @memberOf SchemaTypeOptions
+ * @type Function|Boolean
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'required', opts);
+
+/**
+ * The default value for this path. If a function, Mongoose executes the function
+ * and uses the return value as the default.
+ *
+ * @api public
+ * @property default
+ * @memberOf SchemaTypeOptions
+ * @type Function|Any
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'default', opts);
+
+/**
+ * The model that `populate()` should use if populating this path.
+ *
+ * @api public
+ * @property ref
+ * @memberOf SchemaTypeOptions
+ * @type Function|String
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'ref', opts);
+
+/**
+ * Whether to include or exclude this path by default when loading documents
+ * using `find()`, `findOne()`, etc.
+ *
+ * @api public
+ * @property select
+ * @memberOf SchemaTypeOptions
+ * @type Boolean|Number
+ * @instance
+ */
+
+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.
+ *
+ * @api public
+ * @property index
+ * @memberOf SchemaTypeOptions
+ * @type Boolean|Number|Object
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'index', opts);
+
+/**
+ * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose
+ * will build a unique index on this path when the
+ * model is compiled. [The `unique` option is **not** a validator](/docs/validation.html#the-unique-option-is-not-a-validator).
+ *
+ * @api public
+ * @property unique
+ * @memberOf SchemaTypeOptions
+ * @type Boolean|Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'unique', opts);
+
+/**
+ * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
+ * disallow changes to this path once the document
+ * is saved to the database for the first time. Read more about [immutability in Mongoose here](http://thecodebarbarian.com/whats-new-in-mongoose-5-6-immutable-properties.html).
+ *
+ * @api public
+ * @property immutable
+ * @memberOf SchemaTypeOptions
+ * @type Function|Boolean
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'immutable', opts);
+
+/**
+ * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose will
+ * build a sparse index on this path.
+ *
+ * @api public
+ * @property sparse
+ * @memberOf SchemaTypeOptions
+ * @type Boolean|Number
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'sparse', opts);
+
+/**
+ * If [truthy](https://masteringjs.io/tutorials/fundamentals/truthy), Mongoose
+ * will build a text index on this path.
+ *
+ * @api public
+ * @property text
+ * @memberOf SchemaTypeOptions
+ * @type Boolean|Number|Object
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'text', opts);
+
+/**
+ * Define a transform function for this individual schema type.
+ * Only called when calling `toJSON()` or `toObject()`.
+ *
+ * ####Example:
+ *
+ * const schema = Schema({
+ * myDate: {
+ * type: Date,
+ * transform: v => v.getFullYear()
+ * }
+ * });
+ * const Model = mongoose.model('Test', schema);
+ *
+ * const doc = new Model({ myDate: new Date('2019/06/01') });
+ * doc.myDate instanceof Date; // true
+ *
+ * const res = doc.toObject({ transform: true });
+ * res.myDate; // 2019
+ *
+ * @api public
+ * @property transform
+ * @memberOf SchemaTypeOptions
+ * @type Function
+ * @instance
+ */
+
+Object.defineProperty(SchemaTypeOptions.prototype, 'transform', opts);
+
+module.exports = SchemaTypeOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/VirtualOptions.js b/node_modules/mongoose/lib/options/VirtualOptions.js
new file mode 100644
index 0000000..a266414
--- /dev/null
+++ b/node_modules/mongoose/lib/options/VirtualOptions.js
@@ -0,0 +1,164 @@
+'use strict';
+
+const opts = require('./propertyOptions');
+
+class VirtualOptions {
+ constructor(obj) {
+ Object.assign(this, obj);
+
+ if (obj != null && obj.options != null) {
+ this.options = Object.assign({}, obj.options);
+ }
+ }
+}
+
+/**
+ * Marks this virtual as a populate virtual, and specifies the model to
+ * use for populate.
+ *
+ * @api public
+ * @property ref
+ * @memberOf VirtualOptions
+ * @type String|Model|Function
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'ref', opts);
+
+/**
+ * Marks this virtual as a populate virtual, and specifies the path that
+ * contains the name of the model to populate
+ *
+ * @api public
+ * @property refPath
+ * @memberOf VirtualOptions
+ * @type String|Function
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'refPath', opts);
+
+/**
+ * The name of the property in the local model to match to `foreignField`
+ * in the foreign model.
+ *
+ * @api public
+ * @property localField
+ * @memberOf VirtualOptions
+ * @type String|Function
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'localField', opts);
+
+/**
+ * The name of the property in the foreign model to match to `localField`
+ * in the local model.
+ *
+ * @api public
+ * @property foreignField
+ * @memberOf VirtualOptions
+ * @type String|Function
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'foreignField', opts);
+
+/**
+ * Whether to populate this virtual as a single document (true) or an
+ * array of documents (false).
+ *
+ * @api public
+ * @property justOne
+ * @memberOf VirtualOptions
+ * @type Boolean
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'justOne', opts);
+
+/**
+ * If true, populate just the number of documents where `localField`
+ * matches `foreignField`, as opposed to the documents themselves.
+ *
+ * If `count` is set, it overrides `justOne`.
+ *
+ * @api public
+ * @property count
+ * @memberOf VirtualOptions
+ * @type Boolean
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'count', opts);
+
+/**
+ * Add an additional filter to populate, in addition to `localField`
+ * matches `foreignField`.
+ *
+ * @api public
+ * @property match
+ * @memberOf VirtualOptions
+ * @type Object|Function
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'match', opts);
+
+/**
+ * Additional options to pass to the query used to `populate()`:
+ *
+ * - `sort`
+ * - `skip`
+ * - `limit`
+ *
+ * @api public
+ * @property options
+ * @memberOf VirtualOptions
+ * @type Object
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'options', opts);
+
+/**
+ * If true, add a `skip` to the query used to `populate()`.
+ *
+ * @api public
+ * @property skip
+ * @memberOf VirtualOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'skip', opts);
+
+/**
+ * If true, add a `limit` to the query used to `populate()`.
+ *
+ * @api public
+ * @property limit
+ * @memberOf VirtualOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'limit', opts);
+
+/**
+ * The `limit` option for `populate()` has [some unfortunate edge cases](/docs/populate.html#query-conditions)
+ * when working with multiple documents, like `.find().populate()`. The
+ * `perDocumentLimit` option makes `populate()` execute a separate query
+ * for each document returned from `find()` to ensure each document
+ * gets up to `perDocumentLimit` populated docs if possible.
+ *
+ * @api public
+ * @property perDocumentLimit
+ * @memberOf VirtualOptions
+ * @type Number
+ * @instance
+ */
+
+Object.defineProperty(VirtualOptions.prototype, 'perDocumentLimit', opts);
+
+module.exports = VirtualOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/propertyOptions.js b/node_modules/mongoose/lib/options/propertyOptions.js
new file mode 100644
index 0000000..b7488a3
--- /dev/null
+++ b/node_modules/mongoose/lib/options/propertyOptions.js
@@ -0,0 +1,8 @@
+'use strict';
+
+module.exports = Object.freeze({
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: void 0
+}); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/removeOptions.js b/node_modules/mongoose/lib/options/removeOptions.js
new file mode 100644
index 0000000..0d91586
--- /dev/null
+++ b/node_modules/mongoose/lib/options/removeOptions.js
@@ -0,0 +1,14 @@
+'use strict';
+
+const clone = require('../helpers/clone');
+
+class RemoveOptions {
+ constructor(obj) {
+ if (obj == null) {
+ return;
+ }
+ Object.assign(this, clone(obj));
+ }
+}
+
+module.exports = RemoveOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/options/saveOptions.js b/node_modules/mongoose/lib/options/saveOptions.js
new file mode 100644
index 0000000..22ef437
--- /dev/null
+++ b/node_modules/mongoose/lib/options/saveOptions.js
@@ -0,0 +1,14 @@
+'use strict';
+
+const clone = require('../helpers/clone');
+
+class SaveOptions {
+ constructor(obj) {
+ if (obj == null) {
+ return;
+ }
+ Object.assign(this, clone(obj));
+ }
+}
+
+module.exports = SaveOptions; \ No newline at end of file
diff --git a/node_modules/mongoose/lib/plugins/idGetter.js b/node_modules/mongoose/lib/plugins/idGetter.js
new file mode 100644
index 0000000..f4e6356
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/idGetter.js
@@ -0,0 +1,28 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function(schema) {
+ // ensure the documents receive an id getter unless disabled
+ const autoIdGetter = !schema.paths['id'] &&
+ (!schema.options.noVirtualId && schema.options.id);
+ if (!autoIdGetter) {
+ return;
+ }
+
+ schema.virtual('id').get(idGetter);
+};
+
+/*!
+ * Returns this documents _id cast to a string.
+ */
+
+function idGetter() {
+ if (this._id != null) {
+ return String(this._id);
+ }
+
+ return null;
+}
diff --git a/node_modules/mongoose/lib/plugins/removeSubdocs.js b/node_modules/mongoose/lib/plugins/removeSubdocs.js
new file mode 100644
index 0000000..44b2ea6
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/removeSubdocs.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const each = require('../helpers/each');
+
+/*!
+ * ignore
+ */
+
+module.exports = function(schema) {
+ const unshift = true;
+ schema.s.hooks.pre('remove', false, function(next) {
+ if (this.ownerDocument) {
+ next();
+ return;
+ }
+
+ const _this = this;
+ 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) {
+ next(error);
+ });
+ }
+ next();
+ });
+ }, null, unshift);
+};
diff --git a/node_modules/mongoose/lib/plugins/saveSubdocs.js b/node_modules/mongoose/lib/plugins/saveSubdocs.js
new file mode 100644
index 0000000..c0a3144
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/saveSubdocs.js
@@ -0,0 +1,66 @@
+'use strict';
+
+const each = require('../helpers/each');
+
+/*!
+ * ignore
+ */
+
+module.exports = function(schema) {
+ const unshift = true;
+ schema.s.hooks.pre('save', false, function(next) {
+ if (this.ownerDocument) {
+ next();
+ return;
+ }
+
+ const _this = this;
+ const subdocs = this.$__getAllSubdocs();
+
+ if (!subdocs.length) {
+ next();
+ return;
+ }
+
+ each(subdocs, function(subdoc, cb) {
+ 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) {
+ next(error);
+ });
+ }
+ next();
+ });
+ }, null, unshift);
+
+ schema.s.hooks.post('save', function(doc, next) {
+ if (this.ownerDocument) {
+ next();
+ return;
+ }
+
+ const _this = this;
+ const subdocs = this.$__getAllSubdocs();
+
+ if (!subdocs.length) {
+ next();
+ return;
+ }
+
+ each(subdocs, function(subdoc, cb) {
+ 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) {
+ next(error);
+ });
+ }
+ next();
+ });
+ }, null, unshift);
+};
diff --git a/node_modules/mongoose/lib/plugins/sharding.js b/node_modules/mongoose/lib/plugins/sharding.js
new file mode 100644
index 0000000..560053e
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/sharding.js
@@ -0,0 +1,83 @@
+'use strict';
+
+const objectIdSymbol = require('../helpers/symbols').objectIdSymbol;
+const utils = require('../utils');
+
+/*!
+ * ignore
+ */
+
+module.exports = function shardingPlugin(schema) {
+ schema.post('init', function() {
+ storeShard.call(this);
+ return this;
+ });
+ schema.pre('save', function(next) {
+ applyWhere.call(this);
+ next();
+ });
+ schema.pre('remove', function(next) {
+ applyWhere.call(this);
+ next();
+ });
+ schema.post('save', function() {
+ storeShard.call(this);
+ });
+};
+
+/*!
+ * ignore
+ */
+
+function applyWhere() {
+ let paths;
+ let len;
+
+ if (this.$__.shardval) {
+ paths = Object.keys(this.$__.shardval);
+ len = paths.length;
+
+ this.$where = this.$where || {};
+ for (let i = 0; i < len; ++i) {
+ this.$where[paths[i]] = this.$__.shardval[paths[i]];
+ }
+ }
+}
+
+/*!
+ * ignore
+ */
+
+module.exports.storeShard = storeShard;
+
+/*!
+ * ignore
+ */
+
+function storeShard() {
+ // backwards compat
+ const key = this.schema.options.shardKey || this.schema.options.shardkey;
+ if (!utils.isPOJO(key)) {
+ return;
+ }
+
+ const orig = this.$__.shardval = {};
+ const paths = Object.keys(key);
+ const len = paths.length;
+ let val;
+
+ for (let i = 0; i < len; ++i) {
+ val = this.$__getValue(paths[i]);
+ if (val == null) {
+ orig[paths[i]] = val;
+ } else if (utils.isMongooseObject(val)) {
+ orig[paths[i]] = val.toObject({ depopulate: true, _isNested: true });
+ } else if (val instanceof Date || val[objectIdSymbol]) {
+ orig[paths[i]] = val;
+ } else if (typeof val.valueOf === 'function') {
+ orig[paths[i]] = val.valueOf();
+ } else {
+ orig[paths[i]] = val;
+ }
+ }
+}
diff --git a/node_modules/mongoose/lib/plugins/trackTransaction.js b/node_modules/mongoose/lib/plugins/trackTransaction.js
new file mode 100644
index 0000000..410a596
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/trackTransaction.js
@@ -0,0 +1,91 @@
+'use strict';
+
+const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
+const sessionNewDocuments = require('../helpers/symbols').sessionNewDocuments;
+
+module.exports = function trackTransaction(schema) {
+ schema.pre('save', function() {
+ const session = this.$session();
+ if (session == null) {
+ return;
+ }
+ if (session.transaction == null || session[sessionNewDocuments] == null) {
+ return;
+ }
+
+ if (!session[sessionNewDocuments].has(this)) {
+ const initialState = {};
+ if (this.isNew) {
+ initialState.isNew = true;
+ }
+ if (this.schema.options.versionKey) {
+ initialState.versionKey = this.get(this.schema.options.versionKey);
+ }
+
+ initialState.modifiedPaths = new Set(Object.keys(this.$__.activePaths.states.modify));
+ initialState.atomics = _getAtomics(this);
+
+ session[sessionNewDocuments].set(this, initialState);
+ } else {
+ const state = session[sessionNewDocuments].get(this);
+
+ for (const path of Object.keys(this.$__.activePaths.states.modify)) {
+ state.modifiedPaths.add(path);
+ }
+ state.atomics = _getAtomics(this, state.atomics);
+ }
+ });
+};
+
+function _getAtomics(doc, previous) {
+ const pathToAtomics = new Map();
+ previous = previous || new Map();
+
+ const pathsToCheck = Object.keys(doc.$__.activePaths.init).concat(Object.keys(doc.$__.activePaths.modify));
+
+ for (const path of pathsToCheck) {
+ const val = doc.$__getValue(path);
+ if (val != null &&
+ val instanceof Array &&
+ val.isMongooseDocumentArray &&
+ val.length &&
+ val[arrayAtomicsSymbol] != null &&
+ Object.keys(val[arrayAtomicsSymbol]).length > 0) {
+ const existing = previous.get(path) || {};
+ pathToAtomics.set(path, mergeAtomics(existing, val[arrayAtomicsSymbol]));
+ }
+ }
+
+ const dirty = doc.$__dirty();
+ for (const dirt of dirty) {
+ const path = dirt.path;
+
+ const val = dirt.value;
+ if (val != null && val[arrayAtomicsSymbol] != null && Object.keys(val[arrayAtomicsSymbol]).length > 0) {
+ const existing = previous.get(path) || {};
+ pathToAtomics.set(path, mergeAtomics(existing, val[arrayAtomicsSymbol]));
+ }
+ }
+
+ return pathToAtomics;
+}
+
+function mergeAtomics(destination, source) {
+ destination = destination || {};
+
+ if (source.$pullAll != null) {
+ destination.$pullAll = (destination.$pullAll || []).concat(source.$pullAll);
+ }
+ if (source.$push != null) {
+ destination.$push = destination.$push || {};
+ destination.$push.$each = (destination.$push.$each || []).concat(source.$push.$each);
+ }
+ if (source.$addToSet != null) {
+ destination.$addToSet = (destination.$addToSet || []).concat(source.$addToSet);
+ }
+ if (source.$set != null) {
+ destination.$set = Object.assign(destination.$set || {}, source.$set);
+ }
+
+ return destination;
+} \ No newline at end of file
diff --git a/node_modules/mongoose/lib/plugins/validateBeforeSave.js b/node_modules/mongoose/lib/plugins/validateBeforeSave.js
new file mode 100644
index 0000000..4635de1
--- /dev/null
+++ b/node_modules/mongoose/lib/plugins/validateBeforeSave.js
@@ -0,0 +1,45 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function(schema) {
+ const unshift = true;
+ schema.pre('save', false, function validateBeforeSave(next, options) {
+ const _this = this;
+ // Nested docs have their own presave
+ if (this.ownerDocument) {
+ return next();
+ }
+
+ const hasValidateBeforeSaveOption = options &&
+ (typeof options === 'object') &&
+ ('validateBeforeSave' in options);
+
+ let shouldValidate;
+ if (hasValidateBeforeSaveOption) {
+ shouldValidate = !!options.validateBeforeSave;
+ } else {
+ shouldValidate = this.schema.options.validateBeforeSave;
+ }
+
+ // Validate
+ if (shouldValidate) {
+ const hasValidateModifiedOnlyOption = options &&
+ (typeof options === 'object') &&
+ ('validateModifiedOnly' in options);
+ const validateOptions = hasValidateModifiedOnlyOption ?
+ { validateModifiedOnly: options.validateModifiedOnly } :
+ null;
+ this.validate(validateOptions, function(error) {
+ return _this.schema.s.hooks.execPost('save:error', _this, [_this], { error: error }, function(error) {
+ _this.$op = 'save';
+ next(error);
+ });
+ });
+ } else {
+ next();
+ }
+ }, null, unshift);
+};
diff --git a/node_modules/mongoose/lib/promise_provider.js b/node_modules/mongoose/lib/promise_provider.js
new file mode 100644
index 0000000..3febf36
--- /dev/null
+++ b/node_modules/mongoose/lib/promise_provider.js
@@ -0,0 +1,49 @@
+/*!
+ * ignore
+ */
+
+'use strict';
+
+const assert = require('assert');
+const mquery = require('mquery');
+
+/**
+ * Helper for multiplexing promise implementations
+ *
+ * @api private
+ */
+
+const store = {
+ _promise: null
+};
+
+/**
+ * Get the current promise constructor
+ *
+ * @api private
+ */
+
+store.get = function() {
+ return store._promise;
+};
+
+/**
+ * Set the current promise constructor
+ *
+ * @api private
+ */
+
+store.set = function(lib) {
+ assert.ok(typeof lib === 'function',
+ `mongoose.Promise must be a function, got ${lib}`);
+ store._promise = lib;
+ mquery.Promise = lib;
+};
+
+/*!
+ * Use native promises by default
+ */
+
+store.set(global.Promise);
+
+module.exports = store;
diff --git a/node_modules/mongoose/lib/query.js b/node_modules/mongoose/lib/query.js
new file mode 100644
index 0000000..d270efb
--- /dev/null
+++ b/node_modules/mongoose/lib/query.js
@@ -0,0 +1,5380 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CastError = require('./error/cast');
+const DocumentNotFoundError = require('./error/notFound');
+const Kareem = require('kareem');
+const MongooseError = require('./error/mongooseError');
+const ObjectParameterError = require('./error/objectParameter');
+const QueryCursor = require('./cursor/QueryCursor');
+const ReadPreference = require('./driver').get().ReadPreference;
+const applyGlobalMaxTimeMS = require('./helpers/query/applyGlobalMaxTimeMS');
+const applyWriteConcern = require('./helpers/schema/applyWriteConcern');
+const cast = require('./cast');
+const castArrayFilters = require('./helpers/update/castArrayFilters');
+const castUpdate = require('./helpers/query/castUpdate');
+const completeMany = require('./helpers/query/completeMany');
+const get = require('./helpers/get');
+const promiseOrCallback = require('./helpers/promiseOrCallback');
+const getDiscriminatorByValue = require('./helpers/discriminator/getDiscriminatorByValue');
+const hasDollarKeys = require('./helpers/query/hasDollarKeys');
+const helpers = require('./queryhelpers');
+const isInclusive = require('./helpers/projection/isInclusive');
+const mquery = require('mquery');
+const parseProjection = require('./helpers/projection/parseProjection');
+const removeUnusedArrayFilters = require('./helpers/update/removeUnusedArrayFilters');
+const selectPopulatedFields = require('./helpers/query/selectPopulatedFields');
+const setDefaultsOnInsert = require('./helpers/setDefaultsOnInsert');
+const slice = require('sliced');
+const updateValidators = require('./helpers/updateValidators');
+const util = require('util');
+const utils = require('./utils');
+const wrapThunk = require('./helpers/query/wrapThunk');
+
+/**
+ * Query constructor used for building queries. You do not need
+ * to instantiate a `Query` directly. Instead use Model functions like
+ * [`Model.find()`](/docs/api.html#find_find).
+ *
+ * ####Example:
+ *
+ * const query = MyModel.find(); // `query` is an instance of `Query`
+ * query.setOptions({ lean : true });
+ * query.collection(MyModel.collection);
+ * query.where('age').gte(21).exec(callback);
+ *
+ * // You can instantiate a query directly. There is no need to do
+ * // this unless you're an advanced user with a very good reason to.
+ * const query = new mongoose.Query();
+ *
+ * @param {Object} [options]
+ * @param {Object} [model]
+ * @param {Object} [conditions]
+ * @param {Object} [collection] Mongoose collection
+ * @api public
+ */
+
+function Query(conditions, options, model, collection) {
+ // this stuff is for dealing with custom queries created by #toConstructor
+ if (!this._mongooseOptions) {
+ this._mongooseOptions = {};
+ }
+ options = options || {};
+
+ this._transforms = [];
+ this._hooks = new Kareem();
+ this._executionCount = 0;
+
+ // this is the case where we have a CustomQuery, we need to check if we got
+ // options passed in, and if we did, merge them in
+ const keys = Object.keys(options);
+ for (const key of keys) {
+ this._mongooseOptions[key] = options[key];
+ }
+
+ if (collection) {
+ this.mongooseCollection = collection;
+ }
+
+ if (model) {
+ this.model = model;
+ this.schema = model.schema;
+ }
+
+ // this is needed because map reduce returns a model that can be queried, but
+ // all of the queries on said model should be lean
+ if (this.model && this.model._mapreduce) {
+ this.lean();
+ }
+
+ // inherit mquery
+ mquery.call(this, this.mongooseCollection, options);
+
+ if (conditions) {
+ this.find(conditions);
+ }
+
+ this.options = this.options || {};
+
+ // For gh-6880. mquery still needs to support `fields` by default for old
+ // versions of MongoDB
+ this.$useProjection = true;
+
+ const collation = get(this, 'schema.options.collation', null);
+ if (collation != null) {
+ this.options.collation = collation;
+ }
+}
+
+/*!
+ * inherit mquery
+ */
+
+Query.prototype = new mquery;
+Query.prototype.constructor = Query;
+Query.base = mquery.prototype;
+
+/**
+ * Flag to opt out of using `$geoWithin`.
+ *
+ * mongoose.Query.use$geoWithin = false;
+ *
+ * MongoDB 2.4 deprecated the use of `$within`, replacing it with `$geoWithin`. Mongoose uses `$geoWithin` by default (which is 100% backward compatible with `$within`). If you are running an older version of MongoDB, set this flag to `false` so your `within()` queries continue to work.
+ *
+ * @see http://docs.mongodb.org/manual/reference/operator/geoWithin/
+ * @default true
+ * @property use$geoWithin
+ * @memberOf Query
+ * @receiver Query
+ * @api public
+ */
+
+Query.use$geoWithin = mquery.use$geoWithin;
+
+/**
+ * Converts this query to a customized, reusable query constructor with all arguments and options retained.
+ *
+ * ####Example
+ *
+ * // Create a query for adventure movies and read from the primary
+ * // node in the replica-set unless it is down, in which case we'll
+ * // read from a secondary node.
+ * const query = Movie.find({ tags: 'adventure' }).read('primaryPreferred');
+ *
+ * // create a custom Query constructor based off these settings
+ * const Adventure = query.toConstructor();
+ *
+ * // Adventure is now a subclass of mongoose.Query and works the same way but with the
+ * // default query parameters and options set.
+ * Adventure().exec(callback)
+ *
+ * // further narrow down our query results while still using the previous settings
+ * Adventure().where({ name: /^Life/ }).exec(callback);
+ *
+ * // since Adventure is a stand-alone constructor we can also add our own
+ * // helper methods and getters without impacting global queries
+ * Adventure.prototype.startsWith = function (prefix) {
+ * this.where({ name: new RegExp('^' + prefix) })
+ * return this;
+ * }
+ * Object.defineProperty(Adventure.prototype, 'highlyRated', {
+ * get: function () {
+ * this.where({ rating: { $gt: 4.5 }});
+ * return this;
+ * }
+ * })
+ * Adventure().highlyRated.startsWith('Life').exec(callback)
+ *
+ * @return {Query} subclass-of-Query
+ * @api public
+ */
+
+Query.prototype.toConstructor = function toConstructor() {
+ const model = this.model;
+ const coll = this.mongooseCollection;
+
+ const CustomQuery = function(criteria, options) {
+ if (!(this instanceof CustomQuery)) {
+ return new CustomQuery(criteria, options);
+ }
+ this._mongooseOptions = utils.clone(p._mongooseOptions);
+ Query.call(this, criteria, options || null, model, coll);
+ };
+
+ util.inherits(CustomQuery, model.Query);
+
+ // set inherited defaults
+ const p = CustomQuery.prototype;
+
+ p.options = {};
+
+ // Need to handle `sort()` separately because entries-style `sort()` syntax
+ // `sort([['prop1', 1]])` confuses mquery into losing the outer nested array.
+ // See gh-8159
+ const options = Object.assign({}, this.options);
+ if (options.sort != null) {
+ p.sort(options.sort);
+ delete options.sort;
+ }
+ p.setOptions(options);
+
+ p.op = this.op;
+ p._conditions = utils.clone(this._conditions);
+ p._fields = utils.clone(this._fields);
+ p._update = utils.clone(this._update, {
+ flattenDecimals: false
+ });
+ p._path = this._path;
+ p._distinct = this._distinct;
+ p._collection = this._collection;
+ p._mongooseOptions = this._mongooseOptions;
+
+ return CustomQuery;
+};
+
+/**
+ * Specifies a javascript function or expression to pass to MongoDBs query system.
+ *
+ * ####Example
+ *
+ * query.$where('this.comments.length === 10 || this.name.length === 5')
+ *
+ * // or
+ *
+ * query.$where(function () {
+ * return this.comments.length === 10 || this.name.length === 5;
+ * })
+ *
+ * ####NOTE:
+ *
+ * Only use `$where` when you have a condition that cannot be met using other MongoDB operators like `$lt`.
+ * **Be sure to read about all of [its caveats](http://docs.mongodb.org/manual/reference/operator/where/) before using.**
+ *
+ * @see $where http://docs.mongodb.org/manual/reference/operator/where/
+ * @method $where
+ * @param {String|Function} js javascript string or function
+ * @return {Query} this
+ * @memberOf Query
+ * @instance
+ * @method $where
+ * @api public
+ */
+
+/**
+ * Specifies a `path` for use with chaining.
+ *
+ * ####Example
+ *
+ * // instead of writing:
+ * User.find({age: {$gte: 21, $lte: 65}}, callback);
+ *
+ * // we can instead write:
+ * User.where('age').gte(21).lte(65);
+ *
+ * // passing query conditions is permitted
+ * User.find().where({ name: 'vonderful' })
+ *
+ * // chaining
+ * User
+ * .where('age').gte(21).lte(65)
+ * .where('name', /^vonderful/i)
+ * .where('friends').slice(10)
+ * .exec(callback)
+ *
+ * @method where
+ * @memberOf Query
+ * @instance
+ * @param {String|Object} [path]
+ * @param {any} [val]
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.slice = function() {
+ if (arguments.length === 0) {
+ return this;
+ }
+
+ this._validate('slice');
+
+ let path;
+ let val;
+
+ if (arguments.length === 1) {
+ const arg = arguments[0];
+ if (typeof arg === 'object' && !Array.isArray(arg)) {
+ const keys = Object.keys(arg);
+ const numKeys = keys.length;
+ for (let i = 0; i < numKeys; ++i) {
+ this.slice(keys[i], arg[keys[i]]);
+ }
+ return this;
+ }
+ this._ensurePath('slice');
+ path = this._path;
+ val = arguments[0];
+ } else if (arguments.length === 2) {
+ if ('number' === typeof arguments[0]) {
+ this._ensurePath('slice');
+ path = this._path;
+ val = slice(arguments);
+ } else {
+ path = arguments[0];
+ val = arguments[1];
+ }
+ } else if (arguments.length === 3) {
+ path = arguments[0];
+ val = slice(arguments, 1);
+ }
+
+ const p = {};
+ p[path] = { $slice: val };
+ this.select(p);
+
+ return this;
+};
+
+
+/**
+ * Specifies the complementary comparison value for paths specified with `where()`
+ *
+ * ####Example
+ *
+ * User.where('age').equals(49);
+ *
+ * // is the same as
+ *
+ * User.where('age', 49);
+ *
+ * @method equals
+ * @memberOf Query
+ * @instance
+ * @param {Object} val
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Specifies arguments for an `$or` condition.
+ *
+ * ####Example
+ *
+ * query.or([{ color: 'red' }, { status: 'emergency' }])
+ *
+ * @see $or http://docs.mongodb.org/manual/reference/operator/or/
+ * @method or
+ * @memberOf Query
+ * @instance
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Specifies arguments for a `$nor` condition.
+ *
+ * ####Example
+ *
+ * query.nor([{ color: 'green' }, { status: 'ok' }])
+ *
+ * @see $nor http://docs.mongodb.org/manual/reference/operator/nor/
+ * @method nor
+ * @memberOf Query
+ * @instance
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Specifies arguments for a `$and` condition.
+ *
+ * ####Example
+ *
+ * query.and([{ color: 'green' }, { status: 'ok' }])
+ *
+ * @method and
+ * @memberOf Query
+ * @instance
+ * @see $and http://docs.mongodb.org/manual/reference/operator/and/
+ * @param {Array} array array of conditions
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Specifies a `$gt` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * ####Example
+ *
+ * Thing.find().where('age').gt(21)
+ *
+ * // or
+ * Thing.find().gt('age', 21)
+ *
+ * @method gt
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @see $gt http://docs.mongodb.org/manual/reference/operator/gt/
+ * @api public
+ */
+
+/**
+ * Specifies a `$gte` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method gte
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @see $gte http://docs.mongodb.org/manual/reference/operator/gte/
+ * @api public
+ */
+
+/**
+ * Specifies a `$lt` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method lt
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @see $lt http://docs.mongodb.org/manual/reference/operator/lt/
+ * @api public
+ */
+
+/**
+ * Specifies a `$lte` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @method lte
+ * @see $lte http://docs.mongodb.org/manual/reference/operator/lte/
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a `$ne` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @see $ne http://docs.mongodb.org/manual/reference/operator/ne/
+ * @method ne
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an `$in` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @see $in http://docs.mongodb.org/manual/reference/operator/in/
+ * @method in
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an `$nin` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @see $nin http://docs.mongodb.org/manual/reference/operator/nin/
+ * @method nin
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies an `$all` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * ####Example:
+ *
+ * MyModel.find().where('pets').all(['dog', 'cat', 'ferret']);
+ * // Equivalent:
+ * MyModel.find().all('pets', ['dog', 'cat', 'ferret']);
+ *
+ * @see $all http://docs.mongodb.org/manual/reference/operator/all/
+ * @method all
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Array} val
+ * @api public
+ */
+
+/**
+ * Specifies a `$size` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * ####Example
+ *
+ * MyModel.where('tags').size(0).exec(function (err, docs) {
+ * if (err) return handleError(err);
+ *
+ * assert(Array.isArray(docs));
+ * console.log('documents with 0 tags', docs);
+ * })
+ *
+ * @see $size http://docs.mongodb.org/manual/reference/operator/size/
+ * @method size
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a `$regex` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @see $regex http://docs.mongodb.org/manual/reference/operator/regex/
+ * @method regex
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {String|RegExp} val
+ * @api public
+ */
+
+/**
+ * Specifies a `maxDistance` query condition.
+ *
+ * When called with one argument, the most recent path passed to `where()` is used.
+ *
+ * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
+ * @method maxDistance
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies a `$mod` condition, filters documents for documents whose
+ * `path` property is a number that is equal to `remainder` modulo `divisor`.
+ *
+ * ####Example
+ *
+ * // All find products whose inventory is odd
+ * Product.find().mod('inventory', [2, 1]);
+ * Product.find().where('inventory').mod([2, 1]);
+ * // This syntax is a little strange, but supported.
+ * Product.find().where('inventory').mod(2, 1);
+ *
+ * @method mod
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Array} val must be of length 2, first element is `divisor`, 2nd element is `remainder`.
+ * @return {Query} this
+ * @see $mod http://docs.mongodb.org/manual/reference/operator/mod/
+ * @api public
+ */
+
+Query.prototype.mod = function() {
+ let val;
+ let path;
+
+ if (arguments.length === 1) {
+ this._ensurePath('mod');
+ val = arguments[0];
+ path = this._path;
+ } else if (arguments.length === 2 && !Array.isArray(arguments[1])) {
+ this._ensurePath('mod');
+ val = slice(arguments);
+ path = this._path;
+ } else if (arguments.length === 3) {
+ val = slice(arguments, 1);
+ path = arguments[0];
+ } else {
+ val = arguments[1];
+ path = arguments[0];
+ }
+
+ const conds = this._conditions[path] || (this._conditions[path] = {});
+ conds.$mod = val;
+ return this;
+};
+
+/**
+ * Specifies an `$exists` condition
+ *
+ * ####Example
+ *
+ * // { name: { $exists: true }}
+ * Thing.where('name').exists()
+ * Thing.where('name').exists(true)
+ * Thing.find().exists('name')
+ *
+ * // { name: { $exists: false }}
+ * Thing.where('name').exists(false);
+ * Thing.find().exists('name', false);
+ *
+ * @method exists
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val
+ * @return {Query} this
+ * @see $exists http://docs.mongodb.org/manual/reference/operator/exists/
+ * @api public
+ */
+
+/**
+ * Specifies an `$elemMatch` condition
+ *
+ * ####Example
+ *
+ * query.elemMatch('comment', { author: 'autobot', votes: {$gte: 5}})
+ *
+ * query.where('comment').elemMatch({ author: 'autobot', votes: {$gte: 5}})
+ *
+ * query.elemMatch('comment', function (elem) {
+ * elem.where('author').equals('autobot');
+ * elem.where('votes').gte(5);
+ * })
+ *
+ * query.where('comment').elemMatch(function (elem) {
+ * elem.where({ author: 'autobot' });
+ * elem.where('votes').gte(5);
+ * })
+ *
+ * @method elemMatch
+ * @memberOf Query
+ * @instance
+ * @param {String|Object|Function} path
+ * @param {Object|Function} filter
+ * @return {Query} this
+ * @see $elemMatch http://docs.mongodb.org/manual/reference/operator/elemMatch/
+ * @api public
+ */
+
+/**
+ * Defines a `$within` or `$geoWithin` argument for geo-spatial queries.
+ *
+ * ####Example
+ *
+ * query.where(path).within().box()
+ * query.where(path).within().circle()
+ * query.where(path).within().geometry()
+ *
+ * query.where('loc').within({ center: [50,50], radius: 10, unique: true, spherical: true });
+ * query.where('loc').within({ box: [[40.73, -73.9], [40.7, -73.988]] });
+ * query.where('loc').within({ polygon: [[],[],[],[]] });
+ *
+ * query.where('loc').within([], [], []) // polygon
+ * query.where('loc').within([], []) // box
+ * query.where('loc').within({ type: 'LineString', coordinates: [...] }); // geometry
+ *
+ * **MUST** be used after `where()`.
+ *
+ * ####NOTE:
+ *
+ * As of Mongoose 3.7, `$geoWithin` is always used for queries. To change this behavior, see [Query.use$geoWithin](#query_Query-use%2524geoWithin).
+ *
+ * ####NOTE:
+ *
+ * In Mongoose 3.7, `within` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
+ *
+ * @method within
+ * @see $polygon http://docs.mongodb.org/manual/reference/operator/polygon/
+ * @see $box http://docs.mongodb.org/manual/reference/operator/box/
+ * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
+ * @see $center http://docs.mongodb.org/manual/reference/operator/center/
+ * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
+ * @memberOf Query
+ * @instance
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Specifies a `$slice` projection for an array.
+ *
+ * ####Example
+ *
+ * query.slice('comments', 5)
+ * query.slice('comments', -5)
+ * query.slice('comments', [10, 5])
+ * query.where('comments').slice(5)
+ * query.where('comments').slice([-10, 5])
+ *
+ * @method slice
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Number} val number/range of elements to slice
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields#RetrievingaSubsetofFields-RetrievingaSubrangeofArrayElements
+ * @see $slice http://docs.mongodb.org/manual/reference/projection/slice/#prj._S_slice
+ * @api public
+ */
+
+/**
+ * Specifies the maximum number of documents the query will return.
+ *
+ * ####Example
+ *
+ * query.limit(20)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method limit
+ * @memberOf Query
+ * @instance
+ * @param {Number} val
+ * @api public
+ */
+
+/**
+ * Specifies the number of documents to skip.
+ *
+ * ####Example
+ *
+ * query.skip(100).limit(20)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method skip
+ * @memberOf Query
+ * @instance
+ * @param {Number} val
+ * @see cursor.skip http://docs.mongodb.org/manual/reference/method/cursor.skip/
+ * @api public
+ */
+
+/**
+ * Specifies the maxScan option.
+ *
+ * ####Example
+ *
+ * query.maxScan(100)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method maxScan
+ * @memberOf Query
+ * @instance
+ * @param {Number} val
+ * @see maxScan http://docs.mongodb.org/manual/reference/operator/maxScan/
+ * @api public
+ */
+
+/**
+ * Specifies the batchSize option.
+ *
+ * ####Example
+ *
+ * query.batchSize(100)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method batchSize
+ * @memberOf Query
+ * @instance
+ * @param {Number} val
+ * @see batchSize http://docs.mongodb.org/manual/reference/method/cursor.batchSize/
+ * @api public
+ */
+
+/**
+ * Specifies the `comment` option.
+ *
+ * ####Example
+ *
+ * query.comment('login query')
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method comment
+ * @memberOf Query
+ * @instance
+ * @param {String} val
+ * @see comment http://docs.mongodb.org/manual/reference/operator/comment/
+ * @api public
+ */
+
+/**
+ * Specifies this query as a `snapshot` query.
+ *
+ * ####Example
+ *
+ * query.snapshot() // true
+ * query.snapshot(true)
+ * query.snapshot(false)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method snapshot
+ * @memberOf Query
+ * @instance
+ * @see snapshot http://docs.mongodb.org/manual/reference/operator/snapshot/
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Sets query hints.
+ *
+ * ####Example
+ *
+ * query.hint({ indexA: 1, indexB: -1})
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @method hint
+ * @memberOf Query
+ * @instance
+ * @param {Object} val a hint object
+ * @return {Query} this
+ * @see $hint http://docs.mongodb.org/manual/reference/operator/hint/
+ * @api public
+ */
+
+/**
+ * Get/set the current projection (AKA fields). Pass `null` to remove the
+ * current projection.
+ *
+ * Unlike `projection()`, the `select()` function modifies the current
+ * projection in place. This function overwrites the existing projection.
+ *
+ * ####Example:
+ *
+ * const q = Model.find();
+ * q.projection(); // null
+ *
+ * q.select('a b');
+ * q.projection(); // { a: 1, b: 1 }
+ *
+ * q.projection({ c: 1 });
+ * q.projection(); // { c: 1 }
+ *
+ * q.projection(null);
+ * q.projection(); // null
+ *
+ *
+ * @method projection
+ * @memberOf Query
+ * @instance
+ * @param {Object|null} arg
+ * @return {Object} the current projection
+ * @api public
+ */
+
+Query.prototype.projection = function(arg) {
+ if (arguments.length === 0) {
+ return this._fields;
+ }
+
+ this._fields = {};
+ this._userProvidedFields = {};
+ this.select(arg);
+ return this._fields;
+};
+
+/**
+ * Specifies which document fields to include or exclude (also known as the query "projection")
+ *
+ * When using string syntax, prefixing a path with `-` will flag that path as excluded. When a path does not have the `-` prefix, it is included. Lastly, if a path is prefixed with `+`, it forces inclusion of the path, which is useful for paths excluded at the [schema level](/docs/api.html#schematype_SchemaType-select).
+ *
+ * A projection _must_ be either inclusive or exclusive. In other words, you must
+ * either list the fields to include (which excludes all others), or list the fields
+ * to exclude (which implies all other fields are included). The [`_id` field is the only exception because MongoDB includes it by default](https://docs.mongodb.com/manual/tutorial/project-fields-from-query-results/#suppress-id-field).
+ *
+ * ####Example
+ *
+ * // include a and b, exclude other fields
+ * query.select('a b');
+ * // Equivalent syntaxes:
+ * query.select(['a', 'b']);
+ * query.select({ a: 1, b: 1 });
+ *
+ * // exclude c and d, include other fields
+ * query.select('-c -d');
+ *
+ * // Use `+` to override schema-level `select: false` without making the
+ * // projection inclusive.
+ * const schema = new Schema({
+ * foo: { type: String, select: false },
+ * bar: String
+ * });
+ * // ...
+ * query.select('+foo'); // Override foo's `select: false` without excluding `bar`
+ *
+ * // or you may use object notation, useful when
+ * // you have keys already prefixed with a "-"
+ * query.select({ a: 1, b: 1 });
+ * query.select({ c: 0, d: 0 });
+ *
+ *
+ * @method select
+ * @memberOf Query
+ * @instance
+ * @param {Object|String|Array<String>} arg
+ * @return {Query} this
+ * @see SchemaType
+ * @api public
+ */
+
+Query.prototype.select = function select() {
+ let arg = arguments[0];
+ if (!arg) return this;
+ let i;
+
+ if (arguments.length !== 1) {
+ throw new Error('Invalid select: select only takes 1 argument');
+ }
+
+ this._validate('select');
+
+ const fields = this._fields || (this._fields = {});
+ const userProvidedFields = this._userProvidedFields || (this._userProvidedFields = {});
+
+ arg = parseProjection(arg);
+
+ if (utils.isObject(arg)) {
+ const keys = Object.keys(arg);
+ for (i = 0; i < keys.length; ++i) {
+ fields[keys[i]] = arg[keys[i]];
+ userProvidedFields[keys[i]] = arg[keys[i]];
+ }
+ return this;
+ }
+
+ throw new TypeError('Invalid select() argument. Must be string or object.');
+};
+
+/**
+ * _DEPRECATED_ Sets the slaveOk option.
+ *
+ * **Deprecated** in MongoDB 2.2 in favor of [read preferences](#query_Query-read).
+ *
+ * ####Example:
+ *
+ * query.slaveOk() // true
+ * query.slaveOk(true)
+ * query.slaveOk(false)
+ *
+ * @method slaveOk
+ * @memberOf Query
+ * @instance
+ * @deprecated use read() preferences instead if on mongodb >= 2.2
+ * @param {Boolean} v defaults to true
+ * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
+ * @see slaveOk http://docs.mongodb.org/manual/reference/method/rs.slaveOk/
+ * @see read() #query_Query-read
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Determines the MongoDB nodes from which to read.
+ *
+ * ####Preferences:
+ *
+ * primary - (default) Read from primary only. Operations will produce an error if primary is unavailable. Cannot be combined with tags.
+ * secondary Read from secondary if available, otherwise error.
+ * primaryPreferred Read from primary if available, otherwise a secondary.
+ * secondaryPreferred Read from a secondary if available, otherwise read from the primary.
+ * nearest All operations read from among the nearest candidates, but unlike other modes, this option will include both the primary and all secondaries in the random selection.
+ *
+ * Aliases
+ *
+ * p primary
+ * pp primaryPreferred
+ * s secondary
+ * sp secondaryPreferred
+ * n nearest
+ *
+ * ####Example:
+ *
+ * new Query().read('primary')
+ * new Query().read('p') // same as primary
+ *
+ * new Query().read('primaryPreferred')
+ * new Query().read('pp') // same as primaryPreferred
+ *
+ * new Query().read('secondary')
+ * new Query().read('s') // same as secondary
+ *
+ * new Query().read('secondaryPreferred')
+ * new Query().read('sp') // same as secondaryPreferred
+ *
+ * new Query().read('nearest')
+ * new Query().read('n') // same as nearest
+ *
+ * // read from secondaries with matching tags
+ * new Query().read('s', [{ dc:'sf', s: 1 },{ dc:'ma', s: 2 }])
+ *
+ * Read more about how to use read preferrences [here](http://docs.mongodb.org/manual/applications/replication/#read-preference) and [here](http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences).
+ *
+ * @method read
+ * @memberOf Query
+ * @instance
+ * @param {String} pref one of the listed preference options or aliases
+ * @param {Array} [tags] optional tags for this query
+ * @see mongodb http://docs.mongodb.org/manual/applications/replication/#read-preference
+ * @see driver http://mongodb.github.com/node-mongodb-native/driver-articles/anintroductionto1_1and2_2.html#read-preferences
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.read = function read(pref, tags) {
+ // first cast into a ReadPreference object to support tags
+ const read = new ReadPreference(pref, tags);
+ this.options.readPreference = read;
+ return this;
+};
+
+/**
+ * Sets the [MongoDB session](https://docs.mongodb.com/manual/reference/server-sessions/)
+ * associated with this query. Sessions are how you mark a query as part of a
+ * [transaction](/docs/transactions.html).
+ *
+ * Calling `session(null)` removes the session from this query.
+ *
+ * ####Example:
+ *
+ * const s = await mongoose.startSession();
+ * await mongoose.model('Person').findOne({ name: 'Axl Rose' }).session(s);
+ *
+ * @method session
+ * @memberOf Query
+ * @instance
+ * @param {ClientSession} [session] from `await conn.startSession()`
+ * @see Connection.prototype.startSession() /docs/api.html#connection_Connection-startSession
+ * @see mongoose.startSession() /docs/api.html#mongoose_Mongoose-startSession
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.session = function session(v) {
+ if (v == null) {
+ delete this.options.session;
+ }
+ this.options.session = v;
+ return this;
+};
+
+/**
+ * Sets the specified number of `mongod` servers, or tag set of `mongod` servers,
+ * that must acknowledge this write before this write is considered successful.
+ * This option is only valid for operations that write to the database:
+ *
+ * - `deleteOne()`
+ * - `deleteMany()`
+ * - `findOneAndDelete()`
+ * - `findOneAndReplace()`
+ * - `findOneAndUpdate()`
+ * - `remove()`
+ * - `update()`
+ * - `updateOne()`
+ * - `updateMany()`
+ *
+ * Defaults to the schema's [`writeConcern.w` option](/docs/guide.html#writeConcern)
+ *
+ * ####Example:
+ *
+ * // The 'majority' option means the `deleteOne()` promise won't resolve
+ * // until the `deleteOne()` has propagated to the majority of the replica set
+ * await mongoose.model('Person').
+ * deleteOne({ name: 'Ned Stark' }).
+ * w('majority');
+ *
+ * @method w
+ * @memberOf Query
+ * @instance
+ * @param {String|number} val 0 for fire-and-forget, 1 for acknowledged by one server, 'majority' for majority of the replica set, or [any of the more advanced options](https://docs.mongodb.com/manual/reference/write-concern/#w-option).
+ * @see mongodb https://docs.mongodb.com/manual/reference/write-concern/#w-option
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.w = function w(val) {
+ if (val == null) {
+ delete this.options.w;
+ }
+ this.options.w = val;
+ return this;
+};
+
+/**
+ * Requests acknowledgement that this operation has been persisted to MongoDB's
+ * on-disk journal.
+ * This option is only valid for operations that write to the database:
+ *
+ * - `deleteOne()`
+ * - `deleteMany()`
+ * - `findOneAndDelete()`
+ * - `findOneAndReplace()`
+ * - `findOneAndUpdate()`
+ * - `remove()`
+ * - `update()`
+ * - `updateOne()`
+ * - `updateMany()`
+ *
+ * Defaults to the schema's [`writeConcern.j` option](/docs/guide.html#writeConcern)
+ *
+ * ####Example:
+ *
+ * await mongoose.model('Person').deleteOne({ name: 'Ned Stark' }).j(true);
+ *
+ * @method j
+ * @memberOf Query
+ * @instance
+ * @param {boolean} val
+ * @see mongodb https://docs.mongodb.com/manual/reference/write-concern/#j-option
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.j = function j(val) {
+ if (val == null) {
+ delete this.options.j;
+ }
+ this.options.j = val;
+ return this;
+};
+
+/**
+ * If [`w > 1`](/docs/api.html#query_Query-w), the maximum amount of time to
+ * wait for this write to propagate through the replica set before this
+ * operation fails. The default is `0`, which means no timeout.
+ *
+ * This option is only valid for operations that write to the database:
+ *
+ * - `deleteOne()`
+ * - `deleteMany()`
+ * - `findOneAndDelete()`
+ * - `findOneAndReplace()`
+ * - `findOneAndUpdate()`
+ * - `remove()`
+ * - `update()`
+ * - `updateOne()`
+ * - `updateMany()`
+ *
+ * Defaults to the schema's [`writeConcern.wtimeout` option](/docs/guide.html#writeConcern)
+ *
+ * ####Example:
+ *
+ * // The `deleteOne()` promise won't resolve until this `deleteOne()` has
+ * // propagated to at least `w = 2` members of the replica set. If it takes
+ * // longer than 1 second, this `deleteOne()` will fail.
+ * await mongoose.model('Person').
+ * deleteOne({ name: 'Ned Stark' }).
+ * w(2).
+ * wtimeout(1000);
+ *
+ * @method wtimeout
+ * @memberOf Query
+ * @instance
+ * @param {number} ms number of milliseconds to wait
+ * @see mongodb https://docs.mongodb.com/manual/reference/write-concern/#wtimeout
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.wtimeout = function wtimeout(ms) {
+ if (ms == null) {
+ delete this.options.wtimeout;
+ }
+ this.options.wtimeout = ms;
+ return this;
+};
+
+/**
+ * Sets the readConcern option for the query.
+ *
+ * ####Example:
+ *
+ * new Query().readConcern('local')
+ * new Query().readConcern('l') // same as local
+ *
+ * new Query().readConcern('available')
+ * new Query().readConcern('a') // same as available
+ *
+ * new Query().readConcern('majority')
+ * new Query().readConcern('m') // same as majority
+ *
+ * new Query().readConcern('linearizable')
+ * new Query().readConcern('lz') // same as linearizable
+ *
+ * new Query().readConcern('snapshot')
+ * new Query().readConcern('s') // same as snapshot
+ *
+ *
+ * ####Read Concern Level:
+ *
+ * local MongoDB 3.2+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
+ * available MongoDB 3.6+ The query returns from the instance with no guarantee guarantee that the data has been written to a majority of the replica set members (i.e. may be rolled back).
+ * majority MongoDB 3.2+ The query returns the data that has been acknowledged by a majority of the replica set members. The documents returned by the read operation are durable, even in the event of failure.
+ * linearizable MongoDB 3.4+ The query returns data that reflects all successful majority-acknowledged writes that completed prior to the start of the read operation. The query may wait for concurrently executing writes to propagate to a majority of replica set members before returning results.
+ * snapshot MongoDB 4.0+ Only available for operations within multi-document transactions. Upon transaction commit with write concern "majority", the transaction operations are guaranteed to have read from a snapshot of majority-committed data.
+ *
+ * Aliases
+ *
+ * l local
+ * a available
+ * m majority
+ * lz linearizable
+ * s snapshot
+ *
+ * Read more about how to use read concern [here](https://docs.mongodb.com/manual/reference/read-concern/).
+ *
+ * @memberOf Query
+ * @method readConcern
+ * @param {String} level one of the listed read concern level or their aliases
+ * @see mongodb https://docs.mongodb.com/manual/reference/read-concern/
+ * @return {Query} this
+ * @api public
+ */
+
+/**
+ * Gets query options.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.limit(10);
+ * query.setOptions({ maxTimeMS: 1000 })
+ * query.getOptions(); // { limit: 10, maxTimeMS: 1000 }
+ *
+ * @return {Object} the options
+ * @api public
+ */
+
+Query.prototype.getOptions = function() {
+ return this.options;
+};
+
+/**
+ * Sets query options. Some options only make sense for certain operations.
+ *
+ * ####Options:
+ *
+ * The following options are only for `find()`:
+ *
+ * - [tailable](http://www.mongodb.org/display/DOCS/Tailable+Cursors)
+ * - [sort](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsort(\)%7D%7D)
+ * - [limit](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Blimit%28%29%7D%7D)
+ * - [skip](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bskip%28%29%7D%7D)
+ * - [maxscan](https://docs.mongodb.org/v3.2/reference/operator/meta/maxScan/#metaOp._S_maxScan)
+ * - [batchSize](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7BbatchSize%28%29%7D%7D)
+ * - [comment](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24comment)
+ * - [snapshot](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%7B%7Bsnapshot%28%29%7D%7D)
+ * - [readPreference](http://docs.mongodb.org/manual/applications/replication/#read-preference)
+ * - [hint](http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24hint)
+ *
+ * The following options are only for write operations: `update()`, `updateOne()`, `updateMany()`, `replaceOne()`, `findOneAndUpdate()`, and `findByIdAndUpdate()`:
+ *
+ * - [upsert](https://docs.mongodb.com/manual/reference/method/db.collection.update/)
+ * - [writeConcern](https://docs.mongodb.com/manual/reference/method/db.collection.update/)
+ * - [timestamps](https://mongoosejs.com/docs/guide.html#timestamps): If `timestamps` is set in the schema, set this option to `false` to skip timestamps for that particular update. Has no effect if `timestamps` is not enabled in the schema options.
+ * - omitUndefined: delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * - overwriteDiscriminatorKey: allow setting the discriminator key in the update. Will use the correct discriminator schema if the update changes the discriminator key.
+ * - overwrite: replace the entire document
+ *
+ * The following options are only for `find()`, `findOne()`, `findById()`, `findOneAndUpdate()`, and `findByIdAndUpdate()`:
+ *
+ * - [lean](./api.html#query_Query-lean)
+ * - [populate](/docs/populate.html)
+ * - [projection](/docs/api/query.html#query_Query-projection)
+ *
+ * The following options are only for all operations **except** `update()`, `updateOne()`, `updateMany()`, `remove()`, `deleteOne()`, and `deleteMany()`:
+ *
+ * - [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/)
+ *
+ * The following options are for `findOneAndUpdate()` and `findOneAndRemove()`
+ *
+ * - [useFindAndModify](/docs/deprecations.html#findandmodify)
+ * - rawResult
+ *
+ * The following options are for all operations:
+ *
+ * - [collation](https://docs.mongodb.com/manual/reference/collation/)
+ * - [session](https://docs.mongodb.com/manual/reference/server-sessions/)
+ * - [explain](https://docs.mongodb.com/manual/reference/method/cursor.explain/)
+ *
+ * @param {Object} options
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.setOptions = function(options, overwrite) {
+ // overwrite is only for internal use
+ if (overwrite) {
+ // ensure that _mongooseOptions & options are two different objects
+ this._mongooseOptions = (options && utils.clone(options)) || {};
+ this.options = options || {};
+
+ if ('populate' in options) {
+ this.populate(this._mongooseOptions);
+ }
+ return this;
+ }
+
+ if (options == null) {
+ return this;
+ }
+ if (typeof options !== 'object') {
+ throw new Error('Options must be an object, got "' + options + '"');
+ }
+
+ if (Array.isArray(options.populate)) {
+ const populate = options.populate;
+ delete options.populate;
+ const _numPopulate = populate.length;
+ for (let i = 0; i < _numPopulate; ++i) {
+ this.populate(populate[i]);
+ }
+ }
+
+ if ('useFindAndModify' in options) {
+ this._mongooseOptions.useFindAndModify = options.useFindAndModify;
+ delete options.useFindAndModify;
+ }
+ if ('omitUndefined' in options) {
+ this._mongooseOptions.omitUndefined = options.omitUndefined;
+ delete options.omitUndefined;
+ }
+ if ('setDefaultsOnInsert' in options) {
+ this._mongooseOptions.setDefaultsOnInsert = options.setDefaultsOnInsert;
+ delete options.setDefaultsOnInsert;
+ }
+ if ('overwriteDiscriminatorKey' in options) {
+ this._mongooseOptions.overwriteDiscriminatorKey = options.overwriteDiscriminatorKey;
+ delete options.overwriteDiscriminatorKey;
+ }
+
+ return Query.base.setOptions.call(this, options);
+};
+
+/**
+ * Sets the [`explain` option](https://docs.mongodb.com/manual/reference/method/cursor.explain/),
+ * which makes this query return detailed execution stats instead of the actual
+ * query result. This method is useful for determining what index your queries
+ * use.
+ *
+ * Calling `query.explain(v)` is equivalent to `query.setOption({ explain: v })`
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * const res = await query.find({ a: 1 }).explain('queryPlanner');
+ * console.log(res);
+ *
+ * @param {String} [verbose] The verbosity mode. Either 'queryPlanner', 'executionStats', or 'allPlansExecution'. The default is 'queryPlanner'
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.explain = function(verbose) {
+ if (arguments.length === 0) {
+ this.options.explain = true;
+ return this;
+ }
+ this.options.explain = verbose;
+ return this;
+};
+
+/**
+ * Sets the [maxTimeMS](https://docs.mongodb.com/manual/reference/method/cursor.maxTimeMS/)
+ * option. This will tell the MongoDB server to abort if the query or write op
+ * has been running for more than `ms` milliseconds.
+ *
+ * Calling `query.maxTimeMS(v)` is equivalent to `query.setOption({ maxTimeMS: v })`
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * // Throws an error 'operation exceeded time limit' as long as there's
+ * // >= 1 doc in the queried collection
+ * const res = await query.find({ $where: 'sleep(1000) || true' }).maxTimeMS(100);
+ *
+ * @param {Number} [ms] The number of milliseconds
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.maxTimeMS = function(ms) {
+ this.options.maxTimeMS = ms;
+ return this;
+};
+
+/**
+ * Returns the current query filter (also known as conditions) as a POJO.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.find({ a: 1 }).where('b').gt(2);
+ * query.getFilter(); // { a: 1, b: { $gt: 2 } }
+ *
+ * @return {Object} current query filter
+ * @api public
+ */
+
+Query.prototype.getFilter = function() {
+ return this._conditions;
+};
+
+/**
+ * Returns the current query filter. Equivalent to `getFilter()`.
+ *
+ * You should use `getFilter()` instead of `getQuery()` where possible. `getQuery()`
+ * will likely be deprecated in a future release.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.find({ a: 1 }).where('b').gt(2);
+ * query.getQuery(); // { a: 1, b: { $gt: 2 } }
+ *
+ * @return {Object} current query filter
+ * @api public
+ */
+
+Query.prototype.getQuery = function() {
+ return this._conditions;
+};
+
+/**
+ * Sets the query conditions to the provided JSON object.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.find({ a: 1 })
+ * query.setQuery({ a: 2 });
+ * query.getQuery(); // { a: 2 }
+ *
+ * @param {Object} new query conditions
+ * @return {undefined}
+ * @api public
+ */
+
+Query.prototype.setQuery = function(val) {
+ this._conditions = val;
+};
+
+/**
+ * Returns the current update operations as a JSON object.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.update({}, { $set: { a: 5 } });
+ * query.getUpdate(); // { $set: { a: 5 } }
+ *
+ * @return {Object} current update operations
+ * @api public
+ */
+
+Query.prototype.getUpdate = function() {
+ return this._update;
+};
+
+/**
+ * Sets the current update operation to new value.
+ *
+ * ####Example:
+ *
+ * const query = new Query();
+ * query.update({}, { $set: { a: 5 } });
+ * query.setUpdate({ $set: { b: 6 } });
+ * query.getUpdate(); // { $set: { b: 6 } }
+ *
+ * @param {Object} new update operation
+ * @return {undefined}
+ * @api public
+ */
+
+Query.prototype.setUpdate = function(val) {
+ this._update = val;
+};
+
+/**
+ * Returns fields selection for this query.
+ *
+ * @method _fieldsForExec
+ * @return {Object}
+ * @api private
+ * @receiver Query
+ */
+
+Query.prototype._fieldsForExec = function() {
+ return utils.clone(this._fields);
+};
+
+
+/**
+ * Return an update document with corrected `$set` operations.
+ *
+ * @method _updateForExec
+ * @api private
+ * @receiver Query
+ */
+
+Query.prototype._updateForExec = function() {
+ const update = utils.clone(this._update, {
+ transform: false,
+ depopulate: true
+ });
+ const ops = Object.keys(update);
+ let i = ops.length;
+ const ret = {};
+
+ while (i--) {
+ const op = ops[i];
+
+ if (this.options.overwrite) {
+ ret[op] = update[op];
+ continue;
+ }
+
+ if ('$' !== op[0]) {
+ // fix up $set sugar
+ if (!ret.$set) {
+ if (update.$set) {
+ ret.$set = update.$set;
+ } else {
+ ret.$set = {};
+ }
+ }
+ ret.$set[op] = update[op];
+ ops.splice(i, 1);
+ if (!~ops.indexOf('$set')) ops.push('$set');
+ } else if ('$set' === op) {
+ if (!ret.$set) {
+ ret[op] = update[op];
+ }
+ } else {
+ ret[op] = update[op];
+ }
+ }
+
+ return ret;
+};
+
+/**
+ * Makes sure _path is set.
+ *
+ * @method _ensurePath
+ * @param {String} method
+ * @api private
+ * @receiver Query
+ */
+
+/**
+ * Determines if `conds` can be merged using `mquery().merge()`
+ *
+ * @method canMerge
+ * @memberOf Query
+ * @instance
+ * @param {Object} conds
+ * @return {Boolean}
+ * @api private
+ */
+
+/**
+ * Returns default options for this query.
+ *
+ * @param {Model} model
+ * @api private
+ */
+
+Query.prototype._optionsForExec = function(model) {
+ const options = utils.clone(this.options);
+
+ delete options.populate;
+ model = model || this.model;
+
+ if (!model) {
+ return options;
+ }
+
+ const safe = get(model, 'schema.options.safe', null);
+ if (!('safe' in options) && safe != null) {
+ setSafe(options, safe);
+ }
+
+ // Apply schema-level `writeConcern` option
+ applyWriteConcern(model.schema, options);
+
+ const readPreference = get(model, 'schema.options.read');
+ if (!('readPreference' in options) && readPreference) {
+ options.readPreference = readPreference;
+ }
+
+ if (options.upsert !== void 0) {
+ options.upsert = !!options.upsert;
+ }
+
+ return options;
+};
+
+/*!
+ * ignore
+ */
+
+const safeDeprecationWarning = 'Mongoose: the `safe` option is deprecated. ' +
+ 'Use write concerns instead: http://bit.ly/mongoose-w';
+
+const setSafe = util.deprecate(function setSafe(options, safe) {
+ options.safe = safe;
+}, safeDeprecationWarning);
+
+/**
+ * Sets the lean option.
+ *
+ * Documents returned from queries with the `lean` option enabled are plain
+ * javascript objects, not [Mongoose Documents](/api/document.html). They have no
+ * `save` method, getters/setters, virtuals, or other Mongoose features.
+ *
+ * ####Example:
+ *
+ * new Query().lean() // true
+ * new Query().lean(true)
+ * new Query().lean(false)
+ *
+ * const docs = await Model.find().lean();
+ * docs[0] instanceof mongoose.Document; // false
+ *
+ * [Lean is great for high-performance, read-only cases](/docs/tutorials/lean.html),
+ * especially when combined
+ * with [cursors](/docs/queries.html#streaming).
+ *
+ * If you need virtuals, getters/setters, or defaults with `lean()`, you need
+ * to use a plugin. See:
+ *
+ * - [mongoose-lean-virtuals](https://plugins.mongoosejs.io/plugins/lean-virtuals)
+ * - [mongoose-lean-getters](https://plugins.mongoosejs.io/plugins/lean-getters)
+ * - [mongoose-lean-defaults](https://www.npmjs.com/package/mongoose-lean-defaults)
+ *
+ * @param {Boolean|Object} bool defaults to true
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.lean = function(v) {
+ this._mongooseOptions.lean = arguments.length ? v : true;
+ return this;
+};
+
+/**
+ * Adds a `$set` to this query's update without changing the operation.
+ * This is useful for query middleware so you can add an update regardless
+ * of whether you use `updateOne()`, `updateMany()`, `findOneAndUpdate()`, etc.
+ *
+ * ####Example:
+ *
+ * // Updates `{ $set: { updatedAt: new Date() } }`
+ * new Query().updateOne({}, {}).set('updatedAt', new Date());
+ * new Query().updateMany({}, {}).set({ updatedAt: new Date() });
+ *
+ * @param {String|Object} path path or object of key/value pairs to set
+ * @param {Any} [val] the value to set
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.set = function(path, val) {
+ if (typeof path === 'object') {
+ const keys = Object.keys(path);
+ for (const key of keys) {
+ this.set(key, path[key]);
+ }
+ return this;
+ }
+
+ this._update = this._update || {};
+ this._update.$set = this._update.$set || {};
+ this._update.$set[path] = val;
+ return this;
+};
+
+/**
+ * For update operations, returns the value of a path in the update's `$set`.
+ * Useful for writing getters/setters that can work with both update operations
+ * and `save()`.
+ *
+ * ####Example:
+ *
+ * const query = Model.updateOne({}, { $set: { name: 'Jean-Luc Picard' } });
+ * query.get('name'); // 'Jean-Luc Picard'
+ *
+ * @param {String|Object} path path or object of key/value pairs to get
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.get = function get(path) {
+ const update = this._update;
+ if (update == null) {
+ return void 0;
+ }
+ const $set = update.$set;
+ if ($set == null) {
+ return update[path];
+ }
+
+ if (utils.hasUserDefinedProperty(update, path)) {
+ return update[path];
+ }
+ if (utils.hasUserDefinedProperty($set, path)) {
+ return $set[path];
+ }
+
+ return void 0;
+};
+
+/**
+ * Gets/sets the error flag on this query. If this flag is not null or
+ * undefined, the `exec()` promise will reject without executing.
+ *
+ * ####Example:
+ *
+ * Query().error(); // Get current error value
+ * Query().error(null); // Unset the current error
+ * Query().error(new Error('test')); // `exec()` will resolve with test
+ * Schema.pre('find', function() {
+ * if (!this.getQuery().userId) {
+ * this.error(new Error('Not allowed to query without setting userId'));
+ * }
+ * });
+ *
+ * Note that query casting runs **after** hooks, so cast errors will override
+ * custom errors.
+ *
+ * ####Example:
+ * const TestSchema = new Schema({ num: Number });
+ * const TestModel = db.model('Test', TestSchema);
+ * TestModel.find({ num: 'not a number' }).error(new Error('woops')).exec(function(error) {
+ * // `error` will be a cast error because `num` failed to cast
+ * });
+ *
+ * @param {Error|null} err if set, `exec()` will fail fast before sending the query to MongoDB
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.error = function error(err) {
+ if (arguments.length === 0) {
+ return this._error;
+ }
+
+ this._error = err;
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Query.prototype._unsetCastError = function _unsetCastError() {
+ if (this._error != null && !(this._error instanceof CastError)) {
+ return;
+ }
+ return this.error(null);
+};
+
+/**
+ * Getter/setter around the current mongoose-specific options for this query
+ * Below are the current Mongoose-specific options.
+ *
+ * - `populate`: an array representing what paths will be populated. Should have one entry for each call to [`Query.prototype.populate()`](/docs/api.html#query_Query-populate)
+ * - `lean`: if truthy, Mongoose will not [hydrate](/docs/api.html#model_Model.hydrate) any documents that are returned from this query. See [`Query.prototype.lean()`](/docs/api.html#query_Query-lean) for more information.
+ * - `strict`: controls how Mongoose handles keys that aren't in the schema for updates. This option is `true` by default, which means Mongoose will silently strip any paths in the update that aren't in the schema. See the [`strict` mode docs](/docs/guide.html#strict) for more information.
+ * - `strictQuery`: controls how Mongoose handles keys that aren't in the schema for the query `filter`. This option is `false` by default for backwards compatibility, which means Mongoose will allow `Model.find({ foo: 'bar' })` even if `foo` is not in the schema. See the [`strictQuery` docs](/docs/guide.html#strictQuery) for more information.
+ * - `useFindAndModify`: used to work around the [`findAndModify()` deprecation warning](/docs/deprecations.html#findandmodify)
+ * - `omitUndefined`: delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * - `nearSphere`: use `$nearSphere` instead of `near()`. See the [`Query.prototype.nearSphere()` docs](/docs/api.html#query_Query-nearSphere)
+ *
+ * Mongoose maintains a separate object for internal options because
+ * Mongoose sends `Query.prototype.options` to the MongoDB server, and the
+ * above options are not relevant for the MongoDB server.
+ *
+ * @param {Object} options if specified, overwrites the current options
+ * @return {Object} the options
+ * @api public
+ */
+
+Query.prototype.mongooseOptions = function(v) {
+ if (arguments.length > 0) {
+ this._mongooseOptions = v;
+ }
+ return this._mongooseOptions;
+};
+
+/*!
+ * ignore
+ */
+
+Query.prototype._castConditions = function() {
+ try {
+ this.cast(this.model);
+ this._unsetCastError();
+ } catch (err) {
+ this.error(err);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function _castArrayFilters(query) {
+ try {
+ castArrayFilters(query);
+ } catch (err) {
+ query.error(err);
+ }
+}
+
+/**
+ * Thunk around find()
+ *
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api private
+ */
+Query.prototype._find = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return null;
+ }
+
+ callback = _wrapThunkCallback(this, callback);
+
+ this._applyPaths();
+ this._fields = this._castFields(this._fields);
+
+ const fields = this._fieldsForExec();
+ const mongooseOptions = this._mongooseOptions;
+ const _this = this;
+ const userProvidedFields = _this._userProvidedFields || {};
+
+ applyGlobalMaxTimeMS(this.options, this.model);
+
+ // Separate options to pass down to `completeMany()` in case we need to
+ // set a session on the document
+ const completeManyOptions = Object.assign({}, {
+ session: get(this, 'options.session', null)
+ });
+
+ const cb = (err, docs) => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (docs.length === 0) {
+ return callback(null, docs);
+ }
+ if (this.options.explain) {
+ return callback(null, docs);
+ }
+
+ if (!mongooseOptions.populate) {
+ return mongooseOptions.lean ?
+ callback(null, docs) :
+ completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions, callback);
+ }
+
+ const pop = helpers.preparePopulationOptionsMQ(_this, mongooseOptions);
+ completeManyOptions.populated = pop;
+ _this.model.populate(docs, pop, function(err, docs) {
+ if (err) return callback(err);
+ return mongooseOptions.lean ?
+ callback(null, docs) :
+ completeMany(_this.model, docs, fields, userProvidedFields, completeManyOptions, callback);
+ });
+ };
+
+ const options = this._optionsForExec();
+ options.projection = this._fieldsForExec();
+ const filter = this._conditions;
+
+ this._collection.find(filter, options, cb);
+ return null;
+});
+
+/**
+ * Find all documents that match `selector`. The result will be an array of documents.
+ *
+ * If there are too many documents in the result to fit in memory, use
+ * [`Query.prototype.cursor()`](api.html#query_Query-cursor)
+ *
+ * ####Example
+ *
+ * // Using async/await
+ * const arr = await Movie.find({ year: { $gte: 1980, $lte: 1989 } });
+ *
+ * // Using callbacks
+ * Movie.find({ year: { $gte: 1980, $lte: 1989 } }, function(err, arr) {});
+ *
+ * @param {Object|ObjectId} [filter] mongodb selector. If not specified, returns all documents.
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.find = function(conditions, callback) {
+ this.op = 'find';
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = {};
+ }
+
+ conditions = utils.toObject(conditions);
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (conditions != null) {
+ this.error(new ObjectParameterError(conditions, 'filter', 'find'));
+ }
+
+ // if we don't have a callback, then just return the query object
+ if (!callback) {
+ return Query.base.find.call(this);
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Merges another Query or conditions object into this one.
+ *
+ * When a Query is passed, conditions, field selection and options are merged.
+ *
+ * @param {Query|Object} source
+ * @return {Query} this
+ */
+
+Query.prototype.merge = function(source) {
+ if (!source) {
+ return this;
+ }
+
+ const opts = { overwrite: true };
+
+ if (source instanceof Query) {
+ // if source has a feature, apply it to ourselves
+
+ if (source._conditions) {
+ utils.merge(this._conditions, source._conditions, opts);
+ }
+
+ if (source._fields) {
+ this._fields || (this._fields = {});
+ utils.merge(this._fields, source._fields, opts);
+ }
+
+ if (source.options) {
+ this.options || (this.options = {});
+ utils.merge(this.options, source.options, opts);
+ }
+
+ if (source._update) {
+ this._update || (this._update = {});
+ utils.mergeClone(this._update, source._update);
+ }
+
+ if (source._distinct) {
+ this._distinct = source._distinct;
+ }
+
+ utils.merge(this._mongooseOptions, source._mongooseOptions);
+
+ return this;
+ }
+
+ // plain object
+ utils.merge(this._conditions, source, opts);
+
+ return this;
+};
+
+/**
+ * Adds a collation to this op (MongoDB 3.4 and up)
+ *
+ * @param {Object} value
+ * @return {Query} this
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/method/cursor.collation/#cursor.collation
+ * @api public
+ */
+
+Query.prototype.collation = function(value) {
+ if (this.options == null) {
+ this.options = {};
+ }
+ this.options.collation = value;
+ return this;
+};
+
+/**
+ * Hydrate a single doc from `findOne()`, `findOneAndUpdate()`, etc.
+ *
+ * @api private
+ */
+
+Query.prototype._completeOne = function(doc, res, callback) {
+ if (!doc && !this.options.rawResult) {
+ return callback(null, null);
+ }
+
+ const model = this.model;
+ const projection = utils.clone(this._fields);
+ const userProvidedFields = this._userProvidedFields || {};
+ // `populate`, `lean`
+ const mongooseOptions = this._mongooseOptions;
+ // `rawResult`
+ const options = this.options;
+
+ if (options.explain) {
+ return callback(null, doc);
+ }
+
+ if (!mongooseOptions.populate) {
+ return mongooseOptions.lean ?
+ _completeOneLean(doc, res, options, callback) :
+ completeOne(model, doc, res, options, projection, userProvidedFields,
+ null, callback);
+ }
+
+ const pop = helpers.preparePopulationOptionsMQ(this, this._mongooseOptions);
+ model.populate(doc, pop, (err, doc) => {
+ if (err) {
+ return callback(err);
+ }
+ return mongooseOptions.lean ?
+ _completeOneLean(doc, res, options, callback) :
+ completeOne(model, doc, res, options, projection, userProvidedFields,
+ pop, callback);
+ });
+};
+
+/**
+ * Thunk around findOne()
+ *
+ * @param {Function} [callback]
+ * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/
+ * @api private
+ */
+
+Query.prototype._findOne = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error()) {
+ callback(this.error());
+ return null;
+ }
+
+ this._applyPaths();
+ this._fields = this._castFields(this._fields);
+
+ applyGlobalMaxTimeMS(this.options, this.model);
+
+ // don't pass in the conditions because we already merged them in
+ Query.base.findOne.call(this, {}, (err, doc) => {
+ if (err) {
+ callback(err);
+ return null;
+ }
+
+ this._completeOne(doc, null, _wrapThunkCallback(this, callback));
+ });
+});
+
+/**
+ * Declares the query a findOne operation. When executed, the first found document is passed to the callback.
+ *
+ * Passing a `callback` executes the query. The result of the query is a single document.
+ *
+ * * *Note:* `conditions` is optional, and if `conditions` is null or undefined,
+ * mongoose will send an empty `findOne` command to MongoDB, which will return
+ * an arbitrary document. If you're querying by `_id`, use `Model.findById()`
+ * instead.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOne()`
+ *
+ * ####Example
+ *
+ * const query = Kitten.where({ color: 'white' });
+ * query.findOne(function (err, kitten) {
+ * if (err) return handleError(err);
+ * if (kitten) {
+ * // doc may be null if no document matched
+ * }
+ * });
+ *
+ * @param {Object} [filter] mongodb selector
+ * @param {Object} [projection] optional fields to return
+ * @param {Object} [options] see [`setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback] optional params are (error, document)
+ * @return {Query} this
+ * @see findOne http://docs.mongodb.org/manual/reference/method/db.collection.findOne/
+ * @see Query.select #query_Query-select
+ * @api public
+ */
+
+Query.prototype.findOne = function(conditions, projection, options, callback) {
+ this.op = 'findOne';
+
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = null;
+ projection = null;
+ options = null;
+ } else if (typeof projection === 'function') {
+ callback = projection;
+ options = null;
+ projection = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ }
+
+ // make sure we don't send in the whole Document to merge()
+ conditions = utils.toObject(conditions);
+
+ if (options) {
+ this.setOptions(options);
+ }
+
+ if (projection) {
+ this.select(projection);
+ }
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (conditions != null) {
+ this.error(new ObjectParameterError(conditions, 'filter', 'findOne'));
+ }
+
+ if (!callback) {
+ // already merged in the conditions, don't need to send them in.
+ return Query.base.findOne.call(this);
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Thunk around count()
+ *
+ * @param {Function} [callback]
+ * @see count http://docs.mongodb.org/manual/reference/method/db.collection.count/
+ * @api private
+ */
+
+Query.prototype._count = wrapThunk(function(callback) {
+ try {
+ this.cast(this.model);
+ } catch (err) {
+ this.error(err);
+ }
+
+ if (this.error()) {
+ return callback(this.error());
+ }
+
+ const conds = this._conditions;
+ const options = this._optionsForExec();
+
+ this._collection.count(conds, options, utils.tick(callback));
+});
+
+/**
+ * Thunk around countDocuments()
+ *
+ * @param {Function} [callback]
+ * @see countDocuments http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#countDocuments
+ * @api private
+ */
+
+Query.prototype._countDocuments = wrapThunk(function(callback) {
+ try {
+ this.cast(this.model);
+ } catch (err) {
+ this.error(err);
+ }
+
+ if (this.error()) {
+ return callback(this.error());
+ }
+
+ const conds = this._conditions;
+ const options = this._optionsForExec();
+
+ this._collection.collection.countDocuments(conds, options, utils.tick(callback));
+});
+
+/**
+ * Thunk around estimatedDocumentCount()
+ *
+ * @param {Function} [callback]
+ * @see estimatedDocumentCount http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#estimatedDocumentCount
+ * @api private
+ */
+
+Query.prototype._estimatedDocumentCount = wrapThunk(function(callback) {
+ if (this.error()) {
+ return callback(this.error());
+ }
+
+ const options = this._optionsForExec();
+
+ this._collection.collection.estimatedDocumentCount(options, utils.tick(callback));
+});
+
+/**
+ * Specifies this query as a `count` query.
+ *
+ * This method is deprecated. If you want to count the number of documents in
+ * a collection, e.g. `count({})`, use the [`estimatedDocumentCount()` function](/docs/api.html#query_Query-estimatedDocumentCount)
+ * instead. Otherwise, use the [`countDocuments()`](/docs/api.html#query_Query-countDocuments) function instead.
+ *
+ * Passing a `callback` executes the query.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `count()`
+ *
+ * ####Example:
+ *
+ * const countQuery = model.where({ 'color': 'black' }).count();
+ *
+ * query.count({ color: 'black' }).count(callback)
+ *
+ * query.count({ color: 'black' }, callback)
+ *
+ * query.where('color', 'black').count(function (err, count) {
+ * if (err) return handleError(err);
+ * console.log('there are %d kittens', count);
+ * })
+ *
+ * @deprecated
+ * @param {Object} [filter] count documents that match this object
+ * @param {Function} [callback] optional params are (error, count)
+ * @return {Query} this
+ * @see count http://docs.mongodb.org/manual/reference/method/db.collection.count/
+ * @api public
+ */
+
+Query.prototype.count = function(filter, callback) {
+ this.op = 'count';
+ if (typeof filter === 'function') {
+ callback = filter;
+ filter = undefined;
+ }
+
+ filter = utils.toObject(filter);
+
+ if (mquery.canMerge(filter)) {
+ this.merge(filter);
+ }
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Specifies this query as a `estimatedDocumentCount()` query. Faster than
+ * using `countDocuments()` for large collections because
+ * `estimatedDocumentCount()` uses collection metadata rather than scanning
+ * the entire collection.
+ *
+ * `estimatedDocumentCount()` does **not** accept a filter. `Model.find({ foo: bar }).estimatedDocumentCount()`
+ * is equivalent to `Model.find().estimatedDocumentCount()`
+ *
+ * This function triggers the following middleware.
+ *
+ * - `estimatedDocumentCount()`
+ *
+ * ####Example:
+ *
+ * await Model.find().estimatedDocumentCount();
+ *
+ * @param {Object} [options] passed transparently to the [MongoDB driver](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#estimatedDocumentCount)
+ * @param {Function} [callback] optional params are (error, count)
+ * @return {Query} this
+ * @see estimatedDocumentCount http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#estimatedDocumentCount
+ * @api public
+ */
+
+Query.prototype.estimatedDocumentCount = function(options, callback) {
+ this.op = 'estimatedDocumentCount';
+ if (typeof options === 'function') {
+ callback = options;
+ options = undefined;
+ }
+
+ if (typeof options === 'object' && options != null) {
+ this.setOptions(options);
+ }
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Specifies this query as a `countDocuments()` query. Behaves like `count()`,
+ * except it always does a full collection scan when passed an empty filter `{}`.
+ *
+ * There are also minor differences in how `countDocuments()` handles
+ * [`$where` and a couple geospatial operators](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#countDocuments).
+ * versus `count()`.
+ *
+ * Passing a `callback` executes the query.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `countDocuments()`
+ *
+ * ####Example:
+ *
+ * const countQuery = model.where({ 'color': 'black' }).countDocuments();
+ *
+ * query.countDocuments({ color: 'black' }).count(callback);
+ *
+ * query.countDocuments({ color: 'black' }, callback);
+ *
+ * query.where('color', 'black').countDocuments(function(err, count) {
+ * if (err) return handleError(err);
+ * console.log('there are %d kittens', count);
+ * });
+ *
+ * The `countDocuments()` function is similar to `count()`, but there are a
+ * [few operators that `countDocuments()` does not support](https://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#countDocuments).
+ * Below are the operators that `count()` supports but `countDocuments()` does not,
+ * and the suggested replacement:
+ *
+ * - `$where`: [`$expr`](https://docs.mongodb.com/manual/reference/operator/query/expr/)
+ * - `$near`: [`$geoWithin`](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/) with [`$center`](https://docs.mongodb.com/manual/reference/operator/query/center/#op._S_center)
+ * - `$nearSphere`: [`$geoWithin`](https://docs.mongodb.com/manual/reference/operator/query/geoWithin/) with [`$centerSphere`](https://docs.mongodb.com/manual/reference/operator/query/centerSphere/#op._S_centerSphere)
+ *
+ * @param {Object} [filter] mongodb selector
+ * @param {Function} [callback] optional params are (error, count)
+ * @return {Query} this
+ * @see countDocuments http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#countDocuments
+ * @api public
+ */
+
+Query.prototype.countDocuments = function(conditions, callback) {
+ this.op = 'countDocuments';
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = undefined;
+ }
+
+ conditions = utils.toObject(conditions);
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+ }
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Thunk around distinct()
+ *
+ * @param {Function} [callback]
+ * @see distinct http://docs.mongodb.org/manual/reference/method/db.collection.distinct/
+ * @api private
+ */
+
+Query.prototype.__distinct = wrapThunk(function __distinct(callback) {
+ this._castConditions();
+
+ if (this.error()) {
+ callback(this.error());
+ return null;
+ }
+
+ const options = this._optionsForExec();
+
+ // don't pass in the conditions because we already merged them in
+ this._collection.collection.
+ distinct(this._distinct, this._conditions, options, callback);
+});
+
+/**
+ * Declares or executes a distinct() operation.
+ *
+ * Passing a `callback` executes the query.
+ *
+ * This function does not trigger any middleware.
+ *
+ * ####Example
+ *
+ * distinct(field, conditions, callback)
+ * distinct(field, conditions)
+ * distinct(field, callback)
+ * distinct(field)
+ * distinct(callback)
+ * distinct()
+ *
+ * @param {String} [field]
+ * @param {Object|Query} [filter]
+ * @param {Function} [callback] optional params are (error, arr)
+ * @return {Query} this
+ * @see distinct http://docs.mongodb.org/manual/reference/method/db.collection.distinct/
+ * @api public
+ */
+
+Query.prototype.distinct = function(field, conditions, callback) {
+ this.op = 'distinct';
+ if (!callback) {
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = undefined;
+ } else if (typeof field === 'function') {
+ callback = field;
+ field = undefined;
+ conditions = undefined;
+ }
+ }
+
+ conditions = utils.toObject(conditions);
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (conditions != null) {
+ this.error(new ObjectParameterError(conditions, 'filter', 'distinct'));
+ }
+
+ if (field != null) {
+ this._distinct = field;
+ }
+
+ if (callback != null) {
+ this.exec(callback);
+ }
+
+ return this;
+};
+
+/**
+ * Sets the sort order
+ *
+ * If an object is passed, values allowed are `asc`, `desc`, `ascending`, `descending`, `1`, and `-1`.
+ *
+ * If a string is passed, it must be a space delimited list of path names. The
+ * sort order of each path is ascending unless the path name is prefixed with `-`
+ * which will be treated as descending.
+ *
+ * ####Example
+ *
+ * // sort by "field" ascending and "test" descending
+ * query.sort({ field: 'asc', test: -1 });
+ *
+ * // equivalent
+ * query.sort('field -test');
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @param {Object|String} arg
+ * @return {Query} this
+ * @see cursor.sort http://docs.mongodb.org/manual/reference/method/cursor.sort/
+ * @api public
+ */
+
+Query.prototype.sort = function(arg) {
+ if (arguments.length > 1) {
+ throw new Error('sort() only takes 1 Argument');
+ }
+
+ return Query.base.sort.call(this, arg);
+};
+
+/**
+ * Declare and/or execute this query as a remove() operation. `remove()` is
+ * deprecated, you should use [`deleteOne()`](#query_Query-deleteOne)
+ * or [`deleteMany()`](#query_Query-deleteMany) instead.
+ *
+ * This function does not trigger any middleware
+ *
+ * ####Example
+ *
+ * Character.remove({ name: /Stark/ }, callback);
+ *
+ * This function calls the MongoDB driver's [`Collection#remove()` function](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#remove).
+ * The returned [promise](https://mongoosejs.com/docs/queries.html) resolves to an
+ * object that contains 3 properties:
+ *
+ * - `ok`: `1` if no errors occurred
+ * - `deletedCount`: the number of documents deleted
+ * - `n`: the number of documents deleted. Equal to `deletedCount`.
+ *
+ * ####Example
+ *
+ * const res = await Character.remove({ name: /Stark/ });
+ * // Number of docs deleted
+ * res.deletedCount;
+ *
+ * ####Note
+ *
+ * Calling `remove()` creates a [Mongoose query](./queries.html), and a query
+ * does not execute until you either pass a callback, call [`Query#then()`](#query_Query-then),
+ * or call [`Query#exec()`](#query_Query-exec).
+ *
+ * // not executed
+ * const query = Character.remove({ name: /Stark/ });
+ *
+ * // executed
+ * Character.remove({ name: /Stark/ }, callback);
+ * Character.remove({ name: /Stark/ }).remove(callback);
+ *
+ * // executed without a callback
+ * Character.exec();
+ *
+ * @param {Object|Query} [filter] mongodb selector
+ * @param {Function} [callback] optional params are (error, mongooseDeleteResult)
+ * @return {Query} this
+ * @deprecated
+ * @see deleteWriteOpResult http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~deleteWriteOpResult
+ * @see MongoDB driver remove http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#remove
+ * @api public
+ */
+
+Query.prototype.remove = function(filter, callback) {
+ this.op = 'remove';
+ if (typeof filter === 'function') {
+ callback = filter;
+ filter = null;
+ }
+
+ filter = utils.toObject(filter);
+
+ if (mquery.canMerge(filter)) {
+ this.merge(filter);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (filter != null) {
+ this.error(new ObjectParameterError(filter, 'filter', 'remove'));
+ }
+
+ if (!callback) {
+ return Query.base.remove.call(this);
+ }
+
+ this.exec(callback);
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Query.prototype._remove = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return this;
+ }
+
+ callback = _wrapThunkCallback(this, callback);
+
+ return Query.base.remove.call(this, helpers.handleDeleteWriteOpResult(callback));
+});
+
+/**
+ * Declare and/or execute this query as a `deleteOne()` operation. Works like
+ * remove, except it deletes at most one document regardless of the `single`
+ * option.
+ *
+ * This function triggers `deleteOne` middleware.
+ *
+ * ####Example
+ *
+ * await Character.deleteOne({ name: 'Eddard Stark' });
+ *
+ * // Using callbacks:
+ * Character.deleteOne({ name: 'Eddard Stark' }, callback);
+ *
+ * This function calls the MongoDB driver's [`Collection#deleteOne()` function](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#deleteOne).
+ * The returned [promise](https://mongoosejs.com/docs/queries.html) resolves to an
+ * object that contains 3 properties:
+ *
+ * - `ok`: `1` if no errors occurred
+ * - `deletedCount`: the number of documents deleted
+ * - `n`: the number of documents deleted. Equal to `deletedCount`.
+ *
+ * ####Example
+ *
+ * const res = await Character.deleteOne({ name: 'Eddard Stark' });
+ * // `1` if MongoDB deleted a doc, `0` if no docs matched the filter `{ name: ... }`
+ * res.deletedCount;
+ *
+ * @param {Object|Query} [filter] mongodb selector
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback] optional params are (error, mongooseDeleteResult)
+ * @return {Query} this
+ * @see deleteWriteOpResult http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~deleteWriteOpResult
+ * @see MongoDB Driver deleteOne http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#deleteOne
+ * @api public
+ */
+
+Query.prototype.deleteOne = function(filter, options, callback) {
+ this.op = 'deleteOne';
+ if (typeof filter === 'function') {
+ callback = filter;
+ filter = null;
+ options = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ } else {
+ this.setOptions(options);
+ }
+
+ filter = utils.toObject(filter);
+
+ if (mquery.canMerge(filter)) {
+ this.merge(filter);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (filter != null) {
+ this.error(new ObjectParameterError(filter, 'filter', 'deleteOne'));
+ }
+
+ if (!callback) {
+ return Query.base.deleteOne.call(this);
+ }
+
+ this.exec.call(this, callback);
+
+ return this;
+};
+
+/*!
+ * Internal thunk for `deleteOne()`
+ */
+
+Query.prototype._deleteOne = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return this;
+ }
+
+ callback = _wrapThunkCallback(this, callback);
+
+ return Query.base.deleteOne.call(this, helpers.handleDeleteWriteOpResult(callback));
+});
+
+/**
+ * Declare and/or execute this query as a `deleteMany()` operation. Works like
+ * remove, except it deletes _every_ document that matches `filter` in the
+ * collection, regardless of the value of `single`.
+ *
+ * This function triggers `deleteMany` middleware.
+ *
+ * ####Example
+ *
+ * await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });
+ *
+ * // Using callbacks:
+ * Character.deleteMany({ name: /Stark/, age: { $gte: 18 } }, callback);
+ *
+ * This function calls the MongoDB driver's [`Collection#deleteMany()` function](http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#deleteMany).
+ * The returned [promise](https://mongoosejs.com/docs/queries.html) resolves to an
+ * object that contains 3 properties:
+ *
+ * - `ok`: `1` if no errors occurred
+ * - `deletedCount`: the number of documents deleted
+ * - `n`: the number of documents deleted. Equal to `deletedCount`.
+ *
+ * ####Example
+ *
+ * const res = await Character.deleteMany({ name: /Stark/, age: { $gte: 18 } });
+ * // `0` if no docs matched the filter, number of docs deleted otherwise
+ * res.deletedCount;
+ *
+ * @param {Object|Query} [filter] mongodb selector
+ * @param {Object} [options] optional see [`Query.prototype.setOptions()`](http://mongoosejs.com/docs/api.html#query_Query-setOptions)
+ * @param {Function} [callback] optional params are (error, mongooseDeleteResult)
+ * @return {Query} this
+ * @see deleteWriteOpResult http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#~deleteWriteOpResult
+ * @see MongoDB Driver deleteMany http://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html#deleteMany
+ * @api public
+ */
+
+Query.prototype.deleteMany = function(filter, options, callback) {
+ this.op = 'deleteMany';
+ if (typeof filter === 'function') {
+ callback = filter;
+ filter = null;
+ options = null;
+ } else if (typeof options === 'function') {
+ callback = options;
+ options = null;
+ } else {
+ this.setOptions(options);
+ }
+
+ filter = utils.toObject(filter);
+
+ if (mquery.canMerge(filter)) {
+ this.merge(filter);
+
+ prepareDiscriminatorCriteria(this);
+ } else if (filter != null) {
+ this.error(new ObjectParameterError(filter, 'filter', 'deleteMany'));
+ }
+
+ if (!callback) {
+ return Query.base.deleteMany.call(this);
+ }
+
+ this.exec.call(this, callback);
+
+ return this;
+};
+
+/*!
+ * Internal thunk around `deleteMany()`
+ */
+
+Query.prototype._deleteMany = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return this;
+ }
+
+ callback = _wrapThunkCallback(this, callback);
+
+ return Query.base.deleteMany.call(this, helpers.handleDeleteWriteOpResult(callback));
+});
+
+/*!
+ * hydrates a document
+ *
+ * @param {Model} model
+ * @param {Document} doc
+ * @param {Object} res 3rd parameter to callback
+ * @param {Object} fields
+ * @param {Query} self
+ * @param {Array} [pop] array of paths used in population
+ * @param {Function} callback
+ */
+
+function completeOne(model, doc, res, options, fields, userProvidedFields, pop, callback) {
+ const opts = pop ?
+ { populated: pop }
+ : undefined;
+
+ if (options.rawResult && doc == null) {
+ _init(null);
+ return null;
+ }
+
+ const casted = helpers.createModel(model, doc, fields, userProvidedFields);
+ try {
+ casted.init(doc, opts, _init);
+ } catch (error) {
+ _init(error);
+ }
+
+ function _init(err) {
+ if (err) {
+ return process.nextTick(() => callback(err));
+ }
+
+
+ if (options.rawResult) {
+ if (doc && casted) {
+ casted.$session(options.session);
+ res.value = casted;
+ } else {
+ res.value = null;
+ }
+ return process.nextTick(() => callback(null, res));
+ }
+ casted.$session(options.session);
+ process.nextTick(() => callback(null, casted));
+ }
+}
+
+/*!
+ * If the model is a discriminator type and not root, then add the key & value to the criteria.
+ */
+
+function prepareDiscriminatorCriteria(query) {
+ if (!query || !query.model || !query.model.schema) {
+ return;
+ }
+
+ const schema = query.model.schema;
+
+ if (schema && schema.discriminatorMapping && !schema.discriminatorMapping.isRoot) {
+ query._conditions[schema.discriminatorMapping.key] = schema.discriminatorMapping.value;
+ }
+}
+
+/**
+ * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) update command.
+ *
+ * Finds a matching document, updates it according to the `update` arg, passing any `options`, and returns the found
+ * document (if any) to the callback. The query executes if
+ * `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndUpdate()`
+ *
+ * ####Available options
+ *
+ * - `new`: bool - if true, return the modified document rather than the original. defaults to false (changed in 4.0)
+ * - `upsert`: bool - creates the object if it doesn't exist. defaults to false.
+ * - `fields`: {Object|String} - Field selection. Equivalent to `.select(fields).findOneAndUpdate()`
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * - `rawResult`: if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * - `context` (string) if set to 'query' and `runValidators` is on, `this` will refer to the query in custom validator functions that update validation runs. Does nothing if `runValidators` is false.
+ *
+ * ####Callback Signature
+ * function(error, doc) {
+ * // error: any errors that occurred
+ * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
+ * }
+ *
+ * ####Examples
+ *
+ * query.findOneAndUpdate(conditions, update, options, callback) // executes
+ * query.findOneAndUpdate(conditions, update, options) // returns Query
+ * query.findOneAndUpdate(conditions, update, callback) // executes
+ * query.findOneAndUpdate(conditions, update) // returns Query
+ * query.findOneAndUpdate(update, callback) // returns Query
+ * query.findOneAndUpdate(update) // returns Query
+ * query.findOneAndUpdate(callback) // executes
+ * query.findOneAndUpdate() // returns Query
+ *
+ * @method findOneAndUpdate
+ * @memberOf Query
+ * @instance
+ * @param {Object|Query} [filter]
+ * @param {Object} [doc]
+ * @param {Object} [options]
+ * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
+ * @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
+ * @param {Function} [callback] optional params are (error, doc), _unless_ `rawResult` is used, in which case params are (error, writeOpResult)
+ * @see Tutorial /docs/tutorials/findoneandupdate.html
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.findOneAndUpdate = function(criteria, doc, options, callback) {
+ this.op = 'findOneAndUpdate';
+ this._validate();
+
+ switch (arguments.length) {
+ case 3:
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ break;
+ case 2:
+ if (typeof doc === 'function') {
+ callback = doc;
+ doc = criteria;
+ criteria = undefined;
+ }
+ options = undefined;
+ break;
+ case 1:
+ if (typeof criteria === 'function') {
+ callback = criteria;
+ criteria = options = doc = undefined;
+ } else {
+ doc = criteria;
+ criteria = options = undefined;
+ }
+ }
+
+ if (mquery.canMerge(criteria)) {
+ this.merge(criteria);
+ }
+
+ // apply doc
+ if (doc) {
+ this._mergeUpdate(doc);
+ }
+
+ options = options ? utils.clone(options) : {};
+
+ if (options.projection) {
+ this.select(options.projection);
+ delete options.projection;
+ }
+ if (options.fields) {
+ this.select(options.fields);
+ delete options.fields;
+ }
+
+
+ const returnOriginal = get(this, 'model.base.options.returnOriginal');
+ if (options.returnOriginal == null && returnOriginal != null) {
+ options.returnOriginal = returnOriginal;
+ }
+
+ this.setOptions(options);
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/*!
+ * Thunk around findOneAndUpdate()
+ *
+ * @param {Function} [callback]
+ * @api private
+ */
+
+Query.prototype._findOneAndUpdate = wrapThunk(function(callback) {
+ if (this.error() != null) {
+ return callback(this.error());
+ }
+
+ this._findAndModify('update', callback);
+});
+
+/**
+ * Issues a mongodb [findAndModify](http://www.mongodb.org/display/DOCS/findAndModify+Command) remove command.
+ *
+ * Finds a matching document, removes it, passing the found document (if any) to
+ * the callback. Executes if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndRemove()`
+ *
+ * ####Available options
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ *
+ * ####Callback Signature
+ * function(error, doc) {
+ * // error: any errors that occurred
+ * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
+ * }
+ *
+ * ####Examples
+ *
+ * A.where().findOneAndRemove(conditions, options, callback) // executes
+ * A.where().findOneAndRemove(conditions, options) // return Query
+ * A.where().findOneAndRemove(conditions, callback) // executes
+ * A.where().findOneAndRemove(conditions) // returns Query
+ * A.where().findOneAndRemove(callback) // executes
+ * A.where().findOneAndRemove() // returns Query
+ *
+ * @method findOneAndRemove
+ * @memberOf Query
+ * @instance
+ * @param {Object} [conditions]
+ * @param {Object} [options]
+ * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Function} [callback] optional params are (error, document)
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Query.prototype.findOneAndRemove = function(conditions, options, callback) {
+ this.op = 'findOneAndRemove';
+ this._validate();
+
+ switch (arguments.length) {
+ case 2:
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ break;
+ case 1:
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = undefined;
+ options = undefined;
+ }
+ break;
+ }
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+ }
+
+ options && this.setOptions(options);
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/**
+ * Issues a MongoDB [findOneAndDelete](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndDelete/) command.
+ *
+ * Finds a matching document, removes it, and passes the found document (if any)
+ * to the callback. Executes if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndDelete()`
+ *
+ * This function differs slightly from `Model.findOneAndRemove()` in that
+ * `findOneAndRemove()` becomes a [MongoDB `findAndModify()` command](https://docs.mongodb.com/manual/reference/method/db.collection.findAndModify/),
+ * as opposed to a `findOneAndDelete()` command. For most mongoose use cases,
+ * this distinction is purely pedantic. You should use `findOneAndDelete()`
+ * unless you have a good reason not to.
+ *
+ * ####Available options
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ *
+ * ####Callback Signature
+ * function(error, doc) {
+ * // error: any errors that occurred
+ * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
+ * }
+ *
+ * ####Examples
+ *
+ * A.where().findOneAndDelete(conditions, options, callback) // executes
+ * A.where().findOneAndDelete(conditions, options) // return Query
+ * A.where().findOneAndDelete(conditions, callback) // executes
+ * A.where().findOneAndDelete(conditions) // returns Query
+ * A.where().findOneAndDelete(callback) // executes
+ * A.where().findOneAndDelete() // returns Query
+ *
+ * @method findOneAndDelete
+ * @memberOf Query
+ * @param {Object} [conditions]
+ * @param {Object} [options]
+ * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Function} [callback] optional params are (error, document)
+ * @return {Query} this
+ * @see mongodb http://www.mongodb.org/display/DOCS/findAndModify+Command
+ * @api public
+ */
+
+Query.prototype.findOneAndDelete = function(conditions, options, callback) {
+ this.op = 'findOneAndDelete';
+ this._validate();
+
+ switch (arguments.length) {
+ case 2:
+ if (typeof options === 'function') {
+ callback = options;
+ options = {};
+ }
+ break;
+ case 1:
+ if (typeof conditions === 'function') {
+ callback = conditions;
+ conditions = undefined;
+ options = undefined;
+ }
+ break;
+ }
+
+ if (mquery.canMerge(conditions)) {
+ this.merge(conditions);
+ }
+
+ options && this.setOptions(options);
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/*!
+ * Thunk around findOneAndDelete()
+ *
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api private
+ */
+Query.prototype._findOneAndDelete = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return null;
+ }
+
+ const filter = this._conditions;
+ const options = this._optionsForExec();
+ let fields = null;
+
+ if (this._fields != null) {
+ options.projection = this._castFields(utils.clone(this._fields));
+ fields = options.projection;
+ if (fields instanceof Error) {
+ callback(fields);
+ return null;
+ }
+ }
+
+ this._collection.collection.findOneAndDelete(filter, options, _wrapThunkCallback(this, (err, res) => {
+ if (err) {
+ return callback(err);
+ }
+
+ const doc = res.value;
+
+ return this._completeOne(doc, res, callback);
+ }));
+});
+
+/**
+ * Issues a MongoDB [findOneAndReplace](https://docs.mongodb.com/manual/reference/method/db.collection.findOneAndReplace/) command.
+ *
+ * Finds a matching document, removes it, and passes the found document (if any)
+ * to the callback. Executes if `callback` is passed.
+ *
+ * This function triggers the following middleware.
+ *
+ * - `findOneAndReplace()`
+ *
+ * ####Available options
+ *
+ * - `sort`: if multiple docs are found by the conditions, sets the sort order to choose which doc to update
+ * - `maxTimeMS`: puts a time limit on the query - requires mongodb >= 2.6.0
+ * - `rawResult`: if true, resolves to the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ *
+ * ####Callback Signature
+ * function(error, doc) {
+ * // error: any errors that occurred
+ * // doc: the document before updates are applied if `new: false`, or after updates if `new = true`
+ * }
+ *
+ * ####Examples
+ *
+ * A.where().findOneAndReplace(filter, replacement, options, callback); // executes
+ * A.where().findOneAndReplace(filter, replacement, options); // return Query
+ * A.where().findOneAndReplace(filter, replacement, callback); // executes
+ * A.where().findOneAndReplace(filter); // returns Query
+ * A.where().findOneAndReplace(callback); // executes
+ * A.where().findOneAndReplace(); // returns Query
+ *
+ * @method findOneAndReplace
+ * @memberOf Query
+ * @param {Object} [filter]
+ * @param {Object} [replacement]
+ * @param {Object} [options]
+ * @param {Boolean} [options.rawResult] if true, returns the [raw result from the MongoDB driver](http://mongodb.github.io/node-mongodb-native/2.0/api/Collection.html#findAndModify)
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.new=false] By default, `findOneAndUpdate()` returns the document as it was **before** `update` was applied. If you set `new: true`, `findOneAndUpdate()` will instead give you the object after `update` was applied.
+ * @param {Object} [options.lean] if truthy, mongoose will return the document as a plain JavaScript object rather than a mongoose document. See [`Query.lean()`](/docs/api.html#query_Query-lean) and [the Mongoose lean tutorial](/docs/tutorials/lean.html).
+ * @param {ClientSession} [options.session=null] The session associated with this query. See [transactions docs](/docs/transactions.html).
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Boolean} [options.returnOriginal=null] An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
+ * @param {Function} [callback] optional params are (error, document)
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.findOneAndReplace = function(filter, replacement, options, callback) {
+ this.op = 'findOneAndReplace';
+ this._validate();
+
+ switch (arguments.length) {
+ case 3:
+ if (typeof options === 'function') {
+ callback = options;
+ options = void 0;
+ }
+ break;
+ case 2:
+ if (typeof replacement === 'function') {
+ callback = replacement;
+ replacement = void 0;
+ }
+ break;
+ case 1:
+ if (typeof filter === 'function') {
+ callback = filter;
+ filter = void 0;
+ replacement = void 0;
+ options = void 0;
+ }
+ break;
+ }
+
+ if (mquery.canMerge(filter)) {
+ this.merge(filter);
+ }
+
+ if (replacement != null) {
+ if (hasDollarKeys(replacement)) {
+ throw new Error('The replacement document must not contain atomic operators.');
+ }
+ this._mergeUpdate(replacement);
+ }
+
+ options = options || {};
+
+ const returnOriginal = get(this, 'model.base.options.returnOriginal');
+ if (options.returnOriginal == null && returnOriginal != null) {
+ options.returnOriginal = returnOriginal;
+ }
+
+ this.setOptions(options);
+
+ if (!callback) {
+ return this;
+ }
+
+ this.exec(callback);
+
+ return this;
+};
+
+/*!
+ * Thunk around findOneAndReplace()
+ *
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api private
+ */
+Query.prototype._findOneAndReplace = wrapThunk(function(callback) {
+ this._castConditions();
+
+ if (this.error() != null) {
+ callback(this.error());
+ return null;
+ }
+
+ const filter = this._conditions;
+ const options = this._optionsForExec();
+ convertNewToReturnOriginal(options);
+ let fields = null;
+
+ let castedDoc = new this.model(this._update, null, true);
+ this._update = castedDoc;
+
+ this._applyPaths();
+ if (this._fields != null) {
+ options.projection = this._castFields(utils.clone(this._fields));
+ fields = options.projection;
+ if (fields instanceof Error) {
+ callback(fields);
+ return null;
+ }
+ }
+
+ castedDoc.validate(err => {
+ if (err != null) {
+ return callback(err);
+ }
+
+ if (castedDoc.toBSON) {
+ castedDoc = castedDoc.toBSON();
+ }
+
+ this._collection.collection.findOneAndReplace(filter, castedDoc, options, _wrapThunkCallback(this, (err, res) => {
+ if (err) {
+ return callback(err);
+ }
+
+ const doc = res.value;
+
+ return this._completeOne(doc, res, callback);
+ }));
+ });
+});
+
+/*!
+ * Support the `new` option as an alternative to `returnOriginal` for backwards
+ * compat.
+ */
+
+function convertNewToReturnOriginal(options) {
+ if ('new' in options) {
+ options.returnOriginal = !options['new'];
+ delete options['new'];
+ }
+}
+
+/*!
+ * Thunk around findOneAndRemove()
+ *
+ * @param {Function} [callback]
+ * @return {Query} this
+ * @api private
+ */
+Query.prototype._findOneAndRemove = wrapThunk(function(callback) {
+ if (this.error() != null) {
+ callback(this.error());
+ return;
+ }
+
+ this._findAndModify('remove', callback);
+});
+
+/*!
+ * Get options from query opts, falling back to the base mongoose object.
+ */
+
+function _getOption(query, option, def) {
+ const opts = query._optionsForExec(query.model);
+
+ if (option in opts) {
+ return opts[option];
+ }
+ if (option in query.model.base.options) {
+ return query.model.base.options[option];
+ }
+ return def;
+}
+
+/*!
+ * Override mquery.prototype._findAndModify to provide casting etc.
+ *
+ * @param {String} type - either "remove" or "update"
+ * @param {Function} callback
+ * @api private
+ */
+
+Query.prototype._findAndModify = function(type, callback) {
+ if (typeof callback !== 'function') {
+ throw new Error('Expected callback in _findAndModify');
+ }
+
+ const model = this.model;
+ const schema = model.schema;
+ const _this = this;
+ let fields;
+
+ const castedQuery = castQuery(this);
+ if (castedQuery instanceof Error) {
+ return callback(castedQuery);
+ }
+
+ _castArrayFilters(this);
+
+ const opts = this._optionsForExec(model);
+
+ if ('strict' in opts) {
+ this._mongooseOptions.strict = opts.strict;
+ }
+
+ const isOverwriting = this.options.overwrite && !hasDollarKeys(this._update);
+ if (isOverwriting) {
+ this._update = new this.model(this._update, null, true);
+ }
+
+ if (type === 'remove') {
+ opts.remove = true;
+ } else {
+ if (!('new' in opts) && !('returnOriginal' in opts)) {
+ opts.new = false;
+ }
+ if (!('upsert' in opts)) {
+ opts.upsert = false;
+ }
+ if (opts.upsert || opts['new']) {
+ opts.remove = false;
+ }
+
+ if (!isOverwriting) {
+ this._update = castDoc(this, opts.overwrite);
+ const _opts = Object.assign({}, opts, {
+ setDefaultsOnInsert: this._mongooseOptions.setDefaultsOnInsert
+ });
+ this._update = setDefaultsOnInsert(this._conditions, schema, this._update, _opts);
+ if (!this._update || Object.keys(this._update).length === 0) {
+ if (opts.upsert) {
+ // still need to do the upsert to empty doc
+ const doc = utils.clone(castedQuery);
+ delete doc._id;
+ this._update = { $set: doc };
+ } else {
+ this.findOne(callback);
+ return this;
+ }
+ } else if (this._update instanceof Error) {
+ return callback(this._update);
+ } else {
+ // In order to make MongoDB 2.6 happy (see
+ // https://jira.mongodb.org/browse/SERVER-12266 and related issues)
+ // if we have an actual update document but $set is empty, junk the $set.
+ if (this._update.$set && Object.keys(this._update.$set).length === 0) {
+ delete this._update.$set;
+ }
+ }
+ }
+
+ if (Array.isArray(opts.arrayFilters)) {
+ opts.arrayFilters = removeUnusedArrayFilters(this._update, opts.arrayFilters);
+ }
+ }
+
+ this._applyPaths();
+
+ const options = this._mongooseOptions;
+
+ if (this._fields) {
+ fields = utils.clone(this._fields);
+ opts.projection = this._castFields(fields);
+ if (opts.projection instanceof Error) {
+ return callback(opts.projection);
+ }
+ }
+
+ if (opts.sort) convertSortToArray(opts);
+
+ const cb = function(err, doc, res) {
+ if (err) {
+ return callback(err);
+ }
+
+ _this._completeOne(doc, res, callback);
+ };
+
+ let useFindAndModify = true;
+ const runValidators = _getOption(this, 'runValidators', false);
+ const base = _this.model && _this.model.base;
+ const conn = get(model, 'collection.conn', {});
+ if ('useFindAndModify' in base.options) {
+ useFindAndModify = base.get('useFindAndModify');
+ }
+ if ('useFindAndModify' in conn.config) {
+ useFindAndModify = conn.config.useFindAndModify;
+ }
+ if ('useFindAndModify' in options) {
+ useFindAndModify = options.useFindAndModify;
+ }
+ if (useFindAndModify === false) {
+ // Bypass mquery
+ const collection = _this._collection.collection;
+ convertNewToReturnOriginal(opts);
+
+ if (type === 'remove') {
+ collection.findOneAndDelete(castedQuery, opts, _wrapThunkCallback(_this, function(error, res) {
+ return cb(error, res ? res.value : res, res);
+ }));
+
+ return this;
+ }
+
+ // honors legacy overwrite option for backward compatibility
+ const updateMethod = isOverwriting ? 'findOneAndReplace' : 'findOneAndUpdate';
+
+ if (runValidators) {
+ this.validate(this._update, opts, isOverwriting, error => {
+ if (error) {
+ return callback(error);
+ }
+ if (this._update && this._update.toBSON) {
+ this._update = this._update.toBSON();
+ }
+
+ collection[updateMethod](castedQuery, this._update, opts, _wrapThunkCallback(_this, function(error, res) {
+ return cb(error, res ? res.value : res, res);
+ }));
+ });
+ } else {
+ if (this._update && this._update.toBSON) {
+ this._update = this._update.toBSON();
+ }
+ collection[updateMethod](castedQuery, this._update, opts, _wrapThunkCallback(_this, function(error, res) {
+ return cb(error, res ? res.value : res, res);
+ }));
+ }
+
+ return this;
+ }
+
+ if (runValidators) {
+ this.validate(this._update, opts, isOverwriting, function(error) {
+ if (error) {
+ return callback(error);
+ }
+ _legacyFindAndModify.call(_this, castedQuery, _this._update, opts, cb);
+ });
+ } else {
+ _legacyFindAndModify.call(_this, castedQuery, _this._update, opts, cb);
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+function _completeOneLean(doc, res, opts, callback) {
+ if (opts.rawResult) {
+ return callback(null, res);
+ }
+ return callback(null, doc);
+}
+
+
+/*!
+ * ignore
+ */
+
+const _legacyFindAndModify = util.deprecate(function(filter, update, opts, cb) {
+ if (update && update.toBSON) {
+ update = update.toBSON();
+ }
+ const collection = this._collection;
+ const sort = opts != null && Array.isArray(opts.sort) ? opts.sort : [];
+ const _cb = _wrapThunkCallback(this, function(error, res) {
+ return cb(error, res ? res.value : res, res);
+ });
+ collection.collection._findAndModify(filter, sort, update, opts, _cb);
+}, 'Mongoose: `findOneAndUpdate()` and `findOneAndDelete()` without the ' +
+ '`useFindAndModify` option set to false are deprecated. See: ' +
+ 'https://mongoosejs.com/docs/deprecations.html#findandmodify');
+
+/*!
+ * Override mquery.prototype._mergeUpdate to handle mongoose objects in
+ * updates.
+ *
+ * @param {Object} doc
+ * @api private
+ */
+
+Query.prototype._mergeUpdate = function(doc) {
+ if (doc == null || (typeof doc === 'object' && Object.keys(doc).length === 0)) {
+ return;
+ }
+
+ if (!this._update) {
+ this._update = Array.isArray(doc) ? [] : {};
+ }
+ if (doc instanceof Query) {
+ if (Array.isArray(this._update)) {
+ throw new Error('Cannot mix array and object updates');
+ }
+ if (doc._update) {
+ utils.mergeClone(this._update, doc._update);
+ }
+ } else if (Array.isArray(doc)) {
+ if (!Array.isArray(this._update)) {
+ throw new Error('Cannot mix array and object updates');
+ }
+ this._update = this._update.concat(doc);
+ } else {
+ if (Array.isArray(this._update)) {
+ throw new Error('Cannot mix array and object updates');
+ }
+ utils.mergeClone(this._update, doc);
+ }
+};
+
+/*!
+ * The mongodb driver 1.3.23 only supports the nested array sort
+ * syntax. We must convert it or sorting findAndModify will not work.
+ */
+
+function convertSortToArray(opts) {
+ if (Array.isArray(opts.sort)) {
+ return;
+ }
+ if (!utils.isObject(opts.sort)) {
+ return;
+ }
+
+ const sort = [];
+
+ for (const key in opts.sort) {
+ if (utils.object.hasOwnProperty(opts.sort, key)) {
+ sort.push([key, opts.sort[key]]);
+ }
+ }
+
+ opts.sort = sort;
+}
+
+/*!
+ * ignore
+ */
+
+function _updateThunk(op, callback) {
+ this._castConditions();
+
+ _castArrayFilters(this);
+
+ if (this.error() != null) {
+ callback(this.error());
+ return null;
+ }
+
+ callback = _wrapThunkCallback(this, callback);
+ const oldCb = callback;
+ callback = function(error, result) {
+ oldCb(error, result ? result.result : { ok: 0, n: 0, nModified: 0 });
+ };
+
+ const castedQuery = this._conditions;
+ const options = this._optionsForExec(this.model);
+
+ ++this._executionCount;
+
+ this._update = utils.clone(this._update, options);
+ const isOverwriting = this.options.overwrite && !hasDollarKeys(this._update);
+ if (isOverwriting) {
+ if (op === 'updateOne' || op === 'updateMany') {
+ return callback(new MongooseError('The MongoDB server disallows ' +
+ 'overwriting documents using `' + op + '`. See: ' +
+ 'https://mongoosejs.com/docs/deprecations.html#update'));
+ }
+ this._update = new this.model(this._update, null, true);
+ } else {
+ this._update = castDoc(this, options.overwrite);
+
+ if (this._update instanceof Error) {
+ callback(this._update);
+ return null;
+ }
+
+ if (this._update == null || Object.keys(this._update).length === 0) {
+ callback(null, 0);
+ return null;
+ }
+
+ const _opts = Object.assign({}, options, {
+ setDefaultsOnInsert: this._mongooseOptions.setDefaultsOnInsert
+ });
+ this._update = setDefaultsOnInsert(this._conditions, this.model.schema,
+ this._update, _opts);
+ }
+
+ if (Array.isArray(options.arrayFilters)) {
+ options.arrayFilters = removeUnusedArrayFilters(this._update, options.arrayFilters);
+ }
+
+ const runValidators = _getOption(this, 'runValidators', false);
+ if (runValidators) {
+ this.validate(this._update, options, isOverwriting, err => {
+ if (err) {
+ return callback(err);
+ }
+
+ if (this._update.toBSON) {
+ this._update = this._update.toBSON();
+ }
+ this._collection[op](castedQuery, this._update, options, callback);
+ });
+ return null;
+ }
+
+ if (this._update.toBSON) {
+ this._update = this._update.toBSON();
+ }
+
+ this._collection[op](castedQuery, this._update, options, callback);
+ return null;
+}
+
+/*!
+ * Mongoose calls this function internally to validate the query if
+ * `runValidators` is set
+ *
+ * @param {Object} castedDoc the update, after casting
+ * @param {Object} options the options from `_optionsForExec()`
+ * @param {Function} callback
+ * @api private
+ */
+
+Query.prototype.validate = function validate(castedDoc, options, isOverwriting, callback) {
+ return promiseOrCallback(callback, cb => {
+ try {
+ if (isOverwriting) {
+ castedDoc.validate(cb);
+ } else {
+ updateValidators(this, this.model.schema, castedDoc, options, cb);
+ }
+ } catch (err) {
+ process.nextTick(function() {
+ cb(err);
+ });
+ }
+ });
+};
+
+/*!
+ * Internal thunk for .update()
+ *
+ * @param {Function} callback
+ * @see Model.update #model_Model.update
+ * @api private
+ */
+Query.prototype._execUpdate = wrapThunk(function(callback) {
+ return _updateThunk.call(this, 'update', callback);
+});
+
+/*!
+ * Internal thunk for .updateMany()
+ *
+ * @param {Function} callback
+ * @see Model.update #model_Model.update
+ * @api private
+ */
+Query.prototype._updateMany = wrapThunk(function(callback) {
+ return _updateThunk.call(this, 'updateMany', callback);
+});
+
+/*!
+ * Internal thunk for .updateOne()
+ *
+ * @param {Function} callback
+ * @see Model.update #model_Model.update
+ * @api private
+ */
+Query.prototype._updateOne = wrapThunk(function(callback) {
+ return _updateThunk.call(this, 'updateOne', callback);
+});
+
+/*!
+ * Internal thunk for .replaceOne()
+ *
+ * @param {Function} callback
+ * @see Model.replaceOne #model_Model.replaceOne
+ * @api private
+ */
+Query.prototype._replaceOne = wrapThunk(function(callback) {
+ return _updateThunk.call(this, 'replaceOne', callback);
+});
+
+/**
+ * Declare and/or execute this query as an update() operation.
+ *
+ * _All paths passed that are not [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) operations will become `$set` ops._
+ *
+ * This function triggers the following middleware.
+ *
+ * - `update()`
+ *
+ * ####Example
+ *
+ * Model.where({ _id: id }).update({ title: 'words' })
+ *
+ * // becomes
+ *
+ * Model.where({ _id: id }).update({ $set: { title: 'words' }})
+ *
+ * ####Valid options:
+ *
+ * - `upsert` (boolean) whether to create the doc if it doesn't match (false)
+ * - `multi` (boolean) whether multiple documents should be updated (false)
+ * - `runValidators`: if true, runs [update validators](/docs/validation.html#update-validators) on this command. Update validators validate the update operation against the model's schema.
+ * - `setDefaultsOnInsert`: if this and `upsert` are true, mongoose will apply the [defaults](http://mongoosejs.com/docs/defaults.html) specified in the model's schema if a new document is created. This option only works on MongoDB >= 2.4 because it relies on [MongoDB's `$setOnInsert` operator](https://docs.mongodb.org/v2.4/reference/operator/update/setOnInsert/).
+ * - `strict` (boolean) overrides the `strict` option for this update
+ * - `overwrite` (boolean) disables update-only mode, allowing you to overwrite the doc (false)
+ * - `context` (string) if set to 'query' and `runValidators` is on, `this` will refer to the query in custom validator functions that update validation runs. Does nothing if `runValidators` is false.
+ * - `read`
+ * - `writeConcern`
+ *
+ * ####Note
+ *
+ * Passing an empty object `{}` as the doc will result in a no-op unless the `overwrite` option is passed. Without the `overwrite` option set, the update operation will be ignored and the callback executed without sending the command to MongoDB so as to prevent accidently overwritting documents in the collection.
+ *
+ * ####Note
+ *
+ * The operation is only executed when a callback is passed. To force execution without a callback, we must first call update() and then execute it by using the `exec()` method.
+ *
+ * const q = Model.where({ _id: id });
+ * q.update({ $set: { name: 'bob' }}).update(); // not executed
+ *
+ * q.update({ $set: { name: 'bob' }}).exec(); // executed
+ *
+ * // keys that are not [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) ops become `$set`.
+ * // this executes the same command as the previous example.
+ * q.update({ name: 'bob' }).exec();
+ *
+ * // overwriting with empty docs
+ * const q = Model.where({ _id: id }).setOptions({ overwrite: true })
+ * q.update({ }, callback); // executes
+ *
+ * // multi update with overwrite to empty doc
+ * const q = Model.where({ _id: id });
+ * q.setOptions({ multi: true, overwrite: true })
+ * q.update({ });
+ * q.update(callback); // executed
+ *
+ * // multi updates
+ * Model.where()
+ * .update({ name: /^match/ }, { $set: { arr: [] }}, { multi: true }, callback)
+ *
+ * // more multi updates
+ * Model.where()
+ * .setOptions({ multi: true })
+ * .update({ $set: { arr: [] }}, callback)
+ *
+ * // single update by default
+ * Model.where({ email: 'address@example.com' })
+ * .update({ $inc: { counter: 1 }}, callback)
+ *
+ * API summary
+ *
+ * update(filter, doc, options, cb) // executes
+ * update(filter, doc, options)
+ * update(filter, doc, cb) // executes
+ * update(filter, doc)
+ * update(doc, cb) // executes
+ * update(doc)
+ * update(cb) // executes
+ * update(true) // executes
+ * update()
+ *
+ * @param {Object} [filter]
+ * @param {Object} [doc] the update command
+ * @param {Object} [options]
+ * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] params are (error, writeOpResult)
+ * @return {Query} this
+ * @see Model.update #model_Model.update
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @api public
+ */
+
+Query.prototype.update = function(conditions, doc, options, callback) {
+ if (typeof options === 'function') {
+ // .update(conditions, doc, callback)
+ callback = options;
+ options = null;
+ } else if (typeof doc === 'function') {
+ // .update(doc, callback);
+ callback = doc;
+ doc = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof conditions === 'function') {
+ // .update(callback)
+ callback = conditions;
+ conditions = undefined;
+ doc = undefined;
+ options = undefined;
+ } else if (typeof conditions === 'object' && !doc && !options && !callback) {
+ // .update(doc)
+ doc = conditions;
+ conditions = undefined;
+ options = undefined;
+ callback = undefined;
+ }
+
+ return _update(this, 'update', conditions, doc, options, callback);
+};
+
+/**
+ * Declare and/or execute this query as an updateMany() operation. Same as
+ * `update()`, except MongoDB will update _all_ documents that match
+ * `filter` (as opposed to just the first one) regardless of the value of
+ * the `multi` option.
+ *
+ * **Note** updateMany will _not_ fire update middleware. Use `pre('updateMany')`
+ * and `post('updateMany')` instead.
+ *
+ * ####Example:
+ * const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `updateMany()`
+ *
+ * @param {Object} [filter]
+ * @param {Object} [doc] the update command
+ * @param {Object} [options]
+ * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] params are (error, writeOpResult)
+ * @return {Query} this
+ * @see Model.update #model_Model.update
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @api public
+ */
+
+Query.prototype.updateMany = function(conditions, doc, options, callback) {
+ if (typeof options === 'function') {
+ // .update(conditions, doc, callback)
+ callback = options;
+ options = null;
+ } else if (typeof doc === 'function') {
+ // .update(doc, callback);
+ callback = doc;
+ doc = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof conditions === 'function') {
+ // .update(callback)
+ callback = conditions;
+ conditions = undefined;
+ doc = undefined;
+ options = undefined;
+ } else if (typeof conditions === 'object' && !doc && !options && !callback) {
+ // .update(doc)
+ doc = conditions;
+ conditions = undefined;
+ options = undefined;
+ callback = undefined;
+ }
+
+ return _update(this, 'updateMany', conditions, doc, options, callback);
+};
+
+/**
+ * Declare and/or execute this query as an updateOne() operation. Same as
+ * `update()`, except it does not support the `multi` or `overwrite` options.
+ *
+ * - MongoDB will update _only_ the first document that matches `filter` regardless of the value of the `multi` option.
+ * - Use `replaceOne()` if you want to overwrite an entire document rather than using [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) operators like `$set`.
+ *
+ * **Note** updateOne will _not_ fire update middleware. Use `pre('updateOne')`
+ * and `post('updateOne')` instead.
+ *
+ * ####Example:
+ * const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `updateOne()`
+ *
+ * @param {Object} [filter]
+ * @param {Object} [doc] the update command
+ * @param {Object} [options]
+ * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Note that this allows you to overwrite timestamps. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] params are (error, writeOpResult)
+ * @return {Query} this
+ * @see Model.update #model_Model.update
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @api public
+ */
+
+Query.prototype.updateOne = function(conditions, doc, options, callback) {
+ if (typeof options === 'function') {
+ // .update(conditions, doc, callback)
+ callback = options;
+ options = null;
+ } else if (typeof doc === 'function') {
+ // .update(doc, callback);
+ callback = doc;
+ doc = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof conditions === 'function') {
+ // .update(callback)
+ callback = conditions;
+ conditions = undefined;
+ doc = undefined;
+ options = undefined;
+ } else if (typeof conditions === 'object' && !doc && !options && !callback) {
+ // .update(doc)
+ doc = conditions;
+ conditions = undefined;
+ options = undefined;
+ callback = undefined;
+ }
+
+ return _update(this, 'updateOne', conditions, doc, options, callback);
+};
+
+/**
+ * Declare and/or execute this query as a replaceOne() operation. Same as
+ * `update()`, except MongoDB will replace the existing document and will
+ * not accept any [atomic](https://docs.mongodb.com/manual/tutorial/model-data-for-atomic-operations/#pattern) operators (`$set`, etc.)
+ *
+ * **Note** replaceOne will _not_ fire update middleware. Use `pre('replaceOne')`
+ * and `post('replaceOne')` instead.
+ *
+ * ####Example:
+ * const res = await Person.replaceOne({ _id: 24601 }, { name: 'Jean Valjean' });
+ * res.n; // Number of documents matched
+ * res.nModified; // Number of documents modified
+ *
+ * This function triggers the following middleware.
+ *
+ * - `replaceOne()`
+ *
+ * @param {Object} [filter]
+ * @param {Object} [doc] the update command
+ * @param {Object} [options]
+ * @param {Boolean} [options.multipleCastError] by default, mongoose only returns the first error that occurred in casting the query. Turn on this option to aggregate all the cast errors.
+ * @param {Boolean} [options.omitUndefined=false] If true, delete any properties whose value is `undefined` when casting an update. In other words, if this is set, Mongoose will delete `baz` from the update in `Model.updateOne({}, { foo: 'bar', baz: undefined })` before sending the update to the server.
+ * @param {Boolean|String} [options.strict] overwrites the schema's [strict mode option](http://mongoosejs.com/docs/guide.html#strict)
+ * @param {Boolean} [options.upsert=false] if true, and no documents found, insert a new document
+ * @param {Object} [options.writeConcern=null] sets the [write concern](https://docs.mongodb.com/manual/reference/write-concern/) for replica sets. Overrides the [schema-level write concern](/docs/guide.html#writeConcern)
+ * @param {Boolean} [options.timestamps=null] If set to `false` and [schema-level timestamps](/docs/guide.html#timestamps) are enabled, skip timestamps for this update. Does nothing if schema-level timestamps are not set.
+ * @param {Function} [callback] params are (error, writeOpResult)
+ * @return {Query} this
+ * @see Model.update #model_Model.update
+ * @see Query docs https://mongoosejs.com/docs/queries.html
+ * @see update http://docs.mongodb.org/manual/reference/method/db.collection.update/
+ * @see writeOpResult http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#~WriteOpResult
+ * @see MongoDB docs https://docs.mongodb.com/manual/reference/command/update/#update-command-output
+ * @api public
+ */
+
+Query.prototype.replaceOne = function(conditions, doc, options, callback) {
+ if (typeof options === 'function') {
+ // .update(conditions, doc, callback)
+ callback = options;
+ options = null;
+ } else if (typeof doc === 'function') {
+ // .update(doc, callback);
+ callback = doc;
+ doc = conditions;
+ conditions = {};
+ options = null;
+ } else if (typeof conditions === 'function') {
+ // .update(callback)
+ callback = conditions;
+ conditions = undefined;
+ doc = undefined;
+ options = undefined;
+ } else if (typeof conditions === 'object' && !doc && !options && !callback) {
+ // .update(doc)
+ doc = conditions;
+ conditions = undefined;
+ options = undefined;
+ callback = undefined;
+ }
+
+ this.setOptions({ overwrite: true });
+ return _update(this, 'replaceOne', conditions, doc, options, callback);
+};
+
+/*!
+ * Internal helper for update, updateMany, updateOne, replaceOne
+ */
+
+function _update(query, op, filter, doc, options, callback) {
+ // make sure we don't send in the whole Document to merge()
+ query.op = op;
+ filter = utils.toObject(filter);
+ doc = doc || {};
+
+ // strict is an option used in the update checking, make sure it gets set
+ if (options != null) {
+ if ('strict' in options) {
+ query._mongooseOptions.strict = options.strict;
+ }
+ }
+
+ if (!(filter instanceof Query) &&
+ filter != null &&
+ filter.toString() !== '[object Object]') {
+ query.error(new ObjectParameterError(filter, 'filter', op));
+ } else {
+ query.merge(filter);
+ }
+
+ if (utils.isObject(options)) {
+ query.setOptions(options);
+ }
+
+ query._mergeUpdate(doc);
+
+ // Hooks
+ if (callback) {
+ query.exec(callback);
+
+ return query;
+ }
+
+ return Query.base[op].call(query, filter, void 0, options, callback);
+}
+
+/**
+ * Runs a function `fn` and treats the return value of `fn` as the new value
+ * for the query to resolve to.
+ *
+ * Any functions you pass to `map()` will run **after** any post hooks.
+ *
+ * ####Example:
+ *
+ * const res = await MyModel.findOne().map(res => {
+ * // Sets a `loadedAt` property on the doc that tells you the time the
+ * // document was loaded.
+ * return res == null ?
+ * res :
+ * Object.assign(res, { loadedAt: new Date() });
+ * });
+ *
+ * @method map
+ * @memberOf Query
+ * @instance
+ * @param {Function} fn function to run to transform the query result
+ * @return {Query} this
+ */
+
+Query.prototype.map = function(fn) {
+ this._transforms.push(fn);
+ return this;
+};
+
+/**
+ * Make this query throw an error if no documents match the given `filter`.
+ * This is handy for integrating with async/await, because `orFail()` saves you
+ * an extra `if` statement to check if no document was found.
+ *
+ * ####Example:
+ *
+ * // Throws if no doc returned
+ * await Model.findOne({ foo: 'bar' }).orFail();
+ *
+ * // Throws if no document was updated
+ * await Model.updateOne({ foo: 'bar' }, { name: 'test' }).orFail();
+ *
+ * // Throws "No docs found!" error if no docs match `{ foo: 'bar' }`
+ * await Model.find({ foo: 'bar' }).orFail(new Error('No docs found!'));
+ *
+ * // Throws "Not found" error if no document was found
+ * await Model.findOneAndUpdate({ foo: 'bar' }, { name: 'test' }).
+ * orFail(() => Error('Not found'));
+ *
+ * @method orFail
+ * @memberOf Query
+ * @instance
+ * @param {Function|Error} [err] optional error to throw if no docs match `filter`. If not specified, `orFail()` will throw a `DocumentNotFoundError`
+ * @return {Query} this
+ */
+
+Query.prototype.orFail = function(err) {
+ this.map(res => {
+ switch (this.op) {
+ case 'find':
+ if (res.length === 0) {
+ throw _orFailError(err, this);
+ }
+ break;
+ case 'findOne':
+ if (res == null) {
+ throw _orFailError(err, this);
+ }
+ break;
+ case 'update':
+ case 'updateMany':
+ case 'updateOne':
+ if (get(res, 'nModified') === 0) {
+ throw _orFailError(err, this);
+ }
+ break;
+ case 'findOneAndDelete':
+ case 'findOneAndRemove':
+ if (get(res, 'lastErrorObject.n') === 0) {
+ throw _orFailError(err, this);
+ }
+ break;
+ case 'findOneAndUpdate':
+ case 'findOneAndReplace':
+ if (get(res, 'lastErrorObject.updatedExisting') === false) {
+ throw _orFailError(err, this);
+ }
+ break;
+ case 'deleteMany':
+ case 'deleteOne':
+ case 'remove':
+ if (res.n === 0) {
+ throw _orFailError(err, this);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return res;
+ });
+ return this;
+};
+
+/*!
+ * Get the error to throw for `orFail()`
+ */
+
+function _orFailError(err, query) {
+ if (typeof err === 'function') {
+ err = err.call(query);
+ }
+
+ if (err == null) {
+ err = new DocumentNotFoundError(query.getQuery(), query.model.modelName);
+ }
+
+ return err;
+}
+
+/**
+ * Executes the query
+ *
+ * ####Examples:
+ *
+ * const promise = query.exec();
+ * const promise = query.exec('update');
+ *
+ * query.exec(callback);
+ * query.exec('find', callback);
+ *
+ * @param {String|Function} [operation]
+ * @param {Function} [callback] optional params depend on the function being called
+ * @return {Promise}
+ * @api public
+ */
+
+Query.prototype.exec = function exec(op, callback) {
+ const _this = this;
+ // Ensure that `exec()` is the first thing that shows up in
+ // the stack when cast errors happen.
+ const castError = new CastError();
+
+ if (typeof op === 'function') {
+ callback = op;
+ op = null;
+ } else if (typeof op === 'string') {
+ this.op = op;
+ }
+
+ callback = this.model.$handleCallbackError(callback);
+
+ return promiseOrCallback(callback, (cb) => {
+ cb = this.model.$wrapCallback(cb);
+
+ if (!_this.op) {
+ cb();
+ return;
+ }
+
+ this._hooks.execPre('exec', this, [], (error) => {
+ if (error != null) {
+ return cb(_cleanCastErrorStack(castError, error));
+ }
+ let thunk = '_' + this.op;
+ if (this.op === 'update') {
+ thunk = '_execUpdate';
+ } else if (this.op === 'distinct') {
+ thunk = '__distinct';
+ }
+ this[thunk].call(this, (error, res) => {
+ if (error) {
+ return cb(_cleanCastErrorStack(castError, error));
+ }
+
+ this._hooks.execPost('exec', this, [], {}, (error) => {
+ if (error) {
+ return cb(_cleanCastErrorStack(castError, error));
+ }
+
+ cb(null, res);
+ });
+ });
+ });
+ }, this.model.events);
+};
+
+/*!
+ * ignore
+ */
+
+function _cleanCastErrorStack(castError, error) {
+ if (error instanceof CastError) {
+ castError.copy(error);
+ return castError;
+ }
+
+ return error;
+}
+
+/*!
+ * ignore
+ */
+
+function _wrapThunkCallback(query, cb) {
+ return function(error, res) {
+ if (error != null) {
+ return cb(error);
+ }
+
+ for (const fn of query._transforms) {
+ try {
+ res = fn(res);
+ } catch (error) {
+ return cb(error);
+ }
+ }
+
+ return cb(null, res);
+ };
+}
+
+/**
+ * Executes the query returning a `Promise` which will be
+ * resolved with either the doc(s) or rejected with the error.
+ *
+ * @param {Function} [resolve]
+ * @param {Function} [reject]
+ * @return {Promise}
+ * @api public
+ */
+
+Query.prototype.then = function(resolve, reject) {
+ return this.exec().then(resolve, reject);
+};
+
+/**
+ * Executes the query returning a `Promise` which will be
+ * resolved with either the doc(s) or rejected with the error.
+ * Like `.then()`, but only takes a rejection handler.
+ *
+ * @param {Function} [reject]
+ * @return {Promise}
+ * @api public
+ */
+
+Query.prototype.catch = function(reject) {
+ return this.exec().then(null, reject);
+};
+
+/*!
+ * ignore
+ */
+
+Query.prototype._pre = function(fn) {
+ this._hooks.pre('exec', fn);
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Query.prototype._post = function(fn) {
+ this._hooks.post('exec', fn);
+ return this;
+};
+
+/*!
+ * Casts obj for an update command.
+ *
+ * @param {Object} obj
+ * @return {Object} obj after casting its values
+ * @api private
+ */
+
+Query.prototype._castUpdate = function _castUpdate(obj, overwrite) {
+ let strict;
+ let schema = this.schema;
+
+ const discriminatorKey = schema.options.discriminatorKey;
+ const baseSchema = schema._baseSchema ? schema._baseSchema : schema;
+ if (this._mongooseOptions.overwriteDiscriminatorKey &&
+ obj[discriminatorKey] != null &&
+ baseSchema.discriminators) {
+ const _schema = baseSchema.discriminators[obj[discriminatorKey]];
+ if (_schema != null) {
+ schema = _schema;
+ }
+ }
+
+ if ('strict' in this._mongooseOptions) {
+ strict = this._mongooseOptions.strict;
+ } else if (this.schema && this.schema.options) {
+ strict = this.schema.options.strict;
+ } else {
+ strict = true;
+ }
+
+ let omitUndefined = false;
+ if ('omitUndefined' in this._mongooseOptions) {
+ omitUndefined = this._mongooseOptions.omitUndefined;
+ }
+
+ let useNestedStrict;
+ if ('useNestedStrict' in this.options) {
+ useNestedStrict = this.options.useNestedStrict;
+ }
+
+ let upsert;
+ if ('upsert' in this.options) {
+ upsert = this.options.upsert;
+ }
+
+ const filter = this._conditions;
+ if (schema != null &&
+ utils.hasUserDefinedProperty(filter, schema.options.discriminatorKey) &&
+ typeof filter[schema.options.discriminatorKey] !== 'object' &&
+ schema.discriminators != null) {
+ const discriminatorValue = filter[schema.options.discriminatorKey];
+ const byValue = getDiscriminatorByValue(this.model, discriminatorValue);
+ schema = schema.discriminators[discriminatorValue] ||
+ (byValue && byValue.schema) ||
+ schema;
+ }
+
+ return castUpdate(schema, obj, {
+ overwrite: overwrite,
+ strict: strict,
+ omitUndefined,
+ useNestedStrict: useNestedStrict,
+ upsert: upsert
+ }, this, this._conditions);
+};
+
+/*!
+ * castQuery
+ * @api private
+ */
+
+function castQuery(query) {
+ try {
+ return query.cast(query.model);
+ } catch (err) {
+ return err;
+ }
+}
+
+/*!
+ * castDoc
+ * @api private
+ */
+
+function castDoc(query, overwrite) {
+ try {
+ return query._castUpdate(query._update, overwrite);
+ } catch (err) {
+ return err;
+ }
+}
+
+/**
+ * Specifies paths which should be populated with other documents.
+ *
+ * ####Example:
+ *
+ * let book = await Book.findOne().populate('authors');
+ * book.title; // 'Node.js in Action'
+ * book.authors[0].name; // 'TJ Holowaychuk'
+ * book.authors[1].name; // 'Nathan Rajlich'
+ *
+ * let books = await Book.find().populate({
+ * path: 'authors',
+ * // `match` and `sort` apply to the Author model,
+ * // not the Book model. These options do not affect
+ * // which documents are in `books`, just the order and
+ * // contents of each book document's `authors`.
+ * match: { name: new RegExp('.*h.*', 'i') },
+ * sort: { name: -1 }
+ * });
+ * books[0].title; // 'Node.js in Action'
+ * // Each book's `authors` are sorted by name, descending.
+ * books[0].authors[0].name; // 'TJ Holowaychuk'
+ * books[0].authors[1].name; // 'Marc Harter'
+ *
+ * books[1].title; // 'Professional AngularJS'
+ * // Empty array, no authors' name has the letter 'h'
+ * books[1].authors; // []
+ *
+ * Paths are populated after the query executes and a response is received. A
+ * separate query is then executed for each path specified for population. After
+ * a response for each query has also been returned, the results are passed to
+ * the callback.
+ *
+ * @param {Object|String} path either the path to populate or an object specifying all parameters
+ * @param {Object|String} [select] Field selection for the population query
+ * @param {Model} [model] The model you wish to use for population. If not specified, populate will look up the model by the name in the Schema's `ref` field.
+ * @param {Object} [match] Conditions for the population query
+ * @param {Object} [options] Options for the population query (sort, etc)
+ * @param {String} [options.path=null] The path to populate.
+ * @param {boolean} [options.retainNullValues=false] by default, Mongoose removes null and undefined values from populated arrays. Use this option to make `populate()` retain `null` and `undefined` array entries.
+ * @param {boolean} [options.getters=false] if true, Mongoose will call any getters defined on the `localField`. By default, Mongoose gets the raw value of `localField`. For example, you would need to set this option to `true` if you wanted to [add a `lowercase` getter to your `localField`](/docs/schematypes.html#schematype-options).
+ * @param {boolean} [options.clone=false] When you do `BlogPost.find().populate('author')`, blog posts with the same author will share 1 copy of an `author` doc. Enable this option to make Mongoose clone populated docs before assigning them.
+ * @param {Object|Function} [options.match=null] Add an additional filter to the populate query. Can be a filter object containing [MongoDB query syntax](https://docs.mongodb.com/manual/tutorial/query-documents/), or a function that returns a filter object.
+ * @param {Object} [options.options=null] Additional options like `limit` and `lean`.
+ * @see population ./populate.html
+ * @see Query#select #query_Query-select
+ * @see Model.populate #model_Model.populate
+ * @return {Query} this
+ * @api public
+ */
+
+Query.prototype.populate = function() {
+ // Bail when given no truthy arguments
+ if (!Array.from(arguments).some(Boolean)) {
+ return this;
+ }
+
+ const res = utils.populate.apply(null, arguments);
+
+ // Propagate readConcern and readPreference and lean from parent query,
+ // unless one already specified
+ if (this.options != null) {
+ const readConcern = this.options.readConcern;
+ const readPref = this.options.readPreference;
+
+ for (const populateOptions of res) {
+ if (readConcern != null && get(populateOptions, 'options.readConcern') == null) {
+ populateOptions.options = populateOptions.options || {};
+ populateOptions.options.readConcern = readConcern;
+ }
+ if (readPref != null && get(populateOptions, 'options.readPreference') == null) {
+ populateOptions.options = populateOptions.options || {};
+ populateOptions.options.readPreference = readPref;
+ }
+ }
+ }
+
+ const opts = this._mongooseOptions;
+
+ if (opts.lean != null) {
+ const lean = opts.lean;
+ for (const populateOptions of res) {
+ if (get(populateOptions, 'options.lean') == null) {
+ populateOptions.options = populateOptions.options || {};
+ populateOptions.options.lean = lean;
+ }
+ }
+ }
+
+ if (!utils.isObject(opts.populate)) {
+ opts.populate = {};
+ }
+
+ const pop = opts.populate;
+
+ for (const populateOptions of res) {
+ const path = populateOptions.path;
+ if (pop[path] && pop[path].populate && populateOptions.populate) {
+ populateOptions.populate = pop[path].populate.concat(populateOptions.populate);
+ }
+
+ pop[populateOptions.path] = populateOptions;
+ }
+
+ return this;
+};
+
+/**
+ * Gets a list of paths to be populated by this query
+ *
+ * ####Example:
+ * bookSchema.pre('findOne', function() {
+ * let keys = this.getPopulatedPaths(); // ['author']
+ * });
+ * ...
+ * Book.findOne({}).populate('author');
+ *
+ * ####Example:
+ * // Deep populate
+ * const q = L1.find().populate({
+ * path: 'level2',
+ * populate: { path: 'level3' }
+ * });
+ * q.getPopulatedPaths(); // ['level2', 'level2.level3']
+ *
+ * @return {Array} an array of strings representing populated paths
+ * @api public
+ */
+
+Query.prototype.getPopulatedPaths = function getPopulatedPaths() {
+ const obj = this._mongooseOptions.populate || {};
+ const ret = Object.keys(obj);
+ for (const path of Object.keys(obj)) {
+ const pop = obj[path];
+ if (!Array.isArray(pop.populate)) {
+ continue;
+ }
+ _getPopulatedPaths(ret, pop.populate, path + '.');
+ }
+ return ret;
+};
+
+/*!
+ * ignore
+ */
+
+function _getPopulatedPaths(list, arr, prefix) {
+ for (const pop of arr) {
+ list.push(prefix + pop.path);
+ if (!Array.isArray(pop.populate)) {
+ continue;
+ }
+ _getPopulatedPaths(list, pop.populate, prefix + pop.path + '.');
+ }
+}
+
+/**
+ * Casts this query to the schema of `model`
+ *
+ * ####Note
+ *
+ * If `obj` is present, it is cast instead of this query.
+ *
+ * @param {Model} [model] the model to cast to. If not set, defaults to `this.model`
+ * @param {Object} [obj]
+ * @return {Object}
+ * @api public
+ */
+
+Query.prototype.cast = function(model, obj) {
+ obj || (obj = this._conditions);
+
+ model = model || this.model;
+
+ const discriminatorKey = model.schema.options.discriminatorKey;
+ if (obj != null &&
+ obj.hasOwnProperty(discriminatorKey)) {
+ model = getDiscriminatorByValue(model, obj[discriminatorKey]) || model;
+ }
+
+ try {
+ return cast(model.schema, obj, {
+ upsert: this.options && this.options.upsert,
+ strict: (this.options && 'strict' in this.options) ?
+ this.options.strict :
+ get(model, 'schema.options.strict', null),
+ strictQuery: (this.options && this.options.strictQuery) ||
+ get(model, 'schema.options.strictQuery', null)
+ }, this);
+ } catch (err) {
+ // CastError, assign model
+ if (typeof err.setModel === 'function') {
+ err.setModel(model);
+ }
+ throw err;
+ }
+};
+
+/**
+ * Casts selected field arguments for field selection with mongo 2.2
+ *
+ * query.select({ ids: { $elemMatch: { $in: [hexString] }})
+ *
+ * @param {Object} fields
+ * @see https://github.com/Automattic/mongoose/issues/1091
+ * @see http://docs.mongodb.org/manual/reference/projection/elemMatch/
+ * @api private
+ */
+
+Query.prototype._castFields = function _castFields(fields) {
+ let selected,
+ elemMatchKeys,
+ keys,
+ key,
+ out,
+ i;
+
+ if (fields) {
+ keys = Object.keys(fields);
+ elemMatchKeys = [];
+ i = keys.length;
+
+ // collect $elemMatch args
+ while (i--) {
+ key = keys[i];
+ if (fields[key].$elemMatch) {
+ selected || (selected = {});
+ selected[key] = fields[key];
+ elemMatchKeys.push(key);
+ }
+ }
+ }
+
+ if (selected) {
+ // they passed $elemMatch, cast em
+ try {
+ out = this.cast(this.model, selected);
+ } catch (err) {
+ return err;
+ }
+
+ // apply the casted field args
+ i = elemMatchKeys.length;
+ while (i--) {
+ key = elemMatchKeys[i];
+ fields[key] = out[key];
+ }
+ }
+
+ return fields;
+};
+
+/**
+ * Applies schematype selected options to this query.
+ * @api private
+ */
+
+Query.prototype._applyPaths = function applyPaths() {
+ this._fields = this._fields || {};
+ helpers.applyPaths(this._fields, this.model.schema);
+
+ let _selectPopulatedPaths = true;
+
+ if ('selectPopulatedPaths' in this.model.base.options) {
+ _selectPopulatedPaths = this.model.base.options.selectPopulatedPaths;
+ }
+ if ('selectPopulatedPaths' in this.model.schema.options) {
+ _selectPopulatedPaths = this.model.schema.options.selectPopulatedPaths;
+ }
+
+ if (_selectPopulatedPaths) {
+ selectPopulatedFields(this);
+ }
+};
+
+/**
+ * Returns a wrapper around a [mongodb driver cursor](http://mongodb.github.io/node-mongodb-native/2.1/api/Cursor.html).
+ * A QueryCursor exposes a Streams3 interface, as well as a `.next()` function.
+ *
+ * The `.cursor()` function triggers pre find hooks, but **not** post find hooks.
+ *
+ * ####Example
+ *
+ * // There are 2 ways to use a cursor. First, as a stream:
+ * Thing.
+ * find({ name: /^hello/ }).
+ * cursor().
+ * on('data', function(doc) { console.log(doc); }).
+ * on('end', function() { console.log('Done!'); });
+ *
+ * // Or you can use `.next()` to manually get the next doc in the stream.
+ * // `.next()` returns a promise, so you can use promises or callbacks.
+ * const cursor = Thing.find({ name: /^hello/ }).cursor();
+ * cursor.next(function(error, doc) {
+ * console.log(doc);
+ * });
+ *
+ * // Because `.next()` returns a promise, you can use co
+ * // to easily iterate through all documents without loading them
+ * // all into memory.
+ * co(function*() {
+ * const cursor = Thing.find({ name: /^hello/ }).cursor();
+ * for (let doc = yield cursor.next(); doc != null; doc = yield cursor.next()) {
+ * console.log(doc);
+ * }
+ * });
+ *
+ * ####Valid options
+ *
+ * - `transform`: optional function which accepts a mongoose document. The return value of the function will be emitted on `data` and returned by `.next()`.
+ *
+ * @return {QueryCursor}
+ * @param {Object} [options]
+ * @see QueryCursor
+ * @api public
+ */
+
+Query.prototype.cursor = function cursor(opts) {
+ this._applyPaths();
+ this._fields = this._castFields(this._fields);
+ this.setOptions({ projection: this._fieldsForExec() });
+ if (opts) {
+ this.setOptions(opts);
+ }
+
+ const options = Object.assign({}, this._optionsForExec(), {
+ projection: this.projection()
+ });
+ try {
+ this.cast(this.model);
+ } catch (err) {
+ return (new QueryCursor(this, options))._markError(err);
+ }
+
+ return new QueryCursor(this, options);
+};
+
+// the rest of these are basically to support older Mongoose syntax with mquery
+
+/**
+ * _DEPRECATED_ Alias of `maxScan`
+ *
+ * @deprecated
+ * @see maxScan #query_Query-maxScan
+ * @method maxscan
+ * @memberOf Query
+ * @instance
+ */
+
+Query.prototype.maxscan = Query.base.maxScan;
+
+/**
+ * Sets the tailable option (for use with capped collections).
+ *
+ * ####Example
+ *
+ * query.tailable() // true
+ * query.tailable(true)
+ * query.tailable(false)
+ *
+ * ####Note
+ *
+ * Cannot be used with `distinct()`
+ *
+ * @param {Boolean} bool defaults to true
+ * @param {Object} [opts] options to set
+ * @param {Number} [opts.numberOfRetries] if cursor is exhausted, retry this many times before giving up
+ * @param {Number} [opts.tailableRetryInterval] if cursor is exhausted, wait this many milliseconds before retrying
+ * @see tailable http://docs.mongodb.org/manual/tutorial/create-tailable-cursor/
+ * @api public
+ */
+
+Query.prototype.tailable = function(val, opts) {
+ // we need to support the tailable({ awaitdata : true }) as well as the
+ // tailable(true, {awaitdata :true}) syntax that mquery does not support
+ if (val && val.constructor.name === 'Object') {
+ opts = val;
+ val = true;
+ }
+
+ if (val === undefined) {
+ val = true;
+ }
+
+ if (opts && typeof opts === 'object') {
+ for (const key in opts) {
+ if (key === 'awaitdata') {
+ // For backwards compatibility
+ this.options[key] = !!opts[key];
+ } else {
+ this.options[key] = opts[key];
+ }
+ }
+ }
+
+ return Query.base.tailable.call(this, val);
+};
+
+/**
+ * Declares an intersects query for `geometry()`.
+ *
+ * ####Example
+ *
+ * query.where('path').intersects().geometry({
+ * type: 'LineString'
+ * , coordinates: [[180.0, 11.0], [180, 9.0]]
+ * })
+ *
+ * query.where('path').intersects({
+ * type: 'LineString'
+ * , coordinates: [[180.0, 11.0], [180, 9.0]]
+ * })
+ *
+ * ####NOTE:
+ *
+ * **MUST** be used after `where()`.
+ *
+ * ####NOTE:
+ *
+ * In Mongoose 3.7, `intersects` changed from a getter to a function. If you need the old syntax, use [this](https://github.com/ebensing/mongoose-within).
+ *
+ * @method intersects
+ * @memberOf Query
+ * @instance
+ * @param {Object} [arg]
+ * @return {Query} this
+ * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
+ * @see geoIntersects http://docs.mongodb.org/manual/reference/operator/geoIntersects/
+ * @api public
+ */
+
+/**
+ * Specifies a `$geometry` condition
+ *
+ * ####Example
+ *
+ * const polyA = [[[ 10, 20 ], [ 10, 40 ], [ 30, 40 ], [ 30, 20 ]]]
+ * query.where('loc').within().geometry({ type: 'Polygon', coordinates: polyA })
+ *
+ * // or
+ * const polyB = [[ 0, 0 ], [ 1, 1 ]]
+ * query.where('loc').within().geometry({ type: 'LineString', coordinates: polyB })
+ *
+ * // or
+ * const polyC = [ 0, 0 ]
+ * query.where('loc').within().geometry({ type: 'Point', coordinates: polyC })
+ *
+ * // or
+ * query.where('loc').intersects().geometry({ type: 'Point', coordinates: polyC })
+ *
+ * The argument is assigned to the most recent path passed to `where()`.
+ *
+ * ####NOTE:
+ *
+ * `geometry()` **must** come after either `intersects()` or `within()`.
+ *
+ * The `object` argument must contain `type` and `coordinates` properties.
+ * - type {String}
+ * - coordinates {Array}
+ *
+ * @method geometry
+ * @memberOf Query
+ * @instance
+ * @param {Object} object Must contain a `type` property which is a String and a `coordinates` property which is an Array. See the examples.
+ * @return {Query} this
+ * @see $geometry http://docs.mongodb.org/manual/reference/operator/geometry/
+ * @see http://docs.mongodb.org/manual/release-notes/2.4/#new-geospatial-indexes-with-geojson-and-improved-spherical-geometry
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+/**
+ * Specifies a `$near` or `$nearSphere` condition
+ *
+ * These operators return documents sorted by distance.
+ *
+ * ####Example
+ *
+ * query.where('loc').near({ center: [10, 10] });
+ * query.where('loc').near({ center: [10, 10], maxDistance: 5 });
+ * query.where('loc').near({ center: [10, 10], maxDistance: 5, spherical: true });
+ * query.near('loc', { center: [10, 10], maxDistance: 5 });
+ *
+ * @method near
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Object} val
+ * @return {Query} this
+ * @see $near http://docs.mongodb.org/manual/reference/operator/near/
+ * @see $nearSphere http://docs.mongodb.org/manual/reference/operator/nearSphere/
+ * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+/*!
+ * Overwriting mquery is needed to support a couple different near() forms found in older
+ * versions of mongoose
+ * near([1,1])
+ * near(1,1)
+ * near(field, [1,2])
+ * near(field, 1, 2)
+ * In addition to all of the normal forms supported by mquery
+ */
+
+Query.prototype.near = function() {
+ const params = [];
+ const sphere = this._mongooseOptions.nearSphere;
+
+ // TODO refactor
+
+ if (arguments.length === 1) {
+ if (Array.isArray(arguments[0])) {
+ params.push({ center: arguments[0], spherical: sphere });
+ } else if (typeof arguments[0] === 'string') {
+ // just passing a path
+ params.push(arguments[0]);
+ } else if (utils.isObject(arguments[0])) {
+ if (typeof arguments[0].spherical !== 'boolean') {
+ arguments[0].spherical = sphere;
+ }
+ params.push(arguments[0]);
+ } else {
+ throw new TypeError('invalid argument');
+ }
+ } else if (arguments.length === 2) {
+ if (typeof arguments[0] === 'number' && typeof arguments[1] === 'number') {
+ params.push({ center: [arguments[0], arguments[1]], spherical: sphere });
+ } else if (typeof arguments[0] === 'string' && Array.isArray(arguments[1])) {
+ params.push(arguments[0]);
+ params.push({ center: arguments[1], spherical: sphere });
+ } else if (typeof arguments[0] === 'string' && utils.isObject(arguments[1])) {
+ params.push(arguments[0]);
+ if (typeof arguments[1].spherical !== 'boolean') {
+ arguments[1].spherical = sphere;
+ }
+ params.push(arguments[1]);
+ } else {
+ throw new TypeError('invalid argument');
+ }
+ } else if (arguments.length === 3) {
+ if (typeof arguments[0] === 'string' && typeof arguments[1] === 'number'
+ && typeof arguments[2] === 'number') {
+ params.push(arguments[0]);
+ params.push({ center: [arguments[1], arguments[2]], spherical: sphere });
+ } else {
+ throw new TypeError('invalid argument');
+ }
+ } else {
+ throw new TypeError('invalid argument');
+ }
+
+ return Query.base.near.apply(this, params);
+};
+
+/**
+ * _DEPRECATED_ Specifies a `$nearSphere` condition
+ *
+ * ####Example
+ *
+ * query.where('loc').nearSphere({ center: [10, 10], maxDistance: 5 });
+ *
+ * **Deprecated.** Use `query.near()` instead with the `spherical` option set to `true`.
+ *
+ * ####Example
+ *
+ * query.where('loc').near({ center: [10, 10], spherical: true });
+ *
+ * @deprecated
+ * @see near() #query_Query-near
+ * @see $near http://docs.mongodb.org/manual/reference/operator/near/
+ * @see $nearSphere http://docs.mongodb.org/manual/reference/operator/nearSphere/
+ * @see $maxDistance http://docs.mongodb.org/manual/reference/operator/maxDistance/
+ */
+
+Query.prototype.nearSphere = function() {
+ this._mongooseOptions.nearSphere = true;
+ this.near.apply(this, arguments);
+ return this;
+};
+
+/**
+ * Returns an asyncIterator for use with [`for/await/of` loops](https://thecodebarbarian.com/getting-started-with-async-iterators-in-node-js)
+ * This function *only* works for `find()` queries.
+ * You do not need to call this function explicitly, the JavaScript runtime
+ * will call it for you.
+ *
+ * ####Example
+ *
+ * for await (const doc of Model.aggregate([{ $sort: { name: 1 } }])) {
+ * 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) {
+ Query.prototype[Symbol.asyncIterator] = function() {
+ return this.cursor().transformNull()._transformForAsyncIterator();
+ };
+}
+
+/**
+ * Specifies a `$polygon` condition
+ *
+ * ####Example
+ *
+ * query.where('loc').within().polygon([10,20], [13, 25], [7,15])
+ * query.polygon('loc', [10,20], [13, 25], [7,15])
+ *
+ * @method polygon
+ * @memberOf Query
+ * @instance
+ * @param {String|Array} [path]
+ * @param {Array|Object} [coordinatePairs...]
+ * @return {Query} this
+ * @see $polygon http://docs.mongodb.org/manual/reference/operator/polygon/
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+/**
+ * Specifies a `$box` condition
+ *
+ * ####Example
+ *
+ * const lowerLeft = [40.73083, -73.99756]
+ * const upperRight= [40.741404, -73.988135]
+ *
+ * query.where('loc').within().box(lowerLeft, upperRight)
+ * query.box({ ll : lowerLeft, ur : upperRight })
+ *
+ * @method box
+ * @memberOf Query
+ * @instance
+ * @see $box http://docs.mongodb.org/manual/reference/operator/box/
+ * @see within() Query#within #query_Query-within
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @param {Object} val
+ * @param [Array] Upper Right Coords
+ * @return {Query} this
+ * @api public
+ */
+
+/*!
+ * this is needed to support the mongoose syntax of:
+ * box(field, { ll : [x,y], ur : [x2,y2] })
+ * box({ ll : [x,y], ur : [x2,y2] })
+ */
+
+Query.prototype.box = function(ll, ur) {
+ if (!Array.isArray(ll) && utils.isObject(ll)) {
+ ur = ll.ur;
+ ll = ll.ll;
+ }
+ return Query.base.box.call(this, ll, ur);
+};
+
+/**
+ * Specifies a `$center` or `$centerSphere` condition.
+ *
+ * ####Example
+ *
+ * const area = { center: [50, 50], radius: 10, unique: true }
+ * query.where('loc').within().circle(area)
+ * // alternatively
+ * query.circle('loc', area);
+ *
+ * // spherical calculations
+ * const area = { center: [50, 50], radius: 10, unique: true, spherical: true }
+ * query.where('loc').within().circle(area)
+ * // alternatively
+ * query.circle('loc', area);
+ *
+ * @method circle
+ * @memberOf Query
+ * @instance
+ * @param {String} [path]
+ * @param {Object} area
+ * @return {Query} this
+ * @see $center http://docs.mongodb.org/manual/reference/operator/center/
+ * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
+ * @see $geoWithin http://docs.mongodb.org/manual/reference/operator/geoWithin/
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @api public
+ */
+
+/**
+ * _DEPRECATED_ Alias for [circle](#query_Query-circle)
+ *
+ * **Deprecated.** Use [circle](#query_Query-circle) instead.
+ *
+ * @deprecated
+ * @method center
+ * @memberOf Query
+ * @instance
+ * @api public
+ */
+
+Query.prototype.center = Query.base.circle;
+
+/**
+ * _DEPRECATED_ Specifies a `$centerSphere` condition
+ *
+ * **Deprecated.** Use [circle](#query_Query-circle) instead.
+ *
+ * ####Example
+ *
+ * const area = { center: [50, 50], radius: 10 };
+ * query.where('loc').within().centerSphere(area);
+ *
+ * @deprecated
+ * @param {String} [path]
+ * @param {Object} val
+ * @return {Query} this
+ * @see http://www.mongodb.org/display/DOCS/Geospatial+Indexing
+ * @see $centerSphere http://docs.mongodb.org/manual/reference/operator/centerSphere/
+ * @api public
+ */
+
+Query.prototype.centerSphere = function() {
+ if (arguments[0] && arguments[0].constructor.name === 'Object') {
+ arguments[0].spherical = true;
+ }
+
+ if (arguments[1] && arguments[1].constructor.name === 'Object') {
+ arguments[1].spherical = true;
+ }
+
+ Query.base.circle.apply(this, arguments);
+};
+
+/**
+ * Determines if field selection has been made.
+ *
+ * @method selected
+ * @memberOf Query
+ * @instance
+ * @return {Boolean}
+ * @api public
+ */
+
+/**
+ * Determines if inclusive field selection has been made.
+ *
+ * query.selectedInclusively() // false
+ * query.select('name')
+ * query.selectedInclusively() // true
+ *
+ * @method selectedInclusively
+ * @memberOf Query
+ * @instance
+ * @return {Boolean}
+ * @api public
+ */
+
+Query.prototype.selectedInclusively = function selectedInclusively() {
+ return isInclusive(this._fields);
+};
+
+/**
+ * Determines if exclusive field selection has been made.
+ *
+ * query.selectedExclusively() // false
+ * query.select('-name')
+ * query.selectedExclusively() // true
+ * query.selectedInclusively() // false
+ *
+ * @method selectedExclusively
+ * @memberOf Query
+ * @instance
+ * @return {Boolean}
+ * @api public
+ */
+
+Query.prototype.selectedExclusively = function selectedExclusively() {
+ if (!this._fields) {
+ return false;
+ }
+
+ const keys = Object.keys(this._fields);
+ for (const key of keys) {
+ if (key === '_id') {
+ continue;
+ }
+ if (this._fields[key] === 0 || this._fields[key] === false) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/*!
+ * Export
+ */
+
+module.exports = Query;
diff --git a/node_modules/mongoose/lib/queryhelpers.js b/node_modules/mongoose/lib/queryhelpers.js
new file mode 100644
index 0000000..d0e93b6
--- /dev/null
+++ b/node_modules/mongoose/lib/queryhelpers.js
@@ -0,0 +1,307 @@
+'use strict';
+
+/*!
+ * Module dependencies
+ */
+
+const checkEmbeddedDiscriminatorKeyProjection =
+ require('./helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection');
+const get = require('./helpers/get');
+const getDiscriminatorByValue =
+ require('./helpers/discriminator/getDiscriminatorByValue');
+const isDefiningProjection = require('./helpers/projection/isDefiningProjection');
+const clone = require('./helpers/clone');
+
+/*!
+ * Prepare a set of path options for query population.
+ *
+ * @param {Query} query
+ * @param {Object} options
+ * @return {Array}
+ */
+
+exports.preparePopulationOptions = function preparePopulationOptions(query, options) {
+ const _populate = query.options.populate;
+ const pop = Object.keys(_populate).reduce((vals, key) => vals.concat([_populate[key]]), []);
+
+ // lean options should trickle through all queries
+ if (options.lean != null) {
+ pop.
+ filter(p => get(p, 'options.lean') == null).
+ forEach(makeLean(options.lean));
+ }
+
+ return pop;
+};
+
+/*!
+ * Prepare a set of path options for query population. This is the MongooseQuery
+ * version
+ *
+ * @param {Query} query
+ * @param {Object} options
+ * @return {Array}
+ */
+
+exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query, options) {
+ const _populate = query._mongooseOptions.populate;
+ const pop = Object.keys(_populate).reduce((vals, key) => vals.concat([_populate[key]]), []);
+
+ // lean options should trickle through all queries
+ if (options.lean != null) {
+ pop.
+ filter(p => get(p, 'options.lean') == null).
+ forEach(makeLean(options.lean));
+ }
+
+ const session = get(query, 'options.session', null);
+ if (session != null) {
+ pop.forEach(path => {
+ if (path.options == null) {
+ path.options = { session: session };
+ return;
+ }
+ if (!('session' in path.options)) {
+ path.options.session = session;
+ }
+ });
+ }
+
+ const projection = query._fieldsForExec();
+ pop.forEach(p => {
+ p._queryProjection = projection;
+ });
+
+ return pop;
+};
+
+/*!
+ * If the document is a mapped discriminator type, it returns a model instance for that type, otherwise,
+ * it returns an instance of the given model.
+ *
+ * @param {Model} model
+ * @param {Object} doc
+ * @param {Object} fields
+ *
+ * @return {Document}
+ */
+exports.createModel = function createModel(model, doc, fields, userProvidedFields) {
+ model.hooks.execPreSync('createModel', doc);
+ const discriminatorMapping = model.schema ?
+ model.schema.discriminatorMapping :
+ null;
+
+ const key = discriminatorMapping && discriminatorMapping.isRoot ?
+ discriminatorMapping.key :
+ null;
+
+ const value = doc[key];
+ if (key && value && model.discriminators) {
+ const discriminator = model.discriminators[value] || getDiscriminatorByValue(model, value);
+ if (discriminator) {
+ const _fields = clone(userProvidedFields);
+ exports.applyPaths(_fields, discriminator.schema);
+ return new discriminator(undefined, _fields, true);
+ }
+ }
+
+ return new model(undefined, fields, {
+ skipId: true,
+ isNew: false,
+ willInit: true
+ });
+};
+
+/*!
+ * ignore
+ */
+
+exports.applyPaths = function applyPaths(fields, schema) {
+ // determine if query is selecting or excluding fields
+ let exclude;
+ let keys;
+ let keyIndex;
+
+ if (fields) {
+ keys = Object.keys(fields);
+ keyIndex = keys.length;
+
+ while (keyIndex--) {
+ if (keys[keyIndex][0] === '+') {
+ continue;
+ }
+ const field = fields[keys[keyIndex]];
+ // Skip `$meta` and `$slice`
+ if (!isDefiningProjection(field)) {
+ continue;
+ }
+ exclude = !field;
+ break;
+ }
+ }
+
+ // if selecting, apply default schematype select:true fields
+ // if excluding, apply schematype select:false fields
+
+ const selected = [];
+ const excluded = [];
+ const stack = [];
+
+ analyzeSchema(schema);
+
+ switch (exclude) {
+ case true:
+ for (const fieldName of excluded) {
+ fields[fieldName] = 0;
+ }
+ break;
+ case false:
+ if (schema &&
+ schema.paths['_id'] &&
+ schema.paths['_id'].options &&
+ schema.paths['_id'].options.select === false) {
+ fields._id = 0;
+ }
+
+ for (const fieldName of selected) {
+ fields[fieldName] = fields[fieldName] || 1;
+ }
+ break;
+ case undefined:
+ if (fields == null) {
+ break;
+ }
+ // Any leftover plus paths must in the schema, so delete them (gh-7017)
+ for (const key of Object.keys(fields || {})) {
+ if (key.startsWith('+')) {
+ delete fields[key];
+ }
+ }
+
+ // user didn't specify fields, implies returning all fields.
+ // only need to apply excluded fields and delete any plus paths
+ for (const fieldName of excluded) {
+ fields[fieldName] = 0;
+ }
+ break;
+ }
+
+ function analyzeSchema(schema, prefix) {
+ prefix || (prefix = '');
+
+ // avoid recursion
+ if (stack.indexOf(schema) !== -1) {
+ return [];
+ }
+ stack.push(schema);
+
+ const addedPaths = [];
+ schema.eachPath(function(path, type) {
+ if (prefix) path = prefix + '.' + path;
+
+ const addedPath = analyzePath(path, type);
+ if (addedPath != null) {
+ addedPaths.push(addedPath);
+ }
+
+ // nested schemas
+ if (type.schema) {
+ const _addedPaths = analyzeSchema(type.schema, path);
+
+ // Special case: if discriminator key is the only field that would
+ // be projected in, remove it.
+ if (exclude === false) {
+ checkEmbeddedDiscriminatorKeyProjection(fields, path, type.schema,
+ selected, _addedPaths);
+ }
+ }
+ });
+
+ stack.pop();
+ return addedPaths;
+ }
+
+ function analyzePath(path, type) {
+ const plusPath = '+' + path;
+ const hasPlusPath = fields && plusPath in fields;
+ if (hasPlusPath) {
+ // forced inclusion
+ delete fields[plusPath];
+ }
+
+ if (typeof type.selected !== 'boolean') return;
+
+ if (hasPlusPath) {
+ // forced inclusion
+ delete fields[plusPath];
+
+ // if there are other fields being included, add this one
+ // if no other included fields, leave this out (implied inclusion)
+ if (exclude === false && keys.length > 1 && !~keys.indexOf(path)) {
+ fields[path] = 1;
+ }
+
+ return;
+ }
+
+ // check for parent exclusions
+ const pieces = path.split('.');
+ let cur = '';
+ for (let i = 0; i < pieces.length; ++i) {
+ cur += cur.length ? '.' + pieces[i] : pieces[i];
+ if (excluded.indexOf(cur) !== -1) {
+ return;
+ }
+ }
+
+ // Special case: if user has included a parent path of a discriminator key,
+ // don't explicitly project in the discriminator key because that will
+ // project out everything else under the parent path
+ if (!exclude && get(type, 'options.$skipDiscriminatorCheck', false)) {
+ let cur = '';
+ for (let i = 0; i < pieces.length; ++i) {
+ cur += (cur.length === 0 ? '' : '.') + pieces[i];
+ const projection = get(fields, cur, false) || get(fields, cur + '.$', false);
+ if (projection && typeof projection !== 'object') {
+ return;
+ }
+ }
+ }
+
+ (type.selected ? selected : excluded).push(path);
+ return path;
+ }
+};
+
+/*!
+ * Set each path query option to lean
+ *
+ * @param {Object} option
+ */
+
+function makeLean(val) {
+ return function(option) {
+ option.options || (option.options = {});
+ option.options.lean = val;
+ };
+}
+
+/*!
+ * Handle the `WriteOpResult` from the server
+ */
+
+exports.handleDeleteWriteOpResult = function handleDeleteWriteOpResult(callback) {
+ return function _handleDeleteWriteOpResult(error, res) {
+ if (error) {
+ return callback(error);
+ }
+ const mongooseResult = Object.assign({}, res.result);
+ if (get(res, 'result.n', null) != null) {
+ mongooseResult.deletedCount = res.result.n;
+ }
+ if (res.deletedCount != null) {
+ mongooseResult.deletedCount = res.deletedCount;
+ }
+ return callback(null, mongooseResult);
+ };
+};
diff --git a/node_modules/mongoose/lib/schema.js b/node_modules/mongoose/lib/schema.js
new file mode 100644
index 0000000..2abd0a0
--- /dev/null
+++ b/node_modules/mongoose/lib/schema.js
@@ -0,0 +1,2144 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const EventEmitter = require('events').EventEmitter;
+const Kareem = require('kareem');
+const MongooseError = require('./error/mongooseError');
+const SchemaType = require('./schematype');
+const SchemaTypeOptions = require('./options/SchemaTypeOptions');
+const VirtualOptions = require('./options/VirtualOptions');
+const VirtualType = require('./virtualtype');
+const addAutoId = require('./helpers/schema/addAutoId');
+const arrayParentSymbol = require('./helpers/symbols').arrayParentSymbol;
+const get = require('./helpers/get');
+const getIndexes = require('./helpers/schema/getIndexes');
+const merge = require('./helpers/schema/merge');
+const mpath = require('mpath');
+const readPref = require('./driver').get().ReadPreference;
+const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
+const util = require('util');
+const utils = require('./utils');
+const validateRef = require('./helpers/populate/validateRef');
+
+let MongooseTypes;
+
+const queryHooks = require('./helpers/query/applyQueryMiddleware').
+ middlewareFunctions;
+const documentHooks = require('./helpers/model/applyHooks').middlewareFunctions;
+const hookNames = queryHooks.concat(documentHooks).
+ reduce((s, hook) => s.add(hook), new Set());
+
+let id = 0;
+
+/**
+ * Schema constructor.
+ *
+ * ####Example:
+ *
+ * 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 })
+ *
+ * ####Options:
+ *
+ * - [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
+ * - [capped](/docs/guide.html#capped): bool - defaults to false
+ * - [collection](/docs/guide.html#collection): string - no default
+ * - [id](/docs/guide.html#id): bool - defaults to true
+ * - [_id](/docs/guide.html#_id): bool - defaults to true
+ * - [minimize](/docs/guide.html#minimize): bool - controls [document#toObject](#document_Document-toObject) behavior when called manually - defaults to true
+ * - [read](/docs/guide.html#read): string
+ * - [writeConcern](/docs/guide.html#writeConcern): object - defaults to null, use to override [the MongoDB server's default write concern settings](https://docs.mongodb.com/manual/reference/write-concern/)
+ * - [shardKey](/docs/guide.html#shardKey): object - defaults to `null`
+ * - [strict](/docs/guide.html#strict): bool - defaults to true
+ * - [strictQuery](/docs/guide.html#strictQuery): bool - defaults to false
+ * - [toJSON](/docs/guide.html#toJSON) - object - no default
+ * - [toObject](/docs/guide.html#toObject) - object - no default
+ * - [typeKey](/docs/guide.html#typeKey) - string - defaults to 'type'
+ * - [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 or object - defaults to "__v"
+ * - [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
+ * - [timestamps](/docs/guide.html#timestamps): object or boolean - defaults to `false`. If true, Mongoose adds `createdAt` and `updatedAt` properties to your schema and manages those properties for you.
+ * - [storeSubdocValidationError](/docs/guide.html#storeSubdocValidationError): boolean - Defaults to true. If false, Mongoose will wrap validation errors in single nested document subpaths into a single validation error on the single nested subdoc's path.
+ *
+ * ####Options for Nested Schemas:
+ * - `excludeIndexes`: bool - defaults to `false`. If `true`, skip building indexes on this schema's paths.
+ *
+ * ####Note:
+ *
+ * _When nesting schemas, (`children` in the example above), always declare the child schema first before passing it into its parent._
+ *
+ * @param {Object|Schema|Array} [definition] Can be one of: object describing schema paths, or schema to copy, or array of objects and schemas
+ * @param {Object} [options]
+ * @inherits NodeJS EventEmitter http://nodejs.org/api/events.html#events_class_events_eventemitter
+ * @event `init`: Emitted after the schema is compiled into a `Model`.
+ * @api public
+ */
+
+function Schema(obj, options) {
+ if (!(this instanceof Schema)) {
+ return new Schema(obj, options);
+ }
+
+ this.obj = obj;
+ this.paths = {};
+ this.aliases = {};
+ this.subpaths = {};
+ this.virtuals = {};
+ this.singleNestedPaths = {};
+ this.nested = {};
+ this.inherits = {};
+ this.callQueue = [];
+ this._indexes = [];
+ this.methods = {};
+ this.methodOptions = {};
+ this.statics = {};
+ this.tree = {};
+ this.query = {};
+ this.childSchemas = [];
+ this.plugins = [];
+ // For internal debugging. Do not use this to try to save a schema in MDB.
+ this.$id = ++id;
+
+ this.s = {
+ hooks: new Kareem()
+ };
+
+ this.options = this.defaultOptions(options);
+
+ // build paths
+ if (Array.isArray(obj)) {
+ for (const definition of obj) {
+ this.add(definition);
+ }
+ } else if (obj) {
+ this.add(obj);
+ }
+
+ // check if _id's value is a subdocument (gh-2276)
+ const _idSubDoc = obj && obj._id && utils.isObject(obj._id);
+
+ // ensure the documents get an auto _id unless disabled
+ const auto_id = !this.paths['_id'] &&
+ (!this.options.noId && this.options._id) && !_idSubDoc;
+
+ if (auto_id) {
+ addAutoId(this);
+ }
+
+ this.setupTimestamp(this.options.timestamps);
+}
+
+/*!
+ * Create virtual properties with alias field
+ */
+function aliasFields(schema, paths) {
+ paths = paths || Object.keys(schema.paths);
+ for (const path of paths) {
+ const options = get(schema.paths[path], 'options');
+ if (options == null) {
+ continue;
+ }
+
+ const prop = schema.paths[path].path;
+ const alias = options.alias;
+
+ if (!alias) {
+ continue;
+ }
+
+ if (typeof alias !== 'string') {
+ throw new Error('Invalid value for alias option on ' + prop + ', got ' + alias);
+ }
+
+ schema.aliases[alias] = prop;
+
+ schema.
+ virtual(alias).
+ get((function(p) {
+ return function() {
+ if (typeof this.get === 'function') {
+ return this.get(p);
+ }
+ return this[p];
+ };
+ })(prop)).
+ set((function(p) {
+ return function(v) {
+ return this.$set(p, v);
+ };
+ })(prop));
+ }
+}
+
+/*!
+ * Inherit from EventEmitter.
+ */
+Schema.prototype = Object.create(EventEmitter.prototype);
+Schema.prototype.constructor = Schema;
+Schema.prototype.instanceOfSchema = true;
+
+/*!
+ * ignore
+ */
+
+Object.defineProperty(Schema.prototype, '$schemaType', {
+ configurable: false,
+ enumerable: false,
+ writable: true
+});
+
+/**
+ * Array of child schemas (from document arrays and single nested subdocs)
+ * and their corresponding compiled models. Each element of the array is
+ * an object with 2 properties: `schema` and `model`.
+ *
+ * This property is typically only useful for plugin authors and advanced users.
+ * You do not need to interact with this property at all to use mongoose.
+ *
+ * @api public
+ * @property childSchemas
+ * @memberOf Schema
+ * @instance
+ */
+
+Object.defineProperty(Schema.prototype, 'childSchemas', {
+ configurable: false,
+ enumerable: true,
+ writable: true
+});
+
+/**
+ * The original object passed to the schema constructor
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ a: String }).add({ b: String });
+ * schema.obj; // { a: String }
+ *
+ * @api public
+ * @property obj
+ * @memberOf Schema
+ * @instance
+ */
+
+Schema.prototype.obj;
+
+/**
+ * The paths defined on this schema. The keys are the top-level paths
+ * in this schema, and the values are instances of the SchemaType class.
+ *
+ * ####Example:
+ * const schema = new Schema({ name: String }, { _id: false });
+ * schema.paths; // { name: SchemaString { ... } }
+ *
+ * schema.add({ age: Number });
+ * schema.paths; // { name: SchemaString { ... }, age: SchemaNumber { ... } }
+ *
+ * @api public
+ * @property paths
+ * @memberOf Schema
+ * @instance
+ */
+
+Schema.prototype.paths;
+
+/**
+ * Schema as a tree
+ *
+ * ####Example:
+ * {
+ * '_id' : ObjectId
+ * , 'nested' : {
+ * 'key' : String
+ * }
+ * }
+ *
+ * @api private
+ * @property tree
+ * @memberOf Schema
+ * @instance
+ */
+
+Schema.prototype.tree;
+
+/**
+ * Returns a deep copy of the schema
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String });
+ * const clone = schema.clone();
+ * clone === schema; // false
+ * clone.path('name'); // SchemaString { ... }
+ *
+ * @return {Schema} the cloned schema
+ * @api public
+ * @memberOf Schema
+ * @instance
+ */
+
+Schema.prototype.clone = function() {
+ 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);
+ s.callQueue = this.callQueue.map(function(f) { return f; });
+ s.methods = utils.clone(this.methods);
+ s.methodOptions = utils.clone(this.methodOptions);
+ s.statics = utils.clone(this.statics);
+ s.query = utils.clone(this.query);
+ s.plugins = Array.prototype.slice.call(this.plugins);
+ s._indexes = utils.clone(this._indexes);
+ s.s.hooks = this.s.hooks.clone();
+
+ s.tree = utils.clone(this.tree);
+ s.paths = utils.clone(this.paths);
+ s.nested = utils.clone(this.nested);
+ s.subpaths = utils.clone(this.subpaths);
+ s.singleNestedPaths = utils.clone(this.singleNestedPaths);
+ s.childSchemas = gatherChildSchemas(s);
+
+ s.virtuals = utils.clone(this.virtuals);
+ s.$globalPluginsApplied = this.$globalPluginsApplied;
+ s.$isRootDiscriminator = this.$isRootDiscriminator;
+ s.$implicitlyCreated = this.$implicitlyCreated;
+
+ if (this.discriminatorMapping != null) {
+ s.discriminatorMapping = Object.assign({}, this.discriminatorMapping);
+ }
+ if (this.discriminators != null) {
+ s.discriminators = Object.assign({}, this.discriminators);
+ }
+
+ s.aliases = Object.assign({}, this.aliases);
+
+ // Bubble up `init` for backwards compat
+ s.on('init', v => this.emit('init', v));
+
+ return s;
+};
+
+/**
+ * Returns a new schema that has the picked `paths` from this schema.
+ *
+ * This method is analagous to [Lodash's `pick()` function](https://lodash.com/docs/4.17.15#pick) for Mongoose schemas.
+ *
+ * ####Example:
+ *
+ * const schema = Schema({ name: String, age: Number });
+ * // Creates a new schema with the same `name` path as `schema`,
+ * // but no `age` path.
+ * const newSchema = schema.pick(['name']);
+ *
+ * newSchema.path('name'); // SchemaString { ... }
+ * newSchema.path('age'); // undefined
+ *
+ * @param {Array} paths list of paths to pick
+ * @param {Object} [options] options to pass to the schema constructor. Defaults to `this.options` if not set.
+ * @return {Schema}
+ * @api public
+ */
+
+Schema.prototype.pick = function(paths, options) {
+ const newSchema = new Schema({}, options || this.options);
+ if (!Array.isArray(paths)) {
+ throw new MongooseError('Schema#pick() only accepts an array argument, ' +
+ 'got "' + typeof paths + '"');
+ }
+
+ for (const path of paths) {
+ if (this.nested[path]) {
+ newSchema.add({ [path]: get(this.tree, path) });
+ } else {
+ const schematype = this.path(path);
+ if (schematype == null) {
+ throw new MongooseError('Path `' + path + '` is not in the schema');
+ }
+ newSchema.add({ [path]: schematype });
+ }
+ }
+
+ return newSchema;
+};
+
+/**
+ * Returns default options for this schema, merged with `options`.
+ *
+ * @param {Object} options
+ * @return {Object}
+ * @api private
+ */
+
+Schema.prototype.defaultOptions = function(options) {
+ if (options && options.safe === false) {
+ options.safe = { w: 0 };
+ }
+
+ if (options && options.safe && options.safe.w === 0) {
+ // if you turn off safe writes, then versioning goes off as well
+ options.versionKey = false;
+ }
+
+ this._userProvidedOptions = options == null ? {} : utils.clone(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,
+ shardKey: null,
+ read: null,
+ validateBeforeSave: true,
+ // the following are only applied at construction time
+ noId: false, // deprecated, use { _id: false }
+ _id: true,
+ noVirtualId: false, // deprecated, use { id: false }
+ id: true,
+ typeKey: 'type',
+ typePojoToMixed: 'typePojoToMixed' in baseOptions ? baseOptions.typePojoToMixed : true
+ }, utils.clone(options));
+
+ if (options.read) {
+ options.read = readPref(options.read);
+ }
+
+ if (options.optimisticConcurrency && !options.versionKey) {
+ throw new MongooseError('Must set `versionKey` if using `optimisticConcurrency`');
+ }
+
+ return options;
+};
+
+/**
+ * Adds key path / schema type pairs to this schema.
+ *
+ * ####Example:
+ *
+ * const ToySchema = new Schema();
+ * ToySchema.add({ name: 'string', color: 'string', price: 'number' });
+ *
+ * const TurboManSchema = new Schema();
+ * // You can also `add()` another schema and copy over all paths, virtuals,
+ * // getters, setters, indexes, methods, and statics.
+ * TurboManSchema.add(ToySchema).add({ year: Number });
+ *
+ * @param {Object|Schema} obj plain object with paths to add, or another schema
+ * @param {String} [prefix] path to prefix the newly added paths with
+ * @return {Schema} the Schema instance
+ * @api public
+ */
+
+Schema.prototype.add = function add(obj, prefix) {
+ if (obj instanceof Schema || (obj != null && obj.instanceOfSchema)) {
+ merge(this, obj);
+
+ return this;
+ }
+
+ // Special case: setting top-level `_id` to false should convert to disabling
+ // the `_id` option. This behavior never worked before 5.4.11 but numerous
+ // codebases use it (see gh-7516, gh-7512).
+ if (obj._id === false && prefix == null) {
+ this.options._id = false;
+ }
+
+ prefix = prefix || '';
+ const keys = Object.keys(obj);
+
+ for (const key of keys) {
+ const fullPath = prefix + key;
+
+ if (obj[key] == null) {
+ throw new TypeError('Invalid value for schema path `' + fullPath +
+ '`, got value "' + obj[key] + '"');
+ }
+ // Retain `_id: false` but don't set it as a path, re: gh-8274.
+ if (key === '_id' && obj[key] === false) {
+ continue;
+ }
+ if (obj[key] instanceof VirtualType || get(obj[key], 'constructor.name', null) === 'VirtualType') {
+ this.virtual(obj[key]);
+ continue;
+ }
+
+ if (Array.isArray(obj[key]) && obj[key].length === 1 && obj[key][0] == null) {
+ throw new TypeError('Invalid value for schema Array path `' + fullPath +
+ '`, got value "' + obj[key][0] + '"');
+ }
+
+ if (!(utils.isPOJO(obj[key]) || obj[key] instanceof SchemaTypeOptions)) {
+ // Special-case: Non-options definitely a path so leaf at this node
+ // Examples: Schema instances, SchemaType instances
+ if (prefix) {
+ this.nested[prefix.substr(0, prefix.length - 1)] = true;
+ }
+ this.path(prefix + key, obj[key]);
+ } else if (Object.keys(obj[key]).length < 1) {
+ // Special-case: {} always interpreted as Mixed path so leaf at this node
+ if (prefix) {
+ this.nested[prefix.substr(0, prefix.length - 1)] = true;
+ }
+ this.path(fullPath, obj[key]); // mixed type
+ } else if (!obj[key][this.options.typeKey] || (this.options.typeKey === 'type' && obj[key].type.type)) {
+ // Special-case: POJO with no bona-fide type key - interpret as tree of deep paths so recurse
+ // nested object { last: { name: String }}
+ this.nested[fullPath] = true;
+ this.add(obj[key], fullPath + '.');
+ } else {
+ // There IS a bona-fide type key that may also be a POJO
+ if (!this.options.typePojoToMixed && utils.isPOJO(obj[key][this.options.typeKey])) {
+ // If a POJO is the value of a type key, make it a subdocument
+ if (prefix) {
+ this.nested[prefix.substr(0, prefix.length - 1)] = true;
+ }
+ // Propage `typePojoToMixed` to implicitly created schemas
+ const opts = { typePojoToMixed: false };
+ const _schema = new Schema(obj[key][this.options.typeKey], opts);
+ const schemaWrappedPath = Object.assign({}, obj[key], { [this.options.typeKey]: _schema });
+ this.path(prefix + key, schemaWrappedPath);
+ } else {
+ // Either the type is non-POJO or we interpret it as Mixed anyway
+ if (prefix) {
+ this.nested[prefix.substr(0, prefix.length - 1)] = true;
+ }
+ this.path(prefix + key, obj[key]);
+ }
+ }
+ }
+
+ const addedKeys = Object.keys(obj).
+ map(key => prefix ? prefix + key : key);
+ aliasFields(this, addedKeys);
+ return this;
+};
+
+/**
+ * Reserved document keys.
+ *
+ * Keys in this object are names that are rejected in schema declarations
+ * because they conflict with Mongoose functionality. If you create a schema
+ * using `new Schema()` with one of these property names, Mongoose will throw
+ * an error.
+ *
+ * - _posts
+ * - _pres
+ * - collection
+ * - emit
+ * - errors
+ * - get
+ * - init
+ * - isModified
+ * - isNew
+ * - listeners
+ * - modelName
+ * - on
+ * - once
+ * - populated
+ * - prototype
+ * - remove
+ * - removeListener
+ * - save
+ * - schema
+ * - toObject
+ * - validate
+ *
+ * _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.
+ *
+ * const schema = new Schema(..);
+ * schema.methods.init = function () {} // potentially breaking
+ */
+
+Schema.reserved = Object.create(null);
+Schema.prototype.reserved = Schema.reserved;
+const reserved = Schema.reserved;
+// Core object
+reserved['prototype'] =
+// EventEmitter
+reserved.emit =
+reserved.listeners =
+reserved.on =
+reserved.removeListener =
+// document properties and functions
+reserved.collection =
+reserved.errors =
+reserved.get =
+reserved.init =
+reserved.isModified =
+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.
+ *
+ * Sets a path (if arity 2)
+ * Gets a path (if arity 1)
+ *
+ * ####Example
+ *
+ * schema.path('name') // returns a SchemaType
+ * schema.path('name', Number) // changes the schemaType of `name` to Number
+ *
+ * @param {String} path
+ * @param {Object} constructor
+ * @api public
+ */
+
+Schema.prototype.path = function(path, obj) {
+ // Convert to '.$' to check subpaths re: gh-6405
+ const cleanPath = _pathToPositionalSyntax(path);
+ if (obj === undefined) {
+ let schematype = _getPath(this, path, cleanPath);
+ if (schematype != null) {
+ return schematype;
+ }
+
+ // Look for maps
+ const mapPath = getMapPath(this, path);
+ if (mapPath != null) {
+ return mapPath;
+ }
+
+ // Look if a parent of this path is mixed
+ schematype = this.hasMixedParent(cleanPath);
+ if (schematype != null) {
+ return schematype;
+ }
+
+ // subpaths?
+ return /\.\d+\.?.*$/.test(path)
+ ? getPositionalPath(this, path)
+ : undefined;
+ }
+
+ // some path names conflict with document methods
+ const firstPieceOfPath = path.split('.')[0];
+ if (reserved[firstPieceOfPath]) {
+ 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);
+ }
+
+ // update the tree
+ const subpaths = path.split(/\./);
+ const last = subpaths.pop();
+ let branch = this.tree;
+ let fullPath = '';
+
+ for (const sub of subpaths) {
+ fullPath = fullPath += (fullPath.length > 0 ? '.' : '') + sub;
+ if (!branch[sub]) {
+ this.nested[fullPath] = true;
+ branch[sub] = {};
+ }
+ if (typeof branch[sub] !== 'object') {
+ const msg = 'Cannot set nested path `' + path + '`. '
+ + 'Parent path `'
+ + fullPath
+ + '` already set to type ' + branch[sub].name
+ + '.';
+ throw new Error(msg);
+ }
+ branch = branch[sub];
+ }
+
+ branch[last] = utils.clone(obj);
+
+ this.paths[path] = this.interpretAsType(path, obj, this.options);
+ const schemaType = this.paths[path];
+
+ if (schemaType.$isSchemaMap) {
+ // Maps can have arbitrary keys, so `$*` is internal shorthand for "any key"
+ // The '$' is to imply this path should never be stored in MongoDB so we
+ // can easily build a regexp out of this path, and '*' to imply "any key."
+ const mapPath = path + '.$*';
+ let _mapType = { type: {} };
+ if (utils.hasUserDefinedProperty(obj, 'of')) {
+ const isInlineSchema = utils.isPOJO(obj.of) &&
+ Object.keys(obj.of).length > 0 &&
+ !utils.hasUserDefinedProperty(obj.of, this.options.typeKey);
+ _mapType = isInlineSchema ? new Schema(obj.of) : obj.of;
+ }
+ this.paths[mapPath] = this.interpretAsType(mapPath,
+ _mapType, this.options);
+ schemaType.$__schemaType = this.paths[mapPath];
+ }
+
+ if (schemaType.$isSingleNested) {
+ for (const key in schemaType.schema.paths) {
+ this.singleNestedPaths[path + '.' + key] = schemaType.schema.paths[key];
+ }
+ for (const key in schemaType.schema.singleNestedPaths) {
+ this.singleNestedPaths[path + '.' + key] =
+ schemaType.schema.singleNestedPaths[key];
+ }
+ for (const key in schemaType.schema.subpaths) {
+ this.singleNestedPaths[path + '.' + key] =
+ schemaType.schema.subpaths[key];
+ }
+ for (const key in schemaType.schema.nested) {
+ this.singleNestedPaths[path + '.' + key] = 'nested';
+ }
+
+ Object.defineProperty(schemaType.schema, 'base', {
+ configurable: true,
+ enumerable: false,
+ writable: false,
+ value: this.base
+ });
+
+ schemaType.caster.base = this.base;
+ this.childSchemas.push({
+ schema: schemaType.schema,
+ model: schemaType.caster
+ });
+ } else if (schemaType.$isMongooseDocumentArray) {
+ Object.defineProperty(schemaType.schema, 'base', {
+ configurable: true,
+ enumerable: false,
+ writable: false,
+ value: this.base
+ });
+
+ schemaType.casterConstructor.base = this.base;
+ this.childSchemas.push({
+ schema: schemaType.schema,
+ model: schemaType.casterConstructor
+ });
+ }
+
+ if (schemaType.$isMongooseArray && schemaType.caster instanceof SchemaType) {
+ let arrayPath = path;
+ let _schemaType = schemaType;
+
+ const toAdd = [];
+ while (_schemaType.$isMongooseArray) {
+ arrayPath = arrayPath + '.$';
+
+ // Skip arrays of document arrays
+ if (_schemaType.$isMongooseDocumentArray) {
+ _schemaType.$embeddedSchemaType._arrayPath = arrayPath;
+ _schemaType = _schemaType.$embeddedSchemaType.clone();
+ } else {
+ _schemaType.caster._arrayPath = arrayPath;
+ _schemaType = _schemaType.caster.clone();
+ }
+
+ _schemaType.path = arrayPath;
+ toAdd.push(_schemaType);
+ }
+
+ for (const _schemaType of toAdd) {
+ this.subpaths[_schemaType.path] = _schemaType;
+ }
+ }
+
+ 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;
+ }
+ for (const key of Object.keys(schemaType.schema.subpaths)) {
+ this.subpaths[path + '.' + key] = schemaType.schema.subpaths[key];
+ schemaType.schema.subpaths[key].$isUnderneathDocArray = true;
+ }
+ for (const key of Object.keys(schemaType.schema.singleNestedPaths)) {
+ if (typeof schemaType.schema.singleNestedPaths[cleanPath] !== 'object') {
+ continue;
+ }
+ this.subpaths[path + '.' + key] = schemaType.schema.singleNestedPaths[key];
+ schemaType.schema.singleNestedPaths[key].$isUnderneathDocArray = true;
+ }
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+function gatherChildSchemas(schema) {
+ const childSchemas = [];
+
+ for (const path of Object.keys(schema.paths)) {
+ const schematype = schema.paths[path];
+ if (schematype.$isMongooseDocumentArray || schematype.$isSingleNested) {
+ childSchemas.push({ schema: schematype.schema, model: schematype.caster });
+ }
+ }
+
+ return childSchemas;
+}
+
+/*!
+ * ignore
+ */
+
+function _getPath(schema, path, cleanPath) {
+ if (schema.paths.hasOwnProperty(path)) {
+ return schema.paths[path];
+ }
+ if (schema.subpaths.hasOwnProperty(cleanPath)) {
+ return schema.subpaths[cleanPath];
+ }
+ if (schema.singleNestedPaths.hasOwnProperty(cleanPath) && typeof schema.singleNestedPaths[cleanPath] === 'object') {
+ return schema.singleNestedPaths[cleanPath];
+ }
+
+ return null;
+}
+
+/*!
+ * ignore
+ */
+
+function _pathToPositionalSyntax(path) {
+ if (!/\.\d+/.test(path)) {
+ return path;
+ }
+ return path.replace(/\.\d+\./g, '.$.').replace(/\.\d+$/, '.$');
+}
+
+/*!
+ * ignore
+ */
+
+function getMapPath(schema, path) {
+ for (const _path of Object.keys(schema.paths)) {
+ if (!_path.includes('.$*')) {
+ continue;
+ }
+ const re = new RegExp('^' + _path.replace(/\.\$\*/g, '\\.[^.]+') + '$');
+ if (re.test(path)) {
+ return schema.paths[_path];
+ }
+ }
+
+ return null;
+}
+
+/**
+ * The Mongoose instance this schema is associated with
+ *
+ * @property base
+ * @api private
+ */
+
+Object.defineProperty(Schema.prototype, 'base', {
+ configurable: true,
+ enumerable: false,
+ writable: true,
+ value: null
+});
+
+/**
+ * Converts type arguments into Mongoose Types.
+ *
+ * @param {String} path
+ * @param {Object} obj constructor
+ * @api private
+ */
+
+Schema.prototype.interpretAsType = function(path, obj, options) {
+ if (obj instanceof SchemaType) {
+ const clone = obj.clone();
+ clone.path = path;
+ return clone;
+ }
+
+ // If this schema has an associated Mongoose object, use the Mongoose object's
+ // copy of SchemaTypes re: gh-7158 gh-6933
+ const MongooseTypes = this.base != null ? this.base.Schema.Types : Schema.Types;
+
+ if (!utils.isPOJO(obj) && !(obj instanceof SchemaTypeOptions)) {
+ const constructorName = utils.getFunctionName(obj.constructor);
+ if (constructorName !== 'Object') {
+ const oldObj = obj;
+ obj = {};
+ obj[options.typeKey] = oldObj;
+ }
+ }
+
+ // Get the type making sure to allow keys named "type"
+ // and default to mixed if not specified.
+ // { type: { type: String, default: 'freshcut' } }
+ let type = obj[options.typeKey] && (options.typeKey !== 'type' || !obj.type.type)
+ ? obj[options.typeKey]
+ : {};
+ let name;
+
+ if (utils.isPOJO(type) || type === 'mixed') {
+ return new MongooseTypes.Mixed(path, obj);
+ }
+
+ 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
+ : type[0];
+
+ if (cast && cast.instanceOfSchema) {
+ return new MongooseTypes.DocumentArray(path, cast, obj);
+ }
+ if (cast &&
+ cast[options.typeKey] &&
+ cast[options.typeKey].instanceOfSchema) {
+ return new MongooseTypes.DocumentArray(path, cast[options.typeKey], obj, cast);
+ }
+
+ if (Array.isArray(cast)) {
+ return new MongooseTypes.Array(path, this.interpretAsType(path, cast, options), obj);
+ }
+
+ if (typeof cast === 'string') {
+ cast = MongooseTypes[cast.charAt(0).toUpperCase() + cast.substring(1)];
+ } else if (cast && (!cast[options.typeKey] || (options.typeKey === 'type' && cast.type.type))
+ && utils.isPOJO(cast)) {
+ if (Object.keys(cast).length) {
+ // The `minimize` and `typeKey` options propagate to child schemas
+ // declared inline, like `{ arr: [{ val: { $type: String } }] }`.
+ // See gh-3560
+ const childSchemaOptions = { minimize: options.minimize };
+ if (options.typeKey) {
+ childSchemaOptions.typeKey = options.typeKey;
+ }
+ // propagate 'strict' option to child schema
+ if (options.hasOwnProperty('strict')) {
+ childSchemaOptions.strict = options.strict;
+ }
+ 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);
+ } else {
+ // Special case: empty object becomes mixed
+ return new MongooseTypes.Array(path, MongooseTypes.Mixed, obj);
+ }
+ }
+
+ if (cast) {
+ type = cast[options.typeKey] && (options.typeKey !== 'type' || !cast.type.type)
+ ? cast[options.typeKey]
+ : cast;
+
+ name = typeof type === 'string'
+ ? type
+ : type.schemaName || utils.getFunctionName(type);
+
+ if (!MongooseTypes.hasOwnProperty(name)) {
+ throw new TypeError('Invalid schema configuration: ' +
+ `\`${name}\` is not a valid type within the array \`${path}\`.` +
+ 'See http://bit.ly/mongoose-schematypes for a list of valid schema types.');
+ }
+ }
+
+ return new MongooseTypes.Array(path, cast || MongooseTypes.Mixed, obj, options);
+ }
+
+ if (type && type.instanceOfSchema) {
+ return new MongooseTypes.Embedded(type, path, obj);
+ }
+
+ if (Buffer.isBuffer(type)) {
+ name = 'Buffer';
+ } else if (typeof type === 'function' || typeof type === 'object') {
+ name = type.schemaName || utils.getFunctionName(type);
+ } else {
+ name = type == null ? '' + type : type.toString();
+ }
+
+ if (name) {
+ name = name.charAt(0).toUpperCase() + name.substring(1);
+ }
+ // Special case re: gh-7049 because the bson `ObjectID` class' capitalization
+ // doesn't line up with Mongoose's.
+ if (name === 'ObjectID') {
+ name = 'ObjectId';
+ }
+
+ if (MongooseTypes[name] == null) {
+ throw new TypeError(`Invalid schema configuration: \`${name}\` is not ` +
+ `a valid type at path \`${path}\`. See ` +
+ 'http://bit.ly/mongoose-schematypes for a list of valid schema types.');
+ }
+
+ return new MongooseTypes[name](path, obj);
+};
+
+/**
+ * Iterates the schemas paths similar to Array#forEach.
+ *
+ * The callback is passed the pathname and the schemaType instance.
+ *
+ * ####Example:
+ *
+ * const userSchema = new Schema({ name: String, registeredAt: Date });
+ * userSchema.eachPath((pathname, schematype) => {
+ * // Prints twice:
+ * // name SchemaString { ... }
+ * // registeredAt SchemaDate { ... }
+ * console.log(pathname, schematype);
+ * });
+ *
+ * @param {Function} fn callback function
+ * @return {Schema} this
+ * @api public
+ */
+
+Schema.prototype.eachPath = function(fn) {
+ const keys = Object.keys(this.paths);
+ const len = keys.length;
+
+ for (let i = 0; i < len; ++i) {
+ fn(keys[i], this.paths[keys[i]]);
+ }
+
+ return this;
+};
+
+/**
+ * Returns an Array of path strings that are required by this schema.
+ *
+ * ####Example:
+ * const s = new Schema({
+ * name: { type: String, required: true },
+ * age: { type: String, required: true },
+ * notes: String
+ * });
+ * s.requiredPaths(); // [ 'age', 'name' ]
+ *
+ * @api public
+ * @param {Boolean} invalidate refresh the cache
+ * @return {Array}
+ */
+
+Schema.prototype.requiredPaths = function requiredPaths(invalidate) {
+ if (this._requiredpaths && !invalidate) {
+ return this._requiredpaths;
+ }
+
+ const paths = Object.keys(this.paths);
+ let i = paths.length;
+ const ret = [];
+
+ while (i--) {
+ const path = paths[i];
+ if (this.paths[path].isRequired) {
+ ret.push(path);
+ }
+ }
+ this._requiredpaths = ret;
+ return this._requiredpaths;
+};
+
+/**
+ * Returns indexes from fields and schema-level indexes (cached).
+ *
+ * @api private
+ * @return {Array}
+ */
+
+Schema.prototype.indexedPaths = function indexedPaths() {
+ if (this._indexedpaths) {
+ return this._indexedpaths;
+ }
+ this._indexedpaths = this.indexes();
+ return this._indexedpaths;
+};
+
+/**
+ * Returns the pathType of `path` for this schema.
+ *
+ * Given a path, returns whether it is a real, virtual, nested, or ad-hoc/undefined path.
+ *
+ * ####Example:
+ * const s = new Schema({ name: String, nested: { foo: String } });
+ * s.virtual('foo').get(() => 42);
+ * s.pathType('name'); // "real"
+ * s.pathType('nested'); // "nested"
+ * s.pathType('foo'); // "virtual"
+ * s.pathType('fail'); // "adhocOrUndefined"
+ *
+ * @param {String} path
+ * @return {String}
+ * @api public
+ */
+
+Schema.prototype.pathType = function(path) {
+ // Convert to '.$' to check subpaths re: gh-6405
+ const cleanPath = _pathToPositionalSyntax(path);
+
+ if (this.paths.hasOwnProperty(path)) {
+ return 'real';
+ }
+ if (this.virtuals.hasOwnProperty(path)) {
+ return 'virtual';
+ }
+ if (this.nested.hasOwnProperty(path)) {
+ return 'nested';
+ }
+ if (this.subpaths.hasOwnProperty(cleanPath) || this.subpaths.hasOwnProperty(path)) {
+ return 'real';
+ }
+
+ const singleNestedPath = this.singleNestedPaths.hasOwnProperty(cleanPath) || this.singleNestedPaths.hasOwnProperty(path);
+ if (singleNestedPath) {
+ return singleNestedPath === 'nested' ? 'nested' : 'real';
+ }
+
+ // Look for maps
+ const mapPath = getMapPath(this, path);
+ if (mapPath != null) {
+ return 'real';
+ }
+
+ if (/\.\d+\.|\.\d+$/.test(path)) {
+ return getPositionalPathType(this, path);
+ }
+ return 'adhocOrUndefined';
+};
+
+/**
+ * Returns true iff this path is a child of a mixed schema.
+ *
+ * @param {String} path
+ * @return {Boolean}
+ * @api private
+ */
+
+Schema.prototype.hasMixedParent = function(path) {
+ const subpaths = path.split(/\./g);
+ path = '';
+ for (let i = 0; i < subpaths.length; ++i) {
+ path = i > 0 ? path + '.' + subpaths[i] : subpaths[i];
+ if (path in this.paths &&
+ this.paths[path] instanceof MongooseTypes.Mixed) {
+ return this.paths[path];
+ }
+ }
+
+ return null;
+};
+
+/**
+ * Setup updatedAt and createdAt timestamps to documents if enabled
+ *
+ * @param {Boolean|Object} timestamps timestamps options
+ * @api private
+ */
+Schema.prototype.setupTimestamp = function(timestamps) {
+ return setupTimestamps(this, timestamps);
+};
+
+/*!
+ * ignore. Deprecated re: #6405
+ */
+
+function getPositionalPathType(self, path) {
+ const subpaths = path.split(/\.(\d+)\.|\.(\d+)$/).filter(Boolean);
+ if (subpaths.length < 2) {
+ return self.paths.hasOwnProperty(subpaths[0]) ?
+ self.paths[subpaths[0]] :
+ 'adhocOrUndefined';
+ }
+
+ let val = self.path(subpaths[0]);
+ let isNested = false;
+ if (!val) {
+ return 'adhocOrUndefined';
+ }
+
+ const last = subpaths.length - 1;
+
+ for (let i = 1; i < subpaths.length; ++i) {
+ isNested = false;
+ const subpath = subpaths[i];
+
+ if (i === last && val && !/\D/.test(subpath)) {
+ if (val.$isMongooseDocumentArray) {
+ val = val.$embeddedSchemaType;
+ } else if (val instanceof MongooseTypes.Array) {
+ // StringSchema, NumberSchema, etc
+ val = val.caster;
+ } else {
+ val = undefined;
+ }
+ break;
+ }
+
+ // ignore if its just a position segment: path.0.subpath
+ if (!/\D/.test(subpath)) {
+ // Nested array
+ if (val instanceof MongooseTypes.Array && i !== last) {
+ val = val.caster;
+ }
+ continue;
+ }
+
+ if (!(val && val.schema)) {
+ val = undefined;
+ break;
+ }
+
+ const type = val.schema.pathType(subpath);
+ isNested = (type === 'nested');
+ val = val.schema.path(subpath);
+ }
+
+ self.subpaths[path] = val;
+ if (val) {
+ return 'real';
+ }
+ if (isNested) {
+ return 'nested';
+ }
+ return 'adhocOrUndefined';
+}
+
+
+/*!
+ * ignore
+ */
+
+function getPositionalPath(self, path) {
+ getPositionalPathType(self, path);
+ return self.subpaths[path];
+}
+
+/**
+ * Adds a method call to the queue.
+ *
+ * ####Example:
+ *
+ * schema.methods.print = function() { console.log(this); };
+ * schema.queue('print', []); // Print the doc every one is instantiated
+ *
+ * const Model = mongoose.model('Test', schema);
+ * new Model({ name: 'test' }); // Prints '{"_id": ..., "name": "test" }'
+ *
+ * @param {String} name name of the document method to call later
+ * @param {Array} args arguments to pass to the method
+ * @api public
+ */
+
+Schema.prototype.queue = function(name, args) {
+ this.callQueue.push([name, args]);
+ return this;
+};
+
+/**
+ * Defines a pre hook for the document.
+ *
+ * ####Example
+ *
+ * const toySchema = new Schema({ name: String, created: Date });
+ *
+ * toySchema.pre('save', function(next) {
+ * if (!this.created) this.created = new Date;
+ * next();
+ * });
+ *
+ * toySchema.pre('validate', function(next) {
+ * if (this.name !== 'Woody') this.name = 'Woody';
+ * next();
+ * });
+ *
+ * // Equivalent to calling `pre()` on `find`, `findOne`, `findOneAndUpdate`.
+ * toySchema.pre(/^find/, function(next) {
+ * console.log(this.getFilter());
+ * });
+ *
+ * // Equivalent to calling `pre()` on `updateOne`, `findOneAndUpdate`.
+ * toySchema.pre(['updateOne', 'findOneAndUpdate'], function(next) {
+ * console.log(this.getFilter());
+ * });
+ *
+ * toySchema.pre('deleteOne', function() {
+ * // Runs when you call `Toy.deleteOne()`
+ * });
+ *
+ * toySchema.pre('deleteOne', { document: true }, function() {
+ * // Runs when you call `doc.deleteOne()`
+ * });
+ *
+ * @param {String|RegExp} The method name or regular expression to match method name
+ * @param {Object} [options]
+ * @param {Boolean} [options.document] If `name` is a hook for both document and query middleware, set to `true` to run on document middleware. For example, set `options.document` to `true` to apply this hook to `Document#deleteOne()` rather than `Query#deleteOne()`.
+ * @param {Boolean} [options.query] If `name` is a hook for both document and query middleware, set to `true` to run on query middleware.
+ * @param {Function} callback
+ * @api public
+ */
+
+Schema.prototype.pre = function(name) {
+ if (name instanceof RegExp) {
+ const remainingArgs = Array.prototype.slice.call(arguments, 1);
+ for (const fn of hookNames) {
+ if (name.test(fn)) {
+ this.pre.apply(this, [fn].concat(remainingArgs));
+ }
+ }
+ return this;
+ }
+ if (Array.isArray(name)) {
+ const remainingArgs = Array.prototype.slice.call(arguments, 1);
+ for (const el of name) {
+ this.pre.apply(this, [el].concat(remainingArgs));
+ }
+ return this;
+ }
+ this.s.hooks.pre.apply(this.s.hooks, arguments);
+ return this;
+};
+
+/**
+ * Defines a post hook for the document
+ *
+ * const schema = new Schema(..);
+ * schema.post('save', function (doc) {
+ * console.log('this fired after a document was saved');
+ * });
+ *
+ * schema.post('find', function(docs) {
+ * console.log('this fired after you ran a find query');
+ * });
+ *
+ * schema.post(/Many$/, function(res) {
+ * console.log('this fired after you ran `updateMany()` or `deleteMany()`);
+ * });
+ *
+ * const Model = mongoose.model('Model', schema);
+ *
+ * const m = new Model(..);
+ * m.save(function(err) {
+ * console.log('this fires after the `post` hook');
+ * });
+ *
+ * m.find(function(err, docs) {
+ * console.log('this fires after the post find hook');
+ * });
+ *
+ * @param {String|RegExp} The method name or regular expression to match method name
+ * @param {Object} [options]
+ * @param {Boolean} [options.document] If `name` is a hook for both document and query middleware, set to `true` to run on document middleware.
+ * @param {Boolean} [options.query] If `name` is a hook for both document and query middleware, set to `true` to run on query middleware.
+ * @param {Function} fn callback
+ * @see middleware http://mongoosejs.com/docs/middleware.html
+ * @see kareem http://npmjs.org/package/kareem
+ * @api public
+ */
+
+Schema.prototype.post = function(name) {
+ if (name instanceof RegExp) {
+ const remainingArgs = Array.prototype.slice.call(arguments, 1);
+ for (const fn of hookNames) {
+ if (name.test(fn)) {
+ this.post.apply(this, [fn].concat(remainingArgs));
+ }
+ }
+ return this;
+ }
+ if (Array.isArray(name)) {
+ const remainingArgs = Array.prototype.slice.call(arguments, 1);
+ for (const el of name) {
+ this.post.apply(this, [el].concat(remainingArgs));
+ }
+ return this;
+ }
+ this.s.hooks.post.apply(this.s.hooks, arguments);
+ return this;
+};
+
+/**
+ * Registers a plugin for this schema.
+ *
+ * ####Example:
+ *
+ * const s = new Schema({ name: String });
+ * s.plugin(schema => console.log(schema.path('name').path));
+ * mongoose.model('Test', s); // Prints 'name'
+ *
+ * @param {Function} plugin callback
+ * @param {Object} [opts]
+ * @see plugins
+ * @api public
+ */
+
+Schema.prototype.plugin = function(fn, opts) {
+ if (typeof fn !== 'function') {
+ throw new Error('First param to `schema.plugin()` must be a function, ' +
+ 'got "' + (typeof fn) + '"');
+ }
+
+ if (opts && opts.deduplicate) {
+ for (const plugin of this.plugins) {
+ if (plugin.fn === fn) {
+ return this;
+ }
+ }
+ }
+ this.plugins.push({ fn: fn, opts: opts });
+
+ fn(this, opts);
+ return this;
+};
+
+/**
+ * Adds an instance method to documents constructed from Models compiled from this schema.
+ *
+ * ####Example
+ *
+ * const schema = kittySchema = new Schema(..);
+ *
+ * schema.method('meow', function () {
+ * console.log('meeeeeoooooooooooow');
+ * })
+ *
+ * const Kitty = mongoose.model('Kitty', schema);
+ *
+ * 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.
+ *
+ * schema.method({
+ * purr: function () {}
+ * , scratch: function () {}
+ * });
+ *
+ * // later
+ * 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)
+ *
+ * @param {String|Object} method name
+ * @param {Function} [fn]
+ * @api public
+ */
+
+Schema.prototype.method = function(name, fn, options) {
+ if (typeof name !== 'string') {
+ for (const i in name) {
+ this.methods[i] = name[i];
+ this.methodOptions[i] = utils.clone(options);
+ }
+ } else {
+ this.methods[name] = fn;
+ this.methodOptions[name] = utils.clone(options);
+ }
+ return this;
+};
+
+/**
+ * Adds static "class" methods to Models compiled from this schema.
+ *
+ * ####Example
+ *
+ * const schema = new Schema(..);
+ * // Equivalent to `schema.statics.findByName = function(name) {}`;
+ * schema.static('findByName', function(name) {
+ * return this.find({ name: name });
+ * });
+ *
+ * const Drink = mongoose.model('Drink', schema);
+ * await Drink.findByName('LaCroix');
+ *
+ * If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
+ *
+ * @param {String|Object} name
+ * @param {Function} [fn]
+ * @api public
+ * @see Statics /docs/guide.html#statics
+ */
+
+Schema.prototype.static = function(name, fn) {
+ if (typeof name !== 'string') {
+ for (const i in name) {
+ this.statics[i] = name[i];
+ }
+ } else {
+ this.statics[name] = fn;
+ }
+ return this;
+};
+
+/**
+ * Defines an index (most likely compound) for this schema.
+ *
+ * ####Example
+ *
+ * schema.index({ first: 1, last: -1 })
+ *
+ * @param {Object} fields
+ * @param {Object} [options] 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.
+ * @api public
+ */
+
+Schema.prototype.index = function(fields, options) {
+ fields || (fields = {});
+ options || (options = {});
+
+ if (options.expires) {
+ utils.expires(options);
+ }
+
+ this._indexes.push([fields, options]);
+ return this;
+};
+
+/**
+ * Sets/gets a schema option.
+ *
+ * ####Example
+ *
+ * schema.set('strict'); // 'true' by default
+ * schema.set('strict', false); // Sets 'strict' to false
+ * schema.set('strict'); // 'false'
+ *
+ * @param {String} key option name
+ * @param {Object} [value] if not passed, the current option value is returned
+ * @see Schema ./
+ * @api public
+ */
+
+Schema.prototype.set = function(key, value, _tags) {
+ if (arguments.length === 1) {
+ return this.options[key];
+ }
+
+ switch (key) {
+ case 'read':
+ this.options[key] = readPref(value, _tags);
+ this._userProvidedOptions[key] = this.options[key];
+ break;
+ case 'safe':
+ setSafe(this.options, value);
+ this._userProvidedOptions[key] = this.options[key];
+ break;
+ case 'timestamps':
+ this.setupTimestamp(value);
+ 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];
+ break;
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+const safeDeprecationWarning = 'Mongoose: The `safe` option for schemas is ' +
+ 'deprecated. Use the `writeConcern` option instead: ' +
+ 'http://bit.ly/mongoose-write-concern';
+
+const setSafe = util.deprecate(function setSafe(options, value) {
+ options.safe = value === false ?
+ { w: 0 } :
+ value;
+}, safeDeprecationWarning);
+
+/**
+ * Gets a schema option.
+ *
+ * ####Example:
+ *
+ * schema.get('strict'); // true
+ * schema.set('strict', false);
+ * schema.get('strict'); // false
+ *
+ * @param {String} key option name
+ * @api public
+ * @return {Any} the option's value
+ */
+
+Schema.prototype.get = function(key) {
+ return this.options[key];
+};
+
+/**
+ * The allowed index types
+ *
+ * @receiver Schema
+ * @static indexTypes
+ * @api public
+ */
+
+const indexTypes = '2d 2dsphere hashed text'.split(' ');
+
+Object.defineProperty(Schema, 'indexTypes', {
+ get: function() {
+ return indexTypes;
+ },
+ set: function() {
+ throw new Error('Cannot overwrite Schema.indexTypes');
+ }
+});
+
+/**
+ * Returns a list of indexes that this schema declares, via `schema.index()`
+ * or by `index: true` in a path's options.
+ *
+ * ####Example:
+ *
+ * const userSchema = new Schema({
+ * email: { type: String, required: true, unique: true },
+ * registeredAt: { type: Date, index: true }
+ * });
+ *
+ * // [ [ { email: 1 }, { unique: true, background: true } ],
+ * // [ { registeredAt: 1 }, { background: true } ] ]
+ * userSchema.indexes();
+ *
+ * @api public
+ * @return {Array} list of indexes defined in the schema
+ */
+
+Schema.prototype.indexes = function() {
+ return getIndexes(this);
+};
+
+/**
+ * Creates a virtual type with the given name.
+ *
+ * @param {String} name
+ * @param {Object} [options]
+ * @param {String|Model} [options.ref] model name or model instance. Marks this as a [populate virtual](populate.html#populate-virtuals).
+ * @param {String|Function} [options.localField] Required for populate virtuals. See [populate virtual docs](populate.html#populate-virtuals) for more information.
+ * @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()`.
+ * @return {VirtualType}
+ */
+
+Schema.prototype.virtual = function(name, options) {
+ if (name instanceof VirtualType || (name != null && name.constructor.name === 'VirtualType')) {
+ return this.virtual(name.path, name.options);
+ }
+
+ options = new VirtualOptions(options);
+
+ if (utils.hasUserDefinedProperty(options, ['ref', 'refPath'])) {
+ if (options.localField == null) {
+ throw new Error('Reference virtuals require `localField` option');
+ }
+
+ if (options.foreignField == null) {
+ throw new Error('Reference virtuals require `foreignField` option');
+ }
+
+ this.pre('init', function(obj) {
+ if (mpath.has(name, obj)) {
+ const _v = mpath.get(name, obj);
+ if (!this.$$populatedVirtuals) {
+ this.$$populatedVirtuals = {};
+ }
+
+ if (options.justOne || options.count) {
+ this.$$populatedVirtuals[name] = Array.isArray(_v) ?
+ _v[0] :
+ _v;
+ } else {
+ this.$$populatedVirtuals[name] = Array.isArray(_v) ?
+ _v :
+ _v == null ? [] : [_v];
+ }
+
+ mpath.unset(name, obj);
+ }
+ });
+
+ 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;
+ }).
+ set(function(_v) {
+ if (!this.$$populatedVirtuals) {
+ this.$$populatedVirtuals = {};
+ }
+
+ if (options.justOne || options.count) {
+ this.$$populatedVirtuals[name] = Array.isArray(_v) ?
+ _v[0] :
+ _v;
+
+ if (typeof this.$$populatedVirtuals[name] !== 'object') {
+ this.$$populatedVirtuals[name] = options.count ? _v : null;
+ }
+ } else {
+ this.$$populatedVirtuals[name] = Array.isArray(_v) ?
+ _v :
+ _v == null ? [] : [_v];
+
+ this.$$populatedVirtuals[name] = this.$$populatedVirtuals[name].filter(function(doc) {
+ return doc && typeof doc === 'object';
+ });
+ }
+ });
+ }
+
+ const virtuals = this.virtuals;
+ const parts = name.split('.');
+
+ if (this.pathType(name) === 'real') {
+ throw new Error('Virtual path "' + name + '"' +
+ ' conflicts with a real path in the schema');
+ }
+
+ virtuals[name] = parts.reduce(function(mem, part, i) {
+ mem[part] || (mem[part] = (i === parts.length - 1)
+ ? new VirtualType(options, name)
+ : {});
+ return mem[part];
+ }, this.tree);
+
+ // Workaround for gh-8198: if virtual is under document array, make a fake
+ // virtual. See gh-8210
+ let cur = parts[0];
+ for (let i = 0; i < parts.length - 1; ++i) {
+ if (this.paths[cur] != null && this.paths[cur].$isMongooseDocumentArray) {
+ const remnant = parts.slice(i + 1).join('.');
+ const v = this.paths[cur].schema.virtual(remnant);
+ v.get((v, virtual, doc) => {
+ const parent = doc.__parentArray[arrayParentSymbol];
+ const path = cur + '.' + doc.__index + '.' + remnant;
+ return parent.get(path);
+ });
+ break;
+ }
+
+ cur += '.' + parts[i + 1];
+ }
+
+ return virtuals[name];
+};
+
+/**
+ * Returns the virtual type with the given `name`.
+ *
+ * @param {String} name
+ * @return {VirtualType}
+ */
+
+Schema.prototype.virtualpath = function(name) {
+ return this.virtuals.hasOwnProperty(name) ? this.virtuals[name] : null;
+};
+
+/**
+ * Removes the given `path` (or [`paths`]).
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String, age: Number });
+ * schema.remove('name');
+ * schema.path('name'); // Undefined
+ * schema.path('age'); // SchemaNumber { ... }
+ *
+ * @param {String|Array} path
+ * @return {Schema} the Schema instance
+ * @api public
+ */
+Schema.prototype.remove = function(path) {
+ if (typeof path === 'string') {
+ path = [path];
+ }
+ if (Array.isArray(path)) {
+ path.forEach(function(name) {
+ if (this.path(name) == null && !this.nested[name]) {
+ return;
+ }
+ if (this.nested[name]) {
+ const allKeys = Object.keys(this.paths).
+ concat(Object.keys(this.nested));
+ for (const path of allKeys) {
+ if (path.startsWith(name + '.')) {
+ delete this.paths[path];
+ delete this.nested[path];
+ _deletePath(this, path);
+ }
+ }
+
+ delete this.nested[name];
+ _deletePath(this, name);
+ return;
+ }
+
+ delete this.paths[name];
+ _deletePath(this, name);
+ }, this);
+ }
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+function _deletePath(schema, name) {
+ const pieces = name.split('.');
+ const last = pieces.pop();
+
+ let branch = schema.tree;
+
+ for (const piece of pieces) {
+ branch = branch[piece];
+ }
+
+ delete branch[last];
+}
+
+/**
+ * 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).
+ *
+ * ####Example:
+ *
+ * ```javascript
+ * const md5 = require('md5');
+ * const userSchema = new Schema({ email: String });
+ * class UserClass {
+ * // `gravatarImage` becomes a virtual
+ * get gravatarImage() {
+ * const hash = md5(this.email.toLowerCase());
+ * return `https://www.gravatar.com/avatar/${hash}`;
+ * }
+ *
+ * // `getProfileUrl()` becomes a document method
+ * getProfileUrl() {
+ * return `https://mysite.com/${this.email}`;
+ * }
+ *
+ * // `findByEmail()` becomes a static
+ * static findByEmail(email) {
+ * return this.findOne({ email });
+ * }
+ * }
+ *
+ * // `schema` will now have a `gravatarImage` virtual, a `getProfileUrl()` method,
+ * // and a `findByEmail()` static
+ * userSchema.loadClass(UserClass);
+ * ```
+ *
+ * @param {Function} model
+ * @param {Boolean} [virtualsOnly] if truthy, only pulls virtuals from the class, not methods or statics
+ */
+Schema.prototype.loadClass = function(model, virtualsOnly) {
+ if (model === Object.prototype ||
+ model === Function.prototype ||
+ model.prototype.hasOwnProperty('$isMongooseModelPrototype')) {
+ return this;
+ }
+
+ this.loadClass(Object.getPrototypeOf(model));
+
+ // Add static methods
+ if (!virtualsOnly) {
+ Object.getOwnPropertyNames(model).forEach(function(name) {
+ if (name.match(/^(length|name|prototype)$/)) {
+ return;
+ }
+ const method = Object.getOwnPropertyDescriptor(model, name);
+ if (typeof method.value === 'function') {
+ this.static(name, method.value);
+ }
+ }, this);
+ }
+
+ // Add methods and virtuals
+ Object.getOwnPropertyNames(model.prototype).forEach(function(name) {
+ if (name.match(/^(constructor)$/)) {
+ return;
+ }
+ const method = Object.getOwnPropertyDescriptor(model.prototype, name);
+ if (!virtualsOnly) {
+ if (typeof method.value === 'function') {
+ this.method(name, method.value);
+ }
+ }
+ if (typeof method.get === 'function') {
+ this.virtual(name).get(method.get);
+ }
+ if (typeof method.set === 'function') {
+ this.virtual(name).set(method.set);
+ }
+ }, this);
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+Schema.prototype._getSchema = function(path) {
+ const _this = this;
+ const pathschema = _this.path(path);
+ const resultPath = [];
+
+ if (pathschema) {
+ pathschema.$fullPath = path;
+ return pathschema;
+ }
+
+ function search(parts, schema) {
+ let p = parts.length + 1;
+ let foundschema;
+ let trypath;
+
+ while (p--) {
+ trypath = parts.slice(0, p).join('.');
+ foundschema = schema.path(trypath);
+ if (foundschema) {
+ resultPath.push(trypath);
+
+ if (foundschema.caster) {
+ // array of Mixed?
+ if (foundschema.caster instanceof MongooseTypes.Mixed) {
+ foundschema.caster.$fullPath = resultPath.join('.');
+ return foundschema.caster;
+ }
+
+ // Now that we found the array, we need to check if there
+ // are remaining document paths to look up for casting.
+ // Also we need to handle array.$.path since schema.path
+ // doesn't work for that.
+ // If there is no foundschema.schema we are dealing with
+ // a path like array.$
+ 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;
+ }
+ // 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.$__schemaType;
+ }
+ const ret = search(parts.slice(p + 1), foundschema.$__schemaType.schema);
+ return ret;
+ }
+
+ foundschema.$fullPath = resultPath.join('.');
+
+ return foundschema;
+ }
+ }
+ }
+
+ // look for arrays
+ const parts = path.split('.');
+ for (let i = 0; i < parts.length; ++i) {
+ if (parts[i] === '$' || isArrayFilter(parts[i])) {
+ // Re: gh-5628, because `schema.path()` doesn't take $ into account.
+ parts[i] = '0';
+ }
+ }
+ return search(parts, _this);
+};
+
+/*!
+ * ignore
+ */
+
+Schema.prototype._getPathType = function(path) {
+ const _this = this;
+ const pathschema = _this.path(path);
+
+ if (pathschema) {
+ return 'real';
+ }
+
+ function search(parts, schema) {
+ let p = parts.length + 1,
+ foundschema,
+ trypath;
+
+ while (p--) {
+ trypath = parts.slice(0, p).join('.');
+ foundschema = schema.path(trypath);
+ if (foundschema) {
+ if (foundschema.caster) {
+ // array of Mixed?
+ if (foundschema.caster instanceof MongooseTypes.Mixed) {
+ return { schema: foundschema, pathType: 'mixed' };
+ }
+
+ // Now that we found the array, we need to check if there
+ // are remaining document paths to look up for casting.
+ // Also we need to handle array.$.path since schema.path
+ // doesn't work for that.
+ // If there is no foundschema.schema we are dealing with
+ // a path like array.$
+ if (p !== parts.length && foundschema.schema) {
+ if (parts[p] === '$' || isArrayFilter(parts[p])) {
+ if (p === parts.length - 1) {
+ return { schema: foundschema, pathType: 'nested' };
+ }
+ // comments.$.comments.$.title
+ return search(parts.slice(p + 1), foundschema.schema);
+ }
+ // this is the last path of the selector
+ return search(parts.slice(p), foundschema.schema);
+ }
+ return {
+ schema: foundschema,
+ pathType: foundschema.$isSingleNested ? 'nested' : 'array'
+ };
+ }
+ return { schema: foundschema, pathType: 'real' };
+ } else if (p === parts.length && schema.nested[trypath]) {
+ return { schema: schema, pathType: 'nested' };
+ }
+ }
+ return { schema: foundschema || schema, pathType: 'undefined' };
+ }
+
+ // look for arrays
+ return search(path.split('.'), _this);
+};
+
+/*!
+ * ignore
+ */
+
+function isArrayFilter(piece) {
+ return piece.startsWith('$[') && piece.endsWith(']');
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = Schema;
+
+// require down here because of reference issues
+
+/**
+ * The various built-in Mongoose Schema Types.
+ *
+ * ####Example:
+ *
+ * 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)
+ *
+ * Using this exposed access to the `Mixed` SchemaType, we can use them in our schema.
+ *
+ * const Mixed = mongoose.Schema.Types.Mixed;
+ * new mongoose.Schema({ _user: Mixed })
+ *
+ * @api public
+ */
+
+Schema.Types = MongooseTypes = require('./schema/index');
+
+/*!
+ * ignore
+ */
+
+exports.ObjectId = MongooseTypes.ObjectId;
diff --git a/node_modules/mongoose/lib/schema/SingleNestedPath.js b/node_modules/mongoose/lib/schema/SingleNestedPath.js
new file mode 100644
index 0000000..d0108ee
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/SingleNestedPath.js
@@ -0,0 +1,336 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CastError = require('../error/cast');
+const EventEmitter = require('events').EventEmitter;
+const ObjectExpectedError = require('../error/objectExpected');
+const SchemaSingleNestedOptions = require('../options/SchemaSingleNestedOptions');
+const SchemaType = require('../schematype');
+const $exists = require('./operators/exists');
+const castToNumber = require('./operators/helpers').castToNumber;
+const discriminator = require('../helpers/model/discriminator');
+const geospatial = require('./operators/geospatial');
+const get = require('../helpers/get');
+const getConstructor = require('../helpers/discriminator/getConstructor');
+const handleIdOption = require('../helpers/schema/handleIdOption');
+const internalToObjectOptions = require('../options').internalToObjectOptions;
+
+let Subdocument;
+
+module.exports = SingleNestedPath;
+
+/**
+ * Single nested subdocument SchemaType constructor.
+ *
+ * @param {Schema} schema
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SingleNestedPath(schema, path, options) {
+ schema = handleIdOption(schema, options);
+
+ this.caster = _createConstructor(schema);
+ this.caster.path = path;
+ this.caster.prototype.$basePath = path;
+ this.schema = schema;
+ this.$isSingleNested = true;
+ SchemaType.call(this, path, options, 'Embedded');
+}
+
+/*!
+ * ignore
+ */
+
+SingleNestedPath.prototype = Object.create(SchemaType.prototype);
+SingleNestedPath.prototype.constructor = SingleNestedPath;
+SingleNestedPath.prototype.OptionsConstructor = SchemaSingleNestedOptions;
+
+/*!
+ * ignore
+ */
+
+function _createConstructor(schema, baseClass) {
+ // lazy load
+ Subdocument || (Subdocument = require('../types/subdocument'));
+
+ const _embedded = function SingleNested(value, path, parent) {
+ const _this = this;
+
+ this.$parent = parent;
+ Subdocument.apply(this, arguments);
+
+ this.$session(this.ownerDocument().$session());
+
+ if (parent) {
+ parent.on('save', function() {
+ _this.emit('save', _this);
+ _this.constructor.emit('save', _this);
+ });
+
+ parent.on('isNew', function(val) {
+ _this.isNew = val;
+ _this.emit('isNew', val);
+ _this.constructor.emit('isNew', val);
+ });
+ }
+ };
+
+ const proto = baseClass != null ? baseClass.prototype : Subdocument.prototype;
+ _embedded.prototype = Object.create(proto);
+ _embedded.prototype.$__setSchema(schema);
+ _embedded.prototype.constructor = _embedded;
+ _embedded.schema = schema;
+ _embedded.$isSingleNested = true;
+ _embedded.events = new EventEmitter();
+ _embedded.prototype.toBSON = function() {
+ return this.toObject(internalToObjectOptions);
+ };
+
+ // apply methods
+ for (const i in schema.methods) {
+ _embedded.prototype[i] = schema.methods[i];
+ }
+
+ // apply statics
+ for (const i in schema.statics) {
+ _embedded[i] = schema.statics[i];
+ }
+
+ for (const i in EventEmitter.prototype) {
+ _embedded[i] = EventEmitter.prototype[i];
+ }
+
+ return _embedded;
+}
+
+/*!
+ * Special case for when users use a common location schema to represent
+ * locations for use with $geoWithin.
+ * https://docs.mongodb.org/manual/reference/operator/query/geoWithin/
+ *
+ * @param {Object} val
+ * @api private
+ */
+
+SingleNestedPath.prototype.$conditionalHandlers.$geoWithin = function handle$geoWithin(val) {
+ return { $geometry: this.castForQuery(val.$geometry) };
+};
+
+/*!
+ * ignore
+ */
+
+SingleNestedPath.prototype.$conditionalHandlers.$near =
+SingleNestedPath.prototype.$conditionalHandlers.$nearSphere = geospatial.cast$near;
+
+SingleNestedPath.prototype.$conditionalHandlers.$within =
+SingleNestedPath.prototype.$conditionalHandlers.$geoWithin = geospatial.cast$within;
+
+SingleNestedPath.prototype.$conditionalHandlers.$geoIntersects =
+ geospatial.cast$geoIntersects;
+
+SingleNestedPath.prototype.$conditionalHandlers.$minDistance = castToNumber;
+SingleNestedPath.prototype.$conditionalHandlers.$maxDistance = castToNumber;
+
+SingleNestedPath.prototype.$conditionalHandlers.$exists = $exists;
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @api private
+ */
+
+SingleNestedPath.prototype.cast = function(val, doc, init, priorVal) {
+ if (val && val.$isSingleNested && val.parent === doc) {
+ return val;
+ }
+
+ if (val != null && (typeof val !== 'object' || Array.isArray(val))) {
+ throw new ObjectExpectedError(this.path, val);
+ }
+
+ const Constructor = getConstructor(this.caster, val);
+
+ let subdoc;
+
+ // Only pull relevant selected paths and pull out the base path
+ const parentSelected = get(doc, '$__.selected', {});
+ const path = this.path;
+ const selected = Object.keys(parentSelected).reduce((obj, key) => {
+ if (key.startsWith(path + '.')) {
+ obj[key.substr(path.length + 1)] = parentSelected[key];
+ }
+ return obj;
+ }, {});
+
+ if (init) {
+ subdoc = new Constructor(void 0, selected, doc);
+ subdoc.init(val);
+ } else {
+ if (Object.keys(val).length === 0) {
+ return new Constructor({}, selected, doc, undefined, { priorDoc: priorVal });
+ }
+
+ return new Constructor(val, selected, doc, undefined, { priorDoc: priorVal });
+ }
+
+ return subdoc;
+};
+
+/**
+ * Casts contents for query
+ *
+ * @param {string} [$conditional] optional query operator (like `$eq` or `$in`)
+ * @param {any} value
+ * @api private
+ */
+
+SingleNestedPath.prototype.castForQuery = function($conditional, val, options) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional);
+ }
+ return handler.call(this, val);
+ }
+ val = $conditional;
+ if (val == null) {
+ return val;
+ }
+
+ if (this.options.runSetters) {
+ val = this._applySetters(val);
+ }
+
+ const Constructor = getConstructor(this.caster, val);
+ const overrideStrict = options != null && options.strict != null ?
+ options.strict :
+ void 0;
+
+ try {
+ val = new Constructor(val, overrideStrict);
+ } catch (error) {
+ // Make sure we always wrap in a CastError (gh-6803)
+ if (!(error instanceof CastError)) {
+ throw new CastError('Embedded', val, this.path, error, this);
+ }
+ throw error;
+ }
+ return val;
+};
+
+/**
+ * Async validation on this single nested doc.
+ *
+ * @api private
+ */
+
+SingleNestedPath.prototype.doValidate = function(value, fn, scope, options) {
+ const Constructor = getConstructor(this.caster, value);
+
+ if (options && options.skipSchemaValidators) {
+ if (!(value instanceof Constructor)) {
+ value = new Constructor(value, null, scope);
+ }
+ return value.validate(fn);
+ }
+
+ SchemaType.prototype.doValidate.call(this, value, function(error) {
+ if (error) {
+ return fn(error);
+ }
+ if (!value) {
+ return fn(null);
+ }
+
+ value.validate(fn);
+ }, scope, options);
+};
+
+/**
+ * Synchronously validate this single nested doc
+ *
+ * @api private
+ */
+
+SingleNestedPath.prototype.doValidateSync = function(value, scope, options) {
+ if (!options || !options.skipSchemaValidators) {
+ const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, value, scope);
+ if (schemaTypeError) {
+ return schemaTypeError;
+ }
+ }
+ if (!value) {
+ return;
+ }
+ return value.validateSync();
+};
+
+/**
+ * Adds a discriminator to this single nested subdocument.
+ *
+ * ####Example:
+ * const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
+ * const schema = Schema({ shape: shapeSchema });
+ *
+ * const singleNestedPath = parentSchema.path('shape');
+ * singleNestedPath.discriminator('Circle', Schema({ radius: Number }));
+ *
+ * @param {String} name
+ * @param {Schema} schema fields to add to the schema for instances of this sub-class
+ * @param {String} [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
+ * @return {Function} the constructor Mongoose will use for creating instances of this discriminator model
+ * @see discriminators /docs/discriminators.html
+ * @api public
+ */
+
+SingleNestedPath.prototype.discriminator = function(name, schema, value) {
+ schema = discriminator(this.caster, name, schema, value);
+
+ this.caster.discriminators[name] = _createConstructor(schema, this.caster);
+
+ 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
+ */
+
+SingleNestedPath.prototype.clone = function() {
+ const options = Object.assign({}, this.options);
+ const schematype = new this.constructor(this.schema, this.path, options);
+ schematype.validators = this.validators.slice();
+ if (this.requiredValidator !== undefined) {
+ schematype.requiredValidator = this.requiredValidator;
+ }
+ schematype.caster.discriminators = Object.assign({}, this.caster.discriminators);
+ return schematype;
+};
diff --git a/node_modules/mongoose/lib/schema/array.js b/node_modules/mongoose/lib/schema/array.js
new file mode 100644
index 0000000..828eb1b
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/array.js
@@ -0,0 +1,589 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const $exists = require('./operators/exists');
+const $type = require('./operators/type');
+const MongooseError = require('../error/mongooseError');
+const SchemaArrayOptions = require('../options/SchemaArrayOptions');
+const SchemaType = require('../schematype');
+const CastError = SchemaType.CastError;
+const Mixed = require('./mixed');
+const arrayDepth = require('../helpers/arrayDepth');
+const cast = require('../cast');
+const get = require('../helpers/get');
+const isOperator = require('../helpers/query/isOperator');
+const util = require('util');
+const utils = require('../utils');
+const castToNumber = require('./operators/helpers').castToNumber;
+const geospatial = require('./operators/geospatial');
+const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
+
+let MongooseArray;
+let EmbeddedDoc;
+
+const isNestedArraySymbol = Symbol('mongoose#isNestedArray');
+
+/**
+ * Array SchemaType constructor
+ *
+ * @param {String} key
+ * @param {SchemaType} cast
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaArray(key, cast, options, schemaOptions) {
+ // lazy load
+ EmbeddedDoc || (EmbeddedDoc = require('../types').Embedded);
+
+ let typeKey = 'type';
+ if (schemaOptions && schemaOptions.typeKey) {
+ typeKey = schemaOptions.typeKey;
+ }
+ this.schemaOptions = schemaOptions;
+
+ if (cast) {
+ let castOptions = {};
+
+ if (utils.isPOJO(cast)) {
+ if (cast[typeKey]) {
+ // support { type: Woot }
+ castOptions = utils.clone(cast); // do not alter user arguments
+ delete castOptions[typeKey];
+ cast = cast[typeKey];
+ } else {
+ cast = Mixed;
+ }
+ }
+
+ if (cast === Object) {
+ cast = Mixed;
+ }
+
+ // support { type: 'String' }
+ const name = typeof cast === 'string'
+ ? cast
+ : utils.getFunctionName(cast);
+
+ const Types = require('./index.js');
+ const caster = Types.hasOwnProperty(name) ? Types[name] : cast;
+
+ this.casterConstructor = caster;
+
+ if (this.casterConstructor instanceof SchemaArray) {
+ this.casterConstructor[isNestedArraySymbol] = true;
+ }
+
+ if (typeof caster === 'function' &&
+ !caster.$isArraySubdocument &&
+ !caster.$isSchemaMap) {
+ this.caster = new caster(null, castOptions);
+ } else {
+ this.caster = caster;
+ }
+
+ this.$embeddedSchemaType = this.caster;
+
+ if (!(this.caster instanceof EmbeddedDoc)) {
+ this.caster.path = key;
+ }
+ }
+
+ this.$isMongooseArray = true;
+
+ SchemaType.call(this, key, options, 'Array');
+
+ let defaultArr;
+ let fn;
+
+ if (this.defaultValue != null) {
+ defaultArr = this.defaultValue;
+ fn = typeof defaultArr === 'function';
+ }
+
+ if (!('defaultValue' in this) || this.defaultValue !== void 0) {
+ const defaultFn = function() {
+ let arr = [];
+ if (fn) {
+ arr = defaultArr.call(this);
+ } else if (defaultArr != null) {
+ arr = arr.concat(defaultArr);
+ }
+ // Leave it up to `cast()` to convert the array
+ return arr;
+ };
+ defaultFn.$runBeforeSetters = !fn;
+ this.default(defaultFn);
+ }
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaArray.schemaName = 'Array';
+
+
+/**
+ * Options for all arrays.
+ *
+ * - `castNonArrays`: `true` by default. If `false`, Mongoose will throw a CastError when a value isn't an array. If `true`, Mongoose will wrap the provided value in an array before casting.
+ *
+ * @static options
+ * @api public
+ */
+
+SchemaArray.options = { castNonArrays: true };
+
+SchemaArray.defaultOptions = {};
+
+/**
+ * Sets a default option for all Array instances.
+ *
+ * ####Example:
+ *
+ * // Make all Array instances have `required` of true by default.
+ * mongoose.Schema.Array.set('required', true);
+ *
+ * const User = mongoose.model('User', new Schema({ test: Array }));
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
+ *
+ * @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
+ */
+SchemaArray.set = SchemaType.set;
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaArray.prototype = Object.create(SchemaType.prototype);
+SchemaArray.prototype.constructor = SchemaArray;
+SchemaArray.prototype.OptionsConstructor = SchemaArrayOptions;
+
+/*!
+ * ignore
+ */
+
+SchemaArray._checkRequired = SchemaType.prototype.checkRequired;
+
+/**
+ * Override the function the required validator uses to check whether an array
+ * passes the `required` check.
+ *
+ * ####Example:
+ *
+ * // Require non-empty array to pass `required` check
+ * mongoose.Schema.Types.Array.checkRequired(v => Array.isArray(v) && v.length);
+ *
+ * const M = mongoose.model({ arr: { type: Array, required: true } });
+ * new M({ arr: [] }).validateSync(); // `null`, validation fails!
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaArray.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies the `required` validator.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaArray.prototype.checkRequired = function checkRequired(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ SchemaArray.checkRequired();
+
+ return _checkRequired(value);
+};
+
+/**
+ * Adds an enum validator if this is an array of strings or numbers. Equivalent to
+ * `SchemaString.prototype.enum()` or `SchemaNumber.prototype.enum()`
+ *
+ * @param {String|Object} [args...] enumeration values
+ * @return {SchemaArray} this
+ */
+
+SchemaArray.prototype.enum = function() {
+ let arr = this;
+ while (true) {
+ const instance = get(arr, 'caster.instance');
+ if (instance === 'Array') {
+ arr = arr.caster;
+ continue;
+ }
+ if (instance !== 'String' && instance !== 'Number') {
+ throw new Error('`enum` can only be set on an array of strings or numbers ' +
+ ', not ' + instance);
+ }
+ break;
+ }
+ arr.caster.enum.apply(arr.caster, arguments);
+ return this;
+};
+
+/**
+ * Overrides the getters application for the population special-case
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaArray.prototype.applyGetters = function(value, scope) {
+ if (this.caster.options && this.caster.options.ref) {
+ // means the object id was populated
+ return value;
+ }
+
+ return SchemaType.prototype.applyGetters.call(this, value, scope);
+};
+
+SchemaArray.prototype._applySetters = function(value, scope, init, priorVal) {
+ if (this.casterConstructor instanceof SchemaArray &&
+ 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.$isMongooseDocumentArray) {
+ ++depth;
+ arr = arr.casterConstructor;
+ }
+
+ // No need to wrap empty arrays
+ if (value != null && value.length > 0) {
+ const valueDepth = arrayDepth(value);
+ if (valueDepth.min === valueDepth.max && valueDepth.max < depth && valueDepth.containsNonArrayItem) {
+ for (let i = valueDepth.max; i < depth; ++i) {
+ value = [value];
+ }
+ }
+ }
+ }
+
+ return SchemaType.prototype._applySetters.call(this, value, scope, init, priorVal);
+};
+
+/**
+ * Casts values for set().
+ *
+ * @param {Object} value
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init whether this is an initialization cast
+ * @api private
+ */
+
+SchemaArray.prototype.cast = function(value, doc, init, prev, options) {
+ // lazy load
+ MongooseArray || (MongooseArray = require('../types').Array);
+
+ let i;
+ let l;
+
+ if (Array.isArray(value)) {
+ if (!value.length && doc) {
+ const indexes = doc.schema.indexedPaths();
+
+ const arrayPath = this.path;
+ for (i = 0, l = indexes.length; i < l; ++i) {
+ const pathIndex = indexes[i][0][arrayPath];
+ if (pathIndex === '2dsphere' || pathIndex === '2d') {
+ return;
+ }
+ }
+
+ // Special case: if this index is on the parent of what looks like
+ // GeoJSON, skip setting the default to empty array re: #1668, #3233
+ const arrayGeojsonPath = this.path.endsWith('.coordinates') ?
+ this.path.substr(0, this.path.lastIndexOf('.')) : null;
+ if (arrayGeojsonPath != null) {
+ for (i = 0, l = indexes.length; i < l; ++i) {
+ const pathIndex = indexes[i][0][arrayGeojsonPath];
+ if (pathIndex === '2dsphere') {
+ return;
+ }
+ }
+ }
+ }
+
+ if (!(value && value.isMongooseArray)) {
+ value = new MongooseArray(value, this._arrayPath || 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._arrayPath || this.path, doc);
+ }
+
+ const isPopulated = doc != null && doc.$__ != null && doc.populated(this.path);
+ if (isPopulated) {
+ return value;
+ }
+
+ if (this.caster && this.casterConstructor !== Mixed) {
+ try {
+ for (i = 0, l = value.length; i < l; i++) {
+ // Special case: number arrays disallow undefined.
+ // Re: gh-840
+ // See commit 1298fe92d2c790a90594bd08199e45a4a09162a6
+ if (this.caster.instance === 'Number' && 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;
+ }
+ value[i] = this.caster.cast(value[i], doc, init, void 0, opts);
+ }
+ } catch (e) {
+ // rethrow
+ throw new CastError('[' + e.kind + ']', util.inspect(value), this.path, e, this);
+ }
+ }
+
+ return value;
+ }
+
+ if (init || SchemaArray.options.castNonArrays) {
+ // gh-2442: if we're loading this from the db and its not an array, mark
+ // the whole array as modified.
+ if (!!doc && !!init) {
+ doc.markModified(this.path);
+ }
+ return this.cast([value], doc, init);
+ }
+
+ 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
+ while (arr.$isMongooseArray && !arr.$isMongooseDocumentArray) {
+ arr = arr.casterConstructor;
+ if (arr == null || typeof arr === 'function') {
+ throw new MongooseError('You can only add an embedded discriminator on ' +
+ 'a document array, ' + this.path + ' is a plain array');
+ }
+ }
+ return arr.discriminator(name, schema);
+};
+
+/*!
+ * ignore
+ */
+
+SchemaArray.prototype.clone = function() {
+ const options = Object.assign({}, this.options);
+ const schematype = new this.constructor(this.path, this.caster, options, this.schemaOptions);
+ schematype.validators = this.validators.slice();
+ if (this.requiredValidator !== undefined) {
+ schematype.requiredValidator = this.requiredValidator;
+ }
+ return schematype;
+};
+
+/**
+ * Casts values for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaArray.prototype.castForQuery = function($conditional, value) {
+ let handler;
+ let val;
+
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional + ' with Array.');
+ }
+
+ val = handler.call(this, value);
+ } else {
+ val = $conditional;
+ let Constructor = this.casterConstructor;
+
+ if (val &&
+ Constructor.discriminators &&
+ Constructor.schema &&
+ Constructor.schema.options &&
+ Constructor.schema.options.discriminatorKey) {
+ if (typeof val[Constructor.schema.options.discriminatorKey] === 'string' &&
+ 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]);
+ if (constructorByValue) {
+ Constructor = constructorByValue;
+ }
+ }
+ }
+
+ const proto = this.casterConstructor.prototype;
+ let method = proto && (proto.castForQuery || proto.cast);
+ if (!method && Constructor.castForQuery) {
+ method = Constructor.castForQuery;
+ }
+ const caster = this.caster;
+
+ if (Array.isArray(val)) {
+ this.setters.reverse().forEach(setter => {
+ val = setter.call(this, val, this);
+ });
+ val = val.map(function(v) {
+ if (utils.isObject(v) && v.$elemMatch) {
+ return v;
+ }
+ if (method) {
+ v = method.call(caster, v);
+ return v;
+ }
+ if (v != null) {
+ v = new Constructor(v);
+ return v;
+ }
+ return v;
+ });
+ } else if (method) {
+ val = method.call(caster, val);
+ } else if (val != null) {
+ val = new Constructor(val);
+ }
+ }
+
+ return val;
+};
+
+function cast$all(val) {
+ if (!Array.isArray(val)) {
+ val = [val];
+ }
+
+ val = val.map(function(v) {
+ if (utils.isObject(v)) {
+ const o = {};
+ o[this.path] = v;
+ return cast(this.casterConstructor.schema, o)[this.path];
+ }
+ return v;
+ }, this);
+
+ return this.castForQuery(val);
+}
+
+function cast$elemMatch(val) {
+ const keys = Object.keys(val);
+ const numKeys = keys.length;
+ for (let i = 0; i < numKeys; ++i) {
+ const key = keys[i];
+ const value = val[key];
+ if (isOperator(key) && value != null) {
+ val[key] = this.castForQuery(key, value);
+ }
+ }
+
+ // Is this an embedded discriminator and is the discriminator key set?
+ // If so, use the discriminator schema. See gh-7449
+ const discriminatorKey = get(this,
+ 'casterConstructor.schema.options.discriminatorKey');
+ const discriminators = get(this, 'casterConstructor.schema.discriminators', {});
+ if (discriminatorKey != null &&
+ val[discriminatorKey] != null &&
+ discriminators[val[discriminatorKey]] != null) {
+ return cast(discriminators[val[discriminatorKey]], val);
+ }
+
+ return cast(this.casterConstructor.schema, val);
+}
+
+const handle = SchemaArray.prototype.$conditionalHandlers = {};
+
+handle.$all = cast$all;
+handle.$options = String;
+handle.$elemMatch = cast$elemMatch;
+handle.$geoIntersects = geospatial.cast$geoIntersects;
+handle.$or = createLogicalQueryOperatorHandler('$or');
+handle.$and = createLogicalQueryOperatorHandler('$and');
+handle.$nor = createLogicalQueryOperatorHandler('$nor');
+
+function createLogicalQueryOperatorHandler(op) {
+ return function logicalQueryOperatorHandler(val) {
+ if (!Array.isArray(val)) {
+ throw new TypeError('conditional ' + op + ' requires an array');
+ }
+
+ const ret = [];
+ for (const obj of val) {
+ ret.push(cast(this.casterConstructor.schema, obj));
+ }
+
+ return ret;
+ };
+}
+
+handle.$near =
+handle.$nearSphere = geospatial.cast$near;
+
+handle.$within =
+handle.$geoWithin = geospatial.cast$within;
+
+handle.$size =
+handle.$minDistance =
+handle.$maxDistance = castToNumber;
+
+handle.$exists = $exists;
+handle.$type = $type;
+
+handle.$eq =
+handle.$gt =
+handle.$gte =
+handle.$lt =
+handle.$lte =
+handle.$ne =
+handle.$regex = SchemaArray.prototype.castForQuery;
+
+// `$in` is special because you can also include an empty array in the query
+// like `$in: [1, []]`, see gh-5913
+handle.$nin = SchemaType.prototype.$conditionalHandlers.$nin;
+handle.$in = SchemaType.prototype.$conditionalHandlers.$in;
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaArray;
diff --git a/node_modules/mongoose/lib/schema/boolean.js b/node_modules/mongoose/lib/schema/boolean.js
new file mode 100644
index 0000000..c264084
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/boolean.js
@@ -0,0 +1,258 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CastError = require('../error/cast');
+const SchemaType = require('../schematype');
+const castBoolean = require('../cast/boolean');
+const utils = require('../utils');
+
+/**
+ * Boolean SchemaType constructor.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaBoolean(path, options) {
+ SchemaType.call(this, path, options, 'Boolean');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaBoolean.schemaName = 'Boolean';
+
+SchemaBoolean.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaBoolean.prototype = Object.create(SchemaType.prototype);
+SchemaBoolean.prototype.constructor = SchemaBoolean;
+
+/*!
+ * ignore
+ */
+
+SchemaBoolean._cast = castBoolean;
+
+/**
+ * Sets a default option for all Boolean instances.
+ *
+ * ####Example:
+ *
+ * // Make all booleans have `default` of false.
+ * mongoose.Schema.Boolean.set('default', false);
+ *
+ * const Order = mongoose.model('Order', new Schema({ isPaid: Boolean }));
+ * new Order({ }).isPaid; // 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
+ */
+
+SchemaBoolean.set = SchemaType.set;
+
+/**
+ * Get/set the function used to cast arbitrary values to booleans.
+ *
+ * ####Example:
+ *
+ * // Make Mongoose cast empty string '' to false.
+ * const original = mongoose.Schema.Boolean.cast();
+ * mongoose.Schema.Boolean.cast(v => {
+ * if (v === '') {
+ * return false;
+ * }
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.Schema.Boolean.cast(false);
+ *
+ * @param {Function} caster
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaBoolean.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (v != null && typeof v !== 'boolean') {
+ throw new Error();
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/*!
+ * ignore
+ */
+
+SchemaBoolean._checkRequired = v => v === true || v === false;
+
+/**
+ * Override the function the required validator uses to check whether a boolean
+ * passes the `required` check.
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaBoolean.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator. For a boolean
+ * to satisfy a required validator, it must be strictly equal to true or to
+ * false.
+ *
+ * @param {Any} value
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaBoolean.prototype.checkRequired = function(value) {
+ return this.constructor._checkRequired(value);
+};
+
+/**
+ * Configure which values get casted to `true`.
+ *
+ * ####Example:
+ *
+ * const M = mongoose.model('Test', new Schema({ b: Boolean }));
+ * new M({ b: 'affirmative' }).b; // undefined
+ * mongoose.Schema.Boolean.convertToTrue.add('affirmative');
+ * new M({ b: 'affirmative' }).b; // true
+ *
+ * @property convertToTrue
+ * @type Set
+ * @api public
+ */
+
+Object.defineProperty(SchemaBoolean, 'convertToTrue', {
+ get: () => castBoolean.convertToTrue,
+ set: v => { castBoolean.convertToTrue = v; }
+});
+
+/**
+ * Configure which values get casted to `false`.
+ *
+ * ####Example:
+ *
+ * const M = mongoose.model('Test', new Schema({ b: Boolean }));
+ * new M({ b: 'nay' }).b; // undefined
+ * mongoose.Schema.Types.Boolean.convertToFalse.add('nay');
+ * new M({ b: 'nay' }).b; // false
+ *
+ * @property convertToFalse
+ * @type Set
+ * @api public
+ */
+
+Object.defineProperty(SchemaBoolean, 'convertToFalse', {
+ get: () => castBoolean.convertToFalse,
+ set: v => { castBoolean.convertToFalse = v; }
+});
+
+/**
+ * Casts to boolean
+ *
+ * @param {Object} value
+ * @param {Object} model - this value is optional
+ * @api private
+ */
+
+SchemaBoolean.prototype.cast = function(value) {
+ const castBoolean = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ SchemaBoolean.cast();
+ try {
+ return castBoolean(value);
+ } catch (error) {
+ throw new CastError('Boolean', value, this.path, error, this);
+ }
+};
+
+SchemaBoolean.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {});
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} val
+ * @api private
+ */
+
+SchemaBoolean.prototype.castForQuery = function($conditional, val) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = SchemaBoolean.$conditionalHandlers[$conditional];
+
+ if (handler) {
+ return handler.call(this, val);
+ }
+
+ return this._castForQuery(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.
+ */
+
+module.exports = SchemaBoolean;
diff --git a/node_modules/mongoose/lib/schema/buffer.js b/node_modules/mongoose/lib/schema/buffer.js
new file mode 100644
index 0000000..c5b8cb7
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/buffer.js
@@ -0,0 +1,276 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const MongooseBuffer = require('../types/buffer');
+const SchemaBufferOptions = require('../options/SchemaBufferOptions');
+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
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaBuffer(key, options) {
+ SchemaType.call(this, key, options, 'Buffer');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaBuffer.schemaName = 'Buffer';
+
+SchemaBuffer.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaBuffer.prototype = Object.create(SchemaType.prototype);
+SchemaBuffer.prototype.constructor = SchemaBuffer;
+SchemaBuffer.prototype.OptionsConstructor = SchemaBufferOptions;
+
+/*!
+ * ignore
+ */
+
+SchemaBuffer._checkRequired = v => !!(v && v.length);
+
+/**
+ * Sets a default option for all Buffer instances.
+ *
+ * ####Example:
+ *
+ * // Make all buffers have `required` of true by default.
+ * mongoose.Schema.Buffer.set('required', true);
+ *
+ * const User = mongoose.model('User', new Schema({ test: Buffer }));
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
+ *
+ * @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
+ */
+
+SchemaBuffer.set = SchemaType.set;
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * ####Example:
+ *
+ * // Allow empty strings to pass `required` check
+ * mongoose.Schema.Types.String.checkRequired(v => v != null);
+ *
+ * const M = mongoose.model({ buf: { type: Buffer, required: true } });
+ * new M({ buf: Buffer.from('') }).validateSync(); // validation passes!
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaBuffer.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator. To satisfy a
+ * required validator, a buffer must not be null or undefined and have
+ * non-zero length.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaBuffer.prototype.checkRequired = function(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+ return this.constructor._checkRequired(value);
+};
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaBuffer.prototype.cast = function(value, doc, init) {
+ let ret;
+ 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 (Buffer.isBuffer(value)) {
+ 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;
+ }
+
+ // documents
+ if (value && value._id) {
+ value = value._id;
+ }
+
+ if (value && value.isMongooseBuffer) {
+ return value;
+ }
+
+ 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;
+ }
+
+ 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;
+ }
+
+ if (value === null) {
+ return value;
+ }
+
+
+ const type = typeof value;
+ if (
+ type === 'string' || type === 'number' || Array.isArray(value) ||
+ (type === 'object' && value.type === 'Buffer' && Array.isArray(value.data)) // gh-6863
+ ) {
+ if (type === 'number') {
+ value = [value];
+ }
+ ret = new MongooseBuffer(value, [this.path, doc]);
+ if (this.options.subtype != null) {
+ ret._subtype = this.options.subtype;
+ }
+ return ret;
+ }
+
+ throw new CastError('Buffer', value, this.path, null, this);
+};
+
+/**
+ * Sets the default [subtype](https://studio3t.com/whats-new/best-practices-uuid-mongodb/)
+ * for this buffer. You can find a [list of allowed subtypes here](http://api.mongodb.com/python/current/api/bson/binary.html).
+ *
+ * ####Example:
+ *
+ * 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
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaBuffer.prototype.subtype = function(subtype) {
+ this.options.subtype = subtype;
+ return this;
+};
+
+/*!
+ * ignore
+ */
+function handleSingle(val) {
+ return this.castForQuery(val);
+}
+
+SchemaBuffer.prototype.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $bitsAllClear: handleBitwiseOperator,
+ $bitsAnyClear: handleBitwiseOperator,
+ $bitsAllSet: handleBitwiseOperator,
+ $bitsAnySet: handleBitwiseOperator,
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle
+ });
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaBuffer.prototype.castForQuery = function($conditional, val) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional + ' with Buffer.');
+ }
+ return handler.call(this, val);
+ }
+ val = $conditional;
+ const casted = this._castForQuery(val);
+ return casted ? casted.toObject({ transform: false, virtuals: false }) : casted;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaBuffer;
diff --git a/node_modules/mongoose/lib/schema/date.js b/node_modules/mongoose/lib/schema/date.js
new file mode 100644
index 0000000..4b9ad1c
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/date.js
@@ -0,0 +1,390 @@
+/*!
+ * Module requirements.
+ */
+
+'use strict';
+
+const MongooseError = require('../error/index');
+const SchemaDateOptions = require('../options/SchemaDateOptions');
+const SchemaType = require('../schematype');
+const castDate = require('../cast/date');
+const utils = require('../utils');
+
+const CastError = SchemaType.CastError;
+
+/**
+ * Date SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaDate(key, options) {
+ SchemaType.call(this, key, options, 'Date');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaDate.schemaName = 'Date';
+
+SchemaDate.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaDate.prototype = Object.create(SchemaType.prototype);
+SchemaDate.prototype.constructor = SchemaDate;
+SchemaDate.prototype.OptionsConstructor = SchemaDateOptions;
+
+/*!
+ * ignore
+ */
+
+SchemaDate._cast = castDate;
+
+/**
+ * Sets a default option for all Date instances.
+ *
+ * ####Example:
+ *
+ * // Make all dates have `required` of true by default.
+ * mongoose.Schema.Date.set('required', true);
+ *
+ * const User = mongoose.model('User', new Schema({ test: Date }));
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
+ *
+ * @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
+ */
+
+SchemaDate.set = SchemaType.set;
+
+/**
+ * Get/set the function used to cast arbitrary values to dates.
+ *
+ * ####Example:
+ *
+ * // Mongoose converts empty string '' into `null` for date types. You
+ * // can create a custom caster to disable it.
+ * const original = mongoose.Schema.Types.Date.cast();
+ * mongoose.Schema.Types.Date.cast(v => {
+ * assert.ok(v !== '');
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.Schema.Types.Date.cast(false);
+ *
+ * @param {Function} caster
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaDate.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (v != null && !(v instanceof Date)) {
+ throw new Error();
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/**
+ * Declares a TTL index (rounded to the nearest second) for _Date_ types only.
+ *
+ * This sets the `expireAfterSeconds` index option available in MongoDB >= 2.1.2.
+ * This index type is only compatible with Date types.
+ *
+ * ####Example:
+ *
+ * // expire in 24 hours
+ * new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
+ *
+ * `expires` utilizes the `ms` module from [guille](https://github.com/guille/) allowing us to use a friendlier syntax:
+ *
+ * ####Example:
+ *
+ * // expire in 24 hours
+ * new Schema({ createdAt: { type: Date, expires: '24h' }});
+ *
+ * // expire in 1.5 hours
+ * new Schema({ createdAt: { type: Date, expires: '1.5h' }});
+ *
+ * // expire in 7 days
+ * const schema = new Schema({ createdAt: Date });
+ * schema.path('createdAt').expires('7d');
+ *
+ * @param {Number|String} when
+ * @added 3.0.0
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaDate.prototype.expires = function(when) {
+ if (!this._index || this._index.constructor.name !== 'Object') {
+ this._index = {};
+ }
+
+ this._index.expires = when;
+ utils.expires(this._index);
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+SchemaDate._checkRequired = v => v instanceof Date;
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * ####Example:
+ *
+ * // Allow empty strings to pass `required` check
+ * mongoose.Schema.Types.String.checkRequired(v => v != null);
+ *
+ * const M = mongoose.model({ str: { type: String, required: true } });
+ * new M({ str: '' }).validateSync(); // `null`, validation passes!
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaDate.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator. To satisfy
+ * a required validator, the given value must be an instance of `Date`.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaDate.prototype.checkRequired = function(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ SchemaDate.checkRequired();
+ return _checkRequired(value);
+};
+
+/**
+ * Sets a minimum date validator.
+ *
+ * ####Example:
+ *
+ * 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');
+ * m.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MIN} token which will be replaced with the invalid value
+ * 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).
+ * })
+ *
+ * @param {Date} value minimum date
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaDate.prototype.min = function(value, message) {
+ if (this.minValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.minValidator;
+ }, this);
+ }
+
+ if (value) {
+ let msg = message || MongooseError.messages.Date.min;
+ if (typeof msg === 'string') {
+ msg = msg.replace(/{MIN}/, (value === Date.now ? 'Date.now()' : value.toString()));
+ }
+ const _this = this;
+ this.validators.push({
+ validator: this.minValidator = function(val) {
+ let _value = value;
+ if (typeof value === 'function' && value !== Date.now) {
+ _value = _value.call(this);
+ }
+ const min = (_value === Date.now ? _value() : _this.cast(_value));
+ return val === null || val.valueOf() >= min.valueOf();
+ },
+ message: msg,
+ type: 'min',
+ min: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Sets a maximum date validator.
+ *
+ * ####Example:
+ *
+ * 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');
+ * m.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MAX} token which will be replaced with the invalid value
+ * 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).
+ * })
+ *
+ * @param {Date} maximum date
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaDate.prototype.max = function(value, message) {
+ if (this.maxValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.maxValidator;
+ }, this);
+ }
+
+ if (value) {
+ let msg = message || MongooseError.messages.Date.max;
+ if (typeof msg === 'string') {
+ msg = msg.replace(/{MAX}/, (value === Date.now ? 'Date.now()' : value.toString()));
+ }
+ const _this = this;
+ this.validators.push({
+ validator: this.maxValidator = function(val) {
+ let _value = value;
+ if (typeof _value === 'function' && _value !== Date.now) {
+ _value = _value.call(this);
+ }
+ const max = (_value === Date.now ? _value() : _this.cast(_value));
+ return val === null || val.valueOf() <= max.valueOf();
+ },
+ message: msg,
+ type: 'max',
+ max: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Casts to date
+ *
+ * @param {Object} value to cast
+ * @api private
+ */
+
+SchemaDate.prototype.cast = function(value) {
+ const castDate = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ SchemaDate.cast();
+ try {
+ return castDate(value);
+ } catch (error) {
+ throw new CastError('date', value, this.path, error, this);
+ }
+};
+
+/*!
+ * Date Query casting.
+ *
+ * @api private
+ */
+
+function handleSingle(val) {
+ return this.cast(val);
+}
+
+SchemaDate.prototype.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle
+ });
+
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaDate.prototype.castForQuery = function($conditional, val) {
+ if (arguments.length !== 2) {
+ return this._castForQuery($conditional);
+ }
+
+ const handler = this.$conditionalHandlers[$conditional];
+
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional + ' with Date.');
+ }
+
+ return handler.call(this, val);
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaDate;
diff --git a/node_modules/mongoose/lib/schema/decimal128.js b/node_modules/mongoose/lib/schema/decimal128.js
new file mode 100644
index 0000000..ca9bcb4
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/decimal128.js
@@ -0,0 +1,235 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const SchemaType = require('../schematype');
+const CastError = SchemaType.CastError;
+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.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function Decimal128(key, options) {
+ SchemaType.call(this, key, options, 'Decimal128');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+Decimal128.schemaName = 'Decimal128';
+
+Decimal128.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+Decimal128.prototype = Object.create(SchemaType.prototype);
+Decimal128.prototype.constructor = Decimal128;
+
+/*!
+ * ignore
+ */
+
+Decimal128._cast = castDecimal128;
+
+/**
+ * Sets a default option for all Decimal128 instances.
+ *
+ * ####Example:
+ *
+ * // Make all decimal 128s have `required` of true by default.
+ * mongoose.Schema.Decimal128.set('required', true);
+ *
+ * const User = mongoose.model('User', new Schema({ test: mongoose.Decimal128 }));
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
+ *
+ * @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
+ */
+
+Decimal128.set = SchemaType.set;
+
+/**
+ * Get/set the function used to cast arbitrary values to decimals.
+ *
+ * ####Example:
+ *
+ * // Make Mongoose only refuse to cast numbers as decimal128
+ * const original = mongoose.Schema.Types.Decimal128.cast();
+ * mongoose.Decimal128.cast(v => {
+ * assert.ok(typeof v !== 'number');
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.Decimal128.cast(false);
+ *
+ * @param {Function} [caster]
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+Decimal128.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (v != null && !(v instanceof Decimal128Type)) {
+ throw new Error();
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/*!
+ * ignore
+ */
+
+Decimal128._checkRequired = v => v instanceof Decimal128Type;
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+Decimal128.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+Decimal128.prototype.checkRequired = function checkRequired(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ Decimal128.checkRequired();
+
+ return _checkRequired(value);
+};
+
+/**
+ * Casts to Decimal128
+ *
+ * @param {Object} value
+ * @param {Object} doc
+ * @param {Boolean} init whether this is an initialization cast
+ * @api private
+ */
+
+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;
+ }
+
+ const castDecimal128 = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ Decimal128.cast();
+ try {
+ return castDecimal128(value);
+ } catch (error) {
+ throw new CastError('Decimal128', value, this.path, error, this);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle(val) {
+ return this.cast(val);
+}
+
+Decimal128.prototype.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle
+ });
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Decimal128;
diff --git a/node_modules/mongoose/lib/schema/documentarray.js b/node_modules/mongoose/lib/schema/documentarray.js
new file mode 100644
index 0000000..ac88560
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/documentarray.js
@@ -0,0 +1,546 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const ArrayType = require('./array');
+const CastError = require('../error/cast');
+const EventEmitter = require('events').EventEmitter;
+const SchemaDocumentArrayOptions =
+ require('../options/SchemaDocumentArrayOptions');
+const SchemaType = require('../schematype');
+const ValidationError = require('../error/validation');
+const discriminator = require('../helpers/model/discriminator');
+const get = require('../helpers/get');
+const handleIdOption = require('../helpers/schema/handleIdOption');
+const util = require('util');
+const utils = require('../utils');
+const getConstructor = require('../helpers/discriminator/getConstructor');
+
+const arrayPathSymbol = require('../helpers/symbols').arrayPathSymbol;
+const documentArrayParent = require('../helpers/symbols').documentArrayParent;
+
+let MongooseDocumentArray;
+let Subdocument;
+
+/**
+ * SubdocsArray SchemaType constructor
+ *
+ * @param {String} key
+ * @param {Schema} schema
+ * @param {Object} options
+ * @inherits SchemaArray
+ * @api public
+ */
+
+function DocumentArrayPath(key, schema, options, schemaOptions) {
+ if (schemaOptions != null && schemaOptions._id != null) {
+ schema = handleIdOption(schema, schemaOptions);
+ } else if (options != null && options._id != null) {
+ schema = handleIdOption(schema, options);
+ }
+
+ const EmbeddedDocument = _createConstructor(schema, options);
+ EmbeddedDocument.prototype.$basePath = key;
+
+ ArrayType.call(this, key, EmbeddedDocument, options);
+
+ this.schema = schema;
+ this.schemaOptions = schemaOptions || {};
+ this.$isMongooseDocumentArray = true;
+ this.Constructor = EmbeddedDocument;
+
+ EmbeddedDocument.base = schema.base;
+
+ const fn = this.defaultValue;
+
+ if (!('defaultValue' in this) || fn !== void 0) {
+ this.default(function() {
+ let arr = fn.call(this);
+ if (!Array.isArray(arr)) {
+ arr = [arr];
+ }
+ // Leave it up to `cast()` to convert this to a documentarray
+ return arr;
+ });
+ }
+
+ const parentSchemaType = this;
+ this.$embeddedSchemaType = new SchemaType(key + '.$', {
+ required: get(this, 'schemaOptions.required', false)
+ });
+ this.$embeddedSchemaType.cast = function(value, doc, init) {
+ return parentSchemaType.cast(value, doc, init)[0];
+ };
+ this.$embeddedSchemaType.$isMongooseDocumentArrayElement = true;
+ this.$embeddedSchemaType.caster = this.Constructor;
+ this.$embeddedSchemaType.schema = this.schema;
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+DocumentArrayPath.schemaName = 'DocumentArray';
+
+/**
+ * Options for all document arrays.
+ *
+ * - `castNonArrays`: `true` by default. If `false`, Mongoose will throw a CastError when a value isn't an array. If `true`, Mongoose will wrap the provided value in an array before casting.
+ *
+ * @api public
+ */
+
+DocumentArrayPath.options = { castNonArrays: true };
+
+/*!
+ * Inherits from ArrayType.
+ */
+DocumentArrayPath.prototype = Object.create(ArrayType.prototype);
+DocumentArrayPath.prototype.constructor = DocumentArrayPath;
+DocumentArrayPath.prototype.OptionsConstructor = SchemaDocumentArrayOptions;
+
+/*!
+ * Ignore
+ */
+
+function _createConstructor(schema, options, baseClass) {
+ Subdocument || (Subdocument = require('../types/embedded'));
+
+ // compile an embedded document for this schema
+ function EmbeddedDocument() {
+ Subdocument.apply(this, arguments);
+
+ this.$session(this.ownerDocument().$session());
+ }
+
+ const proto = baseClass != null ? baseClass.prototype : Subdocument.prototype;
+ EmbeddedDocument.prototype = Object.create(proto);
+ EmbeddedDocument.prototype.$__setSchema(schema);
+ EmbeddedDocument.schema = schema;
+ EmbeddedDocument.prototype.constructor = EmbeddedDocument;
+ EmbeddedDocument.$isArraySubdocument = true;
+ EmbeddedDocument.events = new EventEmitter();
+
+ // apply methods
+ for (const i in schema.methods) {
+ EmbeddedDocument.prototype[i] = schema.methods[i];
+ }
+
+ // apply statics
+ for (const i in schema.statics) {
+ EmbeddedDocument[i] = schema.statics[i];
+ }
+
+ for (const i in EventEmitter.prototype) {
+ EmbeddedDocument[i] = EventEmitter.prototype[i];
+ }
+
+ EmbeddedDocument.options = options;
+
+ return EmbeddedDocument;
+}
+
+/**
+ * Adds a discriminator to this document array.
+ *
+ * ####Example:
+ * const shapeSchema = Schema({ name: String }, { discriminatorKey: 'kind' });
+ * const schema = Schema({ shapes: [shapeSchema] });
+ *
+ * const docArrayPath = parentSchema.path('shapes');
+ * docArrayPath.discriminator('Circle', Schema({ radius: Number }));
+ *
+ * @param {String} name
+ * @param {Schema} schema fields to add to the schema for instances of this sub-class
+ * @param {String} [value] the string stored in the `discriminatorKey` property. If not specified, Mongoose uses the `name` parameter.
+ * @see discriminators /docs/discriminators.html
+ * @return {Function} the constructor Mongoose will use for creating instances of this discriminator model
+ * @api public
+ */
+
+DocumentArrayPath.prototype.discriminator = function(name, schema, tiedValue) {
+ if (typeof name === 'function') {
+ name = utils.getFunctionName(name);
+ }
+
+ schema = discriminator(this.casterConstructor, name, schema, tiedValue);
+
+ const EmbeddedDocument = _createConstructor(schema, null, this.casterConstructor);
+ EmbeddedDocument.baseCasterConstructor = this.casterConstructor;
+
+ try {
+ Object.defineProperty(EmbeddedDocument, 'name', {
+ value: name
+ });
+ } catch (error) {
+ // Ignore error, only happens on old versions of node
+ }
+
+ this.casterConstructor.discriminators[name] = EmbeddedDocument;
+
+ return this.casterConstructor.discriminators[name];
+};
+
+/**
+ * Performs local validations first, then validations on each embedded doc
+ *
+ * @api private
+ */
+
+DocumentArrayPath.prototype.doValidate = function(array, fn, scope, options) {
+ // lazy load
+ MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray'));
+
+ const _this = this;
+ try {
+ SchemaType.prototype.doValidate.call(this, array, cb, scope);
+ } catch (err) {
+ err.$isArrayValidatorError = true;
+ return fn(err);
+ }
+
+ function cb(err) {
+ if (err) {
+ err.$isArrayValidatorError = true;
+ return fn(err);
+ }
+
+ let count = array && array.length;
+ let error;
+
+ if (!count) {
+ return fn();
+ }
+ if (options && options.updateValidator) {
+ return fn();
+ }
+ if (!array.isMongooseDocumentArray) {
+ array = new MongooseDocumentArray(array, _this.path, scope);
+ }
+
+ // handle sparse arrays, do not use array.forEach which does not
+ // iterate over sparse elements yet reports array.length including
+ // them :(
+
+ function callback(err) {
+ if (err != null) {
+ error = err;
+ if (!(error instanceof ValidationError)) {
+ error.$isArrayValidatorError = true;
+ }
+ }
+ --count || fn(error);
+ }
+
+ for (let i = 0, len = count; i < len; ++i) {
+ // sidestep sparse entries
+ let doc = array[i];
+ if (doc == null) {
+ --count || fn(error);
+ continue;
+ }
+
+ // If you set the array index directly, the doc might not yet be
+ // a full fledged mongoose subdoc, so make it into one.
+ if (!(doc instanceof Subdocument)) {
+ const Constructor = getConstructor(_this.casterConstructor, array[i]);
+ doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
+ }
+
+ doc.$__validate(callback);
+ }
+ }
+};
+
+/**
+ * Performs local validations first, then validations on each embedded doc.
+ *
+ * ####Note:
+ *
+ * This method ignores the asynchronous validators.
+ *
+ * @return {MongooseError|undefined}
+ * @api private
+ */
+
+DocumentArrayPath.prototype.doValidateSync = function(array, scope) {
+ const schemaTypeError = SchemaType.prototype.doValidateSync.call(this, array, scope);
+ if (schemaTypeError != null) {
+ schemaTypeError.$isArrayValidatorError = true;
+ return schemaTypeError;
+ }
+
+ const count = array && array.length;
+ let resultError = null;
+
+ if (!count) {
+ return;
+ }
+
+ // handle sparse arrays, do not use array.forEach which does not
+ // iterate over sparse elements yet reports array.length including
+ // them :(
+
+ for (let i = 0, len = count; i < len; ++i) {
+ // sidestep sparse entries
+ let doc = array[i];
+ if (!doc) {
+ continue;
+ }
+
+ // If you set the array index directly, the doc might not yet be
+ // a full fledged mongoose subdoc, so make it into one.
+ if (!(doc instanceof Subdocument)) {
+ const Constructor = getConstructor(this.casterConstructor, array[i]);
+ doc = array[i] = new Constructor(doc, array, undefined, undefined, i);
+ }
+
+ const subdocValidateError = doc.validateSync();
+
+ if (subdocValidateError && resultError == null) {
+ resultError = subdocValidateError;
+ }
+ }
+
+ return resultError;
+};
+
+/*!
+ * ignore
+ */
+
+DocumentArrayPath.prototype.getDefault = function(scope) {
+ let ret = typeof this.defaultValue === 'function'
+ ? this.defaultValue.call(scope)
+ : this.defaultValue;
+
+ if (ret == null) {
+ return ret;
+ }
+
+ // lazy load
+ MongooseDocumentArray || (MongooseDocumentArray = require('../types/documentarray'));
+
+ if (!Array.isArray(ret)) {
+ ret = [ret];
+ }
+
+ ret = new MongooseDocumentArray(ret, this.path, scope);
+
+ for (let i = 0; i < ret.length; ++i) {
+ const Constructor = getConstructor(this.casterConstructor, ret[i]);
+ const _subdoc = new Constructor({}, ret, undefined,
+ undefined, i);
+ _subdoc.init(ret[i]);
+ _subdoc.isNew = true;
+
+ // Make sure all paths in the subdoc are set to `default` instead
+ // of `init` since we used `init`.
+ Object.assign(_subdoc.$__.activePaths.default, _subdoc.$__.activePaths.init);
+ _subdoc.$__.activePaths.init = {};
+
+ ret[i] = _subdoc;
+ }
+
+ return ret;
+};
+
+/**
+ * Casts contents
+ *
+ * @param {Object} value
+ * @param {Document} document that triggers the casting
+ * @api private
+ */
+
+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 };
+ options = options || {};
+
+ if (!Array.isArray(value)) {
+ if (!init && !DocumentArrayPath.options.castNonArrays) {
+ throw new CastError('DocumentArray', util.inspect(value), this.path, null, this);
+ }
+ // gh-2442 mark whole array as modified if we're initializing a doc from
+ // the db and the path isn't an array in the document
+ if (!!doc && init) {
+ doc.markModified(this.path);
+ }
+ return this.cast([value], doc, init, prev, options);
+ }
+
+ if (!(value && value.isMongooseDocumentArray) &&
+ !options.skipDocumentArrayCast) {
+ value = new MongooseDocumentArray(value, this.path, doc);
+ } else if (value && value.isMongooseDocumentArray) {
+ // We need to create a new array, otherwise change tracking will
+ // update the old doc (gh-4449)
+ value = new MongooseDocumentArray(value, this.path, doc);
+ }
+
+ if (options.arrayPath != null) {
+ value[arrayPathSymbol] = options.arrayPath;
+ }
+
+ const len = value.length;
+ const initDocumentOptions = { skipId: true, willInit: true };
+
+ for (let i = 0; i < len; ++i) {
+ if (!value[i]) {
+ continue;
+ }
+
+ const Constructor = getConstructor(this.casterConstructor, value[i]);
+
+ // Check if the document has a different schema (re gh-3701)
+ if ((value[i].$__) &&
+ (!(value[i] instanceof Constructor) || value[i][documentArrayParent] !== doc)) {
+ value[i] = value[i].toObject({
+ transform: false,
+ // Special case: if different model, but same schema, apply virtuals
+ // re: gh-7898
+ virtuals: value[i].schema === Constructor.schema
+ });
+ }
+
+ if (value[i] instanceof Subdocument) {
+ // Might not have the correct index yet, so ensure it does.
+ if (value[i].__index == null) {
+ value[i].$setIndex(i);
+ }
+ } else if (value[i] != null) {
+ if (init) {
+ if (doc) {
+ selected || (selected = scopePaths(this, doc.$__.selected, init));
+ } else {
+ selected = true;
+ }
+
+ subdoc = new Constructor(null, value, initDocumentOptions, selected, i);
+ value[i] = subdoc.init(value[i]);
+ } else {
+ if (prev && typeof prev.id === 'function') {
+ subdoc = prev.id(value[i]._id);
+ }
+
+ if (prev && subdoc && utils.deepEqual(subdoc.toObject(_opts), value[i])) {
+ // handle resetting doc with existing id and same data
+ subdoc.set(value[i]);
+ // if set() is hooked it will have no return value
+ // see gh-746
+ value[i] = subdoc;
+ } else {
+ try {
+ subdoc = new Constructor(value[i], value, undefined,
+ undefined, i);
+ // if set() is hooked it will have no return value
+ // see gh-746
+ value[i] = subdoc;
+ } catch (error) {
+ const valueInErrorMessage = util.inspect(value[i]);
+ throw new CastError('embedded', valueInErrorMessage,
+ value[arrayPathSymbol], error, this);
+ }
+ }
+ }
+ }
+ }
+
+ return value;
+};
+
+/*!
+ * ignore
+ */
+
+DocumentArrayPath.prototype.clone = function() {
+ const options = Object.assign({}, this.options);
+ const schematype = new this.constructor(this.path, this.schema, options, this.schemaOptions);
+ schematype.validators = this.validators.slice();
+ if (this.requiredValidator !== undefined) {
+ schematype.requiredValidator = this.requiredValidator;
+ }
+ schematype.Constructor.discriminators = Object.assign({},
+ this.Constructor.discriminators);
+ return schematype;
+};
+
+/*!
+ * Scopes paths selected in a query to this array.
+ * Necessary for proper default application of subdocument values.
+ *
+ * @param {DocumentArrayPath} array - the array to scope `fields` paths
+ * @param {Object|undefined} fields - the root fields selected in the query
+ * @param {Boolean|undefined} init - if we are being created part of a query result
+ */
+
+function scopePaths(array, fields, init) {
+ if (!(init && fields)) {
+ return undefined;
+ }
+
+ const path = array.path + '.';
+ const keys = Object.keys(fields);
+ let i = keys.length;
+ const selected = {};
+ let hasKeys;
+ let key;
+ let sub;
+
+ while (i--) {
+ key = keys[i];
+ if (key.startsWith(path)) {
+ sub = key.substring(path.length);
+ if (sub === '$') {
+ continue;
+ }
+ if (sub.startsWith('$.')) {
+ sub = sub.substr(2);
+ }
+ hasKeys || (hasKeys = true);
+ selected[sub] = fields[key];
+ }
+ }
+
+ 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.
+ */
+
+module.exports = DocumentArrayPath;
diff --git a/node_modules/mongoose/lib/schema/index.js b/node_modules/mongoose/lib/schema/index.js
new file mode 100644
index 0000000..f33b084
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/index.js
@@ -0,0 +1,37 @@
+
+/*!
+ * Module exports.
+ */
+
+'use strict';
+
+exports.String = require('./string');
+
+exports.Number = require('./number');
+
+exports.Boolean = require('./boolean');
+
+exports.DocumentArray = require('./documentarray');
+
+exports.Embedded = require('./SingleNestedPath');
+
+exports.Array = require('./array');
+
+exports.Buffer = require('./buffer');
+
+exports.Date = require('./date');
+
+exports.ObjectId = require('./objectid');
+
+exports.Mixed = require('./mixed');
+
+exports.Decimal128 = exports.Decimal = require('./decimal128');
+
+exports.Map = require('./map');
+
+// alias
+
+exports.Oid = exports.ObjectId;
+exports.Object = exports.Mixed;
+exports.Bool = exports.Boolean;
+exports.ObjectID = exports.ObjectId;
diff --git a/node_modules/mongoose/lib/schema/map.js b/node_modules/mongoose/lib/schema/map.js
new file mode 100644
index 0000000..468faea
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/map.js
@@ -0,0 +1,62 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+const MongooseMap = require('../types/map');
+const SchemaMapOptions = require('../options/SchemaMapOptions');
+const SchemaType = require('../schematype');
+/*!
+ * ignore
+ */
+
+class Map extends SchemaType {
+ constructor(key, options) {
+ super(key, options, 'Map');
+ this.$isSchemaMap = true;
+ }
+
+ set(option, value) {
+ return SchemaType.set(option, value);
+ }
+
+ cast(val, doc, init) {
+ if (val instanceof MongooseMap) {
+ return val;
+ }
+
+ if (init) {
+ const map = new MongooseMap({}, this.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));
+ }
+ } else {
+ for (const key of Object.keys(val)) {
+ map.$init(key, map.$__schemaType.cast(val[key], doc, true));
+ }
+ }
+
+ return map;
+ }
+
+ return new MongooseMap(val, this.path, doc, this.$__schemaType);
+ }
+
+ clone() {
+ const schematype = super.clone();
+
+ if (this.$__schemaType != null) {
+ schematype.$__schemaType = this.$__schemaType.clone();
+ }
+ return schematype;
+ }
+}
+
+Map.prototype.OptionsConstructor = SchemaMapOptions;
+
+Map.defaultOptions = {};
+
+module.exports = Map;
diff --git a/node_modules/mongoose/lib/schema/mixed.js b/node_modules/mongoose/lib/schema/mixed.js
new file mode 100644
index 0000000..88e4db6
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/mixed.js
@@ -0,0 +1,128 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const SchemaType = require('../schematype');
+const symbols = require('./symbols');
+const isObject = require('../helpers/isObject');
+
+/**
+ * Mixed SchemaType constructor.
+ *
+ * @param {String} path
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function Mixed(path, options) {
+ if (options && options.default) {
+ const def = options.default;
+ if (Array.isArray(def) && def.length === 0) {
+ // make sure empty array defaults are handled
+ options.default = Array;
+ } else if (!options.shared && isObject(def) && Object.keys(def).length === 0) {
+ // prevent odd "shared" objects between documents
+ options.default = function() {
+ return {};
+ };
+ }
+ }
+
+ SchemaType.call(this, path, options, 'Mixed');
+
+ this[symbols.schemaMixedSymbol] = true;
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+Mixed.schemaName = 'Mixed';
+
+Mixed.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+Mixed.prototype = Object.create(SchemaType.prototype);
+Mixed.prototype.constructor = Mixed;
+
+/**
+ * Attaches a getter for all Mixed paths.
+ *
+ * ####Example:
+ *
+ * // Hide the 'hidden' path
+ * mongoose.Schema.Mixed.get(v => Object.assign({}, v, { hidden: null }));
+ *
+ * const Model = mongoose.model('Test', new Schema({ test: {} }));
+ * new Model({ test: { hidden: 'Secret!' } }).test.hidden; // null
+ *
+ * @param {Function} getter
+ * @return {this}
+ * @function get
+ * @static
+ * @api public
+ */
+
+Mixed.get = SchemaType.get;
+
+/**
+ * Sets a default option for all Mixed instances.
+ *
+ * ####Example:
+ *
+ * // Make all mixed instances have `required` of true by default.
+ * mongoose.Schema.Mixed.set('required', true);
+ *
+ * const User = mongoose.model('User', new Schema({ test: mongoose.Mixed }));
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
+ *
+ * @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
+ */
+
+Mixed.set = SchemaType.set;
+
+/**
+ * Casts `val` for Mixed.
+ *
+ * _this is a no-op_
+ *
+ * @param {Object} value to cast
+ * @api private
+ */
+
+Mixed.prototype.cast = function(val) {
+ return val;
+};
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $cond
+ * @param {any} [val]
+ * @api private
+ */
+
+Mixed.prototype.castForQuery = function($cond, val) {
+ if (arguments.length === 2) {
+ return val;
+ }
+ return $cond;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = Mixed;
diff --git a/node_modules/mongoose/lib/schema/number.js b/node_modules/mongoose/lib/schema/number.js
new file mode 100644
index 0000000..719a1aa
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/number.js
@@ -0,0 +1,444 @@
+'use strict';
+
+/*!
+ * Module requirements.
+ */
+
+const MongooseError = require('../error/index');
+const SchemaNumberOptions = require('../options/SchemaNumberOptions');
+const SchemaType = require('../schematype');
+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.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaNumber(key, options) {
+ SchemaType.call(this, key, options, 'Number');
+}
+
+/**
+ * Attaches a getter for all Number instances.
+ *
+ * ####Example:
+ *
+ * // Make all numbers round down
+ * mongoose.Number.get(function(v) { return Math.floor(v); });
+ *
+ * const Model = mongoose.model('Test', new Schema({ test: Number }));
+ * new Model({ test: 3.14 }).test; // 3
+ *
+ * @param {Function} getter
+ * @return {this}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaNumber.get = SchemaType.get;
+
+/**
+ * Sets a default option for all Number instances.
+ *
+ * ####Example:
+ *
+ * // Make all numbers have option `min` equal to 0.
+ * mongoose.Schema.Number.set('min', 0);
+ *
+ * const Order = mongoose.model('Order', new Schema({ amount: Number }));
+ * new Order({ amount: -10 }).validateSync().errors.amount.message; // Path `amount` must be larger than 0.
+ *
+ * @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
+ */
+
+SchemaNumber.set = SchemaType.set;
+
+/*!
+ * ignore
+ */
+
+SchemaNumber._cast = castNumber;
+
+/**
+ * Get/set the function used to cast arbitrary values to numbers.
+ *
+ * ####Example:
+ *
+ * // Make Mongoose cast empty strings '' to 0 for paths declared as numbers
+ * const original = mongoose.Number.cast();
+ * mongoose.Number.cast(v => {
+ * if (v === '') { return 0; }
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.Number.cast(false);
+ *
+ * @param {Function} caster
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaNumber.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (typeof v !== 'number') {
+ throw new Error();
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaNumber.schemaName = 'Number';
+
+SchemaNumber.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaNumber.prototype = Object.create(SchemaType.prototype);
+SchemaNumber.prototype.constructor = SchemaNumber;
+SchemaNumber.prototype.OptionsConstructor = SchemaNumberOptions;
+
+/*!
+ * ignore
+ */
+
+SchemaNumber._checkRequired = v => typeof v === 'number' || v instanceof Number;
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaNumber.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaNumber.prototype.checkRequired = function checkRequired(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ SchemaNumber.checkRequired();
+
+ return _checkRequired(value);
+};
+
+/**
+ * Sets a minimum number validator.
+ *
+ * ####Example:
+ *
+ * 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;
+ * m.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MIN} token which will be replaced with the invalid value
+ * 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).
+ * })
+ *
+ * @param {Number} value minimum number
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaNumber.prototype.min = function(value, message) {
+ if (this.minValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.minValidator;
+ }, this);
+ }
+
+ if (value !== null && value !== undefined) {
+ let msg = message || MongooseError.messages.Number.min;
+ msg = msg.replace(/{MIN}/, value);
+ this.validators.push({
+ validator: this.minValidator = function(v) {
+ return v == null || v >= value;
+ },
+ message: msg,
+ type: 'min',
+ min: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Sets a maximum number validator.
+ *
+ * ####Example:
+ *
+ * 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;
+ * m.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MAX} token which will be replaced with the invalid value
+ * 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).
+ * })
+ *
+ * @param {Number} maximum number
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaNumber.prototype.max = function(value, message) {
+ if (this.maxValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.maxValidator;
+ }, this);
+ }
+
+ if (value !== null && value !== undefined) {
+ let msg = message || MongooseError.messages.Number.max;
+ msg = msg.replace(/{MAX}/, value);
+ this.validators.push({
+ validator: this.maxValidator = function(v) {
+ return v == null || v <= value;
+ },
+ message: msg,
+ type: 'max',
+ max: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Sets a enum validator
+ *
+ * ####Example:
+ *
+ * const s = new Schema({ n: { type: Number, enum: [1, 2, 3] });
+ * const M = db.model('M', s);
+ *
+ * const m = new M({ n: 4 });
+ * await m.save(); // throws validation error
+ *
+ * m.n = 3;
+ * await m.save(); // succeeds
+ *
+ * @param {Array} values allowed values
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaNumber.prototype.enum = function(values, message) {
+ if (this.enumValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.enumValidator;
+ }, this);
+ }
+
+ if (!Array.isArray(values)) {
+ values = Array.prototype.slice.call(arguments);
+ message = MongooseError.messages.Number.enum;
+ }
+
+ message = message == null ? MongooseError.messages.Number.enum : message;
+
+ this.enumValidator = v => v == null || values.indexOf(v) !== -1;
+ this.validators.push({
+ validator: this.enumValidator,
+ message: message,
+ type: 'enum',
+ enumValues: values
+ });
+
+ return this;
+};
+
+/**
+ * Casts to number
+ *
+ * @param {Object} value value to cast
+ * @param {Document} doc document that triggers the casting
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaNumber.prototype.cast = function(value, doc, init) {
+ if (SchemaType._isRef(this, value, doc, init)) {
+ // wait! we may need to cast this to a document
+
+ if (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;
+ }
+
+ const val = value && typeof value._id !== 'undefined' ?
+ value._id : // documents
+ value;
+
+ const castNumber = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ SchemaNumber.cast();
+ try {
+ return castNumber(val);
+ } catch (err) {
+ throw new CastError('Number', val, this.path, err, this);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle(val) {
+ return this.cast(val);
+}
+
+function handleArray(val) {
+ const _this = this;
+ if (!Array.isArray(val)) {
+ return [this.cast(val)];
+ }
+ return val.map(function(m) {
+ return _this.cast(m);
+ });
+}
+
+SchemaNumber.prototype.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $bitsAllClear: handleBitwiseOperator,
+ $bitsAnyClear: handleBitwiseOperator,
+ $bitsAllSet: handleBitwiseOperator,
+ $bitsAnySet: handleBitwiseOperator,
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle,
+ $mod: handleArray
+ });
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [value]
+ * @api private
+ */
+
+SchemaNumber.prototype.castForQuery = function($conditional, val) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler) {
+ throw new CastError('number', val, this.path, null, this);
+ }
+ return handler.call(this, val);
+ }
+ val = this._castForQuery($conditional);
+ return val;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaNumber;
diff --git a/node_modules/mongoose/lib/schema/objectid.js b/node_modules/mongoose/lib/schema/objectid.js
new file mode 100644
index 0000000..ee27f2e
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/objectid.js
@@ -0,0 +1,319 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const SchemaObjectIdOptions = require('../options/SchemaObjectIdOptions');
+const SchemaType = require('../schematype');
+const castObjectId = require('../cast/objectid');
+const oid = require('../types/objectid');
+const utils = require('../utils');
+
+const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
+
+const CastError = SchemaType.CastError;
+let Document;
+
+/**
+ * ObjectId SchemaType constructor.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function ObjectId(key, options) {
+ const isKeyHexStr = typeof key === 'string' && key.length === 24 && /^[a-f0-9]+$/i.test(key);
+ const suppressWarning = options && options.suppressWarning;
+ if ((isKeyHexStr || typeof key === 'undefined') && !suppressWarning) {
+ console.warn('mongoose: To create a new ObjectId please try ' +
+ '`Mongoose.Types.ObjectId` instead of using ' +
+ '`Mongoose.Schema.ObjectId`. Set the `suppressWarning` option if ' +
+ 'you\'re trying to create a hex char path in your schema.');
+ console.trace();
+ }
+ SchemaType.call(this, key, options, 'ObjectID');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+ObjectId.schemaName = 'ObjectId';
+
+ObjectId.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+ObjectId.prototype = Object.create(SchemaType.prototype);
+ObjectId.prototype.constructor = ObjectId;
+ObjectId.prototype.OptionsConstructor = SchemaObjectIdOptions;
+
+/**
+ * Attaches a getter for all ObjectId instances
+ *
+ * ####Example:
+ *
+ * // Always convert to string when getting an ObjectId
+ * mongoose.ObjectId.get(v => v.toString());
+ *
+ * const Model = mongoose.model('Test', new Schema({}));
+ * typeof (new Model({})._id); // 'string'
+ *
+ * @param {Function} getter
+ * @return {this}
+ * @function get
+ * @static
+ * @api public
+ */
+
+ObjectId.get = SchemaType.get;
+
+/**
+ * Sets a default option for all ObjectId instances.
+ *
+ * ####Example:
+ *
+ * // Make all object ids have option `required` equal to true.
+ * mongoose.Schema.ObjectId.set('required', true);
+ *
+ * const Order = mongoose.model('Order', new Schema({ userId: ObjectId }));
+ * new Order({ }).validateSync().errors.userId.message; // Path `userId` is required.
+ *
+ * @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
+ */
+
+ObjectId.set = SchemaType.set;
+
+/**
+ * Adds an auto-generated ObjectId default if turnOn is true.
+ * @param {Boolean} turnOn auto generated ObjectId defaults
+ * @api public
+ * @return {SchemaType} this
+ */
+
+ObjectId.prototype.auto = function(turnOn) {
+ if (turnOn) {
+ this.default(defaultId);
+ this.set(resetId);
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+ObjectId._checkRequired = v => v instanceof oid;
+
+/*!
+ * ignore
+ */
+
+ObjectId._cast = castObjectId;
+
+/**
+ * Get/set the function used to cast arbitrary values to objectids.
+ *
+ * ####Example:
+ *
+ * // Make Mongoose only try to cast length 24 strings. By default, any 12
+ * // char string is a valid ObjectId.
+ * const original = mongoose.ObjectId.cast();
+ * mongoose.ObjectId.cast(v => {
+ * assert.ok(typeof v !== 'string' || v.length === 24);
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.ObjectId.cast(false);
+ *
+ * @param {Function} caster
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+ObjectId.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (!(v instanceof oid)) {
+ throw new Error(v + ' is not an instance of ObjectId');
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * ####Example:
+ *
+ * // Allow empty strings to pass `required` check
+ * mongoose.Schema.Types.String.checkRequired(v => v != null);
+ *
+ * const M = mongoose.model({ str: { type: String, required: true } });
+ * new M({ str: '' }).validateSync(); // `null`, validation passes!
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+ObjectId.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Check if the given value satisfies a required validator.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+ObjectId.prototype.checkRequired = function checkRequired(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ ObjectId.checkRequired();
+
+ return _checkRequired(value);
+};
+
+/**
+ * Casts to ObjectId
+ *
+ * @param {Object} value
+ * @param {Object} doc
+ * @param {Boolean} init whether this is an initialization cast
+ * @api private
+ */
+
+ObjectId.prototype.cast = function(value, doc, init) {
+ if (SchemaType._isRef(this, value, doc, init)) {
+ // wait! we may need to cast this to a document
+
+ if (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') {
+ 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;
+ }
+
+ const castObjectId = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ ObjectId.cast();
+ try {
+ return castObjectId(value);
+ } catch (error) {
+ throw new CastError('ObjectId', value, this.path, error, this);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle(val) {
+ return this.cast(val);
+}
+
+ObjectId.prototype.$conditionalHandlers =
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle
+ });
+
+/*!
+ * ignore
+ */
+
+function defaultId() {
+ return new oid();
+}
+
+defaultId.$runBeforeSetters = true;
+
+function resetId(v) {
+ Document || (Document = require('./../document'));
+
+ if (this instanceof Document) {
+ if (v === void 0) {
+ const _v = new oid;
+ this.$__._id = _v;
+ return _v;
+ }
+
+ this.$__._id = v;
+ }
+
+ return v;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = ObjectId;
diff --git a/node_modules/mongoose/lib/schema/operators/bitwise.js b/node_modules/mongoose/lib/schema/operators/bitwise.js
new file mode 100644
index 0000000..07e18cd
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/bitwise.js
@@ -0,0 +1,38 @@
+/*!
+ * Module requirements.
+ */
+
+'use strict';
+
+const CastError = require('../../error/cast');
+
+/*!
+ * ignore
+ */
+
+function handleBitwiseOperator(val) {
+ const _this = this;
+ if (Array.isArray(val)) {
+ return val.map(function(v) {
+ return _castNumber(_this.path, v);
+ });
+ } else if (Buffer.isBuffer(val)) {
+ return val;
+ }
+ // Assume trying to cast to number
+ return _castNumber(_this.path, val);
+}
+
+/*!
+ * ignore
+ */
+
+function _castNumber(path, num) {
+ const v = Number(num);
+ if (isNaN(v)) {
+ throw new CastError('number', num, path);
+ }
+ return v;
+}
+
+module.exports = handleBitwiseOperator;
diff --git a/node_modules/mongoose/lib/schema/operators/exists.js b/node_modules/mongoose/lib/schema/operators/exists.js
new file mode 100644
index 0000000..916b4cb
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/exists.js
@@ -0,0 +1,12 @@
+'use strict';
+
+const castBoolean = require('../../cast/boolean');
+
+/*!
+ * ignore
+ */
+
+module.exports = function(val) {
+ const path = this != null ? this.path : null;
+ return castBoolean(val, path);
+};
diff --git a/node_modules/mongoose/lib/schema/operators/geospatial.js b/node_modules/mongoose/lib/schema/operators/geospatial.js
new file mode 100644
index 0000000..80a6052
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/geospatial.js
@@ -0,0 +1,107 @@
+/*!
+ * Module requirements.
+ */
+
+'use strict';
+
+const castArraysOfNumbers = require('./helpers').castArraysOfNumbers;
+const castToNumber = require('./helpers').castToNumber;
+
+/*!
+ * ignore
+ */
+
+exports.cast$geoIntersects = cast$geoIntersects;
+exports.cast$near = cast$near;
+exports.cast$within = cast$within;
+
+function cast$near(val) {
+ const SchemaArray = require('../array');
+
+ if (Array.isArray(val)) {
+ castArraysOfNumbers(val, this);
+ return val;
+ }
+
+ _castMinMaxDistance(this, val);
+
+ if (val && val.$geometry) {
+ return cast$geometry(val, this);
+ }
+
+ if (!Array.isArray(val)) {
+ throw new TypeError('$near must be either an array or an object ' +
+ 'with a $geometry property');
+ }
+
+ return SchemaArray.prototype.castForQuery.call(this, val);
+}
+
+function cast$geometry(val, self) {
+ switch (val.$geometry.type) {
+ case 'Polygon':
+ case 'LineString':
+ case 'Point':
+ castArraysOfNumbers(val.$geometry.coordinates, self);
+ break;
+ default:
+ // ignore unknowns
+ break;
+ }
+
+ _castMinMaxDistance(self, val);
+
+ return val;
+}
+
+function cast$within(val) {
+ _castMinMaxDistance(this, val);
+
+ if (val.$box || val.$polygon) {
+ const type = val.$box ? '$box' : '$polygon';
+ val[type].forEach(arr => {
+ if (!Array.isArray(arr)) {
+ const msg = 'Invalid $within $box argument. '
+ + 'Expected an array, received ' + arr;
+ throw new TypeError(msg);
+ }
+ arr.forEach((v, i) => {
+ arr[i] = castToNumber.call(this, v);
+ });
+ });
+ } else if (val.$center || val.$centerSphere) {
+ const type = val.$center ? '$center' : '$centerSphere';
+ val[type].forEach((item, i) => {
+ if (Array.isArray(item)) {
+ item.forEach((v, j) => {
+ item[j] = castToNumber.call(this, v);
+ });
+ } else {
+ val[type][i] = castToNumber.call(this, item);
+ }
+ });
+ } else if (val.$geometry) {
+ cast$geometry(val, this);
+ }
+
+ return val;
+}
+
+function cast$geoIntersects(val) {
+ const geo = val.$geometry;
+ if (!geo) {
+ return;
+ }
+
+ cast$geometry(val, this);
+ return val;
+}
+
+function _castMinMaxDistance(self, val) {
+ if (val.$maxDistance) {
+ val.$maxDistance = castToNumber.call(self, val.$maxDistance);
+ }
+ if (val.$minDistance) {
+ val.$minDistance = castToNumber.call(self, val.$minDistance);
+ }
+}
diff --git a/node_modules/mongoose/lib/schema/operators/helpers.js b/node_modules/mongoose/lib/schema/operators/helpers.js
new file mode 100644
index 0000000..a17951c
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/helpers.js
@@ -0,0 +1,32 @@
+'use strict';
+
+/*!
+ * Module requirements.
+ */
+
+const SchemaNumber = require('../number');
+
+/*!
+ * @ignore
+ */
+
+exports.castToNumber = castToNumber;
+exports.castArraysOfNumbers = castArraysOfNumbers;
+
+/*!
+ * @ignore
+ */
+
+function castToNumber(val) {
+ return SchemaNumber.cast()(val);
+}
+
+function castArraysOfNumbers(arr, self) {
+ arr.forEach(function(v, i) {
+ if (Array.isArray(v)) {
+ castArraysOfNumbers(v, self);
+ } else {
+ arr[i] = castToNumber.call(self, v);
+ }
+ });
+}
diff --git a/node_modules/mongoose/lib/schema/operators/text.js b/node_modules/mongoose/lib/schema/operators/text.js
new file mode 100644
index 0000000..4b95916
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/text.js
@@ -0,0 +1,39 @@
+'use strict';
+
+const CastError = require('../../error/cast');
+const castBoolean = require('../../cast/boolean');
+const castString = require('../../cast/string');
+
+/*!
+ * Casts val to an object suitable for `$text`. Throws an error if the object
+ * can't be casted.
+ *
+ * @param {Any} val value to cast
+ * @param {String} [path] path to associate with any errors that occured
+ * @return {Object} casted object
+ * @see https://docs.mongodb.com/manual/reference/operator/query/text/
+ * @api private
+ */
+
+module.exports = function(val, path) {
+ if (val == null || typeof val !== 'object') {
+ throw new CastError('$text', val, path);
+ }
+
+ if (val.$search != null) {
+ val.$search = castString(val.$search, path + '.$search');
+ }
+ if (val.$language != null) {
+ val.$language = castString(val.$language, path + '.$language');
+ }
+ if (val.$caseSensitive != null) {
+ val.$caseSensitive = castBoolean(val.$caseSensitive,
+ path + '.$castSensitive');
+ }
+ if (val.$diacriticSensitive != null) {
+ val.$diacriticSensitive = castBoolean(val.$diacriticSensitive,
+ path + '.$diacriticSensitive');
+ }
+
+ return val;
+};
diff --git a/node_modules/mongoose/lib/schema/operators/type.js b/node_modules/mongoose/lib/schema/operators/type.js
new file mode 100644
index 0000000..c8e391a
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/operators/type.js
@@ -0,0 +1,13 @@
+'use strict';
+
+/*!
+ * ignore
+ */
+
+module.exports = function(val) {
+ if (typeof val !== 'number' && typeof val !== 'string') {
+ throw new Error('$type parameter must be number or string');
+ }
+
+ return val;
+};
diff --git a/node_modules/mongoose/lib/schema/string.js b/node_modules/mongoose/lib/schema/string.js
new file mode 100644
index 0000000..a3bfaf4
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/string.js
@@ -0,0 +1,679 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const SchemaType = require('../schematype');
+const MongooseError = require('../error/index');
+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.
+ *
+ * @param {String} key
+ * @param {Object} options
+ * @inherits SchemaType
+ * @api public
+ */
+
+function SchemaString(key, options) {
+ this.enumValues = [];
+ this.regExp = null;
+ SchemaType.call(this, key, options, 'String');
+}
+
+/**
+ * This schema type's name, to defend against minifiers that mangle
+ * function names.
+ *
+ * @api public
+ */
+SchemaString.schemaName = 'String';
+
+SchemaString.defaultOptions = {};
+
+/*!
+ * Inherits from SchemaType.
+ */
+SchemaString.prototype = Object.create(SchemaType.prototype);
+SchemaString.prototype.constructor = SchemaString;
+Object.defineProperty(SchemaString.prototype, 'OptionsConstructor', {
+ configurable: false,
+ enumerable: false,
+ writable: false,
+ value: SchemaStringOptions
+});
+
+/*!
+ * ignore
+ */
+
+SchemaString._cast = castString;
+
+/**
+ * Get/set the function used to cast arbitrary values to strings.
+ *
+ * ####Example:
+ *
+ * // Throw an error if you pass in an object. Normally, Mongoose allows
+ * // objects with custom `toString()` functions.
+ * const original = mongoose.Schema.Types.String.cast();
+ * mongoose.Schema.Types.String.cast(v => {
+ * assert.ok(v == null || typeof v !== 'object');
+ * return original(v);
+ * });
+ *
+ * // Or disable casting entirely
+ * mongoose.Schema.Types.String.cast(false);
+ *
+ * @param {Function} caster
+ * @return {Function}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaString.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => {
+ if (v != null && typeof v !== 'string') {
+ throw new Error();
+ }
+ return v;
+ };
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/**
+ * Attaches a getter for all String instances.
+ *
+ * ####Example:
+ *
+ * // Make all numbers round down
+ * mongoose.Schema.String.get(v => v.toLowerCase());
+ *
+ * const Model = mongoose.model('Test', new Schema({ test: String }));
+ * new Model({ test: 'FOO' }).test; // 'foo'
+ *
+ * @param {Function} getter
+ * @return {this}
+ * @function get
+ * @static
+ * @api public
+ */
+
+SchemaString.get = SchemaType.get;
+
+/**
+ * Sets a default option for all String instances.
+ *
+ * ####Example:
+ *
+ * // Make all strings have option `trim` equal to true.
+ * mongoose.Schema.String.set('trim', true);
+ *
+ * const User = mongoose.model('User', new Schema({ name: String }));
+ * new User({ name: ' John Doe ' }).name; // 'John Doe'
+ *
+ * @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
+ */
+
+SchemaString.set = SchemaType.set;
+
+/*!
+ * ignore
+ */
+
+SchemaString._checkRequired = v => (v instanceof String || typeof v === 'string') && v.length;
+
+/**
+ * Override the function the required validator uses to check whether a string
+ * passes the `required` check.
+ *
+ * ####Example:
+ *
+ * // Allow empty strings to pass `required` check
+ * mongoose.Schema.Types.String.checkRequired(v => v != null);
+ *
+ * const M = mongoose.model({ str: { type: String, required: true } });
+ * new M({ str: '' }).validateSync(); // `null`, validation passes!
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @function checkRequired
+ * @static
+ * @api public
+ */
+
+SchemaString.checkRequired = SchemaType.checkRequired;
+
+/**
+ * Adds an enum validator
+ *
+ * ####Example:
+ *
+ * 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'
+ * m.save(callback) // success
+ * })
+ *
+ * // or with custom error messages
+ * const enum = {
+ * values: ['opening', 'open', 'closing', 'closed'],
+ * message: 'enum validator failed for path `{PATH}` with value `{VALUE}`'
+ * }
+ * 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'
+ * m.save(callback) // success
+ * })
+ *
+ * @param {String|Object} [args...] enumeration values
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaString.prototype.enum = function() {
+ if (this.enumValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.enumValidator;
+ }, this);
+ this.enumValidator = false;
+ }
+
+ if (arguments[0] === void 0 || arguments[0] === false) {
+ return this;
+ }
+
+ let values;
+ let errorMessage;
+
+ if (utils.isObject(arguments[0])) {
+ values = arguments[0].values;
+ errorMessage = arguments[0].message;
+ } else {
+ values = arguments;
+ errorMessage = MongooseError.messages.String.enum;
+ }
+
+ for (const value of values) {
+ if (value !== undefined) {
+ this.enumValues.push(this.cast(value));
+ }
+ }
+
+ const vals = this.enumValues;
+ this.enumValidator = function(v) {
+ return undefined === v || ~vals.indexOf(v);
+ };
+ this.validators.push({
+ validator: this.enumValidator,
+ message: errorMessage,
+ type: 'enum',
+ enumValues: vals
+ });
+
+ return this;
+};
+
+/**
+ * Adds a lowercase [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
+ *
+ * ####Example:
+ *
+ * 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'
+ *
+ * Note that `lowercase` does **not** affect regular expression queries:
+ *
+ * ####Example:
+ * // Still queries for documents whose `email` matches the regular
+ * // expression /SomeEmail/. Mongoose does **not** convert the RegExp
+ * // to lowercase.
+ * M.find({ email: /SomeEmail/ });
+ *
+ * @api public
+ * @return {SchemaType} this
+ */
+
+SchemaString.prototype.lowercase = function(shouldApply) {
+ if (arguments.length > 0 && !shouldApply) {
+ return this;
+ }
+ return this.set(function(v, self) {
+ if (typeof v !== 'string') {
+ v = self.cast(v);
+ }
+ if (v) {
+ return v.toLowerCase();
+ }
+ return v;
+ });
+};
+
+/**
+ * Adds an uppercase [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
+ *
+ * ####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'
+ *
+ * Note that `uppercase` does **not** affect regular expression queries:
+ *
+ * ####Example:
+ * // Mongoose does **not** convert the RegExp to uppercase.
+ * M.find({ email: /an example/ });
+ *
+ * @api public
+ * @return {SchemaType} this
+ */
+
+SchemaString.prototype.uppercase = function(shouldApply) {
+ if (arguments.length > 0 && !shouldApply) {
+ return this;
+ }
+ return this.set(function(v, self) {
+ if (typeof v !== 'string') {
+ v = self.cast(v);
+ }
+ if (v) {
+ return v.toUpperCase();
+ }
+ return v;
+ });
+};
+
+/**
+ * Adds a trim [setter](http://mongoosejs.com/docs/api.html#schematype_SchemaType-set).
+ *
+ * The string value will be trimmed when set.
+ *
+ * ####Example:
+ *
+ * const s = new Schema({ name: { type: String, trim: true }});
+ * const M = db.model('M', s);
+ * const string = ' some name ';
+ * console.log(string.length); // 11
+ * const m = new M({ name: string });
+ * console.log(m.name.length); // 9
+ *
+ * // Equivalent to `findOne({ name: string.trim() })`
+ * M.findOne({ name: string });
+ *
+ * Note that `trim` does **not** affect regular expression queries:
+ *
+ * ####Example:
+ * // Mongoose does **not** trim whitespace from the RegExp.
+ * M.find({ name: / some name / });
+ *
+ * @api public
+ * @return {SchemaType} this
+ */
+
+SchemaString.prototype.trim = function(shouldTrim) {
+ if (arguments.length > 0 && !shouldTrim) {
+ return this;
+ }
+ return this.set(function(v, self) {
+ if (typeof v !== 'string') {
+ v = self.cast(v);
+ }
+ if (v) {
+ return v.trim();
+ }
+ return v;
+ });
+};
+
+/**
+ * Sets a minimum length validator.
+ *
+ * ####Example:
+ *
+ * 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';
+ * address.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MINLENGTH} token which will be replaced with the minimum allowed length
+ * 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).
+ * })
+ *
+ * @param {Number} value minimum string length
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaString.prototype.minlength = function(value, message) {
+ if (this.minlengthValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.minlengthValidator;
+ }, this);
+ }
+
+ if (value !== null && value !== undefined) {
+ let msg = message || MongooseError.messages.String.minlength;
+ msg = msg.replace(/{MINLENGTH}/, value);
+ this.validators.push({
+ validator: this.minlengthValidator = function(v) {
+ return v === null || v.length >= value;
+ },
+ message: msg,
+ type: 'minlength',
+ minlength: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Sets a maximum length validator.
+ *
+ * ####Example:
+ *
+ * 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';
+ * address.save() // success
+ * })
+ *
+ * // custom error messages
+ * // We can also use the special {MAXLENGTH} token which will be replaced with the maximum allowed length
+ * 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).
+ * })
+ *
+ * @param {Number} value maximum string length
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaString.prototype.maxlength = function(value, message) {
+ if (this.maxlengthValidator) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.maxlengthValidator;
+ }, this);
+ }
+
+ if (value !== null && value !== undefined) {
+ let msg = message || MongooseError.messages.String.maxlength;
+ msg = msg.replace(/{MAXLENGTH}/, value);
+ this.validators.push({
+ validator: this.maxlengthValidator = function(v) {
+ return v === null || v.length <= value;
+ },
+ message: msg,
+ type: 'maxlength',
+ maxlength: value
+ });
+ }
+
+ return this;
+};
+
+/**
+ * Sets a regexp validator.
+ *
+ * Any value that does not pass `regExp`.test(val) will fail validation.
+ *
+ * ####Example:
+ *
+ * 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'
+ * m.validate(function (err) {
+ * assert.ok(err) // success
+ * })
+ * })
+ *
+ * // using a custom error message
+ * 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.
+ *
+ * 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
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @api public
+ */
+
+SchemaString.prototype.match = function match(regExp, message) {
+ // yes, we allow multiple match validators
+
+ const msg = message || MongooseError.messages.String.match;
+
+ const matchValidator = function(v) {
+ if (!regExp) {
+ 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);
+ return ret;
+ };
+
+ this.validators.push({
+ validator: matchValidator,
+ message: msg,
+ type: 'regexp',
+ regexp: regExp
+ });
+ return this;
+};
+
+/**
+ * Check if the given value satisfies the `required` validator. The value is
+ * considered valid if it is a string (that is, not `null` or `undefined`) and
+ * has positive length. The `required` validator **will** fail for empty
+ * strings.
+ *
+ * @param {Any} value
+ * @param {Document} doc
+ * @return {Boolean}
+ * @api public
+ */
+
+SchemaString.prototype.checkRequired = function checkRequired(value, doc) {
+ if (SchemaType._isRef(this, value, doc, true)) {
+ return !!value;
+ }
+
+ // `require('util').inherits()` does **not** copy static properties, and
+ // plugins like mongoose-float use `inherits()` for pre-ES6.
+ const _checkRequired = typeof this.constructor.checkRequired == 'function' ?
+ this.constructor.checkRequired() :
+ SchemaString.checkRequired();
+
+ return _checkRequired(value);
+};
+
+/**
+ * Casts to String
+ *
+ * @api private
+ */
+
+SchemaString.prototype.cast = function(value, doc, init) {
+ if (SchemaType._isRef(this, value, doc, init)) {
+ // wait! we may need to cast this to a document
+
+ if (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;
+ }
+
+ const castString = typeof this.constructor.cast === 'function' ?
+ this.constructor.cast() :
+ SchemaString.cast();
+ try {
+ return castString(value);
+ } catch (error) {
+ throw new CastError('string', value, this.path, null, this);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle(val) {
+ return this.castForQuery(val);
+}
+
+function handleArray(val) {
+ const _this = this;
+ if (!Array.isArray(val)) {
+ return [this.castForQuery(val)];
+ }
+ return val.map(function(m) {
+ return _this.castForQuery(m);
+ });
+}
+
+const $conditionalHandlers = utils.options(SchemaType.prototype.$conditionalHandlers, {
+ $all: handleArray,
+ $gt: handleSingle,
+ $gte: handleSingle,
+ $lt: handleSingle,
+ $lte: handleSingle,
+ $options: String,
+ $regex: handleSingle,
+ $not: handleSingle
+});
+
+Object.defineProperty(SchemaString.prototype, '$conditionalHandlers', {
+ configurable: false,
+ enumerable: false,
+ writable: false,
+ value: Object.freeze($conditionalHandlers)
+});
+
+/**
+ * Casts contents for queries.
+ *
+ * @param {String} $conditional
+ * @param {any} [val]
+ * @api private
+ */
+
+SchemaString.prototype.castForQuery = function($conditional, val) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional + ' with String.');
+ }
+ return handler.call(this, val);
+ }
+ val = $conditional;
+ if (Object.prototype.toString.call(val) === '[object RegExp]') {
+ return val;
+ }
+
+ return this._castForQuery(val);
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = SchemaString;
diff --git a/node_modules/mongoose/lib/schema/symbols.js b/node_modules/mongoose/lib/schema/symbols.js
new file mode 100644
index 0000000..08d1d27
--- /dev/null
+++ b/node_modules/mongoose/lib/schema/symbols.js
@@ -0,0 +1,5 @@
+'use strict';
+
+exports.schemaMixedSymbol = Symbol.for('mongoose:schema_mixed');
+
+exports.builtInMiddleware = Symbol.for('mongoose:built-in-middleware'); \ No newline at end of file
diff --git a/node_modules/mongoose/lib/schematype.js b/node_modules/mongoose/lib/schematype.js
new file mode 100644
index 0000000..af81375
--- /dev/null
+++ b/node_modules/mongoose/lib/schematype.js
@@ -0,0 +1,1581 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const MongooseError = require('./error/index');
+const SchemaTypeOptions = require('./options/SchemaTypeOptions');
+const $exists = require('./schema/operators/exists');
+const $type = require('./schema/operators/type');
+const get = require('./helpers/get');
+const handleImmutable = require('./helpers/schematype/handleImmutable');
+const immediate = require('./helpers/immediate');
+const schemaTypeSymbol = require('./helpers/symbols').schemaTypeSymbol;
+const util = require('util');
+const utils = require('./utils');
+const validatorErrorSymbol = require('./helpers/symbols').validatorErrorSymbol;
+
+const documentIsSelected = require('./helpers/symbols').documentIsSelected;
+const documentIsModified = require('./helpers/symbols').documentIsModified;
+
+const CastError = MongooseError.CastError;
+const ValidatorError = MongooseError.ValidatorError;
+
+/**
+ * SchemaType constructor. Do **not** instantiate `SchemaType` directly.
+ * Mongoose converts your schema paths into SchemaTypes automatically.
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({ name: String });
+ * schema.path('name') instanceof SchemaType; // true
+ *
+ * @param {String} path
+ * @param {SchemaTypeOptions} [options] See [SchemaTypeOptions docs](/docs/api/schematypeoptions.html)
+ * @param {String} [instance]
+ * @api public
+ */
+
+function SchemaType(path, options, instance) {
+ this[schemaTypeSymbol] = true;
+ this.path = path;
+ this.instance = instance;
+ this.validators = [];
+ this.getters = this.constructor.hasOwnProperty('getters') ?
+ this.constructor.getters.slice() :
+ [];
+ this.setters = [];
+
+ options = options || {};
+ const defaultOptions = this.constructor.defaultOptions || {};
+ const defaultOptionsKeys = Object.keys(defaultOptions);
+
+ for (const option of defaultOptionsKeys) {
+ if (defaultOptions.hasOwnProperty(option) && !options.hasOwnProperty(option)) {
+ options[option] = defaultOptions[option];
+ }
+ }
+
+ if (options.select == null) {
+ delete options.select;
+ }
+
+ const Options = this.OptionsConstructor || SchemaTypeOptions;
+ this.options = new Options(options);
+ this._index = null;
+
+
+ if (utils.hasUserDefinedProperty(this.options, 'immutable')) {
+ this.$immutable = this.options.immutable;
+
+ handleImmutable(this);
+ }
+
+ const keys = Object.keys(this.options);
+ for (const prop of keys) {
+ if (prop === 'cast') {
+ continue;
+ }
+ if (utils.hasUserDefinedProperty(this.options, prop) && typeof this[prop] === 'function') {
+ // { unique: true, index: true }
+ if (prop === 'index' && this._index) {
+ if (options.index === false) {
+ const index = this._index;
+ if (typeof index === 'object' && index != null) {
+ if (index.unique) {
+ throw new Error('Path "' + this.path + '" may not have `index` ' +
+ 'set to false and `unique` set to true');
+ }
+ if (index.sparse) {
+ throw new Error('Path "' + this.path + '" may not have `index` ' +
+ 'set to false and `sparse` set to true');
+ }
+ }
+
+ this._index = false;
+ }
+ continue;
+ }
+
+ const val = options[prop];
+ // Special case so we don't screw up array defaults, see gh-5780
+ if (prop === 'default') {
+ this.default(val);
+ continue;
+ }
+
+ const opts = Array.isArray(val) ? val : [val];
+
+ this[prop].apply(this, opts);
+ }
+ }
+
+ Object.defineProperty(this, '$$context', {
+ enumerable: false,
+ configurable: false,
+ writable: true,
+ value: null
+ });
+}
+
+/*!
+ * ignore
+ */
+
+SchemaType.prototype.OptionsConstructor = SchemaTypeOptions;
+
+/**
+ * Get/set the function used to cast arbitrary values to this type.
+ *
+ * ####Example:
+ *
+ * // Disallow `null` for numbers, and don't try to cast any values to
+ * // numbers, so even strings like '123' will cause a CastError.
+ * mongoose.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.cast = function cast(caster) {
+ if (arguments.length === 0) {
+ return this._cast;
+ }
+ if (caster === false) {
+ caster = v => v;
+ }
+ this._cast = caster;
+
+ return this._cast;
+};
+
+/**
+ * Sets a default option for this schema type.
+ *
+ * ####Example:
+ *
+ * // Make all strings be trimmed by default
+ * mongoose.SchemaTypes.String.set('trim', true);
+ *
+ * @param {String} option The name of the option you'd like to set (e.g. trim, lowercase, etc...)
+ * @param {*} value The value of the option you'd like to set.
+ * @return {void}
+ * @static
+ * @receiver SchemaType
+ * @function set
+ * @api public
+ */
+
+SchemaType.set = function set(option, value) {
+ if (!this.hasOwnProperty('defaultOptions')) {
+ this.defaultOptions = Object.assign({}, this.defaultOptions);
+ }
+ this.defaultOptions[option] = value;
+};
+
+/**
+ * Attaches a getter for all instances of this schema type.
+ *
+ * ####Example:
+ *
+ * // Make all numbers round down
+ * mongoose.Number.get(function(v) { return Math.floor(v); });
+ *
+ * @param {Function} getter
+ * @return {this}
+ * @static
+ * @receiver SchemaType
+ * @function get
+ * @api public
+ */
+
+SchemaType.get = function(getter) {
+ this.getters = this.hasOwnProperty('getters') ? this.getters : [];
+ this.getters.push(getter);
+};
+
+/**
+ * Sets a default value for this SchemaType.
+ *
+ * ####Example:
+ *
+ * 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.
+ *
+ * ####Example:
+ *
+ * // values are cast:
+ * 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:
+ * const schema = new Schema({ mixed: Schema.Types.Mixed });
+ * schema.path('mixed').default(function () {
+ * return {};
+ * });
+ *
+ * // if we don't use a function to return object literals for Mixed defaults,
+ * // each document will receive a reference to the same object literal creating
+ * // a "shared" object instance:
+ * const schema = new Schema({ mixed: Schema.Types.Mixed });
+ * schema.path('mixed').default({});
+ * const M = db.model('M', schema);
+ * const m1 = new M;
+ * m1.mixed.added = 1;
+ * console.log(m1.mixed); // { added: 1 }
+ * const m2 = new M;
+ * console.log(m2.mixed); // { added: 1 }
+ *
+ * @param {Function|any} val the default value
+ * @return {defaultValue}
+ * @api public
+ */
+
+SchemaType.prototype.default = function(val) {
+ if (arguments.length === 1) {
+ if (val === void 0) {
+ this.defaultValue = void 0;
+ return void 0;
+ }
+
+ if (val != null && val.instanceOfSchema) {
+ throw new MongooseError('Cannot set default value of path `' + this.path +
+ '` to a mongoose Schema instance.');
+ }
+
+ this.defaultValue = val;
+ return this.defaultValue;
+ } else if (arguments.length > 1) {
+ this.defaultValue = utils.args(arguments);
+ }
+ return this.defaultValue;
+};
+
+/**
+ * Declares the index options for this schematype.
+ *
+ * ####Example:
+ *
+ * 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 });
+ *
+ * ####NOTE:
+ *
+ * _Indexes are created [in the background](https://docs.mongodb.com/manual/core/index-creation/#index-creation-background)
+ * by default. If `background` is set to `false`, MongoDB will not execute any
+ * read/write operations you send until the index build.
+ * Specify `background: false` to override Mongoose's default._
+ *
+ * @param {Object|Boolean|String} options
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.index = function(options) {
+ this._index = options;
+ utils.expires(this._index);
+ return this;
+};
+
+/**
+ * Declares an unique index.
+ *
+ * ####Example:
+ *
+ * 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._
+ *
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.unique = function(bool) {
+ if (this._index === false) {
+ if (!bool) {
+ return;
+ }
+ throw new Error('Path "' + this.path + '" may not have `index` set to ' +
+ 'false and `unique` set to true');
+ }
+ if (this._index == null || this._index === true) {
+ this._index = {};
+ } else if (typeof this._index === 'string') {
+ this._index = { type: this._index };
+ }
+
+ this._index.unique = bool;
+ return this;
+};
+
+/**
+ * Declares a full text index.
+ *
+ * ###Example:
+ *
+ * const s = new Schema({name : {type: String, text : true })
+ * s.path('name').index({text : true});
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.text = function(bool) {
+ if (this._index === false) {
+ if (!bool) {
+ return;
+ }
+ throw new Error('Path "' + this.path + '" may not have `index` set to ' +
+ 'false and `text` set to true');
+ }
+
+ if (this._index === null || this._index === undefined ||
+ typeof this._index === 'boolean') {
+ this._index = {};
+ } else if (typeof this._index === 'string') {
+ this._index = { type: this._index };
+ }
+
+ this._index.text = bool;
+ return this;
+};
+
+/**
+ * Declares a sparse index.
+ *
+ * ####Example:
+ *
+ * const s = new Schema({ name: { type: String, sparse: true } });
+ * s.path('name').index({ sparse: true });
+ *
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.sparse = function(bool) {
+ if (this._index === false) {
+ if (!bool) {
+ return;
+ }
+ throw new Error('Path "' + this.path + '" may not have `index` set to ' +
+ 'false and `sparse` set to true');
+ }
+
+ if (this._index == null || typeof this._index === 'boolean') {
+ this._index = {};
+ } else if (typeof this._index === 'string') {
+ this._index = { type: this._index };
+ }
+
+ this._index.sparse = bool;
+ return this;
+};
+
+/**
+ * Defines this path as immutable. Mongoose prevents you from changing
+ * immutable paths unless the parent document has [`isNew: true`](/docs/api.html#document_Document-isNew).
+ *
+ * ####Example:
+ *
+ * const schema = new Schema({
+ * name: { type: String, immutable: true },
+ * age: Number
+ * });
+ * const Model = mongoose.model('Test', schema);
+ *
+ * await Model.create({ name: 'test' });
+ * const doc = await Model.findOne();
+ *
+ * doc.isNew; // false
+ * doc.name = 'new name';
+ * doc.name; // 'test', because `name` is immutable
+ *
+ * Mongoose also prevents changing immutable properties using `updateOne()`
+ * and `updateMany()` based on [strict mode](/docs/guide.html#strict).
+ *
+ * ####Example:
+ *
+ * // Mongoose will strip out the `name` update, because `name` is immutable
+ * Model.updateOne({}, { $set: { name: 'test2' }, $inc: { age: 1 } });
+ *
+ * // If `strict` is set to 'throw', Mongoose will throw an error if you
+ * // update `name`
+ * const err = await Model.updateOne({}, { name: 'test2' }, { strict: 'throw' }).
+ * then(() => null, err => err);
+ * err.name; // StrictModeError
+ *
+ * // If `strict` is `false`, Mongoose allows updating `name` even though
+ * // the property is immutable.
+ * Model.updateOne({}, { name: 'test2' }, { strict: false });
+ *
+ * @param {Boolean} bool
+ * @return {SchemaType} this
+ * @see isNew /docs/api.html#document_Document-isNew
+ * @api public
+ */
+
+SchemaType.prototype.immutable = function(bool) {
+ this.$immutable = bool;
+ handleImmutable(this);
+
+ 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.
+ *
+ * ####Example:
+ *
+ * function capitalize (val) {
+ * if (typeof val !== 'string') val = '';
+ * return val.charAt(0).toUpperCase() + val.substring(1);
+ * }
+ *
+ * // defining within the schema
+ * const s = new Schema({ name: { type: String, set: capitalize }});
+ *
+ * // or with the SchemaType
+ * 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
+ * document or query.
+ *
+ * Suppose you are implementing user registration for a website. Users provide
+ * an email and password, which gets saved to mongodb. The email is a string
+ * that you will want to normalize to lower case, in order to avoid one email
+ * having more than one account -- e.g., otherwise, avenue@q.com can be registered for 2 accounts via avenue@q.com and AvEnUe@Q.CoM.
+ *
+ * You can set up email lower case normalization easily via a Mongoose setter.
+ *
+ * function toLower(v) {
+ * return v.toLowerCase();
+ * }
+ *
+ * const UserSchema = new Schema({
+ * email: { type: String, set: toLower }
+ * });
+ *
+ * const User = db.model('User', UserSchema);
+ *
+ * const user = new User({email: 'AVENUE@Q.COM'});
+ * console.log(user.email); // 'avenue@q.com'
+ *
+ * // or
+ * 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'
+ *
+ * As you can see above, setters allow you to transform the data before it
+ * stored in MongoDB, or before executing a query.
+ *
+ * _NOTE: we could have also just used the built-in `lowercase: true` SchemaType option instead of defining our own function._
+ *
+ * new Schema({ email: { type: String, lowercase: true }})
+ *
+ * Setters are also passed a second argument, the schematype on which the setter was defined. This allows for tailored behavior based on options passed in the schema.
+ *
+ * function inspector (val, schematype) {
+ * if (schematype.options.required) {
+ * return schematype.path + ' is required';
+ * } else {
+ * return val;
+ * }
+ * }
+ *
+ * const VirusSchema = new Schema({
+ * name: { type: String, required: true, set: inspector },
+ * taxonomy: { type: String, set: inspector }
+ * })
+ *
+ * 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
+ *
+ * You can also use setters to modify other properties on the document. If
+ * you're setting a property `name` on a document, the setter will run with
+ * `this` as the document. Be careful, in mongoose 5 setters will also run
+ * when querying by `name` with `this` as the query.
+ *
+ * ```javascript
+ * const nameSchema = new Schema({ name: String, keywords: [String] });
+ * nameSchema.path('name').set(function(v) {
+ * // Need to check if `this` is a document, because in mongoose 5
+ * // setters will also run on queries, in which case `this` will be a
+ * // mongoose query object.
+ * if (this instanceof Document && v != null) {
+ * this.keywords = v.split(' ');
+ * }
+ * return v;
+ * });
+ * ```
+ *
+ * @param {Function} fn
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.set = function(fn) {
+ if (typeof fn !== 'function') {
+ throw new TypeError('A setter must be a function.');
+ }
+ this.setters.push(fn);
+ return this;
+};
+
+/**
+ * Adds a getter to this schematype.
+ *
+ * ####Example:
+ *
+ * function dob (val) {
+ * if (!val) return val;
+ * return (val.getMonth() + 1) + "/" + val.getDate() + "/" + val.getFullYear();
+ * }
+ *
+ * // defining within the schema
+ * const s = new Schema({ born: { type: Date, get: dob })
+ *
+ * // or by retreiving its SchemaType
+ * 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.
+ *
+ * Suppose you are storing credit card numbers and you want to hide everything except the last 4 digits to the mongoose user. You can do so by defining a getter in the following way:
+ *
+ * function obfuscate (cc) {
+ * return '****-****-****-' + cc.slice(cc.length-4, cc.length);
+ * }
+ *
+ * const AccountSchema = new Schema({
+ * creditCardNumber: { type: String, get: obfuscate }
+ * });
+ *
+ * const Account = db.model('Account', AccountSchema);
+ *
+ * Account.findById(id, function (err, found) {
+ * console.log(found.creditCardNumber); // '****-****-****-1234'
+ * });
+ *
+ * Getters are also passed a second argument, the schematype on which the getter was defined. This allows for tailored behavior based on options passed in the schema.
+ *
+ * function inspector (val, schematype) {
+ * if (schematype.options.required) {
+ * return schematype.path + ' is required';
+ * } else {
+ * return schematype.path + ' is not';
+ * }
+ * }
+ *
+ * const VirusSchema = new Schema({
+ * name: { type: String, required: true, get: inspector },
+ * taxonomy: { type: String, get: inspector }
+ * })
+ *
+ * const Virus = db.model('Virus', VirusSchema);
+ *
+ * Virus.findById(id, function (err, virus) {
+ * console.log(virus.name); // name is required
+ * console.log(virus.taxonomy); // taxonomy is not
+ * })
+ *
+ * @param {Function} fn
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.get = function(fn) {
+ if (typeof fn !== 'function') {
+ throw new TypeError('A getter must be a function.');
+ }
+ this.getters.push(fn);
+ return this;
+};
+
+/**
+ * Adds validator(s) for this document path.
+ *
+ * Validators always receive the value to validate as their first argument and
+ * must return `Boolean`. Returning `false` or throwing an error means
+ * validation failed.
+ *
+ * The error message argument is optional. If not passed, the [default generic error message template](#error_messages_MongooseError-messages) will be used.
+ *
+ * ####Examples:
+ *
+ * // make sure every value is equal to "something"
+ * function validator (val) {
+ * return val == 'something';
+ * }
+ * new Schema({ name: { type: String, validate: validator }});
+ *
+ * // with a custom error message
+ *
+ * const custom = [validator, 'Uh oh, {PATH} does not equal "something".']
+ * new Schema({ name: { type: String, validate: custom }});
+ *
+ * // adding many validators at a time
+ *
+ * const many = [
+ * { validator: validator, msg: 'uh oh' }
+ * , { validator: anotherValidator, msg: 'failed' }
+ * ]
+ * new Schema({ name: { type: String, validate: many }});
+ *
+ * // or utilizing SchemaType methods directly:
+ *
+ * const schema = new Schema({ name: 'string' });
+ * schema.path('name').validate(validator, 'validation of `{PATH}` failed with value `{VALUE}`');
+ *
+ * ####Error message templates:
+ *
+ * From the examples above, you may have noticed that error messages support
+ * basic templating. There are a few other template keywords besides `{PATH}`
+ * and `{VALUE}` too. To find out more, details are available
+ * [here](#error_messages_MongooseError.messages).
+ *
+ * If Mongoose's built-in error message templating isn't enough, Mongoose
+ * supports setting the `message` property to a function.
+ *
+ * schema.path('name').validate({
+ * validator: function() { return v.length > 5; },
+ * // `errors['name']` will be "name must have length 5, got 'foo'"
+ * message: function(props) {
+ * return `${props.path} must have length 5, got '${props.value}'`;
+ * }
+ * });
+ *
+ * To bypass Mongoose's error messages and just copy the error message that
+ * the validator throws, do this:
+ *
+ * schema.path('name').validate({
+ * validator: function() { throw new Error('Oops!'); },
+ * // `errors['name']` will be "Oops!"
+ * message: function(props) { return props.reason.message; }
+ * });
+ *
+ * ####Asynchronous validation:
+ *
+ * Mongoose supports validators that return a promise. A validator that returns
+ * a promise is called an _async validator_. Async validators run in
+ * parallel, and `validate()` will wait until all async validators have settled.
+ *
+ * schema.path('name').validate({
+ * validator: function (value) {
+ * return new Promise(function (resolve, reject) {
+ * resolve(false); // validation failed
+ * });
+ * }
+ * });
+ *
+ * You might use asynchronous validators to retreive other documents from the database to validate against or to meet other I/O bound validation needs.
+ *
+ * Validation occurs `pre('save')` or whenever you manually execute [document#validate](#document_Document-validate).
+ *
+ * If validation fails during `pre('save')` and no callback was passed to receive the error, an `error` event will be emitted on your Models associated db [connection](#connection_Connection), passing the validation error object along.
+ *
+ * const conn = mongoose.createConnection(..);
+ * conn.on('error', handleError);
+ *
+ * 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`
+ * listener to your Model as shown below.
+ *
+ * // registering an error listener on the Model lets us handle errors more locally
+ * Product.on('error', handleError);
+ *
+ * @param {RegExp|Function|Object} obj validator function, or hash describing options
+ * @param {Function} [obj.validator] validator function. If the validator function returns `undefined` or a truthy value, validation succeeds. If it returns [falsy](https://masteringjs.io/tutorials/fundamentals/falsy) (except `undefined`) or throws an error, validation fails.
+ * @param {String|Function} [obj.message] optional error message. If function, should return the error message as a string
+ * @param {Boolean} [obj.propsParameter=false] If true, Mongoose will pass the validator properties object (with the `validator` function, `message`, etc.) as the 2nd arg to the validator function. This is disabled by default because many validators [rely on positional args](https://github.com/chriso/validator.js#validators), so turning this on may cause unpredictable behavior in external validators.
+ * @param {String|Function} [errorMsg] optional error message. If function, should return the error message as a string
+ * @param {String} [type] optional validator type
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.validate = function(obj, message, type) {
+ if (typeof obj === 'function' || obj && utils.getFunctionName(obj.constructor) === 'RegExp') {
+ let properties;
+ if (typeof message === 'function') {
+ properties = { validator: obj, message: message };
+ properties.type = type || 'user defined';
+ } else if (message instanceof Object && !type) {
+ properties = utils.clone(message);
+ if (!properties.message) {
+ properties.message = properties.msg;
+ }
+ properties.validator = obj;
+ properties.type = properties.type || 'user defined';
+ } else {
+ if (message == null) {
+ message = MongooseError.messages.general.default;
+ }
+ if (!type) {
+ type = 'user defined';
+ }
+ properties = { message: message, type: type, validator: obj };
+ }
+
+ if (properties.isAsync) {
+ handleIsAsync();
+ }
+
+ this.validators.push(properties);
+ return this;
+ }
+
+ let i;
+ let length;
+ let arg;
+
+ for (i = 0, length = arguments.length; i < length; i++) {
+ arg = arguments[i];
+ if (!utils.isPOJO(arg)) {
+ const msg = 'Invalid validator. Received (' + typeof arg + ') '
+ + arg
+ + '. See http://mongoosejs.com/docs/api.html#schematype_SchemaType-validate';
+
+ throw new Error(msg);
+ }
+ this.validate(arg.validator, arg);
+ }
+
+ return this;
+};
+
+/*!
+ * ignore
+ */
+
+const handleIsAsync = util.deprecate(function handleIsAsync() {},
+ 'Mongoose: the `isAsync` option for custom validators is deprecated. Make ' +
+ 'your async validators return a promise instead: ' +
+ 'https://mongoosejs.com/docs/validation.html#async-custom-validators');
+
+/**
+ * Adds a required validator to this SchemaType. The validator gets added
+ * to the front of this SchemaType's validators array using `unshift()`.
+ *
+ * ####Example:
+ *
+ * const s = new Schema({ born: { type: Date, required: true })
+ *
+ * // or with custom error message
+ *
+ * const s = new Schema({ born: { type: Date, required: '{PATH} is required!' })
+ *
+ * // or with a function
+ *
+ * const s = new Schema({
+ * userId: ObjectId,
+ * username: {
+ * type: String,
+ * required: function() { return this.userId != null; }
+ * }
+ * })
+ *
+ * // or with a function and a custom message
+ * const s = new Schema({
+ * userId: ObjectId,
+ * username: {
+ * type: String,
+ * required: [
+ * function() { return this.userId != null; },
+ * 'username is required if id is specified'
+ * ]
+ * }
+ * })
+ *
+ * // or through the path API
+ *
+ * s.path('name').required(true);
+ *
+ * // with custom error messaging
+ *
+ * s.path('name').required(true, 'grrr :( ');
+ *
+ * // or make a path conditionally required based on a function
+ * const isOver18 = function() { return this.age >= 18; };
+ * s.path('voterRegistrationId').required(isOver18);
+ *
+ * The required validator uses the SchemaType's `checkRequired` function to
+ * determine whether a given value satisfies the required validator. By default,
+ * a value satisfies the required validator if `val != null` (that is, if
+ * the value is not null nor undefined). However, most built-in mongoose schema
+ * types override the default `checkRequired` function:
+ *
+ * @param {Boolean|Function|Object} required enable/disable the validator, or function that returns required boolean, or options object
+ * @param {Boolean|Function} [options.isRequired] enable/disable the validator, or function that returns required boolean
+ * @param {Function} [options.ErrorConstructor] custom error constructor. The constructor receives 1 parameter, an object containing the validator properties.
+ * @param {String} [message] optional custom error message
+ * @return {SchemaType} this
+ * @see Customized Error Messages #error_messages_MongooseError-messages
+ * @see SchemaArray#checkRequired #schema_array_SchemaArray.checkRequired
+ * @see SchemaBoolean#checkRequired #schema_boolean_SchemaBoolean-checkRequired
+ * @see SchemaBuffer#checkRequired #schema_buffer_SchemaBuffer.schemaName
+ * @see SchemaNumber#checkRequired #schema_number_SchemaNumber-min
+ * @see SchemaObjectId#checkRequired #schema_objectid_ObjectId-auto
+ * @see SchemaString#checkRequired #schema_string_SchemaString-checkRequired
+ * @api public
+ */
+
+SchemaType.prototype.required = function(required, message) {
+ let customOptions = {};
+
+ if (arguments.length > 0 && required == null) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.requiredValidator;
+ }, this);
+
+ this.isRequired = false;
+ delete this.originalRequiredValue;
+ return this;
+ }
+
+ if (typeof required === 'object') {
+ customOptions = required;
+ message = customOptions.message || message;
+ required = required.isRequired;
+ }
+
+ if (required === false) {
+ this.validators = this.validators.filter(function(v) {
+ return v.validator !== this.requiredValidator;
+ }, this);
+
+ this.isRequired = false;
+ delete this.originalRequiredValue;
+ return this;
+ }
+
+ const _this = this;
+ this.isRequired = true;
+
+ this.requiredValidator = function(v) {
+ const cachedRequired = get(this, '$__.cachedRequired');
+
+ // no validation when this path wasn't selected in the query.
+ if (cachedRequired != null && !this[documentIsSelected](_this.path) && !this[documentIsModified](_this.path)) {
+ return true;
+ }
+
+ // `$cachedRequired` gets set in `_evaluateRequiredFunctions()` so we
+ // don't call required functions multiple times in one validate call
+ // See gh-6801
+ if (cachedRequired != null && _this.path in cachedRequired) {
+ const res = cachedRequired[_this.path] ?
+ _this.checkRequired(v, this) :
+ true;
+ delete cachedRequired[_this.path];
+ return res;
+ } else if (typeof required === 'function') {
+ return required.apply(this) ? _this.checkRequired(v, this) : true;
+ }
+
+ return _this.checkRequired(v, this);
+ };
+ this.originalRequiredValue = required;
+
+ if (typeof required === 'string') {
+ message = required;
+ required = undefined;
+ }
+
+ const msg = message || MongooseError.messages.general.required;
+ this.validators.unshift(Object.assign({}, customOptions, {
+ validator: this.requiredValidator,
+ message: msg,
+ type: 'required'
+ }));
+
+ return this;
+};
+
+/**
+ * Set the model that this path refers to. This is the option that [populate](https://mongoosejs.com/docs/populate.html)
+ * looks at to determine the foreign collection it should query.
+ *
+ * ####Example:
+ * const userSchema = new Schema({ name: String });
+ * const User = mongoose.model('User', userSchema);
+ *
+ * const postSchema = new Schema({ user: mongoose.ObjectId });
+ * 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({
+ * user: { type: mongoose.ObjectId, ref: User }
+ * });
+ *
+ * @param {String|Model|Function} ref either a model name, a [Model](https://mongoosejs.com/docs/models.html), or a function that returns a model name or model.
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.ref = function(ref) {
+ this.options.ref = ref;
+ return this;
+};
+
+/**
+ * Gets the default value
+ *
+ * @param {Object} scope the scope which callback are executed
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaType.prototype.getDefault = function(scope, init) {
+ let ret = typeof this.defaultValue === 'function'
+ ? this.defaultValue.call(scope)
+ : this.defaultValue;
+
+ if (ret !== null && ret !== undefined) {
+ if (typeof ret === 'object' && (!this.options || !this.options.shared)) {
+ ret = utils.clone(ret);
+ }
+
+ const casted = this.applySetters(ret, scope, init);
+ if (casted && casted.$isSingleNested) {
+ casted.$parent = scope;
+ }
+ return casted;
+ }
+ return ret;
+};
+
+/*!
+ * Applies setters without casting
+ *
+ * @api private
+ */
+
+SchemaType.prototype._applySetters = function(value, scope, init, priorVal) {
+ let v = value;
+ const setters = this.setters;
+ const caster = this.caster;
+
+ for (const setter of utils.clone(setters).reverse()) {
+ v = setter.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;
+};
+
+/**
+ * Applies setters
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @param {Boolean} init
+ * @api private
+ */
+
+SchemaType.prototype.applySetters = function(value, scope, init, priorVal, options) {
+ let v = this._applySetters(value, scope, init, priorVal, options);
+
+ if (v == null) {
+ return this._castNullish(v);
+ }
+
+ // do not cast until all setters are applied #665
+ v = this.cast(v, scope, init, priorVal, options);
+
+ return v;
+};
+
+/**
+ * Applies getters to a value
+ *
+ * @param {Object} value
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaType.prototype.applyGetters = function(value, scope) {
+ let v = value;
+ const getters = this.getters;
+ const len = getters.length;
+
+ if (len === 0) {
+ return v;
+ }
+
+ for (let i = 0; i < len; ++i) {
+ v = getters[i].call(scope, v, this);
+ }
+
+ return v;
+};
+
+/**
+ * Sets default `select()` behavior for this path.
+ *
+ * Set to `true` if this path should always be included in the results, `false` if it should be excluded by default. This setting can be overridden at the query level.
+ *
+ * ####Example:
+ *
+ * T = db.model('T', new Schema({ x: { type: String, select: true }}));
+ * T.find(..); // field x will always be selected ..
+ * // .. unless overridden;
+ * T.find().select('-x').exec(callback);
+ *
+ * @param {Boolean} val
+ * @return {SchemaType} this
+ * @api public
+ */
+
+SchemaType.prototype.select = function select(val) {
+ this.selected = !!val;
+ return this;
+};
+
+/**
+ * Performs a validation of `value` using the validators declared for this SchemaType.
+ *
+ * @param {any} value
+ * @param {Function} callback
+ * @param {Object} scope
+ * @api private
+ */
+
+SchemaType.prototype.doValidate = function(value, fn, scope, options) {
+ let err = false;
+ const path = this.path;
+
+ // Avoid non-object `validators`
+ const validators = this.validators.
+ filter(v => v != null && typeof v === 'object');
+
+ let count = validators.length;
+
+ if (!count) {
+ return fn(null);
+ }
+
+ const _this = this;
+ validators.forEach(function(v) {
+ if (err) {
+ return;
+ }
+
+ const validator = v.validator;
+ let ok;
+
+ const validatorProperties = utils.clone(v);
+ validatorProperties.path = options && options.path ? options.path : path;
+ validatorProperties.value = value;
+
+ if (validator instanceof RegExp) {
+ validate(validator.test(value), validatorProperties);
+ return;
+ }
+
+ if (typeof validator !== 'function') {
+ return;
+ }
+
+ if (value === undefined && validator !== _this.requiredValidator) {
+ validate(true, validatorProperties);
+ return;
+ }
+
+ if (validatorProperties.isAsync) {
+ asyncValidate(validator, scope, value, validatorProperties, validate);
+ return;
+ }
+
+ try {
+ if (validatorProperties.propsParameter) {
+ ok = validator.call(scope, value, validatorProperties);
+ } else {
+ ok = validator.call(scope, value);
+ }
+ } catch (error) {
+ ok = false;
+ validatorProperties.reason = error;
+ if (error.message) {
+ validatorProperties.message = error.message;
+ }
+ }
+
+ if (ok != null && typeof ok.then === 'function') {
+ ok.then(
+ function(ok) { validate(ok, validatorProperties); },
+ function(error) {
+ validatorProperties.reason = error;
+ validatorProperties.message = error.message;
+ ok = false;
+ validate(ok, validatorProperties);
+ });
+ } else {
+ validate(ok, validatorProperties);
+ }
+
+ });
+
+ function validate(ok, validatorProperties) {
+ if (err) {
+ return;
+ }
+ if (ok === undefined || ok) {
+ if (--count <= 0) {
+ immediate(function() {
+ fn(null);
+ });
+ }
+ } else {
+ const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
+ err = new ErrorConstructor(validatorProperties);
+ err[validatorErrorSymbol] = true;
+ immediate(function() {
+ fn(err);
+ });
+ }
+ }
+};
+
+/*!
+ * Handle async validators
+ */
+
+function asyncValidate(validator, scope, value, props, cb) {
+ let called = false;
+ const returnVal = validator.call(scope, value, function(ok, customMsg) {
+ if (called) {
+ return;
+ }
+ called = true;
+ if (customMsg) {
+ props.message = customMsg;
+ }
+ cb(ok, props);
+ });
+ if (typeof returnVal === 'boolean') {
+ called = true;
+ cb(returnVal, props);
+ } else if (returnVal && typeof returnVal.then === 'function') {
+ // Promise
+ returnVal.then(
+ function(ok) {
+ if (called) {
+ return;
+ }
+ called = true;
+ cb(ok, props);
+ },
+ function(error) {
+ if (called) {
+ return;
+ }
+ called = true;
+
+ props.reason = error;
+ props.message = error.message;
+ cb(false, props);
+ });
+ }
+}
+
+/**
+ * Performs a validation of `value` using the validators declared for this SchemaType.
+ *
+ * ####Note:
+ *
+ * This method ignores the asynchronous validators.
+ *
+ * @param {any} value
+ * @param {Object} scope
+ * @return {MongooseError|undefined}
+ * @api private
+ */
+
+SchemaType.prototype.doValidateSync = function(value, scope, options) {
+ const path = this.path;
+ const count = this.validators.length;
+
+ if (!count) {
+ return null;
+ }
+
+ let validators = this.validators;
+ if (value === void 0) {
+ if (this.validators.length > 0 && this.validators[0].type === 'required') {
+ validators = [this.validators[0]];
+ } else {
+ return null;
+ }
+ }
+
+ let err = null;
+ validators.forEach(function(v) {
+ if (err) {
+ return;
+ }
+
+ if (v == null || typeof v !== 'object') {
+ return;
+ }
+
+ const validator = v.validator;
+ const validatorProperties = utils.clone(v);
+ validatorProperties.path = options && options.path ? options.path : path;
+ validatorProperties.value = value;
+ let ok;
+
+ // Skip any explicit async validators. Validators that return a promise
+ // will still run, but won't trigger any errors.
+ if (validator.isAsync) {
+ return;
+ }
+
+ if (validator instanceof RegExp) {
+ validate(validator.test(value), validatorProperties);
+ return;
+ }
+
+ if (typeof validator !== 'function') {
+ return;
+ }
+
+ try {
+ if (validatorProperties.propsParameter) {
+ ok = validator.call(scope, value, validatorProperties);
+ } else {
+ ok = validator.call(scope, value);
+ }
+ } catch (error) {
+ ok = false;
+ validatorProperties.reason = error;
+ }
+
+ // Skip any validators that return a promise, we can't handle those
+ // synchronously
+ if (ok != null && typeof ok.then === 'function') {
+ return;
+ }
+ validate(ok, validatorProperties);
+ });
+
+ return err;
+
+ function validate(ok, validatorProperties) {
+ if (err) {
+ return;
+ }
+ if (ok !== undefined && !ok) {
+ const ErrorConstructor = validatorProperties.ErrorConstructor || ValidatorError;
+ err = new ErrorConstructor(validatorProperties);
+ err[validatorErrorSymbol] = true;
+ }
+ }
+};
+
+/**
+ * Determines if value is a valid Reference.
+ *
+ * @param {SchemaType} self
+ * @param {Object} value
+ * @param {Document} doc
+ * @param {Boolean} init
+ * @return {Boolean}
+ * @api private
+ */
+
+SchemaType._isRef = function(self, value, doc, init) {
+ // fast path
+ let ref = init && self.options && (self.options.ref || self.options.refPath);
+
+ if (!ref && doc && doc.$__ != null) {
+ // checks for
+ // - this populated with adhoc model and no ref was set in schema OR
+ // - setting / pushing values after population
+ const path = doc.$__fullPath(self.path);
+ const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
+ ref = owner.populated(path) || doc.populated(self.path);
+ }
+
+ if (ref) {
+ if (value == null) {
+ return true;
+ }
+ if (!Buffer.isBuffer(value) && // buffers are objects too
+ value._bsontype !== 'Binary' // raw binary value from the db
+ && utils.isObject(value) // might have deselected _id in population query
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/*!
+ * ignore
+ */
+
+function handleSingle(val) {
+ return this.castForQuery(val);
+}
+
+/*!
+ * ignore
+ */
+
+function handleArray(val) {
+ const _this = this;
+ if (!Array.isArray(val)) {
+ return [this.castForQuery(val)];
+ }
+ return val.map(function(m) {
+ return _this.castForQuery(m);
+ });
+}
+
+/*!
+ * Just like handleArray, except also allows `[]` because surprisingly
+ * `$in: [1, []]` works fine
+ */
+
+function handle$in(val) {
+ const _this = this;
+ if (!Array.isArray(val)) {
+ return [this.castForQuery(val)];
+ }
+ return val.map(function(m) {
+ if (Array.isArray(m) && m.length === 0) {
+ return m;
+ }
+ return _this.castForQuery(m);
+ });
+}
+
+/*!
+ * ignore
+ */
+
+SchemaType.prototype.$conditionalHandlers = {
+ $all: handleArray,
+ $eq: handleSingle,
+ $in: handle$in,
+ $ne: handleSingle,
+ $nin: handle$in,
+ $exists: $exists,
+ $type: $type
+};
+
+/*!
+ * Wraps `castForQuery` to handle context
+ */
+
+SchemaType.prototype.castForQueryWrapper = function(params) {
+ this.$$context = params.context;
+ if ('$conditional' in params) {
+ const ret = this.castForQuery(params.$conditional, params.val);
+ this.$$context = null;
+ return ret;
+ }
+ if (params.$skipQueryCastForUpdate || params.$applySetters) {
+ const ret = this._castForQuery(params.val);
+ this.$$context = null;
+ return ret;
+ }
+
+ const ret = this.castForQuery(params.val);
+ this.$$context = null;
+ return ret;
+};
+
+/**
+ * Cast the given value with the given optional query operator.
+ *
+ * @param {String} [$conditional] query operator, like `$eq` or `$in`
+ * @param {any} val
+ * @api private
+ */
+
+SchemaType.prototype.castForQuery = function($conditional, val) {
+ let handler;
+ if (arguments.length === 2) {
+ handler = this.$conditionalHandlers[$conditional];
+ if (!handler) {
+ throw new Error('Can\'t use ' + $conditional);
+ }
+ return handler.call(this, val);
+ }
+ val = $conditional;
+ return this._castForQuery(val);
+};
+
+/*!
+ * Internal switch for runSetters
+ *
+ * @api private
+ */
+
+SchemaType.prototype._castForQuery = function(val) {
+ return this.applySetters(val, this.$$context);
+};
+
+/**
+ * Override the function the required validator uses to check whether a value
+ * passes the `required` check. Override this on the individual SchemaType.
+ *
+ * ####Example:
+ *
+ * // Use this to allow empty strings to pass the `required` validator
+ * mongoose.Schema.Types.String.checkRequired(v => typeof v === 'string');
+ *
+ * @param {Function} fn
+ * @return {Function}
+ * @static
+ * @receiver SchemaType
+ * @function checkRequired
+ * @api public
+ */
+
+SchemaType.checkRequired = function(fn) {
+ if (arguments.length > 0) {
+ this._checkRequired = fn;
+ }
+
+ return this._checkRequired;
+};
+
+/**
+ * Default check for if this path satisfies the `required` validator.
+ *
+ * @param {any} val
+ * @api private
+ */
+
+SchemaType.prototype.checkRequired = function(val) {
+ return val != null;
+};
+
+/*!
+ * ignore
+ */
+
+SchemaType.prototype.clone = function() {
+ const options = Object.assign({}, this.options);
+ const schematype = new this.constructor(this.path, options, this.instance);
+ schematype.validators = this.validators.slice();
+ if (this.requiredValidator !== undefined) schematype.requiredValidator = this.requiredValidator;
+ if (this.defaultValue !== undefined) schematype.defaultValue = this.defaultValue;
+ if (this.$immutable !== undefined && this.options.immutable === undefined) {
+ schematype.$immutable = this.$immutable;
+
+ handleImmutable(schematype);
+ }
+ if (this._index !== undefined) schematype._index = this._index;
+ if (this.selected !== undefined) schematype.selected = this.selected;
+ if (this.isRequired !== undefined) schematype.isRequired = this.isRequired;
+ if (this.originalRequiredValue !== undefined) schematype.originalRequiredValue = this.originalRequiredValue;
+ schematype.getters = this.getters.slice();
+ schematype.setters = this.setters.slice();
+ return schematype;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = SchemaType;
+
+exports.CastError = CastError;
+
+exports.ValidatorError = ValidatorError;
diff --git a/node_modules/mongoose/lib/statemachine.js b/node_modules/mongoose/lib/statemachine.js
new file mode 100644
index 0000000..7e36dc1
--- /dev/null
+++ b/node_modules/mongoose/lib/statemachine.js
@@ -0,0 +1,180 @@
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const utils = require('./utils');
+
+/*!
+ * StateMachine represents a minimal `interface` for the
+ * constructors it builds via StateMachine.ctor(...).
+ *
+ * @api private
+ */
+
+const StateMachine = module.exports = exports = function StateMachine() {
+};
+
+/*!
+ * StateMachine.ctor('state1', 'state2', ...)
+ * A factory method for subclassing StateMachine.
+ * The arguments are a list of states. For each state,
+ * the constructor's prototype gets state transition
+ * methods named after each state. These transition methods
+ * place their path argument into the given state.
+ *
+ * @param {String} state
+ * @param {String} [state]
+ * @return {Function} subclass constructor
+ * @private
+ */
+
+StateMachine.ctor = function() {
+ const states = utils.args(arguments);
+
+ const ctor = function() {
+ StateMachine.apply(this, arguments);
+ this.paths = {};
+ this.states = {};
+ this.stateNames = states;
+
+ let i = states.length,
+ state;
+
+ while (i--) {
+ state = states[i];
+ this.states[state] = {};
+ }
+ };
+
+ ctor.prototype = new StateMachine();
+
+ states.forEach(function(state) {
+ // Changes the `path`'s state to `state`.
+ ctor.prototype[state] = function(path) {
+ this._changeState(path, state);
+ };
+ });
+
+ return ctor;
+};
+
+/*!
+ * This function is wrapped by the state change functions:
+ *
+ * - `require(path)`
+ * - `modify(path)`
+ * - `init(path)`
+ *
+ * @api private
+ */
+
+StateMachine.prototype._changeState = function _changeState(path, nextState) {
+ const prevBucket = this.states[this.paths[path]];
+ if (prevBucket) delete prevBucket[path];
+
+ this.paths[path] = nextState;
+ this.states[nextState][path] = true;
+};
+
+/*!
+ * ignore
+ */
+
+StateMachine.prototype.clear = function clear(state) {
+ const keys = Object.keys(this.states[state]);
+ let i = keys.length;
+ let path;
+
+ while (i--) {
+ path = keys[i];
+ delete this.states[state][path];
+ delete this.paths[path];
+ }
+};
+
+/*!
+ * Checks to see if at least one path is in the states passed in via `arguments`
+ * e.g., this.some('required', 'inited')
+ *
+ * @param {String} state that we want to check for.
+ * @private
+ */
+
+StateMachine.prototype.some = function some() {
+ const _this = this;
+ const what = arguments.length ? arguments : this.stateNames;
+ return Array.prototype.some.call(what, function(state) {
+ return Object.keys(_this.states[state]).length;
+ });
+};
+
+/*!
+ * This function builds the functions that get assigned to `forEach` and `map`,
+ * since both of those methods share a lot of the same logic.
+ *
+ * @param {String} iterMethod is either 'forEach' or 'map'
+ * @return {Function}
+ * @api private
+ */
+
+StateMachine.prototype._iter = function _iter(iterMethod) {
+ return function() {
+ const numArgs = arguments.length;
+ let states = utils.args(arguments, 0, numArgs - 1);
+ const callback = arguments[numArgs - 1];
+
+ if (!states.length) states = this.stateNames;
+
+ const _this = this;
+
+ const paths = states.reduce(function(paths, state) {
+ return paths.concat(Object.keys(_this.states[state]));
+ }, []);
+
+ return paths[iterMethod](function(path, i, paths) {
+ return callback(path, i, paths);
+ });
+ };
+};
+
+/*!
+ * Iterates over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @private
+ */
+
+StateMachine.prototype.forEach = function forEach() {
+ this.forEach = this._iter('forEach');
+ return this.forEach.apply(this, arguments);
+};
+
+/*!
+ * Maps over the paths that belong to one of the parameter states.
+ *
+ * The function profile can look like:
+ * this.forEach(state1, fn); // iterates over all paths in state1
+ * this.forEach(state1, state2, fn); // iterates over all paths in state1 or state2
+ * this.forEach(fn); // iterates over all paths in all states
+ *
+ * @param {String} [state]
+ * @param {String} [state]
+ * @param {Function} callback
+ * @return {Array}
+ * @private
+ */
+
+StateMachine.prototype.map = function map() {
+ this.map = this._iter('map');
+ return this.map.apply(this, arguments);
+};
diff --git a/node_modules/mongoose/lib/types/array.js b/node_modules/mongoose/lib/types/array.js
new file mode 100644
index 0000000..41c51e5
--- /dev/null
+++ b/node_modules/mongoose/lib/types/array.js
@@ -0,0 +1,66 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const CoreMongooseArray = require('./core_array');
+const Document = require('../document');
+
+const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
+const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
+const arrayPathSymbol = require('../helpers/symbols').arrayPathSymbol;
+const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
+
+const _basePush = Array.prototype.push;
+
+/**
+ * Mongoose Array constructor.
+ *
+ * ####NOTE:
+ *
+ * _Values always have to be passed to the constructor to initialize, otherwise `MongooseArray#push` will mark the array as modified._
+ *
+ * @param {Array} values
+ * @param {String} path
+ * @param {Document} doc parent document
+ * @api private
+ * @inherits Array
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseArray(values, path, doc) {
+ // 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] = {};
+
+ if (Array.isArray(values)) {
+ const len = values.length;
+ for (let i = 0; i < len; ++i) {
+ _basePush.call(arr, values[i]);
+ }
+
+ arr[arrayAtomicsSymbol] = values[arrayAtomicsSymbol] || {};
+ }
+
+ 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) {
+ arr[arrayParentSymbol] = doc;
+ arr[arraySchemaSymbol] = doc.schema.path(path);
+ }
+
+ return arr;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = exports = MongooseArray;
diff --git a/node_modules/mongoose/lib/types/buffer.js b/node_modules/mongoose/lib/types/buffer.js
new file mode 100644
index 0000000..9bac2e8
--- /dev/null
+++ b/node_modules/mongoose/lib/types/buffer.js
@@ -0,0 +1,276 @@
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const Binary = require('../driver').get().Binary;
+const utils = require('../utils');
+const Buffer = require('safe-buffer').Buffer;
+
+/**
+ * Mongoose Buffer constructor.
+ *
+ * Values always have to be passed to the constructor to initialize.
+ *
+ * @param {Buffer} value
+ * @param {String} encode
+ * @param {Number} offset
+ * @api private
+ * @inherits Buffer
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseBuffer(value, encode, offset) {
+ const length = arguments.length;
+ let val;
+
+ if (length === 0 || arguments[0] === null || arguments[0] === undefined) {
+ val = 0;
+ } else {
+ val = value;
+ }
+
+ let encoding;
+ let path;
+ let doc;
+
+ if (Array.isArray(encode)) {
+ // internal casting
+ path = encode[0];
+ doc = encode[1];
+ } else {
+ encoding = encode;
+ }
+
+ let buf;
+ if (typeof val === 'number' || val instanceof Number) {
+ buf = Buffer.alloc(val);
+ } else { // string, array or object { type: 'Buffer', data: [...] }
+ buf = Buffer.from(val, encoding, offset);
+ }
+ utils.decorate(buf, MongooseBuffer.mixin);
+ buf.isMongooseBuffer = true;
+
+ // make sure these internal props don't show up in Object.keys()
+ buf[MongooseBuffer.pathSymbol] = path;
+ buf[parentSymbol] = doc;
+
+ buf._subtype = 0;
+ return buf;
+}
+
+const pathSymbol = Symbol.for('mongoose#Buffer#_path');
+const parentSymbol = Symbol.for('mongoose#Buffer#_parent');
+MongooseBuffer.pathSymbol = pathSymbol;
+
+/*!
+ * Inherit from Buffer.
+ */
+
+MongooseBuffer.mixin = {
+
+ /**
+ * Default subtype for the Binary representing this Buffer
+ *
+ * @api private
+ * @property _subtype
+ * @receiver MongooseBuffer
+ */
+
+ _subtype: undefined,
+
+ /**
+ * Marks this buffer as modified.
+ *
+ * @api private
+ * @method _markModified
+ * @receiver MongooseBuffer
+ */
+
+ _markModified: function() {
+ const parent = this[parentSymbol];
+
+ if (parent) {
+ parent.markModified(this[MongooseBuffer.pathSymbol]);
+ }
+ return this;
+ },
+
+ /**
+ * Writes the buffer.
+ *
+ * @api public
+ * @method write
+ * @receiver MongooseBuffer
+ */
+
+ write: function() {
+ const written = Buffer.prototype.write.apply(this, arguments);
+
+ if (written > 0) {
+ this._markModified();
+ }
+
+ return written;
+ },
+
+ /**
+ * Copies the buffer.
+ *
+ * ####Note:
+ *
+ * `Buffer#copy` does not mark `target` as modified so you must copy from a `MongooseBuffer` for it to work as expected. This is a work around since `copy` modifies the target, not this.
+ *
+ * @return {Number} The number of bytes copied.
+ * @param {Buffer} target
+ * @method copy
+ * @receiver MongooseBuffer
+ */
+
+ copy: function(target) {
+ const ret = Buffer.prototype.copy.apply(this, arguments);
+
+ if (target && target.isMongooseBuffer) {
+ target._markModified();
+ }
+
+ return ret;
+ }
+};
+
+/*!
+ * Compile other Buffer methods marking this buffer as modified.
+ */
+
+(
+// node < 0.5
+ ('writeUInt8 writeUInt16 writeUInt32 writeInt8 writeInt16 writeInt32 ' +
+ 'writeFloat writeDouble fill ' +
+ 'utf8Write binaryWrite asciiWrite set ' +
+
+ // node >= 0.5
+ 'writeUInt16LE writeUInt16BE writeUInt32LE writeUInt32BE ' +
+ 'writeInt16LE writeInt16BE writeInt32LE writeInt32BE ' + 'writeFloatLE writeFloatBE writeDoubleLE writeDoubleBE')
+).split(' ').forEach(function(method) {
+ if (!Buffer.prototype[method]) {
+ return;
+ }
+ MongooseBuffer.mixin[method] = function() {
+ const ret = Buffer.prototype[method].apply(this, arguments);
+ this._markModified();
+ return ret;
+ };
+});
+
+/**
+ * Converts this buffer to its Binary type representation.
+ *
+ * ####SubTypes:
+ *
+ * const bson = require('bson')
+ * bson.BSON_BINARY_SUBTYPE_DEFAULT
+ * bson.BSON_BINARY_SUBTYPE_FUNCTION
+ * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
+ * bson.BSON_BINARY_SUBTYPE_UUID
+ * bson.BSON_BINARY_SUBTYPE_MD5
+ * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
+ *
+ * doc.buffer.toObject(bson.BSON_BINARY_SUBTYPE_USER_DEFINED);
+ *
+ * @see http://bsonspec.org/#/specification
+ * @param {Hex} [subtype]
+ * @return {Binary}
+ * @api public
+ * @method toObject
+ * @receiver MongooseBuffer
+ */
+
+MongooseBuffer.mixin.toObject = function(options) {
+ const subtype = typeof options === 'number'
+ ? options
+ : (this._subtype || 0);
+ return new Binary(Buffer.from(this), subtype);
+};
+
+/**
+ * Converts this buffer for storage in MongoDB, including subtype
+ *
+ * @return {Binary}
+ * @api public
+ * @method toBSON
+ * @receiver MongooseBuffer
+ */
+
+MongooseBuffer.mixin.toBSON = function() {
+ return new Binary(this, this._subtype || 0);
+};
+
+/**
+ * Determines if this buffer is equals to `other` buffer
+ *
+ * @param {Buffer} other
+ * @return {Boolean}
+ * @method equals
+ * @receiver MongooseBuffer
+ */
+
+MongooseBuffer.mixin.equals = function(other) {
+ if (!Buffer.isBuffer(other)) {
+ return false;
+ }
+
+ if (this.length !== other.length) {
+ return false;
+ }
+
+ for (let i = 0; i < this.length; ++i) {
+ if (this[i] !== other[i]) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+/**
+ * Sets the subtype option and marks the buffer modified.
+ *
+ * ####SubTypes:
+ *
+ * const bson = require('bson')
+ * bson.BSON_BINARY_SUBTYPE_DEFAULT
+ * bson.BSON_BINARY_SUBTYPE_FUNCTION
+ * bson.BSON_BINARY_SUBTYPE_BYTE_ARRAY
+ * bson.BSON_BINARY_SUBTYPE_UUID
+ * bson.BSON_BINARY_SUBTYPE_MD5
+ * bson.BSON_BINARY_SUBTYPE_USER_DEFINED
+ *
+ * doc.buffer.subtype(bson.BSON_BINARY_SUBTYPE_UUID);
+ *
+ * @see http://bsonspec.org/#/specification
+ * @param {Hex} subtype
+ * @api public
+ * @method subtype
+ * @receiver MongooseBuffer
+ */
+
+MongooseBuffer.mixin.subtype = function(subtype) {
+ if (typeof subtype !== 'number') {
+ throw new TypeError('Invalid subtype. Expected a number');
+ }
+
+ if (this._subtype !== subtype) {
+ this._markModified();
+ }
+
+ this._subtype = subtype;
+};
+
+/*!
+ * Module exports.
+ */
+
+MongooseBuffer.Binary = Binary;
+
+module.exports = MongooseBuffer;
diff --git a/node_modules/mongoose/lib/types/core_array.js b/node_modules/mongoose/lib/types/core_array.js
new file mode 100644
index 0000000..954df52
--- /dev/null
+++ b/node_modules/mongoose/lib/types/core_array.js
@@ -0,0 +1,958 @@
+'use strict';
+
+const Document = require('../document');
+const EmbeddedDocument = require('./embedded');
+const MongooseError = require('../error/mongooseError');
+const ObjectId = require('./objectid');
+const cleanModifiedSubpaths = require('../helpers/document/cleanModifiedSubpaths');
+const get = require('../helpers/get');
+const internalToObjectOptions = require('../options').internalToObjectOptions;
+const utils = require('../utils');
+const util = require('util');
+
+const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
+const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
+const arrayPathSymbol = require('../helpers/symbols').arrayPathSymbol;
+const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
+const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
+const slicedSymbol = Symbol('mongoose#Array#sliced');
+
+const _basePush = Array.prototype.push;
+
+const validatorsSymbol = Symbol('mongoose#MongooseCoreArray#validators');
+
+/*!
+ * ignore
+ */
+
+class CoreMongooseArray extends Array {
+ get isMongooseArray() {
+ return true;
+ }
+
+ get validators() {
+ return this[validatorsSymbol];
+ }
+
+ set validators(v) {
+ this[validatorsSymbol] = v;
+ }
+
+ /**
+ * Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.
+ *
+ * If no atomics exist, we return all array values after conversion.
+ *
+ * @return {Array}
+ * @method $__getAtomics
+ * @memberOf MongooseArray
+ * @instance
+ * @api private
+ */
+
+ $__getAtomics() {
+ const ret = [];
+ const keys = Object.keys(this[arrayAtomicsSymbol]);
+ let i = keys.length;
+
+ const opts = Object.assign({}, internalToObjectOptions, { _isNested: true });
+
+ if (i === 0) {
+ ret[0] = ['$set', this.toObject(opts)];
+ return ret;
+ }
+
+ while (i--) {
+ const op = keys[i];
+ let val = this[arrayAtomicsSymbol][op];
+
+ // the atomic values which are arrays are not MongooseArrays. we
+ // need to convert their elements as if they were MongooseArrays
+ // to handle populated arrays versus DocumentArrays properly.
+ if (utils.isMongooseObject(val)) {
+ val = val.toObject(opts);
+ } else if (Array.isArray(val)) {
+ val = this.toObject.call(val, opts);
+ } else if (val != null && Array.isArray(val.$each)) {
+ val.$each = this.toObject.call(val.$each, opts);
+ } else if (val != null && typeof val.valueOf === 'function') {
+ val = val.valueOf();
+ }
+
+ if (op === '$addToSet') {
+ val = { $each: val };
+ }
+
+ ret.push([op, val]);
+ }
+
+ return ret;
+ }
+
+ /*!
+ * ignore
+ */
+
+ $atomics() {
+ return this[arrayAtomicsSymbol];
+ }
+
+ /*!
+ * ignore
+ */
+
+ $parent() {
+ return this[arrayParentSymbol];
+ }
+
+ /*!
+ * ignore
+ */
+
+ $path() {
+ return this[arrayPathSymbol];
+ }
+
+ /**
+ * Atomically shifts the array at most one time per document `save()`.
+ *
+ * ####NOTE:
+ *
+ * _Calling this multiple times on an array before saving sends the same command as calling it once._
+ * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
+ *
+ * doc.array = [1,2,3];
+ *
+ * const shifted = doc.array.$shift();
+ * console.log(shifted); // 1
+ * console.log(doc.array); // [2,3]
+ *
+ * // no affect
+ * shifted = doc.array.$shift();
+ * console.log(doc.array); // [2,3]
+ *
+ * doc.save(function (err) {
+ * if (err) return handleError(err);
+ *
+ * // we saved, now $shift works again
+ * shifted = doc.array.$shift();
+ * console.log(shifted ); // 2
+ * console.log(doc.array); // [3]
+ * })
+ *
+ * @api public
+ * @memberOf MongooseArray
+ * @instance
+ * @method $shift
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
+ */
+
+ $shift() {
+ this._registerAtomic('$pop', -1);
+ this._markModified();
+
+ // only allow shifting once
+ if (this._shifted) {
+ return;
+ }
+ this._shifted = true;
+
+ return [].shift.call(this);
+ }
+
+ /**
+ * Pops the array atomically at most one time per document `save()`.
+ *
+ * #### NOTE:
+ *
+ * _Calling this mulitple times on an array before saving sends the same command as calling it once._
+ * _This update is implemented using the MongoDB [$pop](http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop) method which enforces this restriction._
+ *
+ * doc.array = [1,2,3];
+ *
+ * const popped = doc.array.$pop();
+ * console.log(popped); // 3
+ * console.log(doc.array); // [1,2]
+ *
+ * // no affect
+ * popped = doc.array.$pop();
+ * console.log(doc.array); // [1,2]
+ *
+ * doc.save(function (err) {
+ * if (err) return handleError(err);
+ *
+ * // we saved, now $pop works again
+ * popped = doc.array.$pop();
+ * console.log(popped); // 2
+ * console.log(doc.array); // [1]
+ * })
+ *
+ * @api public
+ * @method $pop
+ * @memberOf MongooseArray
+ * @instance
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pop
+ * @method $pop
+ * @memberOf MongooseArray
+ */
+
+ $pop() {
+ this._registerAtomic('$pop', 1);
+ this._markModified();
+
+ // only allow popping once
+ if (this._popped) {
+ return;
+ }
+ this._popped = true;
+
+ return [].pop.call(this);
+ }
+
+ /*!
+ * ignore
+ */
+
+ $schema() {
+ return this[arraySchemaSymbol];
+ }
+
+ /**
+ * Casts a member based on this arrays schema.
+ *
+ * @param {any} value
+ * @return value the casted value
+ * @method _cast
+ * @api private
+ * @memberOf MongooseArray
+ */
+
+ _cast(value) {
+ let populated = false;
+ let Model;
+
+ if (this[arrayParentSymbol]) {
+ populated = this[arrayParentSymbol].populated(this[arrayPathSymbol], true);
+ }
+
+ if (populated && value !== null && value !== undefined) {
+ // cast to the populated Models schema
+ Model = populated.options[populateModelSymbol];
+
+ // only objects are permitted so we can safely assume that
+ // non-objects are to be interpreted as _id
+ if (Buffer.isBuffer(value) ||
+ value instanceof ObjectId || !utils.isObject(value)) {
+ value = { _id: value };
+ }
+
+ // 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;
+ if (!isDisc) {
+ value = new Model(value);
+ }
+ return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], true);
+ }
+
+ return this[arraySchemaSymbol].caster.applySetters(value, this[arrayParentSymbol], false);
+ }
+
+ /**
+ * Internal helper for .map()
+ *
+ * @api private
+ * @return {Number}
+ * @method _mapCast
+ * @memberOf MongooseArray
+ */
+
+ _mapCast(val, index) {
+ return this._cast(val, this.length + index);
+ }
+
+ /**
+ * Marks this array as modified.
+ *
+ * If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)
+ *
+ * @param {EmbeddedDocument} embeddedDoc the embedded doc that invoked this method on the Array
+ * @param {String} embeddedPath the path which changed in the embeddedDoc
+ * @method _markModified
+ * @api private
+ * @memberOf MongooseArray
+ */
+
+ _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
+ dirtyPath = dirtyPath + '.' + this.indexOf(elem) + '.' + 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;
+ }
+
+ /**
+ * Register an atomic operation with the parent.
+ *
+ * @param {Array} op operation
+ * @param {any} val
+ * @method _registerAtomic
+ * @api private
+ * @memberOf MongooseArray
+ */
+
+ _registerAtomic(op, val) {
+ if (this[slicedSymbol]) {
+ return;
+ }
+ if (op === '$set') {
+ // $set takes precedence over all other ops.
+ // mark entire array modified.
+ this[arrayAtomicsSymbol] = { $set: val };
+ cleanModifiedSubpaths(this[arrayParentSymbol], this[arrayPathSymbol]);
+ this._markModified();
+ return this;
+ }
+
+ const atomics = this[arrayAtomicsSymbol];
+
+ // reset pop/shift after save
+ if (op === '$pop' && !('$pop' in atomics)) {
+ const _this = this;
+ this[arrayParentSymbol].once('save', function() {
+ _this._popped = _this._shifted = null;
+ });
+ }
+
+ // check for impossible $atomic combos (Mongo denies more than one
+ // $atomic op on a single path
+ if (this[arrayAtomicsSymbol].$set || Object.keys(atomics).length && !(op in atomics)) {
+ // a different op was previously registered.
+ // save the entire thing.
+ this[arrayAtomicsSymbol] = { $set: this };
+ return this;
+ }
+
+ let selector;
+
+ if (op === '$pullAll' || op === '$addToSet') {
+ atomics[op] || (atomics[op] = []);
+ atomics[op] = atomics[op].concat(val);
+ } else if (op === '$pullDocs') {
+ const pullOp = atomics['$pull'] || (atomics['$pull'] = {});
+ if (val[0] instanceof EmbeddedDocument) {
+ selector = pullOp['$or'] || (pullOp['$or'] = []);
+ Array.prototype.push.apply(selector, val.map(function(v) {
+ return v.toObject({ transform: false, virtuals: false });
+ }));
+ } else {
+ selector = pullOp['_id'] || (pullOp['_id'] = { $in: [] });
+ selector['$in'] = selector['$in'].concat(val);
+ }
+ } else if (op === '$push') {
+ atomics.$push = atomics.$push || { $each: [] };
+ if (val != null && utils.hasUserDefinedProperty(val, '$each')) {
+ atomics.$push = val;
+ } else {
+ atomics.$push.$each = atomics.$push.$each.concat(val);
+ }
+ } else {
+ atomics[op] = val;
+ }
+
+ return this;
+ }
+
+ /**
+ * Adds values to the array if not already present.
+ *
+ * ####Example:
+ *
+ * console.log(doc.array) // [2,3,4]
+ * const added = doc.array.addToSet(4,5);
+ * console.log(doc.array) // [2,3,4,5]
+ * console.log(added) // [5]
+ *
+ * @param {any} [args...]
+ * @return {Array} the values that were added
+ * @memberOf MongooseArray
+ * @api public
+ * @method addToSet
+ */
+
+ addToSet() {
+ _checkManualPopulation(this, arguments);
+
+ let values = [].map.call(arguments, this._mapCast, this);
+ values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
+ const added = [];
+ let type = '';
+ if (values[0] instanceof EmbeddedDocument) {
+ type = 'doc';
+ } else if (values[0] instanceof Date) {
+ type = 'date';
+ }
+
+ values.forEach(function(v) {
+ let found;
+ const val = +v;
+ switch (type) {
+ case 'doc':
+ found = this.some(function(doc) {
+ return doc.equals(v);
+ });
+ break;
+ case 'date':
+ found = this.some(function(d) {
+ return +d === val;
+ });
+ break;
+ default:
+ found = ~this.indexOf(v);
+ }
+
+ if (!found) {
+ [].push.call(this, v);
+ this._registerAtomic('$addToSet', v);
+ this._markModified();
+ [].push.call(added, v);
+ }
+ }, this);
+
+ return added;
+ }
+
+ /**
+ * Returns the number of pending atomic operations to send to the db for this array.
+ *
+ * @api private
+ * @return {Number}
+ * @method hasAtomics
+ * @memberOf MongooseArray
+ */
+
+ hasAtomics() {
+ if (!utils.isPOJO(this[arrayAtomicsSymbol])) {
+ return 0;
+ }
+
+ return Object.keys(this[arrayAtomicsSymbol]).length;
+ }
+
+ /**
+ * Return whether or not the `obj` is included in the array.
+ *
+ * @param {Object} obj the item to check
+ * @return {Boolean}
+ * @api public
+ * @method includes
+ * @memberOf MongooseArray
+ */
+
+ includes(obj, fromIndex) {
+ const ret = this.indexOf(obj, fromIndex);
+ return ret !== -1;
+ }
+
+ /**
+ * Return the index of `obj` or `-1` if not found.
+ *
+ * @param {Object} obj the item to look for
+ * @return {Number}
+ * @api public
+ * @method indexOf
+ * @memberOf MongooseArray
+ */
+
+ indexOf(obj, fromIndex) {
+ if (obj instanceof ObjectId) {
+ obj = obj.toString();
+ }
+
+ fromIndex = fromIndex == null ? 0 : fromIndex;
+ const len = this.length;
+ for (let i = fromIndex; i < len; ++i) {
+ if (obj == this[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Helper for console.log
+ *
+ * @api public
+ * @method inspect
+ * @memberOf MongooseArray
+ */
+
+ inspect() {
+ return JSON.stringify(this);
+ }
+
+ /**
+ * Pushes items to the array non-atomically.
+ *
+ * ####NOTE:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @param {any} [args...]
+ * @api public
+ * @method nonAtomicPush
+ * @memberOf MongooseArray
+ */
+
+ nonAtomicPush() {
+ const values = [].map.call(arguments, this._mapCast, this);
+ const ret = [].push.apply(this, values);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+ }
+
+ /**
+ * Wraps [`Array#pop`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified which will pass the entire thing to $set potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @see MongooseArray#$pop #types_array_MongooseArray-%24pop
+ * @api public
+ * @method pop
+ * @memberOf MongooseArray
+ */
+
+ pop() {
+ const ret = [].pop.call(this);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+ }
+
+ /**
+ * Pulls items from the array atomically. Equality is determined by casting
+ * the provided value to an embedded document and comparing using
+ * [the `Document.equals()` function.](./api.html#document_Document-equals)
+ *
+ * ####Examples:
+ *
+ * doc.array.pull(ObjectId)
+ * doc.array.pull({ _id: 'someId' })
+ * doc.array.pull(36)
+ * doc.array.pull('tag 1', 'tag 2')
+ *
+ * To remove a document from a subdocument array we may pass an object with a matching `_id`.
+ *
+ * doc.subdocs.push({ _id: 4815162342 })
+ * doc.subdocs.pull({ _id: 4815162342 }) // removed
+ *
+ * Or we may passing the _id directly and let mongoose take care of it.
+ *
+ * doc.subdocs.push({ _id: 4815162342 })
+ * doc.subdocs.pull(4815162342); // works
+ *
+ * The first pull call will result in a atomic operation on the database, if pull is called repeatedly without saving the document, a $set operation is used on the complete array instead, overwriting possible changes that happened on the database in the meantime.
+ *
+ * @param {any} [args...]
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
+ * @api public
+ * @method pull
+ * @memberOf MongooseArray
+ */
+
+ pull() {
+ const values = [].map.call(arguments, this._cast, this);
+ const cur = this[arrayParentSymbol].get(this[arrayPathSymbol]);
+ let i = cur.length;
+ let mem;
+
+ while (i--) {
+ mem = cur[i];
+ if (mem instanceof Document) {
+ const some = values.some(function(v) {
+ return mem.equals(v);
+ });
+ if (some) {
+ [].splice.call(cur, i, 1);
+ }
+ } else if (~cur.indexOf.call(values, mem)) {
+ [].splice.call(cur, i, 1);
+ }
+ }
+
+ if (values[0] instanceof EmbeddedDocument) {
+ this._registerAtomic('$pullDocs', values.map(function(v) {
+ return v.$__getValue('_id') || v;
+ }));
+ } else {
+ this._registerAtomic('$pullAll', values);
+ }
+
+ this._markModified();
+
+ // Might have modified child paths and then pulled, like
+ // `doc.children[1].name = 'test';` followed by
+ // `doc.children.remove(doc.children[0]);`. In this case we fall back
+ // to a `$set` on the whole array. See #3511
+ if (cleanModifiedSubpaths(this[arrayParentSymbol], this[arrayPathSymbol]) > 0) {
+ this._registerAtomic('$set', this);
+ }
+
+ return this;
+ }
+
+ /**
+ * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
+ *
+ * ####Example:
+ *
+ * const schema = Schema({ nums: [Number] });
+ * const Model = mongoose.model('Test', schema);
+ *
+ * const doc = await Model.create({ nums: [3, 4] });
+ * doc.nums.push(5); // Add 5 to the end of the array
+ * await doc.save();
+ *
+ * // You can also pass an object with `$each` as the
+ * // first parameter to use MongoDB's `$position`
+ * doc.nums.push({
+ * $each: [1, 2],
+ * $position: 0
+ * });
+ * doc.nums; // [1, 2, 3, 4, 5]
+ *
+ * @param {Object} [args...]
+ * @api public
+ * @method push
+ * @memberOf MongooseArray
+ */
+
+ push() {
+ let values = arguments;
+ let atomic = values;
+ const isOverwrite = values[0] != null &&
+ utils.hasUserDefinedProperty(values[0], '$each');
+ if (isOverwrite) {
+ atomic = values[0];
+ values = values[0].$each;
+ }
+
+ if (this[arraySchemaSymbol] == null) {
+ return _basePush.apply(this, values);
+ }
+
+ _checkManualPopulation(this, values);
+
+ const parent = this[arrayParentSymbol];
+ values = [].map.call(values, this._mapCast, this);
+ values = this[arraySchemaSymbol].applySetters(values, parent, undefined,
+ undefined, { skipDocumentArrayCast: true });
+ let ret;
+ const atomics = this[arrayAtomicsSymbol];
+
+ if (isOverwrite) {
+ atomic.$each = values;
+
+ if (get(atomics, '$push.$each.length', 0) > 0 &&
+ atomics.$push.$position != atomics.$position) {
+ throw new MongooseError('Cannot call `Array#push()` multiple times ' +
+ 'with different `$position`');
+ }
+
+ if (atomic.$position != null) {
+ [].splice.apply(this, [atomic.$position, 0].concat(values));
+ ret = this.length;
+ } else {
+ ret = [].push.apply(this, values);
+ }
+ } else {
+ if (get(atomics, '$push.$each.length', 0) > 0 &&
+ atomics.$push.$position != null) {
+ throw new MongooseError('Cannot call `Array#push()` multiple times ' +
+ 'with different `$position`');
+ }
+ atomic = values;
+ ret = [].push.apply(this, values);
+ }
+ this._registerAtomic('$push', atomic);
+ this._markModified();
+ return ret;
+ }
+
+ /**
+ * Alias of [pull](#mongoosearray_MongooseArray-pull)
+ *
+ * @see MongooseArray#pull #types_array_MongooseArray-pull
+ * @see mongodb http://www.mongodb.org/display/DOCS/Updating/#Updating-%24pull
+ * @api public
+ * @memberOf MongooseArray
+ * @instance
+ * @method remove
+ */
+
+ remove() {
+ return this.pull.apply(this, arguments);
+ }
+
+ /**
+ * Sets the casted `val` at index `i` and marks the array modified.
+ *
+ * ####Example:
+ *
+ * // given documents based on the following
+ * const Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
+ *
+ * const doc = new Doc({ array: [2,3,4] })
+ *
+ * console.log(doc.array) // [2,3,4]
+ *
+ * doc.array.set(1,"5");
+ * console.log(doc.array); // [2,5,4] // properly cast to number
+ * doc.save() // the change is saved
+ *
+ * // VS not using array#set
+ * doc.array[1] = "5";
+ * console.log(doc.array); // [2,"5",4] // no casting
+ * doc.save() // change is not saved
+ *
+ * @return {Array} this
+ * @api public
+ * @method set
+ * @memberOf MongooseArray
+ */
+
+ set(i, val) {
+ const value = this._cast(val, i);
+ this[i] = value;
+ this._markModified(i);
+ return this;
+ }
+
+ /**
+ * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
+ *
+ * ####Example:
+ *
+ * doc.array = [2,3];
+ * const res = doc.array.shift();
+ * console.log(res) // 2
+ * console.log(doc.array) // [3]
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ * @method shift
+ * @memberOf MongooseArray
+ */
+
+ shift() {
+ const ret = [].shift.call(this);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return ret;
+ }
+
+ /**
+ * Wraps [`Array#sort`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort) with proper change tracking.
+ *
+ * ####NOTE:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ * @method sort
+ * @memberOf MongooseArray
+ * @see https://masteringjs.io/tutorials/fundamentals/array-sort
+ */
+
+ sort() {
+ const ret = [].sort.apply(this, arguments);
+ this._registerAtomic('$set', this);
+ return ret;
+ }
+
+ /**
+ * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwritting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ * @method splice
+ * @memberOf MongooseArray
+ * @see https://masteringjs.io/tutorials/fundamentals/array-splice
+ */
+
+ splice() {
+ let ret;
+
+ _checkManualPopulation(this, Array.prototype.slice.call(arguments, 2));
+
+ if (arguments.length) {
+ let vals;
+ if (this[arraySchemaSymbol] == null) {
+ vals = arguments;
+ } else {
+ vals = [];
+ for (let i = 0; i < arguments.length; ++i) {
+ vals[i] = i < 2 ?
+ arguments[i] :
+ this._cast(arguments[i], arguments[0] + (i - 2));
+ }
+ }
+
+ ret = [].splice.apply(this, vals);
+ this._registerAtomic('$set', this);
+ }
+
+ return ret;
+ }
+
+ /*!
+ * ignore
+ */
+
+ slice() {
+ const ret = super.slice.apply(this, arguments);
+ ret[arrayParentSymbol] = this[arrayParentSymbol];
+ ret[arraySchemaSymbol] = this[arraySchemaSymbol];
+ ret[arrayAtomicsSymbol] = this[arrayAtomicsSymbol];
+ ret[slicedSymbol] = true;
+ return ret;
+ }
+
+ /*!
+ * ignore
+ */
+
+ toBSON() {
+ return this.toObject(internalToObjectOptions);
+ }
+
+ /**
+ * Returns a native js Array.
+ *
+ * @param {Object} options
+ * @return {Array}
+ * @api public
+ * @method toObject
+ * @memberOf MongooseArray
+ */
+
+ toObject(options) {
+ if (options && options.depopulate) {
+ options = utils.clone(options);
+ options._isNested = true;
+ return this.map(function(doc) {
+ return doc instanceof Document
+ ? doc.toObject(options)
+ : doc;
+ });
+ }
+
+ return this.slice();
+ }
+
+ /**
+ * Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
+ *
+ * ####Note:
+ *
+ * _marks the entire array as modified, which if saved, will store it as a `$set` operation, potentially overwriting any changes that happen between when you retrieved the object and when you save it._
+ *
+ * @api public
+ * @method unshift
+ * @memberOf MongooseArray
+ */
+
+ unshift() {
+ _checkManualPopulation(this, arguments);
+
+ let values;
+ if (this[arraySchemaSymbol] == null) {
+ values = arguments;
+ } else {
+ values = [].map.call(arguments, this._cast, this);
+ values = this[arraySchemaSymbol].applySetters(values, this[arrayParentSymbol]);
+ }
+
+ [].unshift.apply(this, values);
+ this._registerAtomic('$set', this);
+ this._markModified();
+ return this.length;
+ }
+}
+
+if (util.inspect.custom) {
+ CoreMongooseArray.prototype[util.inspect.custom] =
+ CoreMongooseArray.prototype.inspect;
+}
+
+/*!
+ * ignore
+ */
+
+function _isAllSubdocs(docs, ref) {
+ if (!ref) {
+ return false;
+ }
+
+ for (const arg of docs) {
+ if (arg == null) {
+ return false;
+ }
+ const model = arg.constructor;
+ if (!(arg instanceof Document) ||
+ (model.modelName !== ref && model.baseModelName !== ref)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*!
+ * ignore
+ */
+
+function _checkManualPopulation(arr, docs) {
+ const ref = arr == null ?
+ null :
+ get(arr[arraySchemaSymbol], 'caster.options.ref', null);
+ if (arr.length === 0 &&
+ docs.length > 0) {
+ if (_isAllSubdocs(docs, ref)) {
+ arr[arrayParentSymbol].populated(arr[arrayPathSymbol], [], {
+ [populateModelSymbol]: docs[0].constructor
+ });
+ }
+ }
+}
+
+module.exports = CoreMongooseArray;
diff --git a/node_modules/mongoose/lib/types/decimal128.js b/node_modules/mongoose/lib/types/decimal128.js
new file mode 100644
index 0000000..cb08861
--- /dev/null
+++ b/node_modules/mongoose/lib/types/decimal128.js
@@ -0,0 +1,13 @@
+/**
+ * ObjectId type constructor
+ *
+ * ####Example
+ *
+ * const id = new mongoose.Types.ObjectId;
+ *
+ * @constructor ObjectId
+ */
+
+'use strict';
+
+module.exports = require('../driver').get().Decimal128;
diff --git a/node_modules/mongoose/lib/types/documentarray.js b/node_modules/mongoose/lib/types/documentarray.js
new file mode 100644
index 0000000..2855ae4
--- /dev/null
+++ b/node_modules/mongoose/lib/types/documentarray.js
@@ -0,0 +1,421 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const CoreMongooseArray = require('./core_array');
+const Document = require('../document');
+const ObjectId = require('./objectid');
+const castObjectId = require('../cast/objectid');
+const getDiscriminatorByValue = require('../helpers/discriminator/getDiscriminatorByValue');
+const internalToObjectOptions = require('../options').internalToObjectOptions;
+const util = require('util');
+const utils = require('../utils');
+
+const arrayAtomicsSymbol = require('../helpers/symbols').arrayAtomicsSymbol;
+const arrayParentSymbol = require('../helpers/symbols').arrayParentSymbol;
+const arrayPathSymbol = require('../helpers/symbols').arrayPathSymbol;
+const arraySchemaSymbol = require('../helpers/symbols').arraySchemaSymbol;
+const documentArrayParent = require('../helpers/symbols').documentArrayParent;
+
+const _basePush = Array.prototype.push;
+
+class CoreDocumentArray extends CoreMongooseArray {
+ get isMongooseDocumentArray() {
+ return true;
+ }
+
+ /*!
+ * ignore
+ */
+
+ toBSON() {
+ return this.toObject(internalToObjectOptions);
+ }
+
+ /*!
+ * ignore
+ */
+
+ map() {
+ const ret = super.map.apply(this, arguments);
+ ret[arraySchemaSymbol] = null;
+ ret[arrayPathSymbol] = null;
+ ret[arrayParentSymbol] = null;
+
+ return ret;
+ }
+
+ /**
+ * Overrides MongooseArray#cast
+ *
+ * @method _cast
+ * @api private
+ * @receiver MongooseDocumentArray
+ */
+
+ _cast(value, index) {
+ if (this[arraySchemaSymbol] == null) {
+ return value;
+ }
+ let Constructor = this[arraySchemaSymbol].casterConstructor;
+ const isInstance = Constructor.$isMongooseDocumentArray ?
+ value && value.isMongooseDocumentArray :
+ value instanceof Constructor;
+ if (isInstance ||
+ // Hack re: #5001, see #5005
+ (value && value.constructor && value.constructor.baseCasterConstructor === Constructor)) {
+ if (!(value[documentArrayParent] && value.__parentArray)) {
+ // value may have been created using array.create()
+ value[documentArrayParent] = this[arrayParentSymbol];
+ value.__parentArray = this;
+ }
+ value.$setIndex(index);
+ return value;
+ }
+
+ if (value === undefined || value === null) {
+ return null;
+ }
+
+ // handle cast('string') or cast(ObjectId) etc.
+ // only objects are permitted so we can safely assume that
+ // non-objects are to be interpreted as _id
+ if (Buffer.isBuffer(value) ||
+ value instanceof ObjectId || !utils.isObject(value)) {
+ value = { _id: value };
+ }
+
+ if (value &&
+ Constructor.discriminators &&
+ Constructor.schema &&
+ Constructor.schema.options &&
+ Constructor.schema.options.discriminatorKey) {
+ if (typeof value[Constructor.schema.options.discriminatorKey] === 'string' &&
+ 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]);
+ if (constructorByValue) {
+ Constructor = constructorByValue;
+ }
+ }
+ }
+
+ if (Constructor.$isMongooseDocumentArray) {
+ return Constructor.cast(value, this, undefined, undefined, index);
+ }
+ return new Constructor(value, this, undefined, undefined, index);
+ }
+
+ /**
+ * Searches array items for the first document with a matching _id.
+ *
+ * ####Example:
+ *
+ * const embeddedDoc = m.array.id(some_id);
+ *
+ * @return {EmbeddedDocument|null} the subdocument or null if not found.
+ * @param {ObjectId|String|Number|Buffer} id
+ * @TODO cast to the _id based on schema for proper comparison
+ * @method id
+ * @api public
+ * @receiver MongooseDocumentArray
+ */
+
+ id(id) {
+ let casted;
+ let sid;
+ let _id;
+
+ try {
+ casted = castObjectId(id).toString();
+ } catch (e) {
+ casted = null;
+ }
+
+ for (const val of this) {
+ if (!val) {
+ continue;
+ }
+
+ _id = val.get('_id');
+
+ if (_id === null || typeof _id === 'undefined') {
+ continue;
+ } else if (_id instanceof Document) {
+ sid || (sid = String(id));
+ if (sid == _id._id) {
+ return val;
+ }
+ } else if (!(id instanceof ObjectId) && !(_id instanceof ObjectId)) {
+ if (id == _id || utils.deepEqual(id, _id)) {
+ return val;
+ }
+ } else if (casted == _id) {
+ return val;
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Returns a native js Array of plain js objects
+ *
+ * ####NOTE:
+ *
+ * _Each sub-document is converted to a plain object by calling its `#toObject` method._
+ *
+ * @param {Object} [options] optional options to pass to each documents `toObject` method call during conversion
+ * @return {Array}
+ * @method toObject
+ * @api public
+ * @receiver MongooseDocumentArray
+ */
+
+ toObject(options) {
+ // `[].concat` coerces the return value into a vanilla JS array, rather
+ // than a Mongoose array.
+ return [].concat(this.map(function(doc) {
+ if (doc == null) {
+ return null;
+ }
+ if (typeof doc.toObject !== 'function') {
+ return doc;
+ }
+ return doc.toObject(options);
+ }));
+ }
+
+ slice() {
+ const arr = super.slice.apply(this, arguments);
+ arr[arrayParentSymbol] = this[arrayParentSymbol];
+ arr[arrayPathSymbol] = this[arrayPathSymbol];
+
+ return arr;
+ }
+
+ /**
+ * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
+ *
+ * @param {Object} [args...]
+ * @api public
+ * @method push
+ * @memberOf MongooseDocumentArray
+ */
+
+ push() {
+ const ret = super.push.apply(this, arguments);
+
+ _updateParentPopulated(this);
+
+ return ret;
+ }
+
+ /**
+ * Pulls items from the array atomically.
+ *
+ * @param {Object} [args...]
+ * @api public
+ * @method pull
+ * @memberOf MongooseDocumentArray
+ */
+
+ pull() {
+ const ret = super.pull.apply(this, arguments);
+
+ _updateParentPopulated(this);
+
+ return ret;
+ }
+
+ /**
+ * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
+ */
+
+ shift() {
+ const ret = super.shift.apply(this, arguments);
+
+ _updateParentPopulated(this);
+
+ return ret;
+ }
+
+ /**
+ * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
+ */
+
+ splice() {
+ const ret = super.splice.apply(this, arguments);
+
+ _updateParentPopulated(this);
+
+ return ret;
+ }
+
+ /**
+ * Helper for console.log
+ *
+ * @method inspect
+ * @api public
+ * @receiver MongooseDocumentArray
+ */
+
+ inspect() {
+ return this.toObject();
+ }
+
+ /**
+ * Creates a subdocument casted to this schema.
+ *
+ * This is the same subdocument constructor used for casting.
+ *
+ * @param {Object} obj the value to cast to this arrays SubDocument schema
+ * @method create
+ * @api public
+ * @receiver MongooseDocumentArray
+ */
+
+ create(obj) {
+ let Constructor = this[arraySchemaSymbol].casterConstructor;
+ if (obj &&
+ Constructor.discriminators &&
+ Constructor.schema &&
+ Constructor.schema.options &&
+ Constructor.schema.options.discriminatorKey) {
+ if (typeof obj[Constructor.schema.options.discriminatorKey] === 'string' &&
+ 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]);
+ if (constructorByValue) {
+ Constructor = constructorByValue;
+ }
+ }
+ }
+
+ return new Constructor(obj, this);
+ }
+
+ /*!
+ * ignore
+ */
+
+ notify(event) {
+ const _this = this;
+ return function notify(val, _arr) {
+ _arr = _arr || _this;
+ let i = _arr.length;
+ while (i--) {
+ if (_arr[i] == null) {
+ continue;
+ }
+ switch (event) {
+ // only swap for save event for now, we may change this to all event types later
+ case 'save':
+ val = _this[i];
+ break;
+ default:
+ // NO-OP
+ break;
+ }
+
+ if (_arr[i].isMongooseArray) {
+ notify(val, _arr[i]);
+ } else if (_arr[i]) {
+ _arr[i].emit(event, val);
+ }
+ }
+ };
+ }
+}
+
+if (util.inspect.custom) {
+ CoreDocumentArray.prototype[util.inspect.custom] =
+ CoreDocumentArray.prototype.inspect;
+}
+
+/*!
+ * If this is a document array, each element may contain single
+ * populated paths, so we need to modify the top-level document's
+ * populated cache. See gh-8247, gh-8265.
+ */
+
+function _updateParentPopulated(arr) {
+ const parent = arr[arrayParentSymbol];
+ if (!parent || parent.$__.populated == null) return;
+
+ const populatedPaths = Object.keys(parent.$__.populated).
+ filter(p => p.startsWith(arr[arrayPathSymbol] + '.'));
+
+ for (const path of populatedPaths) {
+ const remnant = path.slice((arr[arrayPathSymbol] + '.').length);
+ if (!Array.isArray(parent.$__.populated[path].value)) {
+ continue;
+ }
+
+ parent.$__.populated[path].value = arr.map(val => val.populated(remnant));
+ }
+}
+
+/**
+ * DocumentArray constructor
+ *
+ * @param {Array} values
+ * @param {String} path the path to this array
+ * @param {Document} doc parent document
+ * @api private
+ * @return {MongooseDocumentArray}
+ * @inherits MongooseArray
+ * @see http://bit.ly/f6CnZU
+ */
+
+function MongooseDocumentArray(values, path, doc) {
+ // TODO: replace this with `new CoreDocumentArray().concat()` when we remove
+ // support for node 4.x and 5.x, see https://i.imgur.com/UAAHk4S.png
+ const arr = new CoreDocumentArray();
+
+ arr[arrayAtomicsSymbol] = {};
+ arr[arraySchemaSymbol] = void 0;
+ if (Array.isArray(values)) {
+ if (values instanceof CoreDocumentArray &&
+ values[arrayPathSymbol] === path &&
+ values[arrayParentSymbol] === doc) {
+ arr[arrayAtomicsSymbol] = Object.assign({}, values[arrayAtomicsSymbol]);
+ }
+ values.forEach(v => {
+ _basePush.call(arr, v);
+ });
+ }
+ arr[arrayPathSymbol] = path;
+
+ // Because doc comes from the context of another function, doc === global
+ // can happen if there was a null somewhere up the chain (see #3020 && #3034)
+ // 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) {
+ arr[arrayParentSymbol] = doc;
+ arr[arraySchemaSymbol] = doc.schema.path(path);
+
+ // `schema.path()` doesn't drill into nested arrays properly yet, see
+ // gh-6398, gh-6602. This is a workaround because nested arrays are
+ // always plain non-document arrays, so once you get to a document array
+ // nesting is done. Matryoshka code.
+ while (arr != null &&
+ arr[arraySchemaSymbol] != null &&
+ arr[arraySchemaSymbol].$isMongooseArray &&
+ !arr[arraySchemaSymbol].$isMongooseDocumentArray) {
+ arr[arraySchemaSymbol] = arr[arraySchemaSymbol].casterConstructor;
+ }
+ }
+
+ return arr;
+}
+
+/*!
+ * Module exports.
+ */
+
+module.exports = MongooseDocumentArray;
diff --git a/node_modules/mongoose/lib/types/embedded.js b/node_modules/mongoose/lib/types/embedded.js
new file mode 100644
index 0000000..18a9778
--- /dev/null
+++ b/node_modules/mongoose/lib/types/embedded.js
@@ -0,0 +1,446 @@
+/* eslint no-func-assign: 1 */
+
+/*!
+ * Module dependencies.
+ */
+
+'use strict';
+
+const Document = require('../document_provider')();
+const EventEmitter = require('events').EventEmitter;
+const ValidationError = require('../error/validation');
+const immediate = require('../helpers/immediate');
+const internalToObjectOptions = require('../options').internalToObjectOptions;
+const get = require('../helpers/get');
+const promiseOrCallback = require('../helpers/promiseOrCallback');
+const util = require('util');
+
+const documentArrayParent = require('../helpers/symbols').documentArrayParent;
+const validatorErrorSymbol = require('../helpers/symbols').validatorErrorSymbol;
+
+/**
+ * EmbeddedDocument constructor.
+ *
+ * @param {Object} obj js object returned from the db
+ * @param {MongooseDocumentArray} parentArr the parent array of this document
+ * @param {Boolean} skipId
+ * @inherits Document
+ * @api private
+ */
+
+function EmbeddedDocument(obj, parentArr, skipId, fields, index) {
+ if (parentArr != null && parentArr.isMongooseDocumentArray) {
+ this.__parentArray = parentArr;
+ this[documentArrayParent] = parentArr.$parent();
+ } else {
+ this.__parentArray = undefined;
+ this[documentArrayParent] = undefined;
+ }
+ this.$setIndex(index);
+ this.$isDocumentArrayElement = true;
+
+ Document.call(this, obj, fields, skipId);
+
+ const _this = this;
+ this.on('isNew', function(val) {
+ _this.isNew = val;
+ });
+
+ _this.on('save', function() {
+ _this.constructor.emit('save', _this);
+ });
+}
+
+/*!
+ * Inherit from Document
+ */
+EmbeddedDocument.prototype = Object.create(Document.prototype);
+EmbeddedDocument.prototype.constructor = EmbeddedDocument;
+
+for (const i in EventEmitter.prototype) {
+ EmbeddedDocument[i] = EventEmitter.prototype[i];
+}
+
+EmbeddedDocument.prototype.toBSON = function() {
+ return this.toObject(internalToObjectOptions);
+};
+
+/*!
+ * ignore
+ */
+
+EmbeddedDocument.prototype.$setIndex = function(index) {
+ this.__index = index;
+
+ if (get(this, '$__.validationError', null) != null) {
+ const keys = Object.keys(this.$__.validationError.errors);
+ for (const key of keys) {
+ this.invalidate(key, this.$__.validationError.errors[key]);
+ }
+ }
+};
+
+/**
+ * Marks the embedded doc modified.
+ *
+ * ####Example:
+ *
+ * const doc = blogpost.comments.id(hexstring);
+ * doc.mixed.type = 'changed';
+ * doc.markModified('mixed.type');
+ *
+ * @param {String} path the path which changed
+ * @api public
+ * @receiver EmbeddedDocument
+ */
+
+EmbeddedDocument.prototype.markModified = function(path) {
+ this.$__.activePaths.modify(path);
+ if (!this.__parentArray) {
+ return;
+ }
+
+ 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),
+ this.__parentArray._markModified();
+ } else {
+ this.__parentArray._markModified(this, path);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+EmbeddedDocument.prototype.populate = function() {
+ throw new Error('Mongoose does not support calling populate() on nested ' +
+ 'docs. Instead of `doc.arr[0].populate("path")`, use ' +
+ '`doc.populate("arr.0.path")`');
+};
+
+/**
+ * Used as a stub for [hooks.js](https://github.com/bnoguchi/hooks-js/tree/31ec571cef0332e21121ee7157e0cf9728572cc3)
+ *
+ * ####NOTE:
+ *
+ * _This is a no-op. Does not actually save the doc to the db._
+ *
+ * @param {Function} [fn]
+ * @return {Promise} resolved Promise
+ * @api private
+ */
+
+EmbeddedDocument.prototype.save = function(options, fn) {
+ if (typeof options === 'function') {
+ fn = options;
+ options = {};
+ }
+ options = options || {};
+
+ if (!options.suppressWarning) {
+ console.warn('mongoose: calling `save()` on a subdoc does **not** save ' +
+ 'the document to MongoDB, it only runs save middleware. ' +
+ 'Use `subdoc.save({ suppressWarning: true })` to hide this warning ' +
+ 'if you\'re sure this behavior is right for your app.');
+ }
+
+ return promiseOrCallback(fn, cb => {
+ this.$__save(cb);
+ });
+};
+
+/**
+ * Used as a stub for middleware
+ *
+ * ####NOTE:
+ *
+ * _This is a no-op. Does not actually save the doc to the db._
+ *
+ * @param {Function} [fn]
+ * @method $__save
+ * @api private
+ */
+
+EmbeddedDocument.prototype.$__save = function(fn) {
+ return immediate(() => fn(null, this));
+};
+
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {EmbeddedDocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+ let owner = sub.ownerDocument();
+
+ function emitRemove() {
+ owner.removeListener('save', emitRemove);
+ owner.removeListener('remove', emitRemove);
+ sub.emit('remove', sub);
+ sub.constructor.emit('remove', sub);
+ owner = sub = null;
+ }
+
+ owner.on('save', emitRemove);
+ owner.on('remove', emitRemove);
+}
+
+/*!
+ * no-op for hooks
+ */
+
+EmbeddedDocument.prototype.$__remove = function(cb) {
+ return cb(null, this);
+};
+
+/**
+ * Removes the subdocument from its parent array.
+ *
+ * @param {Object} [options]
+ * @param {Function} [fn]
+ * @api public
+ */
+
+EmbeddedDocument.prototype.remove = function(options, fn) {
+ if (typeof options === 'function' && !fn) {
+ fn = options;
+ options = undefined;
+ }
+ if (!this.__parentArray || (options && options.noop)) {
+ fn && fn(null);
+ return this;
+ }
+
+ let _id;
+ if (!this.willRemove) {
+ _id = this._doc._id;
+ if (!_id) {
+ throw new Error('For your own good, Mongoose does not know ' +
+ 'how to remove an EmbeddedDocument that has no _id');
+ }
+ this.__parentArray.pull({ _id: _id });
+ this.willRemove = true;
+ registerRemoveListener(this);
+ }
+
+ if (fn) {
+ fn(null);
+ }
+
+ return this;
+};
+
+/**
+ * Override #update method of parent documents.
+ * @api private
+ */
+
+EmbeddedDocument.prototype.update = function() {
+ throw new Error('The #update method is not available on EmbeddedDocuments');
+};
+
+/**
+ * Helper for console.log
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.inspect = function() {
+ return this.toObject({
+ transform: false,
+ virtuals: false,
+ flattenDecimals: false
+ });
+};
+
+if (util.inspect.custom) {
+ /*!
+ * Avoid Node deprecation warning DEP0079
+ */
+
+ EmbeddedDocument.prototype[util.inspect.custom] = EmbeddedDocument.prototype.inspect;
+}
+
+/**
+ * Marks a path as invalid, causing validation to fail.
+ *
+ * @param {String} path the field to invalidate
+ * @param {String|Error} err error which states the reason `path` was invalid
+ * @return {Boolean}
+ * @api public
+ */
+
+EmbeddedDocument.prototype.invalidate = function(path, err, val) {
+ Document.prototype.invalidate.call(this, path, err, val);
+
+ if (!this[documentArrayParent] || this.__index == null) {
+ if (err[validatorErrorSymbol] || err instanceof ValidationError) {
+ return this.ownerDocument().$__.validationError;
+ }
+ throw err;
+ }
+
+ const index = this.__index;
+ const parentPath = this.__parentArray.$path();
+ const fullPath = [parentPath, index, path].join('.');
+ this[documentArrayParent].invalidate(fullPath, err, val);
+
+ return this.ownerDocument().$__.validationError;
+};
+
+/**
+ * Marks a path as valid, removing existing validation errors.
+ *
+ * @param {String} path the field to mark as valid
+ * @api private
+ * @method $markValid
+ * @receiver EmbeddedDocument
+ */
+
+EmbeddedDocument.prototype.$markValid = function(path) {
+ if (!this[documentArrayParent]) {
+ return;
+ }
+
+ const index = this.__index;
+ if (typeof index !== 'undefined') {
+ const parentPath = this.__parentArray.$path();
+ const fullPath = [parentPath, index, path].join('.');
+ this[documentArrayParent].$markValid(fullPath);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+EmbeddedDocument.prototype.$ignore = function(path) {
+ Document.prototype.$ignore.call(this, path);
+
+ if (!this[documentArrayParent]) {
+ return;
+ }
+
+ const index = this.__index;
+ if (typeof index !== 'undefined') {
+ const parentPath = this.__parentArray.$path();
+ const fullPath = [parentPath, index, path].join('.');
+ this[documentArrayParent].$ignore(fullPath);
+ }
+};
+
+/**
+ * Checks if a path is invalid
+ *
+ * @param {String} path the field to check
+ * @api private
+ * @method $isValid
+ * @receiver EmbeddedDocument
+ */
+
+EmbeddedDocument.prototype.$isValid = function(path) {
+ const index = this.__index;
+ if (typeof index !== 'undefined' && this[documentArrayParent]) {
+ return !this[documentArrayParent].$__.validationError ||
+ !this[documentArrayParent].$__.validationError.errors[this.$__fullPath(path)];
+ }
+
+ return true;
+};
+
+/**
+ * Returns the top level document of this sub-document.
+ *
+ * @return {Document}
+ */
+
+EmbeddedDocument.prototype.ownerDocument = function() {
+ if (this.$__.ownerDocument) {
+ return this.$__.ownerDocument;
+ }
+
+ let parent = this[documentArrayParent];
+ if (!parent) {
+ return this;
+ }
+
+ while (parent[documentArrayParent] || parent.$parent) {
+ parent = parent[documentArrayParent] || parent.$parent;
+ }
+
+ this.$__.ownerDocument = parent;
+ return this.$__.ownerDocument;
+};
+
+/**
+ * Returns the full path to this document. If optional `path` is passed, it is appended to the full path.
+ *
+ * @param {String} [path]
+ * @return {String}
+ * @api private
+ * @method $__fullPath
+ * @memberOf EmbeddedDocument
+ * @instance
+ */
+
+EmbeddedDocument.prototype.$__fullPath = function(path) {
+ if (!this.$__.fullPath) {
+ let parent = this; // eslint-disable-line consistent-this
+ if (!parent[documentArrayParent]) {
+ return path;
+ }
+
+ const paths = [];
+ while (parent[documentArrayParent] || parent.$parent) {
+ if (parent[documentArrayParent]) {
+ paths.unshift(parent.__parentArray.$path());
+ } else {
+ paths.unshift(parent.$basePath);
+ }
+ parent = parent[documentArrayParent] || parent.$parent;
+ }
+
+ this.$__.fullPath = paths.join('.');
+
+ if (!this.$__.ownerDocument) {
+ // optimization
+ this.$__.ownerDocument = parent;
+ }
+ }
+
+ return path
+ ? this.$__.fullPath + '.' + path
+ : this.$__.fullPath;
+};
+
+/**
+ * Returns this sub-documents parent document.
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.parent = function() {
+ return this[documentArrayParent];
+};
+
+/**
+ * Returns this sub-documents parent array.
+ *
+ * @api public
+ */
+
+EmbeddedDocument.prototype.parentArray = function() {
+ return this.__parentArray;
+};
+
+/*!
+ * Module exports.
+ */
+
+module.exports = EmbeddedDocument;
diff --git a/node_modules/mongoose/lib/types/index.js b/node_modules/mongoose/lib/types/index.js
new file mode 100644
index 0000000..a1945a0
--- /dev/null
+++ b/node_modules/mongoose/lib/types/index.js
@@ -0,0 +1,20 @@
+
+/*!
+ * Module exports.
+ */
+
+'use strict';
+
+exports.Array = require('./array');
+exports.Buffer = require('./buffer');
+
+exports.Document = // @deprecate
+exports.Embedded = require('./embedded');
+
+exports.DocumentArray = require('./documentarray');
+exports.Decimal128 = require('./decimal128');
+exports.ObjectId = require('./objectid');
+
+exports.Map = require('./map');
+
+exports.Subdocument = require('./subdocument');
diff --git a/node_modules/mongoose/lib/types/map.js b/node_modules/mongoose/lib/types/map.js
new file mode 100644
index 0000000..f50402e
--- /dev/null
+++ b/node_modules/mongoose/lib/types/map.js
@@ -0,0 +1,226 @@
+'use strict';
+
+const Mixed = require('../schema/mixed');
+const deepEqual = require('../utils').deepEqual;
+const get = require('../helpers/get');
+const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
+const util = require('util');
+const specialProperties = require('../helpers/specialProperties');
+
+const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
+
+/*!
+ * ignore
+ */
+
+class MongooseMap extends Map {
+ constructor(v, path, doc, schemaType) {
+ if (v != null && v.constructor.name === '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;
+
+ this.$__runDeferred();
+ }
+
+ $init(key, value) {
+ checkValidKey(key);
+
+ super.set(key, value);
+
+ if (value != null && value.$isSingleNested) {
+ value.$basePath = this.$__path + '.' + key;
+ }
+ }
+
+ $__set(key, value) {
+ super.set(key, value);
+ }
+
+ get(key, options) {
+ options = options || {};
+ if (options.getters === false) {
+ return super.get(key);
+ }
+ return this.$__schemaType.applyGetters(super.get(key), this.$__parent);
+ }
+
+ set(key, value) {
+ checkValidKey(key);
+ value = handleSpreadDoc(value);
+
+ // Weird, but because you can't assign to `this` before calling `super()`
+ // you can't get access to `$__schemaType` to cast in the initial call to
+ // `set()` from the `super()` constructor.
+
+ if (this.$__schemaType == null) {
+ this.$__deferred = this.$__deferred || [];
+ this.$__deferred.push({ key: key, value: value });
+ return;
+ }
+
+ const fullPath = this.$__path + '.' + key;
+ const populated = this.$__parent != null && this.$__parent.$__ ?
+ this.$__parent.populated(fullPath) || this.$__parent.populated(this.$__path) :
+ null;
+ const priorVal = this.get(key);
+
+ if (populated != null) {
+ if (value.$__ == null) {
+ value = new populated.options[populateModelSymbol](value);
+ }
+ value.$__.wasPopulated = true;
+ } else {
+ try {
+ value = this.$__schemaType.
+ applySetters(value, this.$__parent, false, this.get(key));
+ } catch (error) {
+ if (this.$__parent != null && this.$__parent.$__ != null) {
+ this.$__parent.invalidate(fullPath, error);
+ return;
+ }
+ throw error;
+ }
+ }
+
+ super.set(key, value);
+
+ if (value != null && value.$isSingleNested) {
+ value.$basePath = this.$__path + '.' + key;
+ }
+
+ const parent = this.$__parent;
+ if (parent != null && parent.$__ != null && !deepEqual(value, priorVal)) {
+ parent.markModified(this.$__path + '.' + key);
+ }
+ }
+
+ clear() {
+ super.clear();
+ const parent = this.$__parent;
+ if (parent != null) {
+ parent.markModified(this.$__path);
+ }
+ }
+
+ delete(key) {
+ this.set(key, undefined);
+ super.delete(key);
+ }
+
+ toBSON() {
+ return new Map(this);
+ }
+
+ toObject(options) {
+ if (get(options, 'flattenMaps')) {
+ const ret = {};
+ const keys = this.keys();
+ for (const key of keys) {
+ ret[key] = this.get(key);
+ }
+ return ret;
+ }
+
+ return new Map(this);
+ }
+
+ toJSON() {
+ const ret = {};
+ const keys = this.keys();
+ for (const key of keys) {
+ ret[key] = this.get(key);
+ }
+ return ret;
+ }
+
+ inspect() {
+ return new Map(this);
+ }
+
+ $__runDeferred() {
+ if (!this.$__deferred) {
+ return;
+ }
+
+ for (const keyValueObject of this.$__deferred) {
+ this.set(keyValueObject.key, keyValueObject.value);
+ }
+
+ this.$__deferred = null;
+ }
+}
+
+if (util.inspect.custom) {
+ Object.defineProperty(MongooseMap.prototype, util.inspect.custom, {
+ enumerable: false,
+ writable: false,
+ configurable: false,
+ value: MongooseMap.prototype.inspect
+ });
+}
+
+Object.defineProperty(MongooseMap.prototype, '$__set', {
+ enumerable: false,
+ writable: true,
+ configurable: false
+});
+
+Object.defineProperty(MongooseMap.prototype, '$__parent', {
+ enumerable: false,
+ writable: true,
+ configurable: false
+});
+
+Object.defineProperty(MongooseMap.prototype, '$__path', {
+ enumerable: false,
+ writable: true,
+ configurable: false
+});
+
+Object.defineProperty(MongooseMap.prototype, '$__schemaType', {
+ enumerable: false,
+ writable: true,
+ configurable: false
+});
+
+Object.defineProperty(MongooseMap.prototype, '$isMongooseMap', {
+ enumerable: false,
+ writable: false,
+ configurable: false,
+ value: true
+});
+
+Object.defineProperty(MongooseMap.prototype, '$__deferredCalls', {
+ enumerable: false,
+ writable: false,
+ configurable: false,
+ value: true
+});
+
+/*!
+ * Since maps are stored as objects under the hood, keys must be strings
+ * and can't contain any invalid characters
+ */
+
+function checkValidKey(key) {
+ const keyType = typeof key;
+ if (keyType !== 'string') {
+ throw new TypeError(`Mongoose maps only support string keys, got ${keyType}`);
+ }
+ if (key.startsWith('$')) {
+ throw new Error(`Mongoose maps do not support keys that start with "$", got "${key}"`);
+ }
+ if (key.includes('.')) {
+ throw new Error(`Mongoose maps do not support keys that contain ".", got "${key}"`);
+ }
+ if (specialProperties.has(key)) {
+ throw new Error(`Mongoose maps do not support reserved key name "${key}"`);
+ }
+}
+
+module.exports = MongooseMap;
diff --git a/node_modules/mongoose/lib/types/objectid.js b/node_modules/mongoose/lib/types/objectid.js
new file mode 100644
index 0000000..19e3d90
--- /dev/null
+++ b/node_modules/mongoose/lib/types/objectid.js
@@ -0,0 +1,30 @@
+/**
+ * ObjectId type constructor
+ *
+ * ####Example
+ *
+ * const id = new mongoose.Types.ObjectId;
+ *
+ * @constructor ObjectId
+ */
+
+'use strict';
+
+const ObjectId = require('../driver').get().ObjectId;
+const objectIdSymbol = require('../helpers/symbols').objectIdSymbol;
+
+/*!
+ * Getter for convenience with populate, see gh-6115
+ */
+
+Object.defineProperty(ObjectId.prototype, '_id', {
+ enumerable: false,
+ configurable: true,
+ get: function() {
+ return this;
+ }
+});
+
+ObjectId.prototype[objectIdSymbol] = true;
+
+module.exports = ObjectId;
diff --git a/node_modules/mongoose/lib/types/subdocument.js b/node_modules/mongoose/lib/types/subdocument.js
new file mode 100644
index 0000000..d6494ff
--- /dev/null
+++ b/node_modules/mongoose/lib/types/subdocument.js
@@ -0,0 +1,292 @@
+'use strict';
+
+const Document = require('../document');
+const immediate = require('../helpers/immediate');
+const internalToObjectOptions = require('../options').internalToObjectOptions;
+const promiseOrCallback = require('../helpers/promiseOrCallback');
+
+const documentArrayParent = require('../helpers/symbols').documentArrayParent;
+
+module.exports = Subdocument;
+
+/**
+ * Subdocument constructor.
+ *
+ * @inherits Document
+ * @api private
+ */
+
+function Subdocument(value, fields, parent, skipId, options) {
+ this.$isSingleNested = true;
+
+ 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];
+ initedPaths = Object.keys(options.priorDoc._doc || {}).
+ 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,
+ defaults: parent.$__.$options.defaults
+ });
+ }
+ Document.call(this, value, fields, skipId, options);
+
+ if (hasPriorDoc) {
+ for (const key of initedPaths) {
+ if (!this.$__.activePaths.states.modify[key] &&
+ !this.$__.activePaths.states.default[key] &&
+ !this.$__.$setCalled.has(key)) {
+ const schematype = this.schema.path(key);
+ const def = schematype == null ? void 0 : schematype.getDefault(this);
+ if (def === void 0) {
+ delete this._doc[key];
+ } else {
+ this._doc[key] = def;
+ this.$__.activePaths.default(key);
+ }
+ }
+ }
+
+ delete options.priorDoc;
+ delete this.$__.$options.priorDoc;
+ }
+}
+
+Subdocument.prototype = Object.create(Document.prototype);
+
+Subdocument.prototype.toBSON = function() {
+ return this.toObject(internalToObjectOptions);
+};
+
+/**
+ * Used as a stub for middleware
+ *
+ * ####NOTE:
+ *
+ * _This is a no-op. Does not actually save the doc to the db._
+ *
+ * @param {Function} [fn]
+ * @return {Promise} resolved Promise
+ * @api private
+ */
+
+Subdocument.prototype.save = function(options, fn) {
+ if (typeof options === 'function') {
+ fn = options;
+ options = {};
+ }
+ options = options || {};
+
+ if (!options.suppressWarning) {
+ console.warn('mongoose: calling `save()` on a subdoc does **not** save ' +
+ 'the document to MongoDB, it only runs save middleware. ' +
+ 'Use `subdoc.save({ suppressWarning: true })` to hide this warning ' +
+ 'if you\'re sure this behavior is right for your app.');
+ }
+
+ return promiseOrCallback(fn, cb => {
+ this.$__save(cb);
+ });
+};
+
+/**
+ * Used as a stub for middleware
+ *
+ * ####NOTE:
+ *
+ * _This is a no-op. Does not actually save the doc to the db._
+ *
+ * @param {Function} [fn]
+ * @method $__save
+ * @api private
+ */
+
+Subdocument.prototype.$__save = function(fn) {
+ return immediate(() => fn(null, this));
+};
+
+Subdocument.prototype.$isValid = function(path) {
+ if (this.$parent && this.$basePath) {
+ return this.$parent.$isValid([this.$basePath, path].join('.'));
+ }
+ return Document.prototype.$isValid.call(this, path);
+};
+
+Subdocument.prototype.markModified = function(path) {
+ Document.prototype.markModified.call(this, path);
+
+ if (this.$parent && this.$basePath) {
+ if (this.$parent.isDirectModified(this.$basePath)) {
+ return;
+ }
+ this.$parent.markModified([this.$basePath, path].join('.'), this);
+ }
+};
+
+Subdocument.prototype.isModified = function(paths, modifiedPaths) {
+ 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(this.$basePath);
+ }
+
+ return Document.prototype.isModified.call(this, paths, modifiedPaths);
+};
+
+/**
+ * Marks a path as valid, removing existing validation errors.
+ *
+ * @param {String} path the field to mark as valid
+ * @api private
+ * @method $markValid
+ * @receiver Subdocument
+ */
+
+Subdocument.prototype.$markValid = function(path) {
+ Document.prototype.$markValid.call(this, path);
+ if (this.$parent && this.$basePath) {
+ this.$parent.$markValid([this.$basePath, path].join('.'));
+ }
+};
+
+/*!
+ * ignore
+ */
+
+Subdocument.prototype.invalidate = function(path, err, val) {
+ // Hack: array subdocuments' validationError is equal to the owner doc's,
+ // so validating an array subdoc gives the top-level doc back. Temporary
+ // workaround for #5208 so we don't have circular errors.
+ if (err !== this.ownerDocument().$__.validationError) {
+ Document.prototype.invalidate.call(this, path, 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;
+};
+
+/*!
+ * ignore
+ */
+
+Subdocument.prototype.$ignore = function(path) {
+ Document.prototype.$ignore.call(this, path);
+ if (this.$parent && this.$basePath) {
+ this.$parent.$ignore([this.$basePath, path].join('.'));
+ }
+};
+
+/**
+ * Returns the top level document of this sub-document.
+ *
+ * @return {Document}
+ */
+
+Subdocument.prototype.ownerDocument = function() {
+ if (this.$__.ownerDocument) {
+ return this.$__.ownerDocument;
+ }
+
+ let parent = this.$parent;
+ if (!parent) {
+ return this;
+ }
+
+ while (parent.$parent || parent[documentArrayParent]) {
+ parent = parent.$parent || parent[documentArrayParent];
+ }
+
+ this.$__.ownerDocument = parent;
+ return this.$__.ownerDocument;
+};
+
+/**
+ * Returns this sub-documents parent document.
+ *
+ * @api public
+ */
+
+Subdocument.prototype.parent = function() {
+ return this.$parent;
+};
+
+/*!
+ * no-op for hooks
+ */
+
+Subdocument.prototype.$__remove = function(cb) {
+ return cb(null, this);
+};
+
+/**
+ * Null-out this subdoc
+ *
+ * @param {Object} [options]
+ * @param {Function} [callback] optional callback for compatibility with Document.prototype.remove
+ */
+
+Subdocument.prototype.remove = function(options, callback) {
+ if (typeof options === 'function') {
+ 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);
+ }
+
+ if (typeof callback === 'function') {
+ callback(null);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+Subdocument.prototype.populate = function() {
+ throw new Error('Mongoose does not support calling populate() on nested ' +
+ 'docs. Instead of `doc.nested.populate("path")`, use ' +
+ '`doc.populate("nested.path")`');
+};
+
+/*!
+ * Registers remove event listeners for triggering
+ * on subdocuments.
+ *
+ * @param {Subdocument} sub
+ * @api private
+ */
+
+function registerRemoveListener(sub) {
+ let owner = sub.ownerDocument();
+
+ function emitRemove() {
+ owner.removeListener('save', emitRemove);
+ owner.removeListener('remove', emitRemove);
+ sub.emit('remove', sub);
+ sub.constructor.emit('remove', sub);
+ owner = sub = null;
+ }
+
+ owner.on('save', emitRemove);
+ owner.on('remove', emitRemove);
+}
diff --git a/node_modules/mongoose/lib/utils.js b/node_modules/mongoose/lib/utils.js
new file mode 100644
index 0000000..48b29aa
--- /dev/null
+++ b/node_modules/mongoose/lib/utils.js
@@ -0,0 +1,908 @@
+'use strict';
+
+/*!
+ * Module dependencies.
+ */
+
+const ms = require('ms');
+const mpath = require('mpath');
+const sliced = require('sliced');
+const Buffer = require('safe-buffer').Buffer;
+const Decimal = require('./types/decimal128');
+const ObjectId = require('./types/objectid');
+const PopulateOptions = require('./options/PopulateOptions');
+const clone = require('./helpers/clone');
+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 specialProperties = require('./helpers/specialProperties');
+
+let Document;
+
+exports.specialProperties = specialProperties;
+
+/*!
+ * Produces a collection name from model `name`. By default, just returns
+ * the model name
+ *
+ * @param {String} name a model name
+ * @param {Function} pluralize function that pluralizes the collection name
+ * @return {String} a collection name
+ * @api private
+ */
+
+exports.toCollectionName = function(name, pluralize) {
+ if (name === 'system.profile') {
+ return name;
+ }
+ if (name === 'system.indexes') {
+ return name;
+ }
+ if (typeof pluralize === 'function') {
+ return pluralize(name);
+ }
+ return name;
+};
+
+/*!
+ * Determines if `a` and `b` are deep equal.
+ *
+ * Modified from node/lib/assert.js
+ *
+ * @param {any} a a value to compare to `b`
+ * @param {any} b a value to compare to `a`
+ * @return {Boolean}
+ * @api private
+ */
+
+exports.deepEqual = function deepEqual(a, b) {
+ if (a === b) {
+ return true;
+ }
+
+ if (a instanceof Date && b instanceof Date) {
+ return a.getTime() === b.getTime();
+ }
+
+ if ((isBsonType(a, 'ObjectID') && isBsonType(b, 'ObjectID')) ||
+ (isBsonType(a, 'Decimal128') && isBsonType(b, 'Decimal128'))) {
+ return a.toString() === b.toString();
+ }
+
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return a.source === b.source &&
+ a.ignoreCase === b.ignoreCase &&
+ a.multiline === b.multiline &&
+ a.global === b.global;
+ }
+
+ if (typeof a !== 'object' && typeof b !== 'object') {
+ return a === b;
+ }
+
+ if (a === null || b === null || a === undefined || b === undefined) {
+ return false;
+ }
+
+ if (a.prototype !== b.prototype) {
+ return false;
+ }
+
+ // Handle MongooseNumbers
+ if (a instanceof Number && b instanceof Number) {
+ return a.valueOf() === b.valueOf();
+ }
+
+ if (Buffer.isBuffer(a)) {
+ return exports.buffer.areEqual(a, b);
+ }
+
+ if (isMongooseObject(a)) {
+ a = a.toObject();
+ }
+ 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;
+ }
+
+ // having the same number of owned properties (keys incorporates
+ // hasOwnProperty)
+ if (ka.length !== kb.length) {
+ return false;
+ }
+
+ // the same set of keys (although not necessarily the same order),
+ ka.sort();
+ kb.sort();
+
+ // ~~~cheap key test
+ for (i = ka.length - 1; i >= 0; i--) {
+ if (ka[i] !== kb[i]) {
+ return false;
+ }
+ }
+
+ // equivalent values for every corresponding key, and
+ // ~~~possibly expensive deep test
+ for (i = ka.length - 1; i >= 0; i--) {
+ key = ka[i];
+ if (!deepEqual(a[key], b[key])) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+/*!
+ * Get the last element of an array
+ */
+
+exports.last = function(arr) {
+ if (arr.length > 0) {
+ return arr[arr.length - 1];
+ }
+ return void 0;
+};
+
+exports.clone = clone;
+
+/*!
+ * ignore
+ */
+
+exports.promiseOrCallback = promiseOrCallback;
+
+/*!
+ * ignore
+ */
+
+exports.omit = function omit(obj, keys) {
+ if (keys == null) {
+ return Object.assign({}, obj);
+ }
+ if (!Array.isArray(keys)) {
+ keys = [keys];
+ }
+
+ const ret = Object.assign({}, obj);
+ for (const key of keys) {
+ delete ret[key];
+ }
+ return ret;
+};
+
+
+/*!
+ * Shallow copies defaults into options.
+ *
+ * @param {Object} defaults
+ * @param {Object} options
+ * @return {Object} the merged object
+ * @api private
+ */
+
+exports.options = function(defaults, options) {
+ const keys = Object.keys(defaults);
+ let i = keys.length;
+ let k;
+
+ options = options || {};
+
+ while (i--) {
+ k = keys[i];
+ if (!(k in options)) {
+ options[k] = defaults[k];
+ }
+ }
+
+ return options;
+};
+
+/*!
+ * Generates a random string
+ *
+ * @api private
+ */
+
+exports.random = function() {
+ return Math.random().toString().substr(3);
+};
+
+/*!
+ * Merges `from` into `to` without overwriting existing properties.
+ *
+ * @param {Object} to
+ * @param {Object} from
+ * @api private
+ */
+
+exports.merge = function merge(to, from, options, path) {
+ options = options || {};
+
+ const keys = Object.keys(from);
+ let i = 0;
+ const len = keys.length;
+ let key;
+
+ path = path || '';
+ const omitNested = options.omitNested || {};
+
+ while (i < len) {
+ key = keys[i++];
+ if (options.omit && options.omit[key]) {
+ continue;
+ }
+ if (omitNested[path]) {
+ continue;
+ }
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ if (to[key] == null) {
+ to[key] = from[key];
+ } else if (exports.isObject(from[key])) {
+ if (!exports.isObject(to[key])) {
+ to[key] = {};
+ }
+ if (from[key] != null) {
+ // 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());
+ } else {
+ to[key] = from[key].clone();
+ }
+ continue;
+ } else if (from[key] instanceof ObjectId) {
+ to[key] = new ObjectId(from[key]);
+ continue;
+ }
+ }
+ merge(to[key], from[key], options, path ? path + '.' + key : key);
+ } else if (options.overwrite) {
+ to[key] = from[key];
+ }
+ }
+};
+
+/*!
+ * Applies toObject recursively.
+ *
+ * @param {Document|Array|Object} obj
+ * @return {Object}
+ * @api private
+ */
+
+exports.toObject = function toObject(obj) {
+ Document || (Document = require('./document'));
+ let ret;
+
+ if (obj == null) {
+ return obj;
+ }
+
+ if (obj instanceof Document) {
+ return obj.toObject();
+ }
+
+ if (Array.isArray(obj)) {
+ ret = [];
+
+ for (const doc of obj) {
+ ret.push(toObject(doc));
+ }
+
+ return ret;
+ }
+
+ if (exports.isPOJO(obj)) {
+ ret = {};
+
+ for (const k in obj) {
+ if (specialProperties.has(k)) {
+ continue;
+ }
+ ret[k] = toObject(obj[k]);
+ }
+
+ return ret;
+ }
+
+ return obj;
+};
+
+exports.isObject = isObject;
+
+/*!
+ * Determines if `arg` is a plain old JavaScript object (POJO). Specifically,
+ * `arg` must be an object but not an instance of any special class, like String,
+ * ObjectId, etc.
+ *
+ * `Object.getPrototypeOf()` is part of ES5: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf
+ *
+ * @param {Object|Array|String|Function|RegExp|any} arg
+ * @api private
+ * @return {Boolean}
+ */
+
+exports.isPOJO = function isPOJO(arg) {
+ if (arg == null || typeof arg !== 'object') {
+ return false;
+ }
+ const proto = Object.getPrototypeOf(arg);
+ // Prototype may be null if you used `Object.create(null)`
+ // Checking `proto`'s constructor is safe because `getPrototypeOf()`
+ // explicitly crosses the boundary from object data to object metadata
+ return !proto || proto.constructor.name === 'Object';
+};
+
+/*!
+ * Determines if `obj` is a built-in object like an array, date, boolean,
+ * etc.
+ */
+
+exports.isNativeObject = function(arg) {
+ return Array.isArray(arg) ||
+ arg instanceof Date ||
+ arg instanceof Boolean ||
+ arg instanceof Number ||
+ arg instanceof String;
+};
+
+/*!
+ * Determines if `val` is an object that has no own keys
+ */
+
+exports.isEmptyObject = function(val) {
+ return val != null &&
+ typeof val === 'object' &&
+ Object.keys(val).length === 0;
+};
+
+/*!
+ * Search if `obj` or any POJOs nested underneath `obj` has a property named
+ * `key`
+ */
+
+exports.hasKey = function hasKey(obj, key) {
+ const props = Object.keys(obj);
+ for (const prop of props) {
+ if (prop === key) {
+ return true;
+ }
+ if (exports.isPOJO(obj[prop]) && exports.hasKey(obj[prop], key)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+/*!
+ * A faster Array.prototype.slice.call(arguments) alternative
+ * @api private
+ */
+
+exports.args = sliced;
+
+/*!
+ * process.nextTick helper.
+ *
+ * Wraps `callback` in a try/catch + nextTick.
+ *
+ * node-mongodb-native has a habit of state corruption when an error is immediately thrown from within a collection callback.
+ *
+ * @param {Function} callback
+ * @api private
+ */
+
+exports.tick = function tick(callback) {
+ if (typeof callback !== 'function') {
+ return;
+ }
+ return function() {
+ try {
+ callback.apply(this, arguments);
+ } catch (err) {
+ // only nextTick on err to get out of
+ // the event loop and avoid state corruption.
+ process.nextTick(function() {
+ throw err;
+ });
+ }
+ };
+};
+
+/*!
+ * Returns true if `v` is an object that can be serialized as a primitive in
+ * MongoDB
+ */
+
+exports.isMongooseType = function(v) {
+ return v instanceof ObjectId || v instanceof Decimal || v instanceof Buffer;
+};
+
+exports.isMongooseObject = isMongooseObject;
+
+/*!
+ * Converts `expires` options of index objects to `expiresAfterSeconds` options for MongoDB.
+ *
+ * @param {Object} object
+ * @api private
+ */
+
+exports.expires = function expires(object) {
+ if (!(object && object.constructor.name === 'Object')) {
+ return;
+ }
+ if (!('expires' in object)) {
+ return;
+ }
+
+ let when;
+ if (typeof object.expires !== 'string') {
+ when = object.expires;
+ } else {
+ when = Math.round(ms(object.expires) / 1000);
+ }
+ object.expireAfterSeconds = when;
+ delete object.expires;
+};
+
+/*!
+ * populate helper
+ */
+
+exports.populate = function populate(path, select, model, match, options, subPopulate, justOne, count) {
+ // might have passed an object specifying all arguments
+ let obj = null;
+ if (arguments.length === 1) {
+ if (path instanceof PopulateOptions) {
+ return [path];
+ }
+
+ if (Array.isArray(path)) {
+ const singles = makeSingles(path);
+ return singles.map(o => exports.populate(o)[0]);
+ }
+
+ if (exports.isObject(path)) {
+ obj = Object.assign({}, path);
+ } else {
+ obj = { path: path };
+ }
+ } else if (typeof model === 'object') {
+ obj = {
+ path: path,
+ select: select,
+ match: model,
+ options: match
+ };
+ } else {
+ obj = {
+ path: path,
+ select: select,
+ model: model,
+ match: match,
+ options: options,
+ populate: subPopulate,
+ justOne: justOne,
+ count: count
+ };
+ }
+
+ if (typeof obj.path !== 'string') {
+ throw new TypeError('utils.populate: invalid path. Expected string. Got typeof `' + typeof path + '`');
+ }
+
+ return _populateObj(obj);
+
+ // The order of select/conditions args is opposite Model.find but
+ // necessary to keep backward compatibility (select could be
+ // an array, string, or object literal).
+ function makeSingles(arr) {
+ const ret = [];
+ arr.forEach(function(obj) {
+ if (/[\s]/.test(obj.path)) {
+ const paths = obj.path.split(' ');
+ paths.forEach(function(p) {
+ const copy = Object.assign({}, obj);
+ copy.path = p;
+ ret.push(copy);
+ });
+ } else {
+ ret.push(obj);
+ }
+ });
+
+ return ret;
+ }
+};
+
+function _populateObj(obj) {
+ if (Array.isArray(obj.populate)) {
+ const ret = [];
+ obj.populate.forEach(function(obj) {
+ if (/[\s]/.test(obj.path)) {
+ const copy = Object.assign({}, obj);
+ const paths = copy.path.split(' ');
+ paths.forEach(function(p) {
+ copy.path = p;
+ ret.push(exports.populate(copy)[0]);
+ });
+ } else {
+ ret.push(exports.populate(obj)[0]);
+ }
+ });
+ obj.populate = exports.populate(ret);
+ } else if (obj.populate != null && typeof obj.populate === 'object') {
+ obj.populate = exports.populate(obj.populate);
+ }
+
+ const ret = [];
+ const paths = obj.path.split(' ');
+ if (obj.options != null) {
+ obj.options = exports.clone(obj.options);
+ }
+
+ for (const path of paths) {
+ ret.push(new PopulateOptions(Object.assign({}, obj, { path: path })));
+ }
+
+ return ret;
+}
+
+/*!
+ * Return the value of `obj` at the given `path`.
+ *
+ * @param {String} path
+ * @param {Object} obj
+ */
+
+exports.getValue = function(path, obj, map) {
+ return mpath.get(path, obj, '_doc', map);
+};
+
+/*!
+ * Sets the value of `obj` at the given `path`.
+ *
+ * @param {String} path
+ * @param {Anything} val
+ * @param {Object} obj
+ */
+
+exports.setValue = function(path, val, obj, map, _copying) {
+ mpath.set(path, val, obj, '_doc', map, _copying);
+};
+
+/*!
+ * Returns an array of values from object `o`.
+ *
+ * @param {Object} o
+ * @return {Array}
+ * @private
+ */
+
+exports.object = {};
+exports.object.vals = function vals(o) {
+ const keys = Object.keys(o);
+ let i = keys.length;
+ const ret = [];
+
+ while (i--) {
+ ret.push(o[keys[i]]);
+ }
+
+ return ret;
+};
+
+/*!
+ * @see exports.options
+ */
+
+exports.object.shallowCopy = exports.options;
+
+/*!
+ * Safer helper for hasOwnProperty checks
+ *
+ * @param {Object} obj
+ * @param {String} prop
+ */
+
+const hop = Object.prototype.hasOwnProperty;
+exports.object.hasOwnProperty = function(obj, prop) {
+ return hop.call(obj, prop);
+};
+
+/*!
+ * Determine if `val` is null or undefined
+ *
+ * @return {Boolean}
+ */
+
+exports.isNullOrUndefined = function(val) {
+ return val === null || val === undefined;
+};
+
+/*!
+ * ignore
+ */
+
+exports.array = {};
+
+/*!
+ * Flattens an array.
+ *
+ * [ 1, [ 2, 3, [4] ]] -> [1,2,3,4]
+ *
+ * @param {Array} arr
+ * @param {Function} [filter] If passed, will be invoked with each item in the array. If `filter` returns a falsy value, the item will not be included in the results.
+ * @return {Array}
+ * @private
+ */
+
+exports.array.flatten = function flatten(arr, filter, ret) {
+ ret || (ret = []);
+
+ arr.forEach(function(item) {
+ if (Array.isArray(item)) {
+ flatten(item, filter, ret);
+ } else {
+ if (!filter || filter(item)) {
+ ret.push(item);
+ }
+ }
+ });
+
+ return ret;
+};
+
+/*!
+ * ignore
+ */
+
+const _hasOwnProperty = Object.prototype.hasOwnProperty;
+
+exports.hasUserDefinedProperty = function(obj, key) {
+ if (obj == null) {
+ return false;
+ }
+
+ if (Array.isArray(key)) {
+ for (const k of key) {
+ if (exports.hasUserDefinedProperty(obj, k)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (_hasOwnProperty.call(obj, key)) {
+ return true;
+ }
+ if (typeof obj === 'object' && key in obj) {
+ const v = obj[key];
+ return v !== Object.prototype[key] && v !== Array.prototype[key];
+ }
+
+ return false;
+};
+
+/*!
+ * ignore
+ */
+
+const MAX_ARRAY_INDEX = Math.pow(2, 32) - 1;
+
+exports.isArrayIndex = function(val) {
+ if (typeof val === 'number') {
+ return val >= 0 && val <= MAX_ARRAY_INDEX;
+ }
+ if (typeof val === 'string') {
+ if (!/^\d+$/.test(val)) {
+ return false;
+ }
+ val = +val;
+ return val >= 0 && val <= MAX_ARRAY_INDEX;
+ }
+
+ return false;
+};
+
+/*!
+ * Removes duplicate values from an array
+ *
+ * [1, 2, 3, 3, 5] => [1, 2, 3, 5]
+ * [ ObjectId("550988ba0c19d57f697dc45e"), ObjectId("550988ba0c19d57f697dc45e") ]
+ * => [ObjectId("550988ba0c19d57f697dc45e")]
+ *
+ * @param {Array} arr
+ * @return {Array}
+ * @private
+ */
+
+exports.array.unique = function(arr) {
+ const primitives = {};
+ const ids = {};
+ const ret = [];
+
+ for (const item of arr) {
+ if (typeof item === 'number' || typeof item === 'string' || item == null) {
+ if (primitives[item]) {
+ continue;
+ }
+ ret.push(item);
+ primitives[item] = true;
+ } else if (item instanceof ObjectId) {
+ if (ids[item.toString()]) {
+ continue;
+ }
+ ret.push(item);
+ ids[item.toString()] = true;
+ } else {
+ ret.push(item);
+ }
+ }
+
+ return ret;
+};
+
+/*!
+ * Determines if two buffers are equal.
+ *
+ * @param {Buffer} a
+ * @param {Object} b
+ */
+
+exports.buffer = {};
+exports.buffer.areEqual = function(a, b) {
+ if (!Buffer.isBuffer(a)) {
+ return false;
+ }
+ if (!Buffer.isBuffer(b)) {
+ return false;
+ }
+ if (a.length !== b.length) {
+ return false;
+ }
+ for (let i = 0, len = a.length; i < len; ++i) {
+ if (a[i] !== b[i]) {
+ return false;
+ }
+ }
+ return true;
+};
+
+exports.getFunctionName = getFunctionName;
+/*!
+ * Decorate buffers
+ */
+
+exports.decorate = function(destination, source) {
+ for (const key in source) {
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ destination[key] = source[key];
+ }
+};
+
+/**
+ * merges to with a copy of from
+ *
+ * @param {Object} to
+ * @param {Object} fromObj
+ * @api private
+ */
+
+exports.mergeClone = function(to, fromObj) {
+ if (isMongooseObject(fromObj)) {
+ fromObj = fromObj.toObject({
+ transform: false,
+ virtuals: false,
+ depopulate: true,
+ getters: false,
+ flattenDecimals: false
+ });
+ }
+ const keys = Object.keys(fromObj);
+ const len = keys.length;
+ let i = 0;
+ let key;
+
+ while (i < len) {
+ key = keys[i++];
+ if (specialProperties.has(key)) {
+ continue;
+ }
+ if (typeof to[key] === 'undefined') {
+ to[key] = exports.clone(fromObj[key], {
+ transform: false,
+ virtuals: false,
+ depopulate: true,
+ getters: false,
+ flattenDecimals: false
+ });
+ } else {
+ let val = fromObj[key];
+ if (val != null && val.valueOf && !(val instanceof Date)) {
+ val = val.valueOf();
+ }
+ if (exports.isObject(val)) {
+ let obj = val;
+ if (isMongooseObject(val) && !val.isMongooseBuffer) {
+ obj = obj.toObject({
+ transform: false,
+ virtuals: false,
+ depopulate: true,
+ getters: false,
+ flattenDecimals: false
+ });
+ }
+ if (val.isMongooseBuffer) {
+ obj = Buffer.from(obj);
+ }
+ exports.mergeClone(to[key], obj);
+ } else {
+ to[key] = exports.clone(val, {
+ flattenDecimals: false
+ });
+ }
+ }
+ }
+};
+
+/**
+ * Executes a function on each element of an array (like _.each)
+ *
+ * @param {Array} arr
+ * @param {Function} fn
+ * @api private
+ */
+
+exports.each = function(arr, fn) {
+ for (const item of arr) {
+ fn(item);
+ }
+};
+
+/*!
+ * ignore
+ */
+
+exports.getOption = function(name) {
+ const sources = Array.prototype.slice.call(arguments, 1);
+
+ for (const source of sources) {
+ if (source[name] != null) {
+ return source[name];
+ }
+ }
+
+ return null;
+};
+
+/*!
+ * ignore
+ */
+
+exports.noop = function() {};
diff --git a/node_modules/mongoose/lib/validoptions.js b/node_modules/mongoose/lib/validoptions.js
new file mode 100644
index 0000000..510d7e2
--- /dev/null
+++ b/node_modules/mongoose/lib/validoptions.js
@@ -0,0 +1,34 @@
+
+/*!
+ * Valid mongoose options
+ */
+
+'use strict';
+
+const VALID_OPTIONS = Object.freeze([
+ 'applyPluginsToChildSchemas',
+ 'applyPluginsToDiscriminators',
+ 'autoCreate',
+ 'autoIndex',
+ 'bufferCommands',
+ 'cloneSchemas',
+ 'debug',
+ 'maxTimeMS',
+ 'objectIdGetter',
+ 'returnOriginal',
+ 'runValidators',
+ 'selectPopulatedPaths',
+ 'setDefaultsOnInsert',
+ 'strict',
+ 'strictQuery',
+ 'toJSON',
+ 'toObject',
+ 'typePojoToMixed',
+ 'useCreateIndex',
+ 'useFindAndModify',
+ 'useNewUrlParser',
+ 'usePushEach',
+ 'useUnifiedTopology'
+]);
+
+module.exports = VALID_OPTIONS;
diff --git a/node_modules/mongoose/lib/virtualtype.js b/node_modules/mongoose/lib/virtualtype.js
new file mode 100644
index 0000000..35f26b4
--- /dev/null
+++ b/node_modules/mongoose/lib/virtualtype.js
@@ -0,0 +1,168 @@
+'use strict';
+
+/**
+ * VirtualType constructor
+ *
+ * This is what mongoose uses to define virtual attributes via `Schema.prototype.virtual`.
+ *
+ * ####Example:
+ *
+ * const fullname = schema.virtual('fullname');
+ * fullname instanceof mongoose.VirtualType // true
+ *
+ * @param {Object} options
+ * @param {string|function} [options.ref] if `ref` is not nullish, this becomes a [populated virtual](/docs/populate.html#populate-virtuals)
+ * @param {string|function} [options.localField] the local field to populate on if this is a populated virtual.
+ * @param {string|function} [options.foreignField] the foreign field to populate on if this is a populated virtual.
+ * @param {boolean} [options.justOne=false] by default, a populated virtual is an array. If you set `justOne`, the populated virtual will be a single doc or `null`.
+ * @param {boolean} [options.getters=false] if you set this to `true`, Mongoose will call any custom getters you defined on this virtual
+ * @param {boolean} [options.count=false] if you set this to `true`, `populate()` will set this virtual to the number of populated documents, as opposed to the documents themselves, using [`Query#countDocuments()`](./api.html#query_Query-countDocuments)
+ * @param {Object|Function} [options.match=null] add an extra match condition to `populate()`
+ * @param {Number} [options.limit=null] add a default `limit` to the `populate()` query
+ * @param {Number} [options.skip=null] add a default `skip` to the `populate()` query
+ * @param {Number} [options.perDocumentLimit=null] For legacy reasons, `limit` with `populate()` may give incorrect results because it only executes a single query for every document being populated. If you set `perDocumentLimit`, Mongoose will ensure correct `limit` per document by executing a separate query for each document to `populate()`. For example, `.find().populate({ path: 'test', perDocumentLimit: 2 })` will execute 2 additional queries if `.find()` returns 2 documents.
+ * @param {Object} [options.options=null] Additional options like `limit` and `lean`.
+ * @api public
+ */
+
+function VirtualType(options, name) {
+ this.path = name;
+ this.getters = [];
+ this.setters = [];
+ this.options = Object.assign({}, options);
+}
+
+/**
+ * If no getters/getters, add a default
+ *
+ * @param {Function} fn
+ * @return {VirtualType} this
+ * @api private
+ */
+
+VirtualType.prototype._applyDefaultGetters = function() {
+ if (this.getters.length > 0 || this.setters.length > 0) {
+ return;
+ }
+
+ const path = this.path;
+ const internalProperty = '$' + path;
+ this.getters.push(function() {
+ return this[internalProperty];
+ });
+ this.setters.push(function(v) {
+ this[internalProperty] = v;
+ });
+};
+
+/*!
+ * ignore
+ */
+
+VirtualType.prototype.clone = function() {
+ const clone = new VirtualType(this.options, this.path);
+ clone.getters = [].concat(this.getters);
+ clone.setters = [].concat(this.setters);
+ return clone;
+};
+
+/**
+ * Adds a custom getter to this virtual.
+ *
+ * Mongoose calls the getter function with 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
+ * - `doc`: the document this virtual is attached to. Equivalent to `this`.
+ *
+ * ####Example:
+ *
+ * const virtual = schema.virtual('fullname');
+ * virtual.get(function(value, virtual, doc) {
+ * return this.name.first + ' ' + this.name.last;
+ * });
+ *
+ * @param {Function(Any, VirtualType, Document)} fn
+ * @return {VirtualType} this
+ * @api public
+ */
+
+VirtualType.prototype.get = function(fn) {
+ this.getters.push(fn);
+ return this;
+};
+
+/**
+ * Adds a custom setter to this virtual.
+ *
+ * Mongoose calls the setter function with 3 parameters:
+ *
+ * - `value`: the value being set
+ * - `virtual`: the virtual object you're calling `.set()` on
+ * - `doc`: the document this virtual is attached to. Equivalent to `this`.
+ *
+ * ####Example:
+ *
+ * const virtual = schema.virtual('fullname');
+ * virtual.set(function(value, virtual, doc) {
+ * const parts = value.split(' ');
+ * this.name.first = parts[0];
+ * this.name.last = parts[1];
+ * });
+ *
+ * const Model = mongoose.model('Test', schema);
+ * const doc = new Model();
+ * // Calls the setter with `value = 'Jean-Luc Picard'`
+ * doc.fullname = 'Jean-Luc Picard';
+ * doc.name.first; // 'Jean-Luc'
+ * doc.name.last; // 'Picard'
+ *
+ * @param {Function(Any, VirtualType, Document)} fn
+ * @return {VirtualType} this
+ * @api public
+ */
+
+VirtualType.prototype.set = function(fn) {
+ this.setters.push(fn);
+ return this;
+};
+
+/**
+ * Applies getters to `value`.
+ *
+ * @param {Object} value
+ * @param {Document} doc The document this virtual is attached to
+ * @return {any} the value after applying all getters
+ * @api public
+ */
+
+VirtualType.prototype.applyGetters = function(value, doc) {
+ let v = value;
+ for (let l = this.getters.length - 1; l >= 0; l--) {
+ v = this.getters[l].call(doc, v, this, doc);
+ }
+ return v;
+};
+
+/**
+ * Applies setters to `value`.
+ *
+ * @param {Object} value
+ * @param {Document} doc
+ * @return {any} the value after applying all setters
+ * @api public
+ */
+
+VirtualType.prototype.applySetters = function(value, doc) {
+ let v = value;
+ for (let l = this.setters.length - 1; l >= 0; l--) {
+ v = this.setters[l].call(doc, v, this, doc);
+ }
+ return v;
+};
+
+/*!
+ * exports
+ */
+
+module.exports = VirtualType;
diff --git a/node_modules/mongoose/node_modules/ms/index.js b/node_modules/mongoose/node_modules/ms/index.js
new file mode 100644
index 0000000..c4498bc
--- /dev/null
+++ b/node_modules/mongoose/node_modules/ms/index.js
@@ -0,0 +1,162 @@
+/**
+ * Helpers.
+ */
+
+var s = 1000;
+var m = s * 60;
+var h = m * 60;
+var d = h * 24;
+var w = d * 7;
+var y = d * 365.25;
+
+/**
+ * Parse or format the given `val`.
+ *
+ * Options:
+ *
+ * - `long` verbose formatting [false]
+ *
+ * @param {String|Number} val
+ * @param {Object} [options]
+ * @throws {Error} throw an error if val is not a non-empty string or a number
+ * @return {String|Number}
+ * @api public
+ */
+
+module.exports = function(val, options) {
+ options = options || {};
+ var type = typeof val;
+ if (type === 'string' && val.length > 0) {
+ return parse(val);
+ } else if (type === 'number' && isFinite(val)) {
+ return options.long ? fmtLong(val) : fmtShort(val);
+ }
+ throw new Error(
+ 'val is not a non-empty string or a valid number. val=' +
+ JSON.stringify(val)
+ );
+};
+
+/**
+ * Parse the given `str` and return milliseconds.
+ *
+ * @param {String} str
+ * @return {Number}
+ * @api private
+ */
+
+function parse(str) {
+ str = String(str);
+ if (str.length > 100) {
+ return;
+ }
+ var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
+ str
+ );
+ if (!match) {
+ return;
+ }
+ var n = parseFloat(match[1]);
+ var type = (match[2] || 'ms').toLowerCase();
+ switch (type) {
+ case 'years':
+ case 'year':
+ case 'yrs':
+ case 'yr':
+ case 'y':
+ return n * y;
+ case 'weeks':
+ case 'week':
+ case 'w':
+ return n * w;
+ case 'days':
+ case 'day':
+ case 'd':
+ return n * d;
+ case 'hours':
+ case 'hour':
+ case 'hrs':
+ case 'hr':
+ case 'h':
+ return n * h;
+ case 'minutes':
+ case 'minute':
+ case 'mins':
+ case 'min':
+ case 'm':
+ return n * m;
+ case 'seconds':
+ case 'second':
+ case 'secs':
+ case 'sec':
+ case 's':
+ return n * s;
+ case 'milliseconds':
+ case 'millisecond':
+ case 'msecs':
+ case 'msec':
+ case 'ms':
+ return n;
+ default:
+ return undefined;
+ }
+}
+
+/**
+ * Short format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtShort(ms) {
+ var msAbs = Math.abs(ms);
+ if (msAbs >= d) {
+ return Math.round(ms / d) + 'd';
+ }
+ if (msAbs >= h) {
+ return Math.round(ms / h) + 'h';
+ }
+ if (msAbs >= m) {
+ return Math.round(ms / m) + 'm';
+ }
+ if (msAbs >= s) {
+ return Math.round(ms / s) + 's';
+ }
+ return ms + 'ms';
+}
+
+/**
+ * Long format for `ms`.
+ *
+ * @param {Number} ms
+ * @return {String}
+ * @api private
+ */
+
+function fmtLong(ms) {
+ var msAbs = Math.abs(ms);
+ if (msAbs >= d) {
+ return plural(ms, msAbs, d, 'day');
+ }
+ if (msAbs >= h) {
+ return plural(ms, msAbs, h, 'hour');
+ }
+ if (msAbs >= m) {
+ return plural(ms, msAbs, m, 'minute');
+ }
+ if (msAbs >= s) {
+ return plural(ms, msAbs, s, 'second');
+ }
+ return ms + ' ms';
+}
+
+/**
+ * Pluralization helper.
+ */
+
+function plural(ms, msAbs, n, name) {
+ var isPlural = msAbs >= n * 1.5;
+ return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
+}
diff --git a/node_modules/mongoose/node_modules/ms/license.md b/node_modules/mongoose/node_modules/ms/license.md
new file mode 100644
index 0000000..69b6125
--- /dev/null
+++ b/node_modules/mongoose/node_modules/ms/license.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Zeit, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/mongoose/node_modules/ms/package.json b/node_modules/mongoose/node_modules/ms/package.json
new file mode 100644
index 0000000..ca1f8e1
--- /dev/null
+++ b/node_modules/mongoose/node_modules/ms/package.json
@@ -0,0 +1,69 @@
+{
+ "_from": "ms@2.1.2",
+ "_id": "ms@2.1.2",
+ "_inBundle": false,
+ "_integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
+ "_location": "/mongoose/ms",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "ms@2.1.2",
+ "name": "ms",
+ "escapedName": "ms",
+ "rawSpec": "2.1.2",
+ "saveSpec": null,
+ "fetchSpec": "2.1.2"
+ },
+ "_requiredBy": [
+ "/mongoose"
+ ],
+ "_resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "_shasum": "d09d1f357b443f493382a8eb3ccd183872ae6009",
+ "_spec": "ms@2.1.2",
+ "_where": "/home/pruss/Dev/3-minute-website/node_modules/mongoose",
+ "bugs": {
+ "url": "https://github.com/zeit/ms/issues"
+ },
+ "bundleDependencies": false,
+ "deprecated": false,
+ "description": "Tiny millisecond conversion utility",
+ "devDependencies": {
+ "eslint": "4.12.1",
+ "expect.js": "0.3.1",
+ "husky": "0.14.3",
+ "lint-staged": "5.0.0",
+ "mocha": "4.0.1"
+ },
+ "eslintConfig": {
+ "extends": "eslint:recommended",
+ "env": {
+ "node": true,
+ "es6": true
+ }
+ },
+ "files": [
+ "index.js"
+ ],
+ "homepage": "https://github.com/zeit/ms#readme",
+ "license": "MIT",
+ "lint-staged": {
+ "*.js": [
+ "npm run lint",
+ "prettier --single-quote --write",
+ "git add"
+ ]
+ },
+ "main": "./index",
+ "name": "ms",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/zeit/ms.git"
+ },
+ "scripts": {
+ "lint": "eslint lib/* bin/*",
+ "precommit": "lint-staged",
+ "test": "mocha tests.js"
+ },
+ "version": "2.1.2"
+}
diff --git a/node_modules/mongoose/node_modules/ms/readme.md b/node_modules/mongoose/node_modules/ms/readme.md
new file mode 100644
index 0000000..9a1996b
--- /dev/null
+++ b/node_modules/mongoose/node_modules/ms/readme.md
@@ -0,0 +1,60 @@
+# ms
+
+[![Build Status](https://travis-ci.org/zeit/ms.svg?branch=master)](https://travis-ci.org/zeit/ms)
+[![Join the community on Spectrum](https://withspectrum.github.io/badge/badge.svg)](https://spectrum.chat/zeit)
+
+Use this package to easily convert various time formats to milliseconds.
+
+## Examples
+
+```js
+ms('2 days') // 172800000
+ms('1d') // 86400000
+ms('10h') // 36000000
+ms('2.5 hrs') // 9000000
+ms('2h') // 7200000
+ms('1m') // 60000
+ms('5s') // 5000
+ms('1y') // 31557600000
+ms('100') // 100
+ms('-3 days') // -259200000
+ms('-1h') // -3600000
+ms('-200') // -200
+```
+
+### Convert from Milliseconds
+
+```js
+ms(60000) // "1m"
+ms(2 * 60000) // "2m"
+ms(-3 * 60000) // "-3m"
+ms(ms('10 hours')) // "10h"
+```
+
+### Time Format Written-Out
+
+```js
+ms(60000, { long: true }) // "1 minute"
+ms(2 * 60000, { long: true }) // "2 minutes"
+ms(-3 * 60000, { long: true }) // "-3 minutes"
+ms(ms('10 hours'), { long: true }) // "10 hours"
+```
+
+## Features
+
+- Works both in [Node.js](https://nodejs.org) and in the browser
+- If a number is supplied to `ms`, a string with a unit is returned
+- If a string that contains the number is supplied, it returns it as a number (e.g.: it returns `100` for `'100'`)
+- If you pass a string with a number and a valid unit, the number of equivalent milliseconds is returned
+
+## Related Packages
+
+- [ms.macro](https://github.com/knpwrs/ms.macro) - Run `ms` as a macro at build-time.
+
+## Caught a Bug?
+
+1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
+2. Link the package to the global module directory: `npm link`
+3. Within the module you want to test your local development instance of ms, just link it to the dependencies: `npm link ms`. Instead of the default one from npm, Node.js will now use your clone of ms!
+
+As always, you can run the tests using: `npm test`
diff --git a/node_modules/mongoose/node_modules/safe-buffer/LICENSE b/node_modules/mongoose/node_modules/safe-buffer/LICENSE
new file mode 100644
index 0000000..0c068ce
--- /dev/null
+++ b/node_modules/mongoose/node_modules/safe-buffer/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) Feross Aboukhadijeh
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/node_modules/mongoose/node_modules/safe-buffer/README.md b/node_modules/mongoose/node_modules/safe-buffer/README.md
new file mode 100644
index 0000000..e9a81af
--- /dev/null
+++ b/node_modules/mongoose/node_modules/safe-buffer/README.md
@@ -0,0 +1,584 @@
+# safe-buffer [![travis][travis-image]][travis-url] [![npm][npm-image]][npm-url] [![downloads][downloads-image]][downloads-url] [![javascript style guide][standard-image]][standard-url]
+
+[travis-image]: https://img.shields.io/travis/feross/safe-buffer/master.svg
+[travis-url]: https://travis-ci.org/feross/safe-buffer
+[npm-image]: https://img.shields.io/npm/v/safe-buffer.svg
+[npm-url]: https://npmjs.org/package/safe-buffer
+[downloads-image]: https://img.shields.io/npm/dm/safe-buffer.svg
+[downloads-url]: https://npmjs.org/package/safe-buffer
+[standard-image]: https://img.shields.io/badge/code_style-standard-brightgreen.svg
+[standard-url]: https://standardjs.com
+
+#### Safer Node.js Buffer API
+
+**Use the new Node.js Buffer APIs (`Buffer.from`, `Buffer.alloc`,
+`Buffer.allocUnsafe`, `Buffer.allocUnsafeSlow`) in all versions of Node.js.**
+
+**Uses the built-in implementation when available.**
+
+## install
+
+```
+npm install safe-buffer
+```
+
+## usage
+
+The goal of this package is to provide a safe replacement for the node.js `Buffer`.
+
+It's a drop-in replacement for `Buffer`. You can use it by adding one `require` line to
+the top of your node.js modules:
+
+```js
+var Buffer = require('safe-buffer').Buffer
+
+// Existing buffer code will continue to work without issues:
+
+new Buffer('hey', 'utf8')
+new Buffer([1, 2, 3], 'utf8')
+new Buffer(obj)
+new Buffer(16) // create an uninitialized buffer (potentially unsafe)
+
+// But you can use these new explicit APIs to make clear what you want:
+
+Buffer.from('hey', 'utf8') // convert from many types to a Buffer
+Buffer.alloc(16) // create a zero-filled buffer (safe)
+Buffer.allocUnsafe(16) // create an uninitialized buffer (potentially unsafe)
+```
+
+## api
+
+### Class Method: Buffer.from(array)
+<!-- YAML
+added: v3.0.0
+-->
+
+* `array` {Array}
+
+Allocates a new `Buffer` using an `array` of octets.
+
+```js
+const buf = Buffer.from([0x62,0x75,0x66,0x66,0x65,0x72]);
+ // creates a new Buffer containing ASCII bytes
+ // ['b','u','f','f','e','r']
+```
+
+A `TypeError` will be thrown if `array` is not an `Array`.
+
+### Class Method: Buffer.from(arrayBuffer[, byteOffset[, length]])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `arrayBuffer` {ArrayBuffer} The `.buffer` property of a `TypedArray` or
+ a `new ArrayBuffer()`
+* `byteOffset` {Number} Default: `0`
+* `length` {Number} Default: `arrayBuffer.length - byteOffset`
+
+When passed a reference to the `.buffer` property of a `TypedArray` instance,
+the newly created `Buffer` will share the same allocated memory as the
+TypedArray.
+
+```js
+const arr = new Uint16Array(2);
+arr[0] = 5000;
+arr[1] = 4000;
+
+const buf = Buffer.from(arr.buffer); // shares the memory with arr;
+
+console.log(buf);
+ // Prints: <Buffer 88 13 a0 0f>
+
+// changing the TypedArray changes the Buffer also
+arr[1] = 6000;
+
+console.log(buf);
+ // Prints: <Buffer 88 13 70 17>
+```
+
+The optional `byteOffset` and `length` arguments specify a memory range within
+the `arrayBuffer` that will be shared by the `Buffer`.
+
+```js
+const ab = new ArrayBuffer(10);
+const buf = Buffer.from(ab, 0, 2);
+console.log(buf.length);
+ // Prints: 2
+```
+
+A `TypeError` will be thrown if `arrayBuffer` is not an `ArrayBuffer`.
+
+### Class Method: Buffer.from(buffer)
+<!-- YAML
+added: v3.0.0
+-->
+
+* `buffer` {Buffer}
+
+Copies the passed `buffer` data onto a new `Buffer` instance.
+
+```js
+const buf1 = Buffer.from('buffer');
+const buf2 = Buffer.from(buf1);
+
+buf1[0] = 0x61;
+console.log(buf1.toString());
+ // 'auffer'
+console.log(buf2.toString());
+ // 'buffer' (copy is not changed)
+```
+
+A `TypeError` will be thrown if `buffer` is not a `Buffer`.
+
+### Class Method: Buffer.from(str[, encoding])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `str` {String} String to encode.
+* `encoding` {String} Encoding to use, Default: `'utf8'`
+
+Creates a new `Buffer` containing the given JavaScript string `str`. If
+provided, the `encoding` parameter identifies the character encoding.
+If not provided, `encoding` defaults to `'utf8'`.
+
+```js
+const buf1 = Buffer.from('this is a tést');
+console.log(buf1.toString());
+ // prints: this is a tést
+console.log(buf1.toString('ascii'));
+ // prints: this is a tC)st
+
+const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');
+console.log(buf2.toString());
+ // prints: this is a tést
+```
+
+A `TypeError` will be thrown if `str` is not a string.
+
+### Class Method: Buffer.alloc(size[, fill[, encoding]])
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+* `fill` {Value} Default: `undefined`
+* `encoding` {String} Default: `utf8`
+
+Allocates a new `Buffer` of `size` bytes. If `fill` is `undefined`, the
+`Buffer` will be *zero-filled*.
+
+```js
+const buf = Buffer.alloc(5);
+console.log(buf);
+ // <Buffer 00 00 00 00 00>
+```
+
+The `size` must be less than or equal to the value of
+`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
+`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
+be created if a `size` less than or equal to 0 is specified.
+
+If `fill` is specified, the allocated `Buffer` will be initialized by calling
+`buf.fill(fill)`. See [`buf.fill()`][] for more information.
+
+```js
+const buf = Buffer.alloc(5, 'a');
+console.log(buf);
+ // <Buffer 61 61 61 61 61>
+```
+
+If both `fill` and `encoding` are specified, the allocated `Buffer` will be
+initialized by calling `buf.fill(fill, encoding)`. For example:
+
+```js
+const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');
+console.log(buf);
+ // <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>
+```
+
+Calling `Buffer.alloc(size)` can be significantly slower than the alternative
+`Buffer.allocUnsafe(size)` but ensures that the newly created `Buffer` instance
+contents will *never contain sensitive data*.
+
+A `TypeError` will be thrown if `size` is not a number.
+
+### Class Method: Buffer.allocUnsafe(size)
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+
+Allocates a new *non-zero-filled* `Buffer` of `size` bytes. The `size` must
+be less than or equal to the value of `require('buffer').kMaxLength` (on 64-bit
+architectures, `kMaxLength` is `(2^31)-1`). Otherwise, a [`RangeError`][] is
+thrown. A zero-length Buffer will be created if a `size` less than or equal to
+0 is specified.
+
+The underlying memory for `Buffer` instances created in this way is *not
+initialized*. The contents of the newly created `Buffer` are unknown and
+*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
+`Buffer` instances to zeroes.
+
+```js
+const buf = Buffer.allocUnsafe(5);
+console.log(buf);
+ // <Buffer 78 e0 82 02 01>
+ // (octets will be different, every time)
+buf.fill(0);
+console.log(buf);
+ // <Buffer 00 00 00 00 00>
+```
+
+A `TypeError` will be thrown if `size` is not a number.
+
+Note that the `Buffer` module pre-allocates an internal `Buffer` instance of
+size `Buffer.poolSize` that is used as a pool for the fast allocation of new
+`Buffer` instances created using `Buffer.allocUnsafe(size)` (and the deprecated
+`new Buffer(size)` constructor) only when `size` is less than or equal to
+`Buffer.poolSize >> 1` (floor of `Buffer.poolSize` divided by two). The default
+value of `Buffer.poolSize` is `8192` but can be modified.
+
+Use of this pre-allocated internal memory pool is a key difference between
+calling `Buffer.alloc(size, fill)` vs. `Buffer.allocUnsafe(size).fill(fill)`.
+Specifically, `Buffer.alloc(size, fill)` will *never* use the internal Buffer
+pool, while `Buffer.allocUnsafe(size).fill(fill)` *will* use the internal
+Buffer pool if `size` is less than or equal to half `Buffer.poolSize`. The
+difference is subtle but can be important when an application requires the
+additional performance that `Buffer.allocUnsafe(size)` provides.
+
+### Class Method: Buffer.allocUnsafeSlow(size)
+<!-- YAML
+added: v5.10.0
+-->
+
+* `size` {Number}
+
+Allocates a new *non-zero-filled* and non-pooled `Buffer` of `size` bytes. The
+`size` must be less than or equal to the value of
+`require('buffer').kMaxLength` (on 64-bit architectures, `kMaxLength` is
+`(2^31)-1`). Otherwise, a [`RangeError`][] is thrown. A zero-length Buffer will
+be created if a `size` less than or equal to 0 is specified.
+
+The underlying memory for `Buffer` instances created in this way is *not
+initialized*. The contents of the newly created `Buffer` are unknown and
+*may contain sensitive data*. Use [`buf.fill(0)`][] to initialize such
+`Buffer` instances to zeroes.
+
+When using `Buffer.allocUnsafe()` to allocate new `Buffer` instances,
+allocations under 4KB are, by default, sliced from a single pre-allocated
+`Buffer`. This allows applications to avoid the garbage collection overhead of
+creating many individually allocated Buffers. This approach improves both
+performance and memory usage by eliminating the need to track and cleanup as
+many `Persistent` objects.
+
+However, in the case where a developer may need to retain a small chunk of
+memory from a pool for an indeterminate amount of time, it may be appropriate
+to create an un-pooled Buffer instance using `Buffer.allocUnsafeSlow()` then
+copy out the relevant bits.
+
+```js
+// need to keep around a few small chunks of memory
+const store = [];
+
+socket.on('readable', () => {
+ const data = socket.read();
+ // allocate for retained data
+ const sb = Buffer.allocUnsafeSlow(10);
+ // copy the data into the new allocation
+ data.copy(sb, 0, 0, 10);
+ store.push(sb);
+});
+```
+
+Use of `Buffer.allocUnsafeSlow()` should be used only as a last resort *after*
+a developer has observed undue memory retention in their applications.
+
+A `TypeError` will be thrown if `size` is not a number.
+
+### All the Rest
+
+The rest of the `Buffer` API is exactly the same as in node.js.
+[See the docs](https://nodejs.org/api/buffer.html).
+
+
+## Related links
+
+- [Node.js issue: Buffer(number) is unsafe](https://github.com/nodejs/node/issues/4660)
+- [Node.js Enhancement Proposal: Buffer.from/Buffer.alloc/Buffer.zalloc/Buffer() soft-deprecate](https://github.com/nodejs/node-eps/pull/4)
+
+## Why is `Buffer` unsafe?
+
+Today, the node.js `Buffer` constructor is overloaded to handle many different argument
+types like `String`, `Array`, `Object`, `TypedArrayView` (`Uint8Array`, etc.),
+`ArrayBuffer`, and also `Number`.
+
+The API is optimized for convenience: you can throw any type at it, and it will try to do
+what you want.
+
+Because the Buffer constructor is so powerful, you often see code like this:
+
+```js
+// Convert UTF-8 strings to hex
+function toHex (str) {
+ return new Buffer(str).toString('hex')
+}
+```
+
+***But what happens if `toHex` is called with a `Number` argument?***
+
+### Remote Memory Disclosure
+
+If an attacker can make your program call the `Buffer` constructor with a `Number`
+argument, then they can make it allocate uninitialized memory from the node.js process.
+This could potentially disclose TLS private keys, user data, or database passwords.
+
+When the `Buffer` constructor is passed a `Number` argument, it returns an
+**UNINITIALIZED** block of memory of the specified `size`. When you create a `Buffer` like
+this, you **MUST** overwrite the contents before returning it to the user.
+
+From the [node.js docs](https://nodejs.org/api/buffer.html#buffer_new_buffer_size):
+
+> `new Buffer(size)`
+>
+> - `size` Number
+>
+> The underlying memory for `Buffer` instances created in this way is not initialized.
+> **The contents of a newly created `Buffer` are unknown and could contain sensitive
+> data.** Use `buf.fill(0)` to initialize a Buffer to zeroes.
+
+(Emphasis our own.)
+
+Whenever the programmer intended to create an uninitialized `Buffer` you often see code
+like this:
+
+```js
+var buf = new Buffer(16)
+
+// Immediately overwrite the uninitialized buffer with data from another buffer
+for (var i = 0; i < buf.length; i++) {
+ buf[i] = otherBuf[i]
+}
+```
+
+
+### Would this ever be a problem in real code?
+
+Yes. It's surprisingly common to forget to check the type of your variables in a
+dynamically-typed language like JavaScript.
+
+Usually the consequences of assuming the wrong type is that your program crashes with an
+uncaught exception. But the failure mode for forgetting to check the type of arguments to
+the `Buffer` constructor is more catastrophic.
+
+Here's an example of a vulnerable service that takes a JSON payload and converts it to
+hex:
+
+```js
+// Take a JSON payload {str: "some string"} and convert it to hex
+var server = http.createServer(function (req, res) {
+ var data = ''
+ req.setEncoding('utf8')
+ req.on('data', function (chunk) {
+ data += chunk
+ })
+ req.on('end', function () {
+ var body = JSON.parse(data)
+ res.end(new Buffer(body.str).toString('hex'))
+ })
+})
+
+server.listen(8080)
+```
+
+In this example, an http client just has to send:
+
+```json
+{
+ "str": 1000
+}
+```
+
+and it will get back 1,000 bytes of uninitialized memory from the server.
+
+This is a very serious bug. It's similar in severity to the
+[the Heartbleed bug](http://heartbleed.com/) that allowed disclosure of OpenSSL process
+memory by remote attackers.
+
+
+### Which real-world packages were vulnerable?
+
+#### [`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht)
+
+[Mathias Buus](https://github.com/mafintosh) and I
+([Feross Aboukhadijeh](http://feross.org/)) found this issue in one of our own packages,
+[`bittorrent-dht`](https://www.npmjs.com/package/bittorrent-dht). The bug would allow
+anyone on the internet to send a series of messages to a user of `bittorrent-dht` and get
+them to reveal 20 bytes at a time of uninitialized memory from the node.js process.
+
+Here's
+[the commit](https://github.com/feross/bittorrent-dht/commit/6c7da04025d5633699800a99ec3fbadf70ad35b8)
+that fixed it. We released a new fixed version, created a
+[Node Security Project disclosure](https://nodesecurity.io/advisories/68), and deprecated all
+vulnerable versions on npm so users will get a warning to upgrade to a newer version.
+
+#### [`ws`](https://www.npmjs.com/package/ws)
+
+That got us wondering if there were other vulnerable packages. Sure enough, within a short
+period of time, we found the same issue in [`ws`](https://www.npmjs.com/package/ws), the
+most popular WebSocket implementation in node.js.
+
+If certain APIs were called with `Number` parameters instead of `String` or `Buffer` as
+expected, then uninitialized server memory would be disclosed to the remote peer.
+
+These were the vulnerable methods:
+
+```js
+socket.send(number)
+socket.ping(number)
+socket.pong(number)
+```
+
+Here's a vulnerable socket server with some echo functionality:
+
+```js
+server.on('connection', function (socket) {
+ socket.on('message', function (message) {
+ message = JSON.parse(message)
+ if (message.type === 'echo') {
+ socket.send(message.data) // send back the user's message
+ }
+ })
+})
+```
+
+`socket.send(number)` called on the server, will disclose server memory.
+
+Here's [the release](https://github.com/websockets/ws/releases/tag/1.0.1) where the issue
+was fixed, with a more detailed explanation. Props to
+[Arnout Kazemier](https://github.com/3rd-Eden) for the quick fix. Here's the
+[Node Security Project disclosure](https://nodesecurity.io/advisories/67).
+
+
+### What's the solution?
+
+It's important that node.js offers a fast way to get memory otherwise performance-critical
+applications would needlessly get a lot slower.
+
+But we need a better way to *signal our intent* as programmers. **When we want
+uninitialized memory, we should request it explicitly.**
+
+Sensitive functionality should not be packed into a developer-friendly API that loosely
+accepts many different types. This type of API encourages the lazy practice of passing
+variables in without checking the type very carefully.
+
+#### A new API: `Buffer.allocUnsafe(number)`
+
+The functionality of creating buffers with uninitialized memory should be part of another
+API. We propose `Buffer.allocUnsafe(number)`. This way, it's not part of an API that
+frequently gets user input of all sorts of different types passed into it.
+
+```js
+var buf = Buffer.allocUnsafe(16) // careful, uninitialized memory!
+
+// Immediately overwrite the uninitialized buffer with data from another buffer
+for (var i = 0; i < buf.length; i++) {
+ buf[i] = otherBuf[i]
+}
+```
+
+
+### How do we fix node.js core?
+
+We sent [a PR to node.js core](https://github.com/nodejs/node/pull/4514) (merged as
+`semver-major`) which defends against one case:
+
+```js
+var str = 16
+new Buffer(str, 'utf8')
+```
+
+In this situation, it's implied that the programmer intended the first argument to be a
+string, since they passed an encoding as a second argument. Today, node.js will allocate
+uninitialized memory in the case of `new Buffer(number, encoding)`, which is probably not
+what the programmer intended.
+
+But this is only a partial solution, since if the programmer does `new Buffer(variable)`
+(without an `encoding` parameter) there's no way to know what they intended. If `variable`
+is sometimes a number, then uninitialized memory will sometimes be returned.
+
+### What's the real long-term fix?
+
+We could deprecate and remove `new Buffer(number)` and use `Buffer.allocUnsafe(number)` when
+we need uninitialized memory. But that would break 1000s of packages.
+
+~~We believe the best solution is to:~~
+
+~~1. Change `new Buffer(number)` to return safe, zeroed-out memory~~
+
+~~2. Create a new API for creating uninitialized Buffers. We propose: `Buffer.allocUnsafe(number)`~~
+
+#### Update
+
+We now support adding three new APIs:
+
+- `Buffer.from(value)` - convert from any type to a buffer
+- `Buffer.alloc(size)` - create a zero-filled buffer
+- `Buffer.allocUnsafe(size)` - create an uninitialized buffer with given size
+
+This solves the core problem that affected `ws` and `bittorrent-dht` which is
+`Buffer(variable)` getting tricked into taking a number argument.
+
+This way, existing code continues working and the impact on the npm ecosystem will be
+minimal. Over time, npm maintainers can migrate performance-critical code to use
+`Buffer.allocUnsafe(number)` instead of `new Buffer(number)`.
+
+
+### Conclusion
+
+We think there's a serious design issue with the `Buffer` API as it exists today. It
+promotes insecure software by putting high-risk functionality into a convenient API
+with friendly "developer ergonomics".
+
+This wasn't merely a theoretical exercise because we found the issue in some of the
+most popular npm packages.
+
+Fortunately, there's an easy fix that can be applied today. Use `safe-buffer` in place of
+`buffer`.
+
+```js
+var Buffer = require('safe-buffer').Buffer
+```
+
+Eventually, we hope that node.js core can switch to this new, safer behavior. We believe
+the impact on the ecosystem would be minimal since it's not a breaking change.
+Well-maintained, popular packages would be updated to use `Buffer.alloc` quickly, while
+older, insecure packages would magically become safe from this attack vector.
+
+
+## links
+
+- [Node.js PR: buffer: throw if both length and enc are passed](https://github.com/nodejs/node/pull/4514)
+- [Node Security Project disclosure for `ws`](https://nodesecurity.io/advisories/67)
+- [Node Security Project disclosure for`bittorrent-dht`](https://nodesecurity.io/advisories/68)
+
+
+## credit
+
+The original issues in `bittorrent-dht`
+([disclosure](https://nodesecurity.io/advisories/68)) and
+`ws` ([disclosure](https://nodesecurity.io/advisories/67)) were discovered by
+[Mathias Buus](https://github.com/mafintosh) and
+[Feross Aboukhadijeh](http://feross.org/).
+
+Thanks to [Adam Baldwin](https://github.com/evilpacket) for helping disclose these issues
+and for his work running the [Node Security Project](https://nodesecurity.io/).
+
+Thanks to [John Hiesey](https://github.com/jhiesey) for proofreading this README and
+auditing the code.
+
+
+## license
+
+MIT. Copyright (C) [Feross Aboukhadijeh](http://feross.org)
diff --git a/node_modules/mongoose/node_modules/safe-buffer/index.d.ts b/node_modules/mongoose/node_modules/safe-buffer/index.d.ts
new file mode 100644
index 0000000..e9fed80
--- /dev/null
+++ b/node_modules/mongoose/node_modules/safe-buffer/index.d.ts
@@ -0,0 +1,187 @@
+declare module "safe-buffer" {
+ export class Buffer {
+ length: number
+ write(string: string, offset?: number, length?: number, encoding?: string): number;
+ toString(encoding?: string, start?: number, end?: number): string;
+ toJSON(): { type: 'Buffer', data: any[] };
+ equals(otherBuffer: Buffer): boolean;
+ compare(otherBuffer: Buffer, targetStart?: number, targetEnd?: number, sourceStart?: number, sourceEnd?: number): number;
+ copy(targetBuffer: Buffer, targetStart?: number, sourceStart?: number, sourceEnd?: number): number;
+ slice(start?: number, end?: number): Buffer;
+ writeUIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeUIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeIntLE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ writeIntBE(value: number, offset: number, byteLength: number, noAssert?: boolean): number;
+ readUIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readUIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readIntLE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readIntBE(offset: number, byteLength: number, noAssert?: boolean): number;
+ readUInt8(offset: number, noAssert?: boolean): number;
+ readUInt16LE(offset: number, noAssert?: boolean): number;
+ readUInt16BE(offset: number, noAssert?: boolean): number;
+ readUInt32LE(offset: number, noAssert?: boolean): number;
+ readUInt32BE(offset: number, noAssert?: boolean): number;
+ readInt8(offset: number, noAssert?: boolean): number;
+ readInt16LE(offset: number, noAssert?: boolean): number;
+ readInt16BE(offset: number, noAssert?: boolean): number;
+ readInt32LE(offset: number, noAssert?: boolean): number;
+ readInt32BE(offset: number, noAssert?: boolean): number;
+ readFloatLE(offset: number, noAssert?: boolean): number;
+ readFloatBE(offset: number, noAssert?: boolean): number;
+ readDoubleLE(offset: number, noAssert?: boolean): number;
+ readDoubleBE(offset: number, noAssert?: boolean): number;
+ swap16(): Buffer;
+ swap32(): Buffer;
+ swap64(): Buffer;
+ writeUInt8(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt16LE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt16BE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt32LE(value: number, offset: number, noAssert?: boolean): number;
+ writeUInt32BE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt8(value: number, offset: number, noAssert?: boolean): number;
+ writeInt16LE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt16BE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt32LE(value: number, offset: number, noAssert?: boolean): number;
+ writeInt32BE(value: number, offset: number, noAssert?: boolean): number;
+ writeFloatLE(value: number, offset: number, noAssert?: boolean): number;
+ writeFloatBE(value: number, offset: number, noAssert?: boolean): number;
+ writeDoubleLE(value: number, offset: number, noAssert?: boolean): number;
+ writeDoubleBE(value: number, offset: number, noAssert?: boolean): number;
+ fill(value: any, offset?: number, end?: number): this;
+ indexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+ lastIndexOf(value: string | number | Buffer, byteOffset?: number, encoding?: string): number;
+ includes(value: string | number | Buffer, byteOffset?: number, encoding?: string): boolean;
+
+ /**
+ * Allocates a new buffer containing the given {str}.
+ *
+ * @param str String to store in buffer.
+ * @param encoding encoding to use, optional. Default is 'utf8'
+ */
+ constructor (str: string, encoding?: string);
+ /**
+ * Allocates a new buffer of {size} octets.
+ *
+ * @param size count of octets to allocate.
+ */
+ constructor (size: number);
+ /**
+ * Allocates a new buffer containing the given {array} of octets.
+ *
+ * @param array The octets to store.
+ */
+ constructor (array: Uint8Array);
+ /**
+ * Produces a Buffer backed by the same allocated memory as
+ * the given {ArrayBuffer}.
+ *
+ *
+ * @param arrayBuffer The ArrayBuffer with which to share memory.
+ */
+ constructor (arrayBuffer: ArrayBuffer);
+ /**
+ * Allocates a new buffer containing the given {array} of octets.
+ *
+ * @param array The octets to store.
+ */
+ constructor (array: any[]);
+ /**
+ * Copies the passed {buffer} data onto a new {Buffer} instance.
+ *
+ * @param buffer The buffer to copy.
+ */
+ constructor (buffer: Buffer);
+ prototype: Buffer;
+ /**
+ * Allocates a new Buffer using an {array} of octets.
+ *
+ * @param array
+ */
+ static from(array: any[]): Buffer;
+ /**
+ * When passed a reference to the .buffer property of a TypedArray instance,
+ * the newly created Buffer will share the same allocated memory as the TypedArray.
+ * The optional {byteOffset} and {length} arguments specify a memory range
+ * within the {arrayBuffer} that will be shared by the Buffer.
+ *
+ * @param arrayBuffer The .buffer property of a TypedArray or a new ArrayBuffer()
+ * @param byteOffset
+ * @param length
+ */
+ static from(arrayBuffer: ArrayBuffer, byteOffset?: number, length?: number): Buffer;
+ /**
+ * Copies the passed {buffer} data onto a new Buffer instance.
+ *
+ * @param buffer
+ */
+ static from(buffer: Buffer): Buffer;
+ /**
+ * Creates a new Buffer containing the given JavaScript string {str}.
+ * If provided, the {encoding} parameter identifies the character encoding.
+ * If not provided, {encoding} defaults to 'utf8'.
+ *
+ * @param str
+ */
+ static from(str: string, encoding?: string): Buffer;
+ /**
+ * Returns true if {obj} is a Buffer
+ *
+ * @param obj object to test.
+ */
+ static isBuffer(obj: any): obj is Buffer;
+ /**
+ * Returns true if {encoding} is a valid encoding argument.
+ * Valid string encodings in Node 0.12: 'ascii'|'utf8'|'utf16le'|'ucs2'(alias of 'utf16le')|'base64'|'binary'(deprecated)|'hex'
+ *
+ * @param encoding string to test.
+ */
+ static isEncoding(encoding: string): boolean;
+ /**
+ * Gives the actual byte length of a string. encoding defaults to 'utf8'.
+ * This is not the same as String.prototype.length since that returns the number of characters in a string.
+ *
+ * @param string string to test.
+ * @param encoding encoding used to evaluate (defaults to 'utf8')
+ */
+ static byteLength(string: string, encoding?: string): number;
+ /**
+ * Returns a buffer which is the result of concatenating all the buffers in the list together.
+ *
+ * If the list has no items, or if the totalLength is 0, then it returns a zero-length buffer.
+ * If the list has exactly one item, then the first item of the list is returned.
+ * If the list has more than one item, then a new Buffer is created.
+ *
+ * @param list An array of Buffer objects to concatenate
+ * @param totalLength Total length of the buffers when concatenated.
+ * If totalLength is not provided, it is read from the buffers in the list. However, this adds an additional loop to the function, so it is faster to provide the length explicitly.
+ */
+ static concat(list: Buffer[], totalLength?: number): Buffer;
+ /**
+ * The same as buf1.compare(buf2).
+ */
+ static compare(buf1: Buffer, buf2: Buffer): number;
+ /**
+ * Allocates a new buffer of {size} octets.
+ *
+ * @param size count of octets to allocate.
+ * @param fill if specified, buffer will be initialized by calling buf.fill(fill).
+ * If parameter is omitted, buffer will be filled with zeros.
+ * @param encoding encoding used for call to buf.fill while initalizing
+ */
+ static alloc(size: number, fill?: string | Buffer | number, encoding?: string): Buffer;
+ /**
+ * Allocates a new buffer of {size} octets, leaving memory not initialized, so the contents
+ * of the newly created Buffer are unknown and may contain sensitive data.
+ *
+ * @param size count of octets to allocate
+ */
+ static allocUnsafe(size: number): Buffer;
+ /**
+ * Allocates a new non-pooled buffer of {size} octets, leaving memory not initialized, so the contents
+ * of the newly created Buffer are unknown and may contain sensitive data.
+ *
+ * @param size count of octets to allocate
+ */
+ static allocUnsafeSlow(size: number): Buffer;
+ }
+} \ No newline at end of file
diff --git a/node_modules/mongoose/node_modules/safe-buffer/index.js b/node_modules/mongoose/node_modules/safe-buffer/index.js
new file mode 100644
index 0000000..f8d3ec9
--- /dev/null
+++ b/node_modules/mongoose/node_modules/safe-buffer/index.js
@@ -0,0 +1,65 @@
+/*! safe-buffer. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
+/* eslint-disable node/no-deprecated-api */
+var buffer = require('buffer')
+var Buffer = buffer.Buffer
+
+// alternative to using Object.keys for old browsers
+function copyProps (src, dst) {
+ for (var key in src) {
+ dst[key] = src[key]
+ }
+}
+if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
+ module.exports = buffer
+} else {
+ // Copy properties from require('buffer')
+ copyProps(buffer, exports)
+ exports.Buffer = SafeBuffer
+}
+
+function SafeBuffer (arg, encodingOrOffset, length) {
+ return Buffer(arg, encodingOrOffset, length)
+}
+
+SafeBuffer.prototype = Object.create(Buffer.prototype)
+
+// Copy static methods from Buffer
+copyProps(Buffer, SafeBuffer)
+
+SafeBuffer.from = function (arg, encodingOrOffset, length) {
+ if (typeof arg === 'number') {
+ throw new TypeError('Argument must not be a number')
+ }
+ return Buffer(arg, encodingOrOffset, length)
+}
+
+SafeBuffer.alloc = function (size, fill, encoding) {
+ if (typeof size !== 'number') {
+ throw new TypeError('Argument must be a number')
+ }
+ var buf = Buffer(size)
+ if (fill !== undefined) {
+ if (typeof encoding === 'string') {
+ buf.fill(fill, encoding)
+ } else {
+ buf.fill(fill)
+ }
+ } else {
+ buf.fill(0)
+ }
+ return buf
+}
+
+SafeBuffer.allocUnsafe = function (size) {
+ if (typeof size !== 'number') {
+ throw new TypeError('Argument must be a number')
+ }
+ return Buffer(size)
+}
+
+SafeBuffer.allocUnsafeSlow = function (size) {
+ if (typeof size !== 'number') {
+ throw new TypeError('Argument must be a number')
+ }
+ return buffer.SlowBuffer(size)
+}
diff --git a/node_modules/mongoose/node_modules/safe-buffer/package.json b/node_modules/mongoose/node_modules/safe-buffer/package.json
new file mode 100644
index 0000000..75ff24c
--- /dev/null
+++ b/node_modules/mongoose/node_modules/safe-buffer/package.json
@@ -0,0 +1,76 @@
+{
+ "_from": "safe-buffer@5.2.1",
+ "_id": "safe-buffer@5.2.1",
+ "_inBundle": false,
+ "_integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "_location": "/mongoose/safe-buffer",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "version",
+ "registry": true,
+ "raw": "safe-buffer@5.2.1",
+ "name": "safe-buffer",
+ "escapedName": "safe-buffer",
+ "rawSpec": "5.2.1",
+ "saveSpec": null,
+ "fetchSpec": "5.2.1"
+ },
+ "_requiredBy": [
+ "/mongoose"
+ ],
+ "_resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "_shasum": "1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6",
+ "_spec": "safe-buffer@5.2.1",
+ "_where": "/home/pruss/Dev/3-minute-website/node_modules/mongoose",
+ "author": {
+ "name": "Feross Aboukhadijeh",
+ "email": "feross@feross.org",
+ "url": "https://feross.org"
+ },
+ "bugs": {
+ "url": "https://github.com/feross/safe-buffer/issues"
+ },
+ "bundleDependencies": false,
+ "deprecated": false,
+ "description": "Safer Node.js Buffer API",
+ "devDependencies": {
+ "standard": "*",
+ "tape": "^5.0.0"
+ },
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "homepage": "https://github.com/feross/safe-buffer",
+ "keywords": [
+ "buffer",
+ "buffer allocate",
+ "node security",
+ "safe",
+ "safe-buffer",
+ "security",
+ "uninitialized"
+ ],
+ "license": "MIT",
+ "main": "index.js",
+ "name": "safe-buffer",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/feross/safe-buffer.git"
+ },
+ "scripts": {
+ "test": "standard && tape test/*.js"
+ },
+ "types": "index.d.ts",
+ "version": "5.2.1"
+}
diff --git a/node_modules/mongoose/package.json b/node_modules/mongoose/package.json
new file mode 100644
index 0000000..08ff10a
--- /dev/null
+++ b/node_modules/mongoose/package.json
@@ -0,0 +1,256 @@
+{
+ "_from": "mongoose@^5.10.13",
+ "_id": "mongoose@5.10.14",
+ "_inBundle": false,
+ "_integrity": "sha512-lG7TCyjGjVPM4R1HWCyWZbdK7hC4MdWRG7P95hDENXSvaLkGLiP7WZbGT83KzLY8+400x1p6C53UALD3MqpsCA==",
+ "_location": "/mongoose",
+ "_phantomChildren": {},
+ "_requested": {
+ "type": "range",
+ "registry": true,
+ "raw": "mongoose@^5.10.13",
+ "name": "mongoose",
+ "escapedName": "mongoose",
+ "rawSpec": "^5.10.13",
+ "saveSpec": null,
+ "fetchSpec": "^5.10.13"
+ },
+ "_requiredBy": [
+ "/"
+ ],
+ "_resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.10.14.tgz",
+ "_shasum": "2f245ea578c008939599356ff6a8ba7e7643f987",
+ "_spec": "mongoose@^5.10.13",
+ "_where": "/home/pruss/Dev/3-minute-website",
+ "author": {
+ "name": "Guillermo Rauch",
+ "email": "guillermo@learnboost.com"
+ },
+ "browser": "./dist/browser.umd.js",
+ "bugs": {
+ "url": "https://github.com/Automattic/mongoose/issues/new"
+ },
+ "bundleDependencies": false,
+ "dependencies": {
+ "bson": "^1.1.4",
+ "kareem": "2.3.1",
+ "mongodb": "3.6.3",
+ "mongoose-legacy-pluralize": "1.0.2",
+ "mpath": "0.7.0",
+ "mquery": "3.2.2",
+ "ms": "2.1.2",
+ "regexp-clone": "1.0.0",
+ "safe-buffer": "5.2.1",
+ "sift": "7.0.1",
+ "sliced": "1.0.1"
+ },
+ "deprecated": false,
+ "description": "Mongoose MongoDB ODM",
+ "devDependencies": {
+ "@babel/core": "7.10.5",
+ "@babel/preset-env": "7.10.4",
+ "acquit": "1.x",
+ "acquit-ignore": "0.1.x",
+ "acquit-require": "0.1.x",
+ "async": "2.6.2",
+ "babel-loader": "8.1.0",
+ "benchmark": "2.1.4",
+ "bluebird": "3.5.5",
+ "chalk": "2.4.2",
+ "cheerio": "1.0.0-rc.2",
+ "co": "4.6.0",
+ "dox": "0.3.1",
+ "eslint": "7.1.0",
+ "eslint-plugin-mocha-no-only": "1.1.0",
+ "highlight.js": "9.1.0",
+ "lodash.isequal": "4.5.0",
+ "lodash.isequalwith": "4.4.0",
+ "marked": "1.1.1",
+ "mocha": "5.x",
+ "moment": "2.x",
+ "mongodb-topology-manager": "1.0.11",
+ "mongoose-long": "0.2.1",
+ "node-static": "0.7.11",
+ "object-sizeof": "1.3.0",
+ "pug": "2.0.3",
+ "q": "1.5.1",
+ "semver": "5.5.0",
+ "uuid": "2.0.3",
+ "uuid-parse": "1.0.0",
+ "validator": "10.8.0",
+ "webpack": "4.44.0"
+ },
+ "directories": {
+ "lib": "./lib/mongoose"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ },
+ "eslintConfig": {
+ "extends": [
+ "eslint:recommended"
+ ],
+ "plugins": [
+ "mocha-no-only"
+ ],
+ "parserOptions": {
+ "ecmaVersion": 2015
+ },
+ "env": {
+ "node": true,
+ "es6": true
+ },
+ "rules": {
+ "comma-style": "error",
+ "indent": [
+ "error",
+ 2,
+ {
+ "SwitchCase": 1,
+ "VariableDeclarator": 2
+ }
+ ],
+ "keyword-spacing": "error",
+ "no-whitespace-before-property": "error",
+ "no-buffer-constructor": "warn",
+ "no-console": "off",
+ "no-multi-spaces": "error",
+ "no-constant-condition": "off",
+ "func-call-spacing": "error",
+ "no-trailing-spaces": "error",
+ "no-undef": "error",
+ "no-unneeded-ternary": "error",
+ "no-const-assign": "error",
+ "no-useless-rename": "error",
+ "no-dupe-keys": "error",
+ "space-in-parens": [
+ "error",
+ "never"
+ ],
+ "spaced-comment": [
+ "error",
+ "always",
+ {
+ "block": {
+ "markers": [
+ "!"
+ ],
+ "balanced": true
+ }
+ }
+ ],
+ "key-spacing": [
+ "error",
+ {
+ "beforeColon": false,
+ "afterColon": true
+ }
+ ],
+ "comma-spacing": [
+ "error",
+ {
+ "before": false,
+ "after": true
+ }
+ ],
+ "array-bracket-spacing": 1,
+ "arrow-spacing": [
+ "error",
+ {
+ "before": true,
+ "after": true
+ }
+ ],
+ "object-curly-spacing": [
+ "error",
+ "always"
+ ],
+ "comma-dangle": [
+ "error",
+ "never"
+ ],
+ "no-unreachable": "error",
+ "quotes": [
+ "error",
+ "single"
+ ],
+ "quote-props": [
+ "error",
+ "as-needed"
+ ],
+ "semi": "error",
+ "no-extra-semi": "error",
+ "semi-spacing": "error",
+ "no-spaced-func": "error",
+ "no-throw-literal": "error",
+ "space-before-blocks": "error",
+ "space-before-function-paren": [
+ "error",
+ "never"
+ ],
+ "space-infix-ops": "error",
+ "space-unary-ops": "error",
+ "no-var": "warn",
+ "prefer-const": "warn",
+ "strict": [
+ "error",
+ "global"
+ ],
+ "no-restricted-globals": [
+ "error",
+ {
+ "name": "context",
+ "message": "Don't use Mocha's global context"
+ }
+ ],
+ "no-prototype-builtins": "off",
+ "mocha-no-only/mocha-no-only": [
+ "error"
+ ]
+ }
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/mongoose"
+ },
+ "homepage": "https://mongoosejs.com",
+ "keywords": [
+ "mongodb",
+ "document",
+ "model",
+ "schema",
+ "database",
+ "odm",
+ "data",
+ "datastore",
+ "query",
+ "nosql",
+ "orm",
+ "db"
+ ],
+ "license": "MIT",
+ "main": "./index.js",
+ "mocha": {
+ "extension": [
+ "test.js"
+ ],
+ "watch-files": [
+ "test/**/*.js"
+ ]
+ },
+ "name": "mongoose",
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/Automattic/mongoose.git"
+ },
+ "scripts": {
+ "build-browser": "node build-browser.js",
+ "lint": "eslint .",
+ "prepublishOnly": "npm run build-browser",
+ "release": "git pull && git push origin master --tags && npm publish",
+ "release-legacy": "git pull origin 4.x && git push origin 4.x --tags && npm publish --tag legacy",
+ "test": "mocha --exit",
+ "test-cov": "nyc --reporter=html --reporter=text npm test"
+ },
+ "version": "5.10.14"
+}
diff --git a/node_modules/mongoose/tools/auth.js b/node_modules/mongoose/tools/auth.js
new file mode 100644
index 0000000..7cfaf86
--- /dev/null
+++ b/node_modules/mongoose/tools/auth.js
@@ -0,0 +1,30 @@
+'use strict';
+
+const Server = require('mongodb-topology-manager').Server;
+const co = require('co');
+const mongodb = require('mongodb');
+
+co(function*() {
+ // Create new instance
+ const server = new Server('mongod', {
+ auth: null,
+ dbpath: '/data/db/27017'
+ });
+
+ // Purge the directory
+ yield server.purge();
+
+ // Start process
+ yield server.start();
+
+ const db = yield mongodb.MongoClient.connect('mongodb://localhost:27017/admin');
+
+ yield db.addUser('passwordIsTaco', 'taco', {
+ roles: ['dbOwner']
+ });
+
+ console.log('done');
+}).catch(error => {
+ console.error(error);
+ process.exit(-1);
+});
diff --git a/node_modules/mongoose/tools/repl.js b/node_modules/mongoose/tools/repl.js
new file mode 100644
index 0000000..8139a51
--- /dev/null
+++ b/node_modules/mongoose/tools/repl.js
@@ -0,0 +1,36 @@
+'use strict';
+
+const co = require('co');
+
+co(function*() {
+ const ReplSet = require('mongodb-topology-manager').ReplSet;
+
+ // Create new instance
+ const topology = new ReplSet('mongod', [{
+ // mongod process options
+ options: {
+ bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000`
+ }
+ }, {
+ // mongod process options
+ options: {
+ bind_ip: 'localhost', port: 31001, dbpath: `/data/db/31001`
+ }
+ }, {
+ // Type of node
+ arbiterOnly: true,
+ // mongod process options
+ options: {
+ bind_ip: 'localhost', port: 31002, dbpath: `/data/db/31002`
+ }
+ }], {
+ replSet: 'rs'
+ });
+
+ yield topology.start();
+
+ console.log('done');
+}).catch(error => {
+ console.error(error);
+ process.exit(-1);
+});
diff --git a/node_modules/mongoose/tools/sharded.js b/node_modules/mongoose/tools/sharded.js
new file mode 100644
index 0000000..2b0cc04
--- /dev/null
+++ b/node_modules/mongoose/tools/sharded.js
@@ -0,0 +1,45 @@
+'use strict';
+
+const co = require('co');
+
+co(function*() {
+ const Sharded = require('mongodb-topology-manager').Sharded;
+
+ // Create new instance
+ const topology = new Sharded({
+ mongod: 'mongod',
+ mongos: 'mongos'
+ });
+
+ yield topology.addShard([{
+ options: {
+ bind_ip: 'localhost', port: 31000, dbpath: `/data/db/31000`, shardsvr: null
+ }
+ }], { replSet: 'rs1' });
+
+ yield topology.addConfigurationServers([{
+ options: {
+ bind_ip: 'localhost', port: 35000, dbpath: `/data/db/35000`
+ }
+ }], { replSet: 'rs0' });
+
+ yield topology.addProxies([{
+ bind_ip: 'localhost', port: 51000, configdb: 'localhost:35000'
+ }], {
+ binary: 'mongos'
+ });
+
+ console.log('Start...');
+ // Start up topology
+ yield topology.start();
+
+ console.log('Started');
+
+ // Shard db
+ yield topology.enableSharding('test');
+
+ console.log('done');
+}).catch(error => {
+ console.error(error);
+ process.exit(-1);
+});