@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,54 @@
1
+ 'use strict';
2
+
3
+ const isOperator = require('./isOperator');
4
+
5
+ module.exports = function castFilterPath(ctx, schematype, val) {
6
+ const any$conditionals = Object.keys(val).some(isOperator);
7
+
8
+ if (!any$conditionals) {
9
+ return schematype.castForQuery(
10
+ null,
11
+ val,
12
+ ctx
13
+ );
14
+ }
15
+
16
+ const ks = Object.keys(val);
17
+
18
+ let k = ks.length;
19
+
20
+ while (k--) {
21
+ const $cond = ks[k];
22
+ const nested = val[$cond];
23
+
24
+ if ($cond === '$not') {
25
+ if (nested && schematype && !schematype.embeddedSchemaType && !schematype.Constructor) {
26
+ const _keys = Object.keys(nested);
27
+ if (_keys.length && isOperator(_keys[0])) {
28
+ for (const key of Object.keys(nested)) {
29
+ nested[key] = schematype.castForQuery(
30
+ key,
31
+ nested[key],
32
+ ctx
33
+ );
34
+ }
35
+ } else {
36
+ val[$cond] = schematype.castForQuery(
37
+ $cond,
38
+ nested,
39
+ ctx
40
+ );
41
+ }
42
+ continue;
43
+ }
44
+ } else {
45
+ val[$cond] = schematype.castForQuery(
46
+ $cond,
47
+ nested,
48
+ ctx
49
+ );
50
+ }
51
+ }
52
+
53
+ return val;
54
+ };
@@ -0,0 +1,643 @@
1
+ 'use strict';
2
+
3
+ const CastError = require('../../error/cast');
4
+ const MongooseError = require('../../error/mongooseError');
5
+ const SchemaString = require('../../schema/string');
6
+ const StrictModeError = require('../../error/strict');
7
+ const ValidationError = require('../../error/validation');
8
+ const castNumber = require('../../cast/number');
9
+ const cast = require('../../cast');
10
+ const getConstructorName = require('../getConstructorName');
11
+ const getDiscriminatorByValue = require('../discriminator/getDiscriminatorByValue');
12
+ const getEmbeddedDiscriminatorPath = require('./getEmbeddedDiscriminatorPath');
13
+ const handleImmutable = require('./handleImmutable');
14
+ const moveImmutableProperties = require('../update/moveImmutableProperties');
15
+ const schemaMixedSymbol = require('../../schema/symbols').schemaMixedSymbol;
16
+ const setDottedPath = require('../path/setDottedPath');
17
+ const utils = require('../../utils');
18
+ const { internalToObjectOptions } = require('../../options');
19
+
20
+ const mongodbUpdateOperators = new Set([
21
+ '$currentDate',
22
+ '$inc',
23
+ '$min',
24
+ '$max',
25
+ '$mul',
26
+ '$rename',
27
+ '$set',
28
+ '$setOnInsert',
29
+ '$unset',
30
+ '$addToSet',
31
+ '$pop',
32
+ '$pull',
33
+ '$push',
34
+ '$pullAll',
35
+ '$bit'
36
+ ]);
37
+
38
+ /**
39
+ * Casts an update op based on the given schema
40
+ *
41
+ * @param {Schema} schema
42
+ * @param {Object} obj
43
+ * @param {Object} [options]
44
+ * @param {Boolean|String} [options.strict] defaults to true
45
+ * @param {Query} context passed to setters
46
+ * @return {Boolean} true iff the update is non-empty
47
+ * @api private
48
+ */
49
+ module.exports = function castUpdate(schema, obj, options, context, filter) {
50
+ if (obj == null) {
51
+ return undefined;
52
+ }
53
+ options = options || {};
54
+ // Update pipeline
55
+ if (Array.isArray(obj)) {
56
+ const len = obj.length;
57
+ for (let i = 0; i < len; ++i) {
58
+ const ops = Object.keys(obj[i]);
59
+ for (const op of ops) {
60
+ obj[i][op] = castPipelineOperator(op, obj[i][op]);
61
+ }
62
+ }
63
+ return obj;
64
+ }
65
+
66
+ if (schema != null &&
67
+ filter != null &&
68
+ utils.hasUserDefinedProperty(filter, schema.options.discriminatorKey) &&
69
+ typeof filter[schema.options.discriminatorKey] !== 'object' &&
70
+ schema.discriminators != null) {
71
+ const discriminatorValue = filter[schema.options.discriminatorKey];
72
+ const byValue = getDiscriminatorByValue(context.model.discriminators, discriminatorValue);
73
+ schema = schema.discriminators[discriminatorValue] ||
74
+ byValue?.schema ||
75
+ schema;
76
+ } else if (schema != null &&
77
+ options.overwriteDiscriminatorKey &&
78
+ utils.hasUserDefinedProperty(obj, schema.options.discriminatorKey) &&
79
+ schema.discriminators != null) {
80
+ const discriminatorValue = obj[schema.options.discriminatorKey];
81
+ const byValue = getDiscriminatorByValue(context.model.discriminators, discriminatorValue);
82
+ schema = schema.discriminators[discriminatorValue] ||
83
+ byValue?.schema ||
84
+ schema;
85
+ } else if (schema != null &&
86
+ options.overwriteDiscriminatorKey &&
87
+ obj.$set != null &&
88
+ utils.hasUserDefinedProperty(obj.$set, schema.options.discriminatorKey) &&
89
+ schema.discriminators != null) {
90
+ const discriminatorValue = obj.$set[schema.options.discriminatorKey];
91
+ const byValue = getDiscriminatorByValue(context.model.discriminators, discriminatorValue);
92
+ schema = schema.discriminators[discriminatorValue] ||
93
+ byValue?.schema ||
94
+ schema;
95
+ }
96
+
97
+ if (options.upsert) {
98
+ moveImmutableProperties(schema, obj, context);
99
+ }
100
+
101
+ const ops = Object.keys(obj);
102
+ let i = ops.length;
103
+ const ret = {};
104
+ let val;
105
+ let hasDollarKey = false;
106
+
107
+ filter = filter || {};
108
+ while (i--) {
109
+ const op = ops[i];
110
+ if (!mongodbUpdateOperators.has(op)) {
111
+ // fix up $set sugar
112
+ if (!ret.$set) {
113
+ if (obj.$set) {
114
+ ret.$set = obj.$set;
115
+ } else {
116
+ ret.$set = {};
117
+ }
118
+ }
119
+ ret.$set[op] = obj[op];
120
+ ops.splice(i, 1);
121
+ if (!~ops.indexOf('$set')) ops.push('$set');
122
+ } else if (op === '$set') {
123
+ if (!ret.$set) {
124
+ ret[op] = obj[op];
125
+ }
126
+ } else {
127
+ ret[op] = obj[op];
128
+ }
129
+ }
130
+ // cast each value
131
+ i = ops.length;
132
+ while (i--) {
133
+ const op = ops[i];
134
+ val = ret[op];
135
+ hasDollarKey = hasDollarKey || op.startsWith('$');
136
+ if (val?.$__) {
137
+ val = val.toObject(internalToObjectOptions);
138
+ ret[op] = val;
139
+ }
140
+ if (val &&
141
+ typeof val === 'object' &&
142
+ !Buffer.isBuffer(val) &&
143
+ mongodbUpdateOperators.has(op)) {
144
+ walkUpdatePath(schema, val, op, options, context, filter);
145
+ } else {
146
+ const msg = 'Invalid atomic update value for ' + op + '. '
147
+ + 'Expected an object, received ' + typeof val;
148
+ throw new Error(msg);
149
+ }
150
+
151
+ if (op.startsWith('$') && utils.isEmptyObject(val)) {
152
+ delete ret[op];
153
+ }
154
+ }
155
+
156
+ if (utils.hasOwnKeys(ret) === false &&
157
+ options.upsert &&
158
+ utils.hasOwnKeys(filter)) {
159
+ // Trick the driver into allowing empty upserts to work around
160
+ // https://github.com/mongodb/node-mongodb-native/pull/2490
161
+ // Shallow clone to avoid passing defaults in re: gh-13962
162
+ return { $setOnInsert: { ...filter } };
163
+ }
164
+ return ret;
165
+ };
166
+
167
+ /*!
168
+ * ignore
169
+ */
170
+
171
+ function castPipelineOperator(op, val) {
172
+ if (op === '$unset') {
173
+ if (typeof val !== 'string' && (!Array.isArray(val) || val.find(v => typeof v !== 'string'))) {
174
+ throw new MongooseError('Invalid $unset in pipeline, must be ' +
175
+ ' a string or an array of strings');
176
+ }
177
+ return val;
178
+ }
179
+ if (op === '$project') {
180
+ if (val == null || typeof val !== 'object') {
181
+ throw new MongooseError('Invalid $project in pipeline, must be an object');
182
+ }
183
+ return val;
184
+ }
185
+ if (op === '$addFields' || op === '$set') {
186
+ if (val == null || typeof val !== 'object') {
187
+ throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
188
+ }
189
+ return val;
190
+ } else if (op === '$replaceRoot' || op === '$replaceWith') {
191
+ if (val == null || typeof val !== 'object') {
192
+ throw new MongooseError('Invalid ' + op + ' in pipeline, must be an object');
193
+ }
194
+ return val;
195
+ }
196
+
197
+ throw new MongooseError('Invalid update pipeline operator: "' + op + '"');
198
+ }
199
+
200
+ /**
201
+ * Walk each path of obj and cast its values
202
+ * according to its schema.
203
+ *
204
+ * @param {Schema} schema
205
+ * @param {Object} obj part of a query
206
+ * @param {String} op the atomic operator ($pull, $set, etc)
207
+ * @param {Object} [options]
208
+ * @param {Boolean|String} [options.strict]
209
+ * @param {Query} context
210
+ * @param {Object} filter
211
+ * @param {String} pref path prefix (internal only)
212
+ * @return {Bool} true if this path has keys to update
213
+ * @api private
214
+ */
215
+
216
+ function walkUpdatePath(schema, obj, op, options, context, filter, prefix) {
217
+ const strict = options.strict;
218
+ prefix = prefix ? prefix + '.' : '';
219
+ const keys = Object.keys(obj);
220
+ let i = keys.length;
221
+ let hasKeys = false;
222
+ let schematype;
223
+ let key;
224
+ let val;
225
+
226
+ let aggregatedError = null;
227
+
228
+ const strictMode = strict ?? schema.options.strict;
229
+
230
+ while (i--) {
231
+ key = keys[i];
232
+ val = obj[key];
233
+
234
+ // `$pull` is special because we need to cast the RHS as a query, not as
235
+ // an update.
236
+ if (op === '$pull') {
237
+ schematype = schema._getSchema(prefix + key);
238
+ if (schematype == null) {
239
+ const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, prefix + key, options);
240
+ if (_res.schematype != null) {
241
+ schematype = _res.schematype;
242
+ }
243
+ }
244
+ if (schematype?.schema != null) {
245
+ obj[key] = cast(schematype.schema, obj[key], options, context);
246
+ hasKeys = true;
247
+ continue;
248
+ }
249
+ }
250
+
251
+ const discriminatorKey = (prefix ? prefix + key : key);
252
+ if (
253
+ schema.discriminatorMapping != null &&
254
+ discriminatorKey === schema.options.discriminatorKey &&
255
+ schema.discriminatorMapping.value !== obj[key] &&
256
+ !options.overwriteDiscriminatorKey
257
+ ) {
258
+ if (strictMode === 'throw') {
259
+ const err = new Error('Can\'t modify discriminator key "' + discriminatorKey + '" on discriminator model');
260
+ aggregatedError = _appendError(err, context, discriminatorKey, aggregatedError);
261
+ continue;
262
+ } else if (strictMode) {
263
+ delete obj[key];
264
+ continue;
265
+ }
266
+ }
267
+
268
+ if (getConstructorName(val) === 'Object') {
269
+ // watch for embedded doc schemas
270
+ schematype = schema._getSchema(prefix + key);
271
+
272
+ if (schematype == null) {
273
+ const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, prefix + key, options);
274
+ if (_res.schematype != null) {
275
+ schematype = _res.schematype;
276
+ }
277
+ }
278
+
279
+ if (op !== '$setOnInsert' &&
280
+ handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
281
+ continue;
282
+ }
283
+
284
+ if (schematype && (schematype.embeddedSchemaType || schematype.Constructor) && op in castOps) {
285
+ // embedded doc schema
286
+ if ('$each' in val) {
287
+ hasKeys = true;
288
+ try {
289
+ obj[key] = {
290
+ $each: castUpdateVal(schematype, val.$each, op, key, context, prefix + key)
291
+ };
292
+ } catch (error) {
293
+ aggregatedError = _appendError(error, context, key, aggregatedError);
294
+ }
295
+
296
+ if (val.$slice != null) {
297
+ obj[key].$slice = val.$slice | 0;
298
+ }
299
+
300
+ if (val.$sort) {
301
+ obj[key].$sort = val.$sort;
302
+ }
303
+
304
+ if (val.$position != null) {
305
+ obj[key].$position = castNumber(val.$position);
306
+ }
307
+ } else {
308
+ if (schematype?.$isSingleNested) {
309
+ const _strict = strict == null ? schematype.schema.options.strict : strict;
310
+ try {
311
+ obj[key] = schematype.castForQuery(null, val, context, { strict: _strict });
312
+ } catch (error) {
313
+ aggregatedError = _appendError(error, context, key, aggregatedError);
314
+ }
315
+ } else {
316
+ try {
317
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
318
+ } catch (error) {
319
+ aggregatedError = _appendError(error, context, key, aggregatedError);
320
+ }
321
+ }
322
+
323
+ if (obj[key] === void 0) {
324
+ delete obj[key];
325
+ continue;
326
+ }
327
+
328
+ hasKeys = true;
329
+ }
330
+ } else if ((op === '$currentDate') || (op in castOps && schematype)) {
331
+ // $currentDate can take an object
332
+ try {
333
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
334
+ } catch (error) {
335
+ aggregatedError = _appendError(error, context, key, aggregatedError);
336
+ }
337
+
338
+ if (obj[key] === void 0) {
339
+ delete obj[key];
340
+ continue;
341
+ }
342
+
343
+ hasKeys = true;
344
+ } else if (op === '$rename') {
345
+ const schematype = new SchemaString(`${prefix}${key}.$rename`);
346
+ try {
347
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
348
+ } catch (error) {
349
+ aggregatedError = _appendError(error, context, key, aggregatedError);
350
+ }
351
+
352
+ if (obj[key] === void 0) {
353
+ delete obj[key];
354
+ continue;
355
+ }
356
+
357
+ hasKeys = true;
358
+ } else {
359
+ const pathToCheck = (prefix + key);
360
+ const v = schema._getPathType(pathToCheck);
361
+ let _strict = strict;
362
+ if (v?.schema && _strict == null) {
363
+ _strict = v.schema.options.strict;
364
+ }
365
+
366
+ if (v.pathType === 'undefined') {
367
+ if (_strict === 'throw') {
368
+ throw new StrictModeError(pathToCheck);
369
+ } else if (_strict) {
370
+ delete obj[key];
371
+ continue;
372
+ }
373
+ }
374
+
375
+ // gh-2314
376
+ // we should be able to set a schema-less field
377
+ // to an empty object literal
378
+ hasKeys |= walkUpdatePath(schema, val, op, options, context, filter, prefix + key) ||
379
+ (utils.isObject(val) && utils.hasOwnKeys(val) === false);
380
+ }
381
+ } else {
382
+ const isModifier = (key === '$each' || key === '$or' || key === '$and' || key === '$in');
383
+ if (isModifier && !prefix) {
384
+ throw new MongooseError('Invalid update: Unexpected modifier "' + key + '" as a key in operator. '
385
+ + 'Did you mean something like { $addToSet: { fieldName: { $each: [...] } } }? '
386
+ + 'Modifiers such as "$each", "$or", "$and", "$in" must appear under a valid field path.');
387
+ }
388
+ const checkPath = isModifier ? prefix : prefix + key;
389
+ schematype = schema._getSchema(checkPath);
390
+
391
+ // You can use `$setOnInsert` with immutable keys
392
+ if (op !== '$setOnInsert' &&
393
+ handleImmutable(schematype, strict, obj, key, prefix + key, options, context)) {
394
+ continue;
395
+ }
396
+
397
+ let pathDetails = schema._getPathType(checkPath);
398
+
399
+ // If no schema type, check for embedded discriminators because the
400
+ // filter or update may imply an embedded discriminator type. See #8378
401
+ if (schematype == null) {
402
+ const _res = getEmbeddedDiscriminatorPath(schema, obj, filter, checkPath, options);
403
+ if (_res.schematype != null) {
404
+ schematype = _res.schematype;
405
+ pathDetails = _res.type;
406
+ }
407
+ }
408
+
409
+ let isStrict = strict;
410
+ if (pathDetails?.schema && strict == null) {
411
+ isStrict = pathDetails.schema.options.strict;
412
+ }
413
+
414
+ const skip = isStrict &&
415
+ !schematype &&
416
+ !/real|nested/.test(pathDetails.pathType);
417
+
418
+ if (skip) {
419
+ // Even if strict is `throw`, avoid throwing an error because of
420
+ // virtuals because of #6731
421
+ if (isStrict === 'throw' && schema.virtuals[checkPath] == null) {
422
+ throw new StrictModeError(prefix + key);
423
+ } else {
424
+ delete obj[key];
425
+ }
426
+ } else {
427
+ if (op === '$rename') {
428
+ if (obj[key] == null) {
429
+ throw new CastError('String', obj[key], `${prefix}${key}.$rename`);
430
+ }
431
+ const schematype = new SchemaString(`${prefix}${key}.$rename`, null, null, schema);
432
+ obj[key] = schematype.castForQuery(null, obj[key], context);
433
+ continue;
434
+ }
435
+
436
+ try {
437
+ if (prefix.length === 0 || key.indexOf('.') === -1) {
438
+ obj[key] = castUpdateVal(schematype, val, op, key, context, prefix + key);
439
+ } else if (isStrict !== false || schematype != null) {
440
+ // Setting a nested dotted path that's in the schema. We don't allow paths with '.' in
441
+ // a schema, so replace the dotted path with a nested object to avoid ending up with
442
+ // dotted properties in the updated object. See (gh-10200)
443
+ setDottedPath(obj, key, castUpdateVal(schematype, val, op, key, context, prefix + key));
444
+ delete obj[key];
445
+ }
446
+ } catch (error) {
447
+ aggregatedError = _appendError(error, context, key, aggregatedError);
448
+ }
449
+
450
+ if (Array.isArray(obj[key]) && (op === '$addToSet' || op === '$push') && key !== '$each') {
451
+ if (schematype &&
452
+ schematype.embeddedSchemaType &&
453
+ !schematype.embeddedSchemaType.$isMongooseArray &&
454
+ !schematype.embeddedSchemaType[schemaMixedSymbol]) {
455
+ obj[key] = { $each: obj[key] };
456
+ }
457
+ }
458
+
459
+ if (obj[key] === void 0) {
460
+ delete obj[key];
461
+ continue;
462
+ }
463
+
464
+ hasKeys = true;
465
+ }
466
+ }
467
+ }
468
+
469
+ if (aggregatedError != null) {
470
+ throw aggregatedError;
471
+ }
472
+
473
+ return hasKeys;
474
+ }
475
+
476
+ /*!
477
+ * ignore
478
+ */
479
+
480
+ function _appendError(error, query, key, aggregatedError) {
481
+ if (typeof query !== 'object' || !query.options.multipleCastError) {
482
+ throw error;
483
+ }
484
+ aggregatedError = aggregatedError || new ValidationError();
485
+ aggregatedError.addError(key, error);
486
+ return aggregatedError;
487
+ }
488
+
489
+ /**
490
+ * These operators should be cast to numbers instead
491
+ * of their path schema type.
492
+ * @api private
493
+ */
494
+
495
+ const numberOps = {
496
+ $pop: 1,
497
+ $inc: 1
498
+ };
499
+
500
+ /**
501
+ * These ops require no casting because the RHS doesn't do anything.
502
+ * @api private
503
+ */
504
+
505
+ const noCastOps = {
506
+ $unset: 1
507
+ };
508
+
509
+ /**
510
+ * These operators require casting docs
511
+ * to real Documents for Update operations.
512
+ * @api private
513
+ */
514
+
515
+ const castOps = {
516
+ $push: 1,
517
+ $addToSet: 1,
518
+ $set: 1,
519
+ $setOnInsert: 1
520
+ };
521
+
522
+ /*!
523
+ * ignore
524
+ */
525
+
526
+ const overwriteOps = {
527
+ $set: 1,
528
+ $setOnInsert: 1
529
+ };
530
+
531
+ /**
532
+ * Casts `val` according to `schema` and atomic `op`.
533
+ *
534
+ * @param {SchemaType} schema
535
+ * @param {Object} val
536
+ * @param {String} op the atomic operator ($pull, $set, etc)
537
+ * @param {String} $conditional
538
+ * @param {Query} context
539
+ * @param {String} path
540
+ * @api private
541
+ */
542
+
543
+ function castUpdateVal(schema, val, op, $conditional, context, path) {
544
+ if (!schema) {
545
+ // non-existing schema path
546
+ if (op in numberOps) {
547
+ try {
548
+ return castNumber(val);
549
+ } catch {
550
+ throw new CastError('number', val, path);
551
+ }
552
+ }
553
+ return val;
554
+ }
555
+
556
+ const cond = schema.$isMongooseArray
557
+ && op in castOps
558
+ && (utils.isObject(val) || Array.isArray(val));
559
+ if (cond && !overwriteOps[op]) {
560
+ // Cast values for ops that add data to MongoDB.
561
+ // Ensures embedded documents get ObjectIds etc.
562
+ let schemaArrayDepth = 0;
563
+ let cur = schema;
564
+ while (cur.$isMongooseArray) {
565
+ ++schemaArrayDepth;
566
+ cur = cur.embeddedSchemaType;
567
+ }
568
+ let arrayDepth = 0;
569
+ let _val = val;
570
+ while (Array.isArray(_val)) {
571
+ ++arrayDepth;
572
+ _val = _val[0];
573
+ }
574
+
575
+ const additionalNesting = schemaArrayDepth - arrayDepth;
576
+ while (arrayDepth < schemaArrayDepth) {
577
+ val = [val];
578
+ ++arrayDepth;
579
+ }
580
+
581
+ let tmp = schema.applySetters(Array.isArray(val) ? val : [val], context);
582
+
583
+ for (let i = 0; i < additionalNesting; ++i) {
584
+ tmp = tmp[0];
585
+ }
586
+ return tmp;
587
+ }
588
+
589
+ if (op in noCastOps) {
590
+ return val;
591
+ }
592
+ if (op in numberOps) {
593
+ // Null and undefined not allowed for $pop, $inc
594
+ if (val == null) {
595
+ throw new CastError('number', val, schema.path);
596
+ }
597
+ if (op === '$inc') {
598
+ // Support `$inc` with long, int32, etc. (gh-4283)
599
+ return schema.castForQuery(
600
+ null,
601
+ val,
602
+ context
603
+ );
604
+ }
605
+ try {
606
+ return castNumber(val);
607
+ } catch {
608
+ throw new CastError('number', val, schema.path);
609
+ }
610
+ }
611
+ if (op === '$currentDate') {
612
+ if (typeof val === 'object') {
613
+ return { $type: val.$type };
614
+ }
615
+ return Boolean(val);
616
+ }
617
+
618
+ if (mongodbUpdateOperators.has($conditional)) {
619
+ return schema.castForQuery(
620
+ $conditional,
621
+ val,
622
+ context
623
+ );
624
+ }
625
+
626
+ if (overwriteOps[op]) {
627
+ const skipQueryCastForUpdate = val != null
628
+ && schema.$isMongooseArray
629
+ && schema.$fullPath != null
630
+ && !schema.$fullPath.match(/\d+$/);
631
+ const applySetters = schema[schemaMixedSymbol] != null;
632
+ if (skipQueryCastForUpdate || applySetters) {
633
+ return schema.applySetters(val, context);
634
+ }
635
+ return schema.castForQuery(
636
+ null,
637
+ val,
638
+ context
639
+ );
640
+ }
641
+
642
+ return schema.castForQuery(null, val, context);
643
+ }