@depup/mongoose 9.1.3-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/LICENSE.md +22 -0
  2. package/README.md +397 -0
  3. package/SECURITY.md +1 -0
  4. package/eslint.config.mjs +198 -0
  5. package/index.js +64 -0
  6. package/lib/aggregate.js +1189 -0
  7. package/lib/cast/bigint.js +46 -0
  8. package/lib/cast/boolean.js +32 -0
  9. package/lib/cast/date.js +41 -0
  10. package/lib/cast/decimal128.js +39 -0
  11. package/lib/cast/double.js +50 -0
  12. package/lib/cast/int32.js +36 -0
  13. package/lib/cast/number.js +42 -0
  14. package/lib/cast/objectid.js +29 -0
  15. package/lib/cast/string.js +37 -0
  16. package/lib/cast/uuid.js +35 -0
  17. package/lib/cast.js +436 -0
  18. package/lib/collection.js +321 -0
  19. package/lib/connection.js +1855 -0
  20. package/lib/connectionState.js +26 -0
  21. package/lib/constants.js +73 -0
  22. package/lib/cursor/aggregationCursor.js +466 -0
  23. package/lib/cursor/changeStream.js +198 -0
  24. package/lib/cursor/queryCursor.js +622 -0
  25. package/lib/document.js +5521 -0
  26. package/lib/driver.js +15 -0
  27. package/lib/drivers/SPEC.md +4 -0
  28. package/lib/drivers/node-mongodb-native/bulkWriteResult.js +5 -0
  29. package/lib/drivers/node-mongodb-native/collection.js +393 -0
  30. package/lib/drivers/node-mongodb-native/connection.js +506 -0
  31. package/lib/drivers/node-mongodb-native/index.js +10 -0
  32. package/lib/error/browserMissingSchema.js +29 -0
  33. package/lib/error/bulkSaveIncompleteError.js +44 -0
  34. package/lib/error/bulkWriteError.js +41 -0
  35. package/lib/error/cast.js +158 -0
  36. package/lib/error/createCollectionsError.js +26 -0
  37. package/lib/error/divergentArray.js +40 -0
  38. package/lib/error/eachAsyncMultiError.js +41 -0
  39. package/lib/error/index.js +237 -0
  40. package/lib/error/invalidSchemaOption.js +32 -0
  41. package/lib/error/messages.js +47 -0
  42. package/lib/error/missingSchema.js +33 -0
  43. package/lib/error/mongooseError.js +13 -0
  44. package/lib/error/notFound.js +47 -0
  45. package/lib/error/objectExpected.js +31 -0
  46. package/lib/error/objectParameter.js +31 -0
  47. package/lib/error/overwriteModel.js +31 -0
  48. package/lib/error/parallelSave.js +33 -0
  49. package/lib/error/parallelValidate.js +33 -0
  50. package/lib/error/serverSelection.js +62 -0
  51. package/lib/error/setOptionError.js +103 -0
  52. package/lib/error/strict.js +35 -0
  53. package/lib/error/strictPopulate.js +31 -0
  54. package/lib/error/syncIndexes.js +30 -0
  55. package/lib/error/validation.js +97 -0
  56. package/lib/error/validator.js +100 -0
  57. package/lib/error/version.js +38 -0
  58. package/lib/helpers/aggregate/prepareDiscriminatorPipeline.js +39 -0
  59. package/lib/helpers/aggregate/stringifyFunctionOperators.js +50 -0
  60. package/lib/helpers/arrayDepth.js +33 -0
  61. package/lib/helpers/clone.js +204 -0
  62. package/lib/helpers/common.js +127 -0
  63. package/lib/helpers/createJSONSchemaTypeDefinition.js +24 -0
  64. package/lib/helpers/cursor/eachAsync.js +225 -0
  65. package/lib/helpers/discriminator/applyEmbeddedDiscriminators.js +36 -0
  66. package/lib/helpers/discriminator/areDiscriminatorValuesEqual.js +16 -0
  67. package/lib/helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection.js +12 -0
  68. package/lib/helpers/discriminator/getConstructor.js +29 -0
  69. package/lib/helpers/discriminator/getDiscriminatorByValue.js +28 -0
  70. package/lib/helpers/discriminator/getSchemaDiscriminatorByValue.js +27 -0
  71. package/lib/helpers/discriminator/mergeDiscriminatorSchema.js +91 -0
  72. package/lib/helpers/document/applyDefaults.js +132 -0
  73. package/lib/helpers/document/applyTimestamps.js +106 -0
  74. package/lib/helpers/document/applyVirtuals.js +147 -0
  75. package/lib/helpers/document/cleanModifiedSubpaths.js +45 -0
  76. package/lib/helpers/document/compile.js +238 -0
  77. package/lib/helpers/document/getDeepestSubdocumentForPath.js +38 -0
  78. package/lib/helpers/document/getEmbeddedDiscriminatorPath.js +53 -0
  79. package/lib/helpers/document/handleSpreadDoc.js +35 -0
  80. package/lib/helpers/each.js +25 -0
  81. package/lib/helpers/error/combinePathErrors.js +22 -0
  82. package/lib/helpers/firstKey.js +8 -0
  83. package/lib/helpers/get.js +65 -0
  84. package/lib/helpers/getConstructorName.js +16 -0
  85. package/lib/helpers/getDefaultBulkwriteResult.js +18 -0
  86. package/lib/helpers/getFunctionName.js +10 -0
  87. package/lib/helpers/immediate.js +16 -0
  88. package/lib/helpers/indexes/applySchemaCollation.js +13 -0
  89. package/lib/helpers/indexes/decorateDiscriminatorIndexOptions.js +14 -0
  90. package/lib/helpers/indexes/getRelatedIndexes.js +63 -0
  91. package/lib/helpers/indexes/isDefaultIdIndex.js +18 -0
  92. package/lib/helpers/indexes/isIndexEqual.js +95 -0
  93. package/lib/helpers/indexes/isIndexSpecEqual.js +32 -0
  94. package/lib/helpers/indexes/isTextIndex.js +16 -0
  95. package/lib/helpers/indexes/isTimeseriesIndex.js +16 -0
  96. package/lib/helpers/isAsyncFunction.js +9 -0
  97. package/lib/helpers/isBsonType.js +15 -0
  98. package/lib/helpers/isMongooseObject.js +22 -0
  99. package/lib/helpers/isObject.js +16 -0
  100. package/lib/helpers/isPOJO.js +12 -0
  101. package/lib/helpers/isPromise.js +6 -0
  102. package/lib/helpers/isSimpleValidator.js +22 -0
  103. package/lib/helpers/minimize.js +41 -0
  104. package/lib/helpers/model/applyDefaultsToPOJO.js +52 -0
  105. package/lib/helpers/model/applyHooks.js +140 -0
  106. package/lib/helpers/model/applyMethods.js +70 -0
  107. package/lib/helpers/model/applyStaticHooks.js +33 -0
  108. package/lib/helpers/model/applyStatics.js +13 -0
  109. package/lib/helpers/model/castBulkWrite.js +316 -0
  110. package/lib/helpers/model/decorateBulkWriteResult.js +8 -0
  111. package/lib/helpers/model/discriminator.js +265 -0
  112. package/lib/helpers/model/pushNestedArrayPaths.js +15 -0
  113. package/lib/helpers/omitUndefined.js +20 -0
  114. package/lib/helpers/once.js +12 -0
  115. package/lib/helpers/parallelLimit.js +37 -0
  116. package/lib/helpers/path/parentPaths.js +18 -0
  117. package/lib/helpers/path/setDottedPath.js +33 -0
  118. package/lib/helpers/pluralize.js +95 -0
  119. package/lib/helpers/populate/assignRawDocsToIdStructure.js +129 -0
  120. package/lib/helpers/populate/assignVals.js +360 -0
  121. package/lib/helpers/populate/createPopulateQueryFilter.js +97 -0
  122. package/lib/helpers/populate/getModelsMapForPopulate.js +776 -0
  123. package/lib/helpers/populate/getSchemaTypes.js +228 -0
  124. package/lib/helpers/populate/getVirtual.js +103 -0
  125. package/lib/helpers/populate/leanPopulateMap.js +7 -0
  126. package/lib/helpers/populate/lookupLocalFields.js +40 -0
  127. package/lib/helpers/populate/markArraySubdocsPopulated.js +49 -0
  128. package/lib/helpers/populate/modelNamesFromRefPath.js +66 -0
  129. package/lib/helpers/populate/removeDeselectedForeignField.js +31 -0
  130. package/lib/helpers/populate/setPopulatedVirtualValue.js +33 -0
  131. package/lib/helpers/populate/skipPopulateValue.js +10 -0
  132. package/lib/helpers/populate/validateRef.js +19 -0
  133. package/lib/helpers/printJestWarning.js +21 -0
  134. package/lib/helpers/processConnectionOptions.js +65 -0
  135. package/lib/helpers/projection/applyProjection.js +83 -0
  136. package/lib/helpers/projection/hasIncludedChildren.js +41 -0
  137. package/lib/helpers/projection/isDefiningProjection.js +18 -0
  138. package/lib/helpers/projection/isExclusive.js +37 -0
  139. package/lib/helpers/projection/isInclusive.js +39 -0
  140. package/lib/helpers/projection/isNestedProjection.js +8 -0
  141. package/lib/helpers/projection/isPathExcluded.js +40 -0
  142. package/lib/helpers/projection/isPathSelectedInclusive.js +28 -0
  143. package/lib/helpers/projection/isSubpath.js +14 -0
  144. package/lib/helpers/projection/parseProjection.js +33 -0
  145. package/lib/helpers/query/applyGlobalOption.js +29 -0
  146. package/lib/helpers/query/cast$expr.js +287 -0
  147. package/lib/helpers/query/castFilterPath.js +54 -0
  148. package/lib/helpers/query/castUpdate.js +643 -0
  149. package/lib/helpers/query/getEmbeddedDiscriminatorPath.js +103 -0
  150. package/lib/helpers/query/handleImmutable.js +44 -0
  151. package/lib/helpers/query/handleReadPreferenceAliases.js +23 -0
  152. package/lib/helpers/query/hasDollarKeys.js +23 -0
  153. package/lib/helpers/query/isOperator.js +14 -0
  154. package/lib/helpers/query/sanitizeFilter.js +38 -0
  155. package/lib/helpers/query/sanitizeProjection.js +14 -0
  156. package/lib/helpers/query/selectPopulatedFields.js +62 -0
  157. package/lib/helpers/query/trusted.js +13 -0
  158. package/lib/helpers/query/validOps.js +3 -0
  159. package/lib/helpers/schema/addAutoId.js +7 -0
  160. package/lib/helpers/schema/applyBuiltinPlugins.js +12 -0
  161. package/lib/helpers/schema/applyPlugins.js +55 -0
  162. package/lib/helpers/schema/applyReadConcern.js +20 -0
  163. package/lib/helpers/schema/applyWriteConcern.js +39 -0
  164. package/lib/helpers/schema/cleanPositionalOperators.js +12 -0
  165. package/lib/helpers/schema/getIndexes.js +171 -0
  166. package/lib/helpers/schema/getKeysInSchemaOrder.js +28 -0
  167. package/lib/helpers/schema/getPath.js +43 -0
  168. package/lib/helpers/schema/getSubdocumentStrictValue.js +32 -0
  169. package/lib/helpers/schema/handleIdOption.js +20 -0
  170. package/lib/helpers/schema/handleTimestampOption.js +24 -0
  171. package/lib/helpers/schema/idGetter.js +34 -0
  172. package/lib/helpers/schema/merge.js +36 -0
  173. package/lib/helpers/schematype/handleImmutable.js +50 -0
  174. package/lib/helpers/setDefaultsOnInsert.js +158 -0
  175. package/lib/helpers/specialProperties.js +3 -0
  176. package/lib/helpers/symbols.js +20 -0
  177. package/lib/helpers/timers.js +3 -0
  178. package/lib/helpers/timestamps/setDocumentTimestamps.js +26 -0
  179. package/lib/helpers/timestamps/setupTimestamps.js +116 -0
  180. package/lib/helpers/topology/allServersUnknown.js +12 -0
  181. package/lib/helpers/topology/isAtlas.js +31 -0
  182. package/lib/helpers/topology/isSSLError.js +16 -0
  183. package/lib/helpers/update/applyTimestampsToChildren.js +193 -0
  184. package/lib/helpers/update/applyTimestampsToUpdate.js +131 -0
  185. package/lib/helpers/update/castArrayFilters.js +113 -0
  186. package/lib/helpers/update/decorateUpdateWithVersionKey.js +35 -0
  187. package/lib/helpers/update/modifiedPaths.js +33 -0
  188. package/lib/helpers/update/moveImmutableProperties.js +53 -0
  189. package/lib/helpers/update/removeUnusedArrayFilters.js +32 -0
  190. package/lib/helpers/update/updatedPathsByArrayFilter.js +27 -0
  191. package/lib/helpers/updateValidators.js +193 -0
  192. package/lib/index.js +17 -0
  193. package/lib/internal.js +46 -0
  194. package/lib/model.js +5010 -0
  195. package/lib/modifiedPathsSnapshot.js +9 -0
  196. package/lib/mongoose.js +1411 -0
  197. package/lib/options/populateOptions.js +36 -0
  198. package/lib/options/propertyOptions.js +8 -0
  199. package/lib/options/saveOptions.js +16 -0
  200. package/lib/options/schemaArrayOptions.js +78 -0
  201. package/lib/options/schemaBufferOptions.js +38 -0
  202. package/lib/options/schemaDateOptions.js +71 -0
  203. package/lib/options/schemaDocumentArrayOptions.js +68 -0
  204. package/lib/options/schemaMapOptions.js +43 -0
  205. package/lib/options/schemaNumberOptions.js +101 -0
  206. package/lib/options/schemaObjectIdOptions.js +64 -0
  207. package/lib/options/schemaStringOptions.js +138 -0
  208. package/lib/options/schemaSubdocumentOptions.js +66 -0
  209. package/lib/options/schemaTypeOptions.js +244 -0
  210. package/lib/options/schemaUnionOptions.js +32 -0
  211. package/lib/options/virtualOptions.js +164 -0
  212. package/lib/options.js +17 -0
  213. package/lib/plugins/index.js +6 -0
  214. package/lib/plugins/saveSubdocs.js +76 -0
  215. package/lib/plugins/sharding.js +84 -0
  216. package/lib/plugins/trackTransaction.js +84 -0
  217. package/lib/plugins/validateBeforeSave.js +41 -0
  218. package/lib/query.js +5673 -0
  219. package/lib/queryHelpers.js +387 -0
  220. package/lib/schema/array.js +699 -0
  221. package/lib/schema/bigint.js +282 -0
  222. package/lib/schema/boolean.js +332 -0
  223. package/lib/schema/buffer.js +343 -0
  224. package/lib/schema/date.js +467 -0
  225. package/lib/schema/decimal128.js +263 -0
  226. package/lib/schema/documentArray.js +656 -0
  227. package/lib/schema/documentArrayElement.js +137 -0
  228. package/lib/schema/double.js +246 -0
  229. package/lib/schema/index.js +32 -0
  230. package/lib/schema/int32.js +289 -0
  231. package/lib/schema/map.js +201 -0
  232. package/lib/schema/mixed.js +146 -0
  233. package/lib/schema/number.js +510 -0
  234. package/lib/schema/objectId.js +333 -0
  235. package/lib/schema/operators/bitwise.js +38 -0
  236. package/lib/schema/operators/exists.js +12 -0
  237. package/lib/schema/operators/geospatial.js +107 -0
  238. package/lib/schema/operators/helpers.js +32 -0
  239. package/lib/schema/operators/text.js +39 -0
  240. package/lib/schema/operators/type.js +20 -0
  241. package/lib/schema/string.js +733 -0
  242. package/lib/schema/subdocument.js +436 -0
  243. package/lib/schema/symbols.js +5 -0
  244. package/lib/schema/union.js +113 -0
  245. package/lib/schema/uuid.js +305 -0
  246. package/lib/schema.js +3226 -0
  247. package/lib/schemaType.js +1835 -0
  248. package/lib/stateMachine.js +232 -0
  249. package/lib/types/array/index.js +119 -0
  250. package/lib/types/array/isMongooseArray.js +5 -0
  251. package/lib/types/array/methods/index.js +1095 -0
  252. package/lib/types/arraySubdocument.js +207 -0
  253. package/lib/types/buffer.js +294 -0
  254. package/lib/types/decimal128.js +13 -0
  255. package/lib/types/documentArray/index.js +113 -0
  256. package/lib/types/documentArray/isMongooseDocumentArray.js +5 -0
  257. package/lib/types/documentArray/methods/index.js +415 -0
  258. package/lib/types/double.js +13 -0
  259. package/lib/types/index.js +23 -0
  260. package/lib/types/map.js +419 -0
  261. package/lib/types/objectid.js +41 -0
  262. package/lib/types/subdocument.js +464 -0
  263. package/lib/types/uuid.js +13 -0
  264. package/lib/utils.js +1054 -0
  265. package/lib/validOptions.js +42 -0
  266. package/lib/virtualType.js +204 -0
  267. package/package.json +148 -0
  268. package/types/aggregate.d.ts +180 -0
  269. package/types/augmentations.d.ts +9 -0
  270. package/types/callback.d.ts +8 -0
  271. package/types/collection.d.ts +49 -0
  272. package/types/connection.d.ts +297 -0
  273. package/types/cursor.d.ts +67 -0
  274. package/types/document.d.ts +374 -0
  275. package/types/error.d.ts +143 -0
  276. package/types/expressions.d.ts +3053 -0
  277. package/types/helpers.d.ts +32 -0
  278. package/types/index.d.ts +1056 -0
  279. package/types/indexes.d.ts +97 -0
  280. package/types/inferhydrateddoctype.d.ts +115 -0
  281. package/types/inferrawdoctype.d.ts +135 -0
  282. package/types/inferschematype.d.ts +337 -0
  283. package/types/middlewares.d.ts +59 -0
  284. package/types/models.d.ts +1306 -0
  285. package/types/mongooseoptions.d.ts +228 -0
  286. package/types/pipelinestage.d.ts +333 -0
  287. package/types/populate.d.ts +53 -0
  288. package/types/query.d.ts +934 -0
  289. package/types/schemaoptions.d.ts +282 -0
  290. package/types/schematypes.d.ts +654 -0
  291. package/types/session.d.ts +32 -0
  292. package/types/types.d.ts +109 -0
  293. package/types/utility.d.ts +175 -0
  294. package/types/validation.d.ts +39 -0
  295. package/types/virtuals.d.ts +14 -0
@@ -0,0 +1,1095 @@
1
+ 'use strict';
2
+
3
+ const Document = require('../../../document');
4
+ const ArraySubdocument = require('../../arraySubdocument');
5
+ const MongooseError = require('../../../error/mongooseError');
6
+ const cleanModifiedSubpaths = require('../../../helpers/document/cleanModifiedSubpaths');
7
+ const clone = require('../../../helpers/clone');
8
+ const internalToObjectOptions = require('../../../options').internalToObjectOptions;
9
+ const mpath = require('mpath');
10
+ const utils = require('../../../utils');
11
+ const isBsonType = require('../../../helpers/isBsonType');
12
+
13
+ const arrayAtomicsBackupSymbol = require('../../../helpers/symbols').arrayAtomicsBackupSymbol;
14
+ const arrayAtomicsSymbol = require('../../../helpers/symbols').arrayAtomicsSymbol;
15
+ const arrayParentSymbol = require('../../../helpers/symbols').arrayParentSymbol;
16
+ const arrayPathSymbol = require('../../../helpers/symbols').arrayPathSymbol;
17
+ const arraySchemaSymbol = require('../../../helpers/symbols').arraySchemaSymbol;
18
+ const populateModelSymbol = require('../../../helpers/symbols').populateModelSymbol;
19
+ const slicedSymbol = Symbol('mongoose#Array#sliced');
20
+
21
+ const _basePush = Array.prototype.push;
22
+
23
+ /*!
24
+ * ignore
25
+ */
26
+
27
+ const methods = {
28
+ /**
29
+ * Depopulates stored atomic operation values as necessary for direct insertion to MongoDB.
30
+ *
31
+ * If no atomics exist, we return all array values after conversion.
32
+ *
33
+ * @return {Array}
34
+ * @method $__getAtomics
35
+ * @memberOf MongooseArray
36
+ * @instance
37
+ * @api private
38
+ */
39
+
40
+ $__getAtomics() {
41
+ const ret = [];
42
+ const keys = Object.keys(this[arrayAtomicsSymbol] || {});
43
+ let i = keys.length;
44
+
45
+ const opts = Object.assign({}, internalToObjectOptions, { _isNested: true });
46
+
47
+ if (i === 0) {
48
+ ret[0] = ['$set', this.toObject(opts)];
49
+ return ret;
50
+ }
51
+
52
+ while (i--) {
53
+ const op = keys[i];
54
+ let val = this[arrayAtomicsSymbol][op];
55
+
56
+ // the atomic values which are arrays are not MongooseArrays. we
57
+ // need to convert their elements as if they were MongooseArrays
58
+ // to handle populated arrays versus DocumentArrays properly.
59
+ if (utils.isMongooseObject(val)) {
60
+ val = val.toObject(opts);
61
+ } else if (Array.isArray(val)) {
62
+ val = this.toObject.call(val, opts);
63
+ } else if (Array.isArray(val?.$each)) {
64
+ val.$each = this.toObject.call(val.$each, opts);
65
+ } else if (typeof val?.valueOf === 'function') {
66
+ val = val.valueOf();
67
+ }
68
+
69
+ if (op === '$addToSet') {
70
+ val = { $each: val };
71
+ }
72
+
73
+ ret.push([op, val]);
74
+ }
75
+
76
+ return ret;
77
+ },
78
+
79
+ /**
80
+ * Public API for getting atomics. Alias for $__getAtomics() that can be
81
+ * implemented by custom container types.
82
+ *
83
+ * @return {Array}
84
+ * @method getAtomics
85
+ * @memberOf MongooseArray
86
+ * @instance
87
+ * @api public
88
+ */
89
+
90
+ getAtomics() {
91
+ return this.$__getAtomics();
92
+ },
93
+
94
+ /**
95
+ * Clears all pending atomic operations. Called by Mongoose after save().
96
+ *
97
+ * @return {void}
98
+ * @method clearAtomics
99
+ * @memberOf MongooseArray
100
+ * @instance
101
+ * @api public
102
+ */
103
+
104
+ clearAtomics() {
105
+ this[arrayAtomicsBackupSymbol] = this[arrayAtomicsSymbol];
106
+ this[arrayAtomicsSymbol] = {};
107
+ },
108
+
109
+ /*!
110
+ * ignore
111
+ */
112
+
113
+ $atomics() {
114
+ return this[arrayAtomicsSymbol];
115
+ },
116
+
117
+ /*!
118
+ * ignore
119
+ */
120
+
121
+ $parent() {
122
+ return this[arrayParentSymbol];
123
+ },
124
+
125
+ /*!
126
+ * ignore
127
+ */
128
+
129
+ $path() {
130
+ return this[arrayPathSymbol];
131
+ },
132
+
133
+ /*!
134
+ * ignore
135
+ */
136
+ $schemaType() {
137
+ return this[arraySchemaSymbol];
138
+ },
139
+
140
+ /**
141
+ * Atomically shifts the array at most one time per document `save()`.
142
+ *
143
+ * #### Note:
144
+ *
145
+ * _Calling this multiple times on an array before saving sends the same command as calling it once._
146
+ * _This update is implemented using the MongoDB [$pop](https://www.mongodb.com/docs/manual/reference/operator/update/pop/) method which enforces this restriction._
147
+ *
148
+ * doc.array = [1,2,3];
149
+ *
150
+ * const shifted = doc.array.$shift();
151
+ * console.log(shifted); // 1
152
+ * console.log(doc.array); // [2,3]
153
+ *
154
+ * // no affect
155
+ * shifted = doc.array.$shift();
156
+ * console.log(doc.array); // [2,3]
157
+ *
158
+ * doc.save(function (err) {
159
+ * if (err) return handleError(err);
160
+ *
161
+ * // we saved, now $shift works again
162
+ * shifted = doc.array.$shift();
163
+ * console.log(shifted ); // 2
164
+ * console.log(doc.array); // [3]
165
+ * })
166
+ *
167
+ * @api public
168
+ * @memberOf MongooseArray
169
+ * @instance
170
+ * @method $shift
171
+ * @see mongodb https://www.mongodb.com/docs/manual/reference/operator/update/pop/
172
+ */
173
+
174
+ $shift() {
175
+ this._registerAtomic('$pop', -1);
176
+ this._markModified();
177
+
178
+ // only allow shifting once
179
+ const __array = this.__array;
180
+ if (__array._shifted) {
181
+ return;
182
+ }
183
+ __array._shifted = true;
184
+
185
+ return [].shift.call(__array);
186
+ },
187
+
188
+ /**
189
+ * Pops the array atomically at most one time per document `save()`.
190
+ *
191
+ * #### NOTE:
192
+ *
193
+ * _Calling this multiple times on an array before saving sends the same command as calling it once._
194
+ * _This update is implemented using the MongoDB [$pop](https://www.mongodb.com/docs/manual/reference/operator/update/pop/) method which enforces this restriction._
195
+ *
196
+ * doc.array = [1,2,3];
197
+ *
198
+ * const popped = doc.array.$pop();
199
+ * console.log(popped); // 3
200
+ * console.log(doc.array); // [1,2]
201
+ *
202
+ * // no affect
203
+ * popped = doc.array.$pop();
204
+ * console.log(doc.array); // [1,2]
205
+ *
206
+ * doc.save(function (err) {
207
+ * if (err) return handleError(err);
208
+ *
209
+ * // we saved, now $pop works again
210
+ * popped = doc.array.$pop();
211
+ * console.log(popped); // 2
212
+ * console.log(doc.array); // [1]
213
+ * })
214
+ *
215
+ * @api public
216
+ * @method $pop
217
+ * @memberOf MongooseArray
218
+ * @instance
219
+ * @see mongodb https://www.mongodb.com/docs/manual/reference/operator/update/pop/
220
+ * @method $pop
221
+ * @memberOf MongooseArray
222
+ */
223
+
224
+ $pop() {
225
+ this._registerAtomic('$pop', 1);
226
+ this._markModified();
227
+
228
+ // only allow popping once
229
+ if (this._popped) {
230
+ return;
231
+ }
232
+ this._popped = true;
233
+
234
+ return [].pop.call(this);
235
+ },
236
+
237
+ /*!
238
+ * ignore
239
+ */
240
+
241
+ $schema() {
242
+ return this[arraySchemaSymbol];
243
+ },
244
+
245
+ /**
246
+ * Casts a member based on this arrays schema.
247
+ *
248
+ * @param {any} value
249
+ * @return value the casted value
250
+ * @method _cast
251
+ * @api private
252
+ * @memberOf MongooseArray
253
+ */
254
+
255
+ _cast(value) {
256
+ let populated = false;
257
+ let Model;
258
+
259
+ const parent = this[arrayParentSymbol];
260
+ if (parent) {
261
+ populated = parent.$populated(this[arrayPathSymbol], true);
262
+ }
263
+
264
+ if (populated && value != null) {
265
+ // cast to the populated Models schema
266
+ Model = populated.options[populateModelSymbol];
267
+ if (Model == null) {
268
+ throw new MongooseError('No populated model found for path `' + this[arrayPathSymbol] + '`. This is likely a bug in Mongoose, please report an issue on github.com/Automattic/mongoose.');
269
+ }
270
+
271
+ // only objects are permitted so we can safely assume that
272
+ // non-objects are to be interpreted as _id
273
+ if (Buffer.isBuffer(value) ||
274
+ isBsonType(value, 'ObjectId') || !utils.isObject(value)) {
275
+ value = { _id: value };
276
+ }
277
+
278
+ // gh-2399
279
+ // we should cast model only when it's not a discriminator
280
+ const isDisc = value.schema?.discriminatorMapping?.key !== undefined;
281
+ if (!isDisc) {
282
+ value = new Model(value);
283
+ }
284
+ return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, true);
285
+ }
286
+
287
+ return this[arraySchemaSymbol].embeddedSchemaType.applySetters(value, parent, false);
288
+ },
289
+
290
+ /**
291
+ * Internal helper for .map()
292
+ *
293
+ * @api private
294
+ * @return {Number}
295
+ * @method _mapCast
296
+ * @memberOf MongooseArray
297
+ */
298
+
299
+ _mapCast(val, index) {
300
+ return this._cast(val, this.length + index);
301
+ },
302
+
303
+ /**
304
+ * Marks this array as modified.
305
+ *
306
+ * If it bubbles up from an embedded document change, then it takes the following arguments (otherwise, takes 0 arguments)
307
+ *
308
+ * @param {ArraySubdocument} subdoc the embedded doc that invoked this method on the Array
309
+ * @param {String} embeddedPath the path which changed in the subdoc
310
+ * @method _markModified
311
+ * @api private
312
+ * @memberOf MongooseArray
313
+ */
314
+
315
+ _markModified(elem) {
316
+ const parent = this[arrayParentSymbol];
317
+ let dirtyPath;
318
+
319
+ if (parent) {
320
+ dirtyPath = this[arrayPathSymbol];
321
+
322
+ if (arguments.length) {
323
+ dirtyPath = dirtyPath + '.' + elem;
324
+ }
325
+
326
+ if (dirtyPath != null && dirtyPath.endsWith('.$')) {
327
+ return this;
328
+ }
329
+
330
+ parent.markModified(dirtyPath, arguments.length !== 0 ? elem : parent);
331
+ }
332
+
333
+ return this;
334
+ },
335
+
336
+ /**
337
+ * Register an atomic operation with the parent.
338
+ *
339
+ * @param {Array} op operation
340
+ * @param {any} val
341
+ * @method _registerAtomic
342
+ * @api private
343
+ * @memberOf MongooseArray
344
+ */
345
+
346
+ _registerAtomic(op, val) {
347
+ if (this[slicedSymbol]) {
348
+ return;
349
+ }
350
+ if (op === '$set') {
351
+ // $set takes precedence over all other ops.
352
+ // mark entire array modified.
353
+ this[arrayAtomicsSymbol] = { $set: val };
354
+ cleanModifiedSubpaths(this[arrayParentSymbol], this[arrayPathSymbol]);
355
+ this._markModified();
356
+ return this;
357
+ }
358
+
359
+ const atomics = this[arrayAtomicsSymbol];
360
+
361
+ // reset pop/shift after save
362
+ if (op === '$pop' && !('$pop' in atomics)) {
363
+ const _this = this;
364
+ this[arrayParentSymbol].once('save', function() {
365
+ _this._popped = _this._shifted = null;
366
+ });
367
+ }
368
+
369
+ // check for impossible $atomic combos (Mongo denies more than one
370
+ // $atomic op on a single path
371
+ if (atomics.$set || utils.hasOwnKeys(atomics) && !(op in atomics)) {
372
+ // a different op was previously registered.
373
+ // save the entire thing.
374
+ this[arrayAtomicsSymbol] = { $set: this };
375
+ return this;
376
+ }
377
+
378
+ let selector;
379
+
380
+ if (op === '$pullAll' || op === '$addToSet') {
381
+ atomics[op] || (atomics[op] = []);
382
+ atomics[op] = atomics[op].concat(val);
383
+ } else if (op === '$pullDocs') {
384
+ const pullOp = atomics['$pull'] || (atomics['$pull'] = {});
385
+ if (val[0] instanceof ArraySubdocument) {
386
+ selector = pullOp['$or'] || (pullOp['$or'] = []);
387
+ Array.prototype.push.apply(selector, val.map(v => {
388
+ return v.toObject({
389
+ transform: (doc, ret) => {
390
+ if (v == null || v.$__ == null) {
391
+ return ret;
392
+ }
393
+
394
+ Object.keys(v.$__.activePaths.getStatePaths('default')).forEach(path => {
395
+ mpath.unset(path, ret);
396
+
397
+ _minimizePath(ret, path);
398
+ });
399
+
400
+ return ret;
401
+ },
402
+ virtuals: false
403
+ });
404
+ }));
405
+ } else {
406
+ selector = pullOp['_id'] || (pullOp['_id'] = { $in: [] });
407
+ selector['$in'] = selector['$in'].concat(val);
408
+ }
409
+ } else if (op === '$push') {
410
+ atomics.$push = atomics.$push || { $each: [] };
411
+ if (val != null && utils.hasUserDefinedProperty(val, '$each')) {
412
+ atomics.$push = val;
413
+ } else {
414
+ if (val.length === 1) {
415
+ atomics.$push.$each.push(val[0]);
416
+ } else if (val.length < 10000) {
417
+ atomics.$push.$each.push(...val);
418
+ } else {
419
+ for (const v of val) {
420
+ atomics.$push.$each.push(v);
421
+ }
422
+ }
423
+ }
424
+ } else {
425
+ atomics[op] = val;
426
+ }
427
+
428
+ return this;
429
+ },
430
+
431
+ /**
432
+ * Adds values to the array if not already present.
433
+ *
434
+ * #### Example:
435
+ *
436
+ * console.log(doc.array) // [2,3,4]
437
+ * const added = doc.array.addToSet(4,5);
438
+ * console.log(doc.array) // [2,3,4,5]
439
+ * console.log(added) // [5]
440
+ *
441
+ * @param {...any} [args]
442
+ * @return {Array} the values that were added
443
+ * @memberOf MongooseArray
444
+ * @api public
445
+ * @method addToSet
446
+ */
447
+
448
+ addToSet() {
449
+ _checkManualPopulation(this, arguments);
450
+ _depopulateIfNecessary(this, arguments);
451
+
452
+ const values = [].map.call(arguments, this._mapCast, this);
453
+ const added = [];
454
+ let type = '';
455
+ if (values[0] instanceof ArraySubdocument) {
456
+ type = 'doc';
457
+ } else if (values[0] instanceof Date) {
458
+ type = 'date';
459
+ } else if (isBsonType(values[0], 'ObjectId')) {
460
+ type = 'ObjectId';
461
+ }
462
+
463
+ const rawValues = utils.isMongooseArray(values) ? values.__array : values;
464
+ const rawArray = utils.isMongooseArray(this) ? this.__array : this;
465
+
466
+ rawValues.forEach(function(v) {
467
+ let found;
468
+ const val = +v;
469
+ switch (type) {
470
+ case 'doc':
471
+ found = this.some(function(doc) {
472
+ return doc.equals(v);
473
+ });
474
+ break;
475
+ case 'date':
476
+ found = this.some(function(d) {
477
+ return +d === val;
478
+ });
479
+ break;
480
+ case 'ObjectId':
481
+ found = this.find(o => o.toString() === v.toString());
482
+ break;
483
+ default:
484
+ found = ~this.indexOf(v);
485
+ break;
486
+ }
487
+
488
+ if (!found) {
489
+ this._markModified();
490
+ rawArray.push(v);
491
+ this._registerAtomic('$addToSet', v);
492
+ [].push.call(added, v);
493
+ }
494
+ }, this);
495
+
496
+ return added;
497
+ },
498
+
499
+ /**
500
+ * Returns the number of pending atomic operations to send to the db for this array.
501
+ *
502
+ * @api private
503
+ * @return {Number}
504
+ * @method hasAtomics
505
+ * @memberOf MongooseArray
506
+ */
507
+
508
+ hasAtomics() {
509
+ if (!utils.isPOJO(this[arrayAtomicsSymbol])) {
510
+ return 0;
511
+ }
512
+
513
+ return Object.keys(this[arrayAtomicsSymbol]).length;
514
+ },
515
+
516
+ /**
517
+ * Return whether or not the `obj` is included in the array.
518
+ *
519
+ * @param {Object} obj the item to check
520
+ * @param {Number} fromIndex
521
+ * @return {Boolean}
522
+ * @api public
523
+ * @method includes
524
+ * @memberOf MongooseArray
525
+ */
526
+
527
+ includes(obj, fromIndex) {
528
+ const ret = this.indexOf(obj, fromIndex);
529
+ return ret !== -1;
530
+ },
531
+
532
+ /**
533
+ * Return the index of `obj` or `-1` if not found.
534
+ *
535
+ * @param {Object} obj the item to look for
536
+ * @param {Number} fromIndex
537
+ * @return {Number}
538
+ * @api public
539
+ * @method indexOf
540
+ * @memberOf MongooseArray
541
+ */
542
+
543
+ indexOf(obj, fromIndex) {
544
+ if (isBsonType(obj, 'ObjectId')) {
545
+ obj = obj.toString();
546
+ }
547
+
548
+ fromIndex = fromIndex == null ? 0 : fromIndex;
549
+ const len = this.length;
550
+ for (let i = fromIndex; i < len; ++i) {
551
+ if (obj == this[i]) {
552
+ return i;
553
+ }
554
+ }
555
+ return -1;
556
+ },
557
+
558
+ /**
559
+ * Helper for console.log
560
+ *
561
+ * @api public
562
+ * @method inspect
563
+ * @memberOf MongooseArray
564
+ */
565
+
566
+ inspect() {
567
+ return JSON.stringify(this);
568
+ },
569
+
570
+ /**
571
+ * Pushes items to the array non-atomically.
572
+ *
573
+ * #### Note:
574
+ *
575
+ * _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._
576
+ *
577
+ * @param {...any} [args]
578
+ * @api public
579
+ * @method nonAtomicPush
580
+ * @memberOf MongooseArray
581
+ */
582
+
583
+ nonAtomicPush() {
584
+ const values = [].map.call(arguments, this._mapCast, this);
585
+ this._markModified();
586
+ const ret = [].push.apply(this, values);
587
+ this._registerAtomic('$set', this);
588
+ return ret;
589
+ },
590
+
591
+ /**
592
+ * Wraps [`Array#pop`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/pop) with proper change tracking.
593
+ *
594
+ * #### Note:
595
+ *
596
+ * _marks the entire array as modified which will pass the entire thing to $set potentially overwriting any changes that happen between when you retrieved the object and when you save it._
597
+ *
598
+ * @see MongooseArray#$pop https://mongoosejs.com/docs/api/array.html#MongooseArray.prototype.$pop()
599
+ * @api public
600
+ * @method pop
601
+ * @memberOf MongooseArray
602
+ */
603
+
604
+ pop() {
605
+ this._markModified();
606
+ const ret = [].pop.call(this);
607
+ this._registerAtomic('$set', this);
608
+ return ret;
609
+ },
610
+
611
+ /**
612
+ * Pulls items from the array atomically. Equality is determined by casting
613
+ * the provided value to an embedded document and comparing using
614
+ * [the `Document.equals()` function.](https://mongoosejs.com/docs/api/document.html#Document.prototype.equals())
615
+ *
616
+ * #### Example:
617
+ *
618
+ * doc.array.pull(ObjectId)
619
+ * doc.array.pull({ _id: 'someId' })
620
+ * doc.array.pull(36)
621
+ * doc.array.pull('tag 1', 'tag 2')
622
+ *
623
+ * To remove a document from a subdocument array we may pass an object with a matching `_id`.
624
+ *
625
+ * doc.subdocs.push({ _id: 4815162342 })
626
+ * doc.subdocs.pull({ _id: 4815162342 }) // removed
627
+ *
628
+ * Or we may passing the _id directly and let mongoose take care of it.
629
+ *
630
+ * doc.subdocs.push({ _id: 4815162342 })
631
+ * doc.subdocs.pull(4815162342); // works
632
+ *
633
+ * 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.
634
+ *
635
+ * @param {...any} [args]
636
+ * @see mongodb https://www.mongodb.com/docs/manual/reference/operator/update/pull/
637
+ * @api public
638
+ * @method pull
639
+ * @memberOf MongooseArray
640
+ */
641
+
642
+ pull() {
643
+ const values = [].map.call(arguments, (v, i) => this._cast(v, i, { defaults: false }), this);
644
+ let cur = this;
645
+ if (utils.isMongooseArray(cur)) {
646
+ cur = cur.__array;
647
+ }
648
+ let i = cur.length;
649
+ let mem;
650
+ this._markModified();
651
+
652
+ while (i--) {
653
+ mem = cur[i];
654
+ if (mem instanceof Document) {
655
+ const some = values.some(function(v) {
656
+ return mem.equals(v);
657
+ });
658
+ if (some) {
659
+ cur.splice(i, 1);
660
+ }
661
+ } else if (~this.indexOf.call(values, mem)) {
662
+ cur.splice(i, 1);
663
+ }
664
+ }
665
+
666
+ if (values[0] instanceof ArraySubdocument) {
667
+ this._registerAtomic('$pullDocs', values.map(function(v) {
668
+ const _id = v.$__getValue('_id');
669
+ if (_id === undefined || v.$isDefault('_id')) {
670
+ return v;
671
+ }
672
+ return _id;
673
+ }));
674
+ } else {
675
+ this._registerAtomic('$pullAll', values);
676
+ }
677
+
678
+
679
+ // Might have modified child paths and then pulled, like
680
+ // `doc.children[1].name = 'test';` followed by
681
+ // `doc.children.remove(doc.children[0]);`. In this case we fall back
682
+ // to a `$set` on the whole array. See #3511
683
+ if (cleanModifiedSubpaths(this[arrayParentSymbol], this[arrayPathSymbol]) > 0) {
684
+ this._registerAtomic('$set', this);
685
+ }
686
+
687
+ return this;
688
+ },
689
+
690
+ /**
691
+ * Wraps [`Array#push`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push) with proper change tracking.
692
+ *
693
+ * #### Example:
694
+ *
695
+ * const schema = Schema({ nums: [Number] });
696
+ * const Model = mongoose.model('Test', schema);
697
+ *
698
+ * const doc = await Model.create({ nums: [3, 4] });
699
+ * doc.nums.push(5); // Add 5 to the end of the array
700
+ * await doc.save();
701
+ *
702
+ * // You can also pass an object with `$each` as the
703
+ * // first parameter to use MongoDB's `$position`
704
+ * doc.nums.push({
705
+ * $each: [1, 2],
706
+ * $position: 0
707
+ * });
708
+ * doc.nums; // [1, 2, 3, 4, 5]
709
+ *
710
+ * @param {...Object} [args]
711
+ * @api public
712
+ * @method push
713
+ * @memberOf MongooseArray
714
+ */
715
+
716
+ push() {
717
+ let values = arguments;
718
+ let atomic = values;
719
+ const isOverwrite = values[0] != null &&
720
+ utils.hasUserDefinedProperty(values[0], '$each');
721
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
722
+ if (isOverwrite) {
723
+ atomic = values[0];
724
+ values = values[0].$each;
725
+ }
726
+
727
+ if (this[arraySchemaSymbol] == null) {
728
+ return _basePush.apply(this, values);
729
+ }
730
+
731
+ _checkManualPopulation(this, values);
732
+ _depopulateIfNecessary(this, values);
733
+
734
+ values = [].map.call(values, this._mapCast, this);
735
+ let ret;
736
+ const atomics = this[arrayAtomicsSymbol];
737
+ this._markModified();
738
+ if (isOverwrite) {
739
+ atomic.$each = values;
740
+
741
+ if ((atomics.$push && atomics.$push.$each && atomics.$push.$each.length || 0) !== 0 &&
742
+ atomics.$push.$position != atomic.$position) {
743
+ if (atomic.$position != null) {
744
+ [].splice.apply(arr, [atomic.$position, 0].concat(values));
745
+ ret = arr.length;
746
+ } else {
747
+ ret = [].push.apply(arr, values);
748
+ }
749
+
750
+ this._registerAtomic('$set', this);
751
+ } else if (atomic.$position != null) {
752
+ [].splice.apply(arr, [atomic.$position, 0].concat(values));
753
+ ret = this.length;
754
+ } else {
755
+ ret = [].push.apply(arr, values);
756
+ }
757
+ } else {
758
+ atomic = values;
759
+ ret = _basePush.apply(arr, values);
760
+ }
761
+
762
+ this._registerAtomic('$push', atomic);
763
+
764
+ return ret;
765
+ },
766
+
767
+ /**
768
+ * Alias of [pull](https://mongoosejs.com/docs/api/array.html#MongooseArray.prototype.pull())
769
+ *
770
+ * @see MongooseArray#pull https://mongoosejs.com/docs/api/array.html#MongooseArray.prototype.pull()
771
+ * @see mongodb https://www.mongodb.com/docs/manual/reference/operator/update/pull/
772
+ * @api public
773
+ * @memberOf MongooseArray
774
+ * @instance
775
+ * @method remove
776
+ */
777
+
778
+ remove() {
779
+ return this.pull.apply(this, arguments);
780
+ },
781
+
782
+ /**
783
+ * Sets the casted `val` at index `i` and marks the array modified.
784
+ *
785
+ * #### Example:
786
+ *
787
+ * // given documents based on the following
788
+ * const Doc = mongoose.model('Doc', new Schema({ array: [Number] }));
789
+ *
790
+ * const doc = new Doc({ array: [2,3,4] })
791
+ *
792
+ * console.log(doc.array) // [2,3,4]
793
+ *
794
+ * doc.array.set(1,"5");
795
+ * console.log(doc.array); // [2,5,4] // properly cast to number
796
+ * doc.save() // the change is saved
797
+ *
798
+ * // VS not using array#set
799
+ * doc.array[1] = "5";
800
+ * console.log(doc.array); // [2,"5",4] // no casting
801
+ * doc.save() // change is not saved
802
+ *
803
+ * @return {Array} this
804
+ * @api public
805
+ * @method set
806
+ * @memberOf MongooseArray
807
+ */
808
+
809
+ set(i, val, skipModified) {
810
+ const arr = this.__array;
811
+ if (skipModified) {
812
+ arr[i] = val;
813
+ return this;
814
+ }
815
+ const value = methods._cast.call(this, val, i);
816
+ methods._markModified.call(this, i);
817
+ arr[i] = value;
818
+ return this;
819
+ },
820
+
821
+ /**
822
+ * Wraps [`Array#shift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
823
+ *
824
+ * #### Example:
825
+ *
826
+ * doc.array = [2,3];
827
+ * const res = doc.array.shift();
828
+ * console.log(res) // 2
829
+ * console.log(doc.array) // [3]
830
+ *
831
+ * #### Note:
832
+ *
833
+ * _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._
834
+ *
835
+ * @api public
836
+ * @method shift
837
+ * @memberOf MongooseArray
838
+ */
839
+
840
+ shift() {
841
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
842
+ this._markModified();
843
+ const ret = [].shift.call(arr);
844
+ this._registerAtomic('$set', this);
845
+ return ret;
846
+ },
847
+
848
+ /**
849
+ * Wraps [`Array#sort`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/sort) with proper change tracking.
850
+ *
851
+ * #### Note:
852
+ *
853
+ * _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._
854
+ *
855
+ * @api public
856
+ * @method sort
857
+ * @memberOf MongooseArray
858
+ * @see MasteringJS: Array sort https://masteringjs.io/tutorials/fundamentals/array-sort
859
+ */
860
+
861
+ sort() {
862
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
863
+ const ret = [].sort.apply(arr, arguments);
864
+ this._registerAtomic('$set', this);
865
+ return ret;
866
+ },
867
+
868
+ /**
869
+ * Wraps [`Array#splice`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice) with proper change tracking and casting.
870
+ *
871
+ * #### Note:
872
+ *
873
+ * _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._
874
+ *
875
+ * @api public
876
+ * @method splice
877
+ * @memberOf MongooseArray
878
+ * @see MasteringJS: Array splice https://masteringjs.io/tutorials/fundamentals/array-splice
879
+ */
880
+
881
+ splice() {
882
+ let ret;
883
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
884
+
885
+ this._markModified();
886
+ _checkManualPopulation(this, Array.prototype.slice.call(arguments, 2));
887
+
888
+ if (arguments.length) {
889
+ let vals;
890
+ if (this[arraySchemaSymbol] == null) {
891
+ vals = arguments;
892
+ } else {
893
+ vals = [];
894
+ for (let i = 0; i < arguments.length; ++i) {
895
+ vals[i] = i < 2 ?
896
+ arguments[i] :
897
+ this._cast(arguments[i], arguments[0] + (i - 2));
898
+ }
899
+ }
900
+
901
+ ret = [].splice.apply(arr, vals);
902
+ this._registerAtomic('$set', this);
903
+ }
904
+
905
+ return ret;
906
+ },
907
+
908
+ /*!
909
+ * ignore
910
+ */
911
+
912
+ toBSON() {
913
+ return this.toObject(internalToObjectOptions);
914
+ },
915
+
916
+ /**
917
+ * Returns a native js Array.
918
+ *
919
+ * @param {Object} options
920
+ * @return {Array}
921
+ * @api public
922
+ * @method toObject
923
+ * @memberOf MongooseArray
924
+ */
925
+
926
+ toObject(options) {
927
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
928
+ if (options?.depopulate) {
929
+ options = clone(options);
930
+ options._isNested = true;
931
+ // Ensure return value is a vanilla array, because in Node.js 6+ `map()`
932
+ // is smart enough to use the inherited array's constructor.
933
+ return [].concat(arr).map(function(doc) {
934
+ return doc instanceof Document
935
+ ? doc.toObject(options)
936
+ : doc;
937
+ });
938
+ }
939
+
940
+ return [].concat(arr);
941
+ },
942
+
943
+ $toObject() {
944
+ return this.constructor.prototype.toObject.apply(this, arguments);
945
+ },
946
+ /**
947
+ * Wraps [`Array#unshift`](https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/unshift) with proper change tracking.
948
+ *
949
+ * #### Note:
950
+ *
951
+ * _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._
952
+ *
953
+ * @api public
954
+ * @method unshift
955
+ * @memberOf MongooseArray
956
+ */
957
+
958
+ unshift() {
959
+ _checkManualPopulation(this, arguments);
960
+
961
+ let values;
962
+ if (this[arraySchemaSymbol] == null) {
963
+ values = arguments;
964
+ } else {
965
+ values = [].map.call(arguments, this._cast, this);
966
+ }
967
+
968
+ const arr = utils.isMongooseArray(this) ? this.__array : this;
969
+ this._markModified();
970
+ [].unshift.apply(arr, values);
971
+ this._registerAtomic('$set', this);
972
+ return this.length;
973
+ }
974
+ };
975
+
976
+ /*!
977
+ * ignore
978
+ */
979
+
980
+ function _isAllSubdocs(docs, ref) {
981
+ if (!ref) {
982
+ return false;
983
+ }
984
+
985
+ for (const arg of docs) {
986
+ if (arg == null) {
987
+ return false;
988
+ }
989
+ const model = arg.constructor;
990
+ if (!(arg instanceof Document) ||
991
+ (model.modelName !== ref && model.baseModelName !== ref)) {
992
+ return false;
993
+ }
994
+ }
995
+
996
+ return true;
997
+ }
998
+
999
+ /*!
1000
+ * Minimize _just_ empty objects along the path chain specified
1001
+ * by `parts`, ignoring all other paths. Useful in cases where
1002
+ * you want to minimize after unsetting a path.
1003
+ *
1004
+ * #### Example:
1005
+ *
1006
+ * const obj = { foo: { bar: { baz: {} } }, a: {} };
1007
+ * _minimizePath(obj, 'foo.bar.baz');
1008
+ * obj; // { a: {} }
1009
+ */
1010
+
1011
+ function _minimizePath(obj, parts, i) {
1012
+ if (typeof parts === 'string') {
1013
+ if (parts.indexOf('.') === -1) {
1014
+ return;
1015
+ }
1016
+
1017
+ parts = mpath.stringToParts(parts);
1018
+ }
1019
+ i = i || 0;
1020
+ if (i >= parts.length) {
1021
+ return;
1022
+ }
1023
+ if (obj == null || typeof obj !== 'object') {
1024
+ return;
1025
+ }
1026
+
1027
+ _minimizePath(obj[parts[0]], parts, i + 1);
1028
+ if (obj[parts[0]] != null && typeof obj[parts[0]] === 'object' && utils.hasOwnKeys(obj[parts[0]]) === false) {
1029
+ delete obj[parts[0]];
1030
+ }
1031
+ }
1032
+
1033
+ /*!
1034
+ * ignore
1035
+ */
1036
+
1037
+ function _checkManualPopulation(arr, docs) {
1038
+ const ref = arr == null ?
1039
+ null :
1040
+ arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
1041
+ if (arr.length === 0 &&
1042
+ docs.length !== 0) {
1043
+ if (_isAllSubdocs(docs, ref)) {
1044
+ arr[arrayParentSymbol].$populated(arr[arrayPathSymbol], [], {
1045
+ [populateModelSymbol]: docs[0].constructor
1046
+ });
1047
+ }
1048
+ }
1049
+ }
1050
+
1051
+ /*!
1052
+ * If `docs` isn't all instances of the right model, depopulate `arr`
1053
+ */
1054
+
1055
+ function _depopulateIfNecessary(arr, docs) {
1056
+ const ref = arr == null ?
1057
+ null :
1058
+ arr[arraySchemaSymbol]?.embeddedSchemaType?.options?.ref || null;
1059
+ const parentDoc = arr[arrayParentSymbol];
1060
+ const path = arr[arrayPathSymbol];
1061
+ if (!ref || !parentDoc.populated(path)) {
1062
+ return;
1063
+ }
1064
+ for (const doc of docs) {
1065
+ if (doc == null) {
1066
+ continue;
1067
+ }
1068
+ if (typeof doc !== 'object' || doc instanceof String || doc instanceof Number || doc instanceof Buffer || utils.isMongooseType(doc)) {
1069
+ parentDoc.depopulate(path);
1070
+ break;
1071
+ }
1072
+ }
1073
+ }
1074
+
1075
+ const returnVanillaArrayMethods = [
1076
+ 'filter',
1077
+ 'flat',
1078
+ 'flatMap',
1079
+ 'map',
1080
+ 'slice'
1081
+ ];
1082
+ for (const method of returnVanillaArrayMethods) {
1083
+ if (Array.prototype[method] == null) {
1084
+ continue;
1085
+ }
1086
+
1087
+ methods[method] = function() {
1088
+ const _arr = utils.isMongooseArray(this) ? this.__array : this;
1089
+ const arr = [].concat(_arr);
1090
+
1091
+ return arr[method].apply(arr, arguments);
1092
+ };
1093
+ }
1094
+
1095
+ module.exports = methods;