@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,33 @@
1
+ 'use strict';
2
+
3
+ const specialProperties = require('../specialProperties');
4
+
5
+
6
+ module.exports = function setDottedPath(obj, path, val) {
7
+ if (path.indexOf('.') === -1) {
8
+ if (specialProperties.has(path)) {
9
+ return;
10
+ }
11
+
12
+ obj[path] = val;
13
+ return;
14
+ }
15
+ const parts = path.split('.');
16
+
17
+ const last = parts.pop();
18
+ let cur = obj;
19
+ for (const part of parts) {
20
+ if (specialProperties.has(part)) {
21
+ continue;
22
+ }
23
+ if (cur[part] == null) {
24
+ cur[part] = {};
25
+ }
26
+
27
+ cur = cur[part];
28
+ }
29
+
30
+ if (!specialProperties.has(last)) {
31
+ cur[last] = val;
32
+ }
33
+ };
@@ -0,0 +1,95 @@
1
+ 'use strict';
2
+
3
+ module.exports = pluralize;
4
+
5
+ /**
6
+ * Pluralization rules.
7
+ */
8
+
9
+ exports.pluralization = [
10
+ [/human$/gi, 'humans'],
11
+ [/(m|wom)an$/gi, '$1en'],
12
+ [/(pe)rson$/gi, '$1ople'],
13
+ [/(child)$/gi, '$1ren'],
14
+ [/^(ox)$/gi, '$1en'],
15
+ [/(ax|test)is$/gi, '$1es'],
16
+ [/(octop|cact|foc|fung|nucle)us$/gi, '$1i'],
17
+ [/(alias|status|virus)$/gi, '$1es'],
18
+ [/(bu)s$/gi, '$1ses'],
19
+ [/(buffal|tomat|potat)o$/gi, '$1oes'],
20
+ [/([ti])um$/gi, '$1a'],
21
+ [/sis$/gi, 'ses'],
22
+ [/(?:([^f])fe|([lr])f)$/gi, '$1$2ves'],
23
+ [/(hive)$/gi, '$1s'],
24
+ [/([^aeiouy]|qu)y$/gi, '$1ies'],
25
+ [/(x|ch|ss|sh)$/gi, '$1es'],
26
+ [/(matr|vert|ind)ix|ex$/gi, '$1ices'],
27
+ [/([m|l])ouse$/gi, '$1ice'],
28
+ [/(kn|w|l)ife$/gi, '$1ives'],
29
+ [/(quiz)$/gi, '$1zes'],
30
+ [/^goose$/i, 'geese'],
31
+ [/s$/gi, 's'],
32
+ [/([^a-z])$/, '$1'],
33
+ [/$/gi, 's']
34
+ ];
35
+ const rules = exports.pluralization;
36
+
37
+ /**
38
+ * Uncountable words.
39
+ *
40
+ * These words are applied while processing the argument to `toCollectionName`.
41
+ * @api public
42
+ */
43
+
44
+ exports.uncountables = [
45
+ 'advice',
46
+ 'energy',
47
+ 'excretion',
48
+ 'digestion',
49
+ 'cooperation',
50
+ 'health',
51
+ 'justice',
52
+ 'labour',
53
+ 'machinery',
54
+ 'equipment',
55
+ 'information',
56
+ 'pollution',
57
+ 'sewage',
58
+ 'paper',
59
+ 'money',
60
+ 'species',
61
+ 'series',
62
+ 'rain',
63
+ 'rice',
64
+ 'fish',
65
+ 'sheep',
66
+ 'moose',
67
+ 'deer',
68
+ 'news',
69
+ 'expertise',
70
+ 'status',
71
+ 'media'
72
+ ];
73
+ const uncountables = exports.uncountables;
74
+
75
+ /**
76
+ * Pluralize function.
77
+ *
78
+ * @author TJ Holowaychuk (extracted from _ext.js_)
79
+ * @param {String} string to pluralize
80
+ * @api private
81
+ */
82
+
83
+ function pluralize(str) {
84
+ let found;
85
+ str = str.toLowerCase();
86
+ if (!~uncountables.indexOf(str)) {
87
+ found = rules.filter(function(rule) {
88
+ return str.match(rule[0]);
89
+ });
90
+ if (found[0]) {
91
+ return str.replace(found[0][0], found[0][1]);
92
+ }
93
+ }
94
+ return str;
95
+ }
@@ -0,0 +1,129 @@
1
+ 'use strict';
2
+
3
+ const clone = require('../../helpers/clone');
4
+ const leanPopulateMap = require('./leanPopulateMap');
5
+ const modelSymbol = require('../symbols').modelSymbol;
6
+ const utils = require('../../utils');
7
+
8
+ module.exports = assignRawDocsToIdStructure;
9
+
10
+ const kHasArray = Symbol('mongoose#assignRawDocsToIdStructure#hasArray');
11
+
12
+ /**
13
+ * Assign `vals` returned by mongo query to the `rawIds`
14
+ * structure returned from utils.getVals() honoring
15
+ * query sort order if specified by user.
16
+ *
17
+ * This can be optimized.
18
+ *
19
+ * Rules:
20
+ *
21
+ * if the value of the path is not an array, use findOne rules, else find.
22
+ * for findOne the results are assigned directly to doc path (including null results).
23
+ * for find, if user specified sort order, results are assigned directly
24
+ * else documents are put back in original order of array if found in results
25
+ *
26
+ * @param {Array} rawIds
27
+ * @param {Array} resultDocs
28
+ * @param {Array} resultOrder
29
+ * @param {Object} options
30
+ * @param {Boolean} recursed
31
+ * @api private
32
+ */
33
+
34
+ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, recursed) {
35
+ // honor user specified sort order, unless we're populating a single
36
+ // virtual underneath an array (e.g. populating `employees.mostRecentShift` where
37
+ // `mostRecentShift` is a virtual with `justOne`)
38
+ const newOrder = [];
39
+ const sorting = options.isVirtual && options.justOne && rawIds.length > 1
40
+ ? false :
41
+ options.sort && rawIds.length > 1;
42
+ const nullIfNotFound = options.$nullIfNotFound;
43
+ let doc;
44
+ let sid;
45
+ let id;
46
+
47
+ if (utils.isMongooseArray(rawIds)) {
48
+ rawIds = rawIds.__array;
49
+ }
50
+
51
+ let i = 0;
52
+ const len = rawIds.length;
53
+
54
+ if (sorting && recursed && options[kHasArray] === undefined) {
55
+ options[kHasArray] = false;
56
+ for (const key in resultOrder) {
57
+ if (Array.isArray(resultOrder[key])) {
58
+ options[kHasArray] = true;
59
+ break;
60
+ }
61
+ }
62
+ }
63
+
64
+ for (i = 0; i < len; ++i) {
65
+ id = rawIds[i];
66
+
67
+ if (Array.isArray(id)) {
68
+ // handle [ [id0, id2], [id3] ]
69
+ assignRawDocsToIdStructure(id, resultDocs, resultOrder, options, true);
70
+ newOrder.push(id);
71
+ continue;
72
+ }
73
+
74
+ if (id === null && sorting === false) {
75
+ // keep nulls for findOne unless sorting, which always
76
+ // removes them (backward compat)
77
+ newOrder.push(id);
78
+ continue;
79
+ }
80
+
81
+ sid = String(id);
82
+ doc = resultDocs[sid];
83
+ // If user wants separate copies of same doc, use this option
84
+ if (options.clone && doc != null) {
85
+ if (options.lean) {
86
+ const _model = leanPopulateMap.get(doc);
87
+ doc = clone(doc);
88
+ leanPopulateMap.set(doc, _model);
89
+ } else {
90
+ doc = doc.constructor.hydrate(doc._doc);
91
+ }
92
+ }
93
+
94
+ if (recursed) {
95
+ if (doc) {
96
+ if (sorting) {
97
+ const _resultOrder = resultOrder[sid];
98
+ if (options[kHasArray]) {
99
+ // If result arrays, rely on the MongoDB server response for ordering
100
+ newOrder.push(doc);
101
+ } else {
102
+ newOrder[_resultOrder] = doc;
103
+ }
104
+ } else {
105
+ newOrder.push(doc);
106
+ }
107
+ } else if (id?.[modelSymbol] != null) {
108
+ newOrder.push(id);
109
+ } else {
110
+ newOrder.push(options.retainNullValues || nullIfNotFound ? null : id);
111
+ }
112
+ } else {
113
+ // apply findOne behavior - if document in results, assign, else assign null
114
+ newOrder[i] = doc || null;
115
+ }
116
+ }
117
+
118
+ rawIds.length = 0;
119
+ if (newOrder.length) {
120
+ // reassign the documents based on corrected order
121
+
122
+ // forEach skips over sparse entries in arrays so we
123
+ // can safely use this to our advantage dealing with sorted
124
+ // result sets too.
125
+ newOrder.forEach(function(doc, i) {
126
+ rawIds[i] = doc;
127
+ });
128
+ }
129
+ }
@@ -0,0 +1,360 @@
1
+ 'use strict';
2
+
3
+ const MongooseMap = require('../../types/map');
4
+ const SkipPopulateValue = require('./skipPopulateValue');
5
+ const assignRawDocsToIdStructure = require('./assignRawDocsToIdStructure');
6
+ const get = require('../get');
7
+ const getVirtual = require('./getVirtual');
8
+ const leanPopulateMap = require('./leanPopulateMap');
9
+ const lookupLocalFields = require('./lookupLocalFields');
10
+ const markArraySubdocsPopulated = require('./markArraySubdocsPopulated');
11
+ const mpath = require('mpath');
12
+ const sift = require('sift').default;
13
+ const utils = require('../../utils');
14
+ const { populateModelSymbol } = require('../symbols');
15
+
16
+ module.exports = function assignVals(o) {
17
+ // Options that aren't explicitly listed in `populateOptions`
18
+ const userOptions = Object.assign({}, get(o, 'allOptions.options.options'), get(o, 'allOptions.options'));
19
+ // `o.options` contains options explicitly listed in `populateOptions`, like
20
+ // `match` and `limit`.
21
+ const populateOptions = Object.assign({}, o.options, userOptions, {
22
+ justOne: o.justOne,
23
+ isVirtual: o.isVirtual
24
+ });
25
+ populateOptions.$nullIfNotFound = o.isVirtual;
26
+ const populatedModel = o.populatedModel;
27
+
28
+ const originalIds = [].concat(o.rawIds);
29
+
30
+ // replace the original ids in our intermediate _ids structure
31
+ // with the documents found by query
32
+ o.allIds = [].concat(o.allIds);
33
+ assignRawDocsToIdStructure(o.rawIds, o.rawDocs, o.rawOrder, populateOptions);
34
+
35
+ // now update the original documents being populated using the
36
+ // result structure that contains real documents.
37
+ const docs = o.docs;
38
+ const rawIds = o.rawIds;
39
+ const options = o.options;
40
+ const count = o.count && o.isVirtual;
41
+ let i;
42
+ let setValueIndex = 0;
43
+
44
+ function setValue(val) {
45
+ ++setValueIndex;
46
+ if (count) {
47
+ return val;
48
+ }
49
+ if (val instanceof SkipPopulateValue) {
50
+ return val.val;
51
+ }
52
+ if (val === void 0) {
53
+ return val;
54
+ }
55
+
56
+ const _allIds = o.allIds[i];
57
+
58
+ if (o.path.endsWith('.$*')) {
59
+ // Skip maps re: gh-12494
60
+ return valueFilter(val, options, populateOptions, _allIds);
61
+ }
62
+
63
+ if (o.justOne === true && Array.isArray(val)) {
64
+ // Might be an embedded discriminator (re: gh-9244) with multiple models, so make sure to pick the right
65
+ // model before assigning.
66
+ const ret = [];
67
+ for (const doc of val) {
68
+ const _docPopulatedModel = leanPopulateMap.get(doc);
69
+ if (_docPopulatedModel == null || _docPopulatedModel === populatedModel) {
70
+ ret.push(doc);
71
+ }
72
+ }
73
+ // Since we don't want to have to create a new mongoosearray, make sure to
74
+ // modify the array in place
75
+ while (val.length > ret.length) {
76
+ Array.prototype.pop.apply(val, []);
77
+ }
78
+ for (let i = 0; i < ret.length; ++i) {
79
+ val[i] = ret[i];
80
+ }
81
+
82
+ return valueFilter(val[0], options, populateOptions, _allIds);
83
+ } else if (o.justOne === false && !Array.isArray(val)) {
84
+ return valueFilter([val], options, populateOptions, _allIds);
85
+ } else if (o.justOne === true && !Array.isArray(val) && Array.isArray(_allIds)) {
86
+ return valueFilter(val, options, populateOptions, val == null ? val : _allIds[setValueIndex - 1]);
87
+ }
88
+ return valueFilter(val, options, populateOptions, _allIds);
89
+ }
90
+
91
+ for (i = 0; i < docs.length; ++i) {
92
+ setValueIndex = 0;
93
+ const _path = o.path.endsWith('.$*') ? o.path.slice(0, -3) : o.path;
94
+ const existingVal = mpath.get(_path, docs[i], lookupLocalFields);
95
+ if (existingVal == null && !getVirtual(o.originalModel.schema, _path)) {
96
+ continue;
97
+ }
98
+
99
+ let valueToSet;
100
+ if (count) {
101
+ valueToSet = numDocs(rawIds[i]);
102
+ } else if (Array.isArray(o.match)) {
103
+ valueToSet = Array.isArray(rawIds[i]) ?
104
+ rawIds[i].filter(v => v == null || sift(o.match[i])(v)) :
105
+ [rawIds[i]].filter(v => v == null || sift(o.match[i])(v))[0];
106
+ } else {
107
+ valueToSet = rawIds[i];
108
+ }
109
+
110
+ // If we're populating a map, the existing value will be an object, so
111
+ // we need to transform again
112
+ const originalSchema = o.originalModel.schema;
113
+ const isDoc = get(docs[i], '$__', null) != null;
114
+ let isMap = isDoc ?
115
+ existingVal instanceof Map :
116
+ utils.isPOJO(existingVal);
117
+ // If we pass the first check, also make sure the local field's schematype
118
+ // is map (re: gh-6460)
119
+ isMap = isMap && get(originalSchema._getSchema(_path), '$isSchemaMap');
120
+ if (!o.isVirtual && isMap) {
121
+ const _keys = existingVal instanceof Map ?
122
+ Array.from(existingVal.keys()) :
123
+ Object.keys(existingVal);
124
+ valueToSet = valueToSet.reduce((cur, v, i) => {
125
+ cur.set(_keys[i], v);
126
+ return cur;
127
+ }, new Map());
128
+ }
129
+
130
+ if (isDoc && Array.isArray(valueToSet)) {
131
+ for (const val of valueToSet) {
132
+ if (val?.$__ != null) {
133
+ val.$__.parent = docs[i];
134
+ }
135
+ }
136
+ } else if (isDoc && valueToSet?.$__ != null) {
137
+ valueToSet.$__.parent = docs[i];
138
+ }
139
+
140
+ if (o.isVirtual && isDoc) {
141
+ docs[i].$populated(_path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
142
+ // If virtual populate and doc is already init-ed, need to walk through
143
+ // the actual doc to set rather than setting `_doc` directly
144
+ if (Array.isArray(valueToSet)) {
145
+ valueToSet = valueToSet.map(v => v == null ? void 0 : v);
146
+ }
147
+ mpath.set(
148
+ _path,
149
+ valueToSet,
150
+ docs[i],
151
+ // Handle setting paths underneath maps using $* by converting arrays into maps of values
152
+ function lookup(obj, part, val) {
153
+ if (arguments.length >= 3) {
154
+ obj[part] = val;
155
+ return obj[part];
156
+ }
157
+ if (obj instanceof Map && part === '$*') {
158
+ return [...obj.values()];
159
+ }
160
+ return obj[part];
161
+ },
162
+ setValue,
163
+ false
164
+ );
165
+ continue;
166
+ }
167
+
168
+ const parts = _path.split('.');
169
+ let cur = docs[i];
170
+ for (let j = 0; j < parts.length - 1; ++j) {
171
+ // If we get to an array with a dotted path, like `arr.foo`, don't set
172
+ // `foo` on the array.
173
+ if (Array.isArray(cur) && !utils.isArrayIndex(parts[j])) {
174
+ break;
175
+ }
176
+
177
+ if (parts[j] === '$*') {
178
+ break;
179
+ }
180
+
181
+ if (cur[parts[j]] == null) {
182
+ // If nothing to set, avoid creating an unnecessary array. Otherwise
183
+ // we'll end up with a single doc in the array with only defaults.
184
+ // See gh-8342, gh-8455
185
+ const curPath = parts.slice(0, j + 1).join('.');
186
+ const schematype = originalSchema._getSchema(curPath);
187
+ if (valueToSet == null && schematype?.$isMongooseArray) {
188
+ break;
189
+ }
190
+ cur[parts[j]] = {};
191
+ }
192
+ cur = cur[parts[j]];
193
+ // If the property in MongoDB is a primitive, we won't be able to populate
194
+ // the nested path, so skip it. See gh-7545
195
+ if (typeof cur !== 'object') {
196
+ break;
197
+ }
198
+ }
199
+ if (docs[i].$__) {
200
+ o.allOptions.options[populateModelSymbol] = o.allOptions.model;
201
+ docs[i].$populated(_path, o.unpopulatedValues[i], o.allOptions.options);
202
+
203
+ if (valueToSet?.$__ != null) {
204
+ valueToSet.$__.wasPopulated = { value: o.unpopulatedValues[i] };
205
+ }
206
+
207
+ if (valueToSet instanceof Map && !valueToSet.$isMongooseMap) {
208
+ valueToSet = new MongooseMap(valueToSet, _path, docs[i], docs[i].schema.path(_path).$__schemaType);
209
+ }
210
+ }
211
+
212
+ // If lean, need to check that each individual virtual respects
213
+ // `justOne`, because you may have a populated virtual with `justOne`
214
+ // underneath an array. See gh-6867
215
+ mpath.set(_path, valueToSet, docs[i], lookupLocalFields, setValue, false);
216
+
217
+ if (docs[i].$__) {
218
+ markArraySubdocsPopulated(docs[i], [o.allOptions.options]);
219
+ }
220
+ }
221
+ };
222
+
223
+ function numDocs(v) {
224
+ if (Array.isArray(v)) {
225
+ // If setting underneath an array of populated subdocs, we may have an
226
+ // array of arrays. See gh-7573
227
+ if (v.some(el => Array.isArray(el) || el === null)) {
228
+ return v.map(el => {
229
+ if (el == null) {
230
+ return 0;
231
+ }
232
+ if (Array.isArray(el)) {
233
+ return el.filter(el => el != null).length;
234
+ }
235
+ return 1;
236
+ });
237
+ }
238
+ return v.filter(el => el != null).length;
239
+ }
240
+ return v == null ? 0 : 1;
241
+ }
242
+
243
+ /**
244
+ * 1) Apply backwards compatible find/findOne behavior to sub documents
245
+ *
246
+ * find logic:
247
+ * a) filter out non-documents
248
+ * b) remove _id from sub docs when user specified
249
+ *
250
+ * findOne
251
+ * a) if no doc found, set to null
252
+ * b) remove _id from sub docs when user specified
253
+ *
254
+ * 2) Remove _ids when specified by users query.
255
+ *
256
+ * background:
257
+ * _ids are left in the query even when user excludes them so
258
+ * that population mapping can occur.
259
+ * @param {Any} val
260
+ * @param {Object} assignmentOpts
261
+ * @param {Object} populateOptions
262
+ * @param {Function} [populateOptions.transform]
263
+ * @param {Boolean} allIds
264
+ * @api private
265
+ */
266
+
267
+ function valueFilter(val, assignmentOpts, populateOptions, allIds) {
268
+ const userSpecifiedTransform = typeof populateOptions.transform === 'function';
269
+ const transform = userSpecifiedTransform ? populateOptions.transform : v => v;
270
+ if (Array.isArray(val)) {
271
+ // find logic
272
+ const ret = [];
273
+ const numValues = val.length;
274
+ for (let i = 0; i < numValues; ++i) {
275
+ let subdoc = val[i];
276
+ const _allIds = Array.isArray(allIds) ? allIds[i] : allIds;
277
+ if (!isPopulatedObject(subdoc) && (!populateOptions.retainNullValues || subdoc != null) && !userSpecifiedTransform) {
278
+ continue;
279
+ } else if (!populateOptions.retainNullValues && subdoc == null) {
280
+ continue;
281
+ } else if (userSpecifiedTransform) {
282
+ subdoc = transform(isPopulatedObject(subdoc) ? subdoc : null, _allIds);
283
+ }
284
+ maybeRemoveId(subdoc, assignmentOpts);
285
+ ret.push(subdoc);
286
+ if (assignmentOpts.originalLimit &&
287
+ ret.length >= assignmentOpts.originalLimit) {
288
+ break;
289
+ }
290
+ }
291
+
292
+ const rLen = ret.length;
293
+ // Since we don't want to have to create a new mongoosearray, make sure to
294
+ // modify the array in place
295
+ while (val.length > rLen) {
296
+ Array.prototype.pop.apply(val, []);
297
+ }
298
+ let i = 0;
299
+ if (utils.isMongooseArray(val)) {
300
+ for (i = 0; i < rLen; ++i) {
301
+ val.set(i, ret[i], true);
302
+ }
303
+ } else {
304
+ for (i = 0; i < rLen; ++i) {
305
+ val[i] = ret[i];
306
+ }
307
+ }
308
+ return val;
309
+ }
310
+
311
+ // findOne
312
+ if (isPopulatedObject(val) || utils.isPOJO(val)) {
313
+ maybeRemoveId(val, assignmentOpts);
314
+ return transform(val, allIds);
315
+ }
316
+ if (val instanceof Map) {
317
+ return val;
318
+ }
319
+
320
+ if (populateOptions.justOne === false) {
321
+ return [];
322
+ }
323
+
324
+ return val == null ? transform(val, allIds) : transform(null, allIds);
325
+ }
326
+
327
+ /**
328
+ * Remove _id from `subdoc` if user specified "lean" query option
329
+ * @param {Document} subdoc
330
+ * @param {Object} assignmentOpts
331
+ * @api private
332
+ */
333
+
334
+ function maybeRemoveId(subdoc, assignmentOpts) {
335
+ if (subdoc != null && assignmentOpts.excludeId) {
336
+ if (typeof subdoc.$__setValue === 'function') {
337
+ delete subdoc._doc._id;
338
+ } else {
339
+ delete subdoc._id;
340
+ }
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Determine if `obj` is something we can set a populated path to. Can be a
346
+ * document, a lean document, or an array/map that contains docs.
347
+ * @param {Any} obj
348
+ * @api private
349
+ */
350
+
351
+ function isPopulatedObject(obj) {
352
+ if (obj == null) {
353
+ return false;
354
+ }
355
+
356
+ return Array.isArray(obj) ||
357
+ obj.$isMongooseMap ||
358
+ obj.$__ != null ||
359
+ leanPopulateMap.has(obj);
360
+ }