@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,387 @@
1
+ 'use strict';
2
+
3
+ /*!
4
+ * Module dependencies
5
+ */
6
+
7
+ const PopulateOptions = require('./options/populateOptions');
8
+ const checkEmbeddedDiscriminatorKeyProjection =
9
+ require('./helpers/discriminator/checkEmbeddedDiscriminatorKeyProjection');
10
+ const get = require('./helpers/get');
11
+ const getDiscriminatorByValue =
12
+ require('./helpers/discriminator/getDiscriminatorByValue');
13
+ const isDefiningProjection = require('./helpers/projection/isDefiningProjection');
14
+ const clone = require('./helpers/clone');
15
+ const isPathSelectedInclusive = require('./helpers/projection/isPathSelectedInclusive');
16
+
17
+ /**
18
+ * Prepare a set of path options for query population. This is the MongooseQuery
19
+ * version
20
+ *
21
+ * @param {Query} query
22
+ * @param {Object} options
23
+ * @return {Array}
24
+ */
25
+
26
+ exports.preparePopulationOptionsMQ = function preparePopulationOptionsMQ(query, options) {
27
+ const _populate = query._mongooseOptions.populate;
28
+ const pop = Object.keys(_populate).reduce((vals, key) => vals.concat([_populate[key]]), []);
29
+
30
+ // lean options should trickle through all queries
31
+ if (options.lean != null) {
32
+ pop
33
+ .filter(p => p?.options?.lean == null)
34
+ .forEach(makeLean(options.lean));
35
+ }
36
+
37
+ const session = query?.options?.session || null;
38
+ if (session != null) {
39
+ pop.forEach(path => {
40
+ if (path.options == null) {
41
+ path.options = { session: session };
42
+ return;
43
+ }
44
+ if (!('session' in path.options)) {
45
+ path.options.session = session;
46
+ }
47
+ });
48
+ }
49
+
50
+ const projection = query._fieldsForExec();
51
+ for (let i = 0; i < pop.length; ++i) {
52
+ if (pop[i] instanceof PopulateOptions) {
53
+ pop[i] = new PopulateOptions({
54
+ ...pop[i],
55
+ _queryProjection: projection,
56
+ _localModel: query.model
57
+ });
58
+ } else {
59
+ pop[i]._queryProjection = projection;
60
+ pop[i]._localModel = query.model;
61
+ }
62
+ }
63
+
64
+ return pop;
65
+ };
66
+
67
+ /**
68
+ * If the document is a mapped discriminator type, it returns a model instance for that type, otherwise,
69
+ * it returns an instance of the given model.
70
+ *
71
+ * @param {Model} model
72
+ * @param {Object} doc
73
+ * @param {Object} fields
74
+ *
75
+ * @return {Document}
76
+ */
77
+ exports.createModel = function createModel(model, doc, fields, userProvidedFields, options) {
78
+ model.hooks.execPreSync('createModel', doc);
79
+ const discriminatorMapping = model.schema ?
80
+ model.schema.discriminatorMapping :
81
+ null;
82
+
83
+ const key = discriminatorMapping?.isRoot ?
84
+ discriminatorMapping.key :
85
+ null;
86
+
87
+ const value = doc[key];
88
+ if (key && value && model.discriminators) {
89
+ const discriminator = model.discriminators[value] || getDiscriminatorByValue(model.discriminators, value);
90
+ if (discriminator) {
91
+ const _fields = clone(userProvidedFields);
92
+ exports.applyPaths(_fields, discriminator.schema);
93
+ return new discriminator(undefined, _fields, { skipId: true });
94
+ }
95
+ }
96
+
97
+ const _opts = {
98
+ skipId: true,
99
+ isNew: false,
100
+ willInit: true
101
+ };
102
+ if (options != null && 'defaults' in options) {
103
+ _opts.defaults = options.defaults;
104
+ }
105
+ return new model(undefined, fields, _opts);
106
+ };
107
+
108
+ /*!
109
+ * ignore
110
+ */
111
+
112
+ exports.createModelAndInit = function createModelAndInit(model, doc, fields, userProvidedFields, options, populatedIds, callback) {
113
+ const initOpts = populatedIds ?
114
+ { populated: populatedIds } :
115
+ undefined;
116
+
117
+ const casted = exports.createModel(model, doc, fields, userProvidedFields, options);
118
+ try {
119
+ casted.$init(doc, initOpts, callback);
120
+ } catch (error) {
121
+ callback(error, casted);
122
+ }
123
+ };
124
+
125
+ /*!
126
+ * ignore
127
+ */
128
+
129
+ exports.applyPaths = function applyPaths(fields, schema, sanitizeProjection) {
130
+ // determine if query is selecting or excluding fields
131
+ let exclude;
132
+ let keys;
133
+ const minusPathsToSkip = new Set();
134
+
135
+ if (fields) {
136
+ keys = Object.keys(fields);
137
+
138
+ // Collapse minus paths
139
+ const minusPaths = [];
140
+ for (let i = 0; i < keys.length; ++i) {
141
+ const key = keys[i];
142
+ if (keys[i][0] !== '-') {
143
+ continue;
144
+ }
145
+
146
+ delete fields[key];
147
+ if (key === '-_id') {
148
+ fields['_id'] = 0;
149
+ } else {
150
+ minusPaths.push(key.slice(1));
151
+ }
152
+ }
153
+
154
+ keys = Object.keys(fields);
155
+ for (let keyIndex = 0; keyIndex < keys.length; ++keyIndex) {
156
+ if (keys[keyIndex][0] === '+') {
157
+ continue;
158
+ }
159
+ const field = fields[keys[keyIndex]];
160
+ // Skip `$meta` and `$slice`
161
+ if (!isDefiningProjection(field)) {
162
+ continue;
163
+ }
164
+ if (keys[keyIndex] === '_id' && keys.length > 1) {
165
+ continue;
166
+ }
167
+ if (keys[keyIndex] === schema.options.discriminatorKey && keys.length > 1 && field != null && !field) {
168
+ continue;
169
+ }
170
+ exclude = !field;
171
+ break;
172
+ }
173
+
174
+ // Potentially add back minus paths based on schema-level path config
175
+ // and whether the projection is inclusive
176
+ for (const path of minusPaths) {
177
+ const type = schema.path(path);
178
+ // If the path isn't selected by default or the projection is not
179
+ // inclusive, minus path is treated as equivalent to `key: 0`.
180
+ // But we also allow using `-name` to remove `name` from an inclusive
181
+ // projection if `name` has schema-level `select: true`.
182
+ if (!type?.selected || exclude !== false) {
183
+ fields[path] = 0;
184
+ exclude = true;
185
+ } else if (type?.selected && exclude === false) {
186
+ // Make a note of minus paths that are overwriting paths that are
187
+ // included by default.
188
+ minusPathsToSkip.add(path);
189
+ }
190
+ }
191
+ }
192
+
193
+ // if selecting, apply default schematype select:true fields
194
+ // if excluding, apply schematype select:false fields
195
+ const selected = [];
196
+ const excluded = [];
197
+ const stack = [];
198
+
199
+ analyzeSchema(schema);
200
+ switch (exclude) {
201
+ case true:
202
+ for (const fieldName of excluded) {
203
+ fields[fieldName] = 0;
204
+ }
205
+ break;
206
+ case false:
207
+ if (schema?.paths['_id']?.options?.select === false) {
208
+ fields._id = 0;
209
+ }
210
+
211
+ for (const fieldName of selected) {
212
+ if (minusPathsToSkip.has(fieldName)) {
213
+ continue;
214
+ }
215
+ if (isPathSelectedInclusive(fields, fieldName)) {
216
+ continue;
217
+ }
218
+ fields[fieldName] = fields[fieldName] || 1;
219
+ }
220
+ break;
221
+ case undefined:
222
+ if (fields == null) {
223
+ break;
224
+ }
225
+ // Any leftover plus paths must in the schema, so delete them (gh-7017)
226
+ for (const key of Object.keys(fields || {})) {
227
+ if (key.startsWith('+')) {
228
+ delete fields[key];
229
+ }
230
+ }
231
+
232
+ // user didn't specify fields, implies returning all fields.
233
+ // only need to apply excluded fields and delete any plus paths
234
+ for (const fieldName of excluded) {
235
+ if (fields[fieldName] != null) {
236
+ // Skip applying default projections to fields with non-defining
237
+ // projections, like `$slice`
238
+ continue;
239
+ }
240
+ fields[fieldName] = 0;
241
+ }
242
+ break;
243
+ }
244
+
245
+ function analyzeSchema(schema, prefix) {
246
+ prefix || (prefix = '');
247
+
248
+ // avoid recursion
249
+ if (stack.indexOf(schema) !== -1) {
250
+ return [];
251
+ }
252
+ stack.push(schema);
253
+
254
+ const addedPaths = [];
255
+ schema.eachPath(function(path, type) {
256
+ if (prefix) path = prefix + '.' + path;
257
+ if (type.$isSchemaMap || path.endsWith('.$*')) {
258
+ const plusPath = '+' + path;
259
+ const hasPlusPath = fields && plusPath in fields;
260
+ if (type.options?.select === false && !hasPlusPath) {
261
+ excluded.push(path);
262
+ }
263
+ return;
264
+ }
265
+ let addedPath = analyzePath(path, type);
266
+ // arrays
267
+ if (addedPath == null && !Array.isArray(type) && type.$isMongooseArray && !type.$isMongooseDocumentArray) {
268
+ addedPath = analyzePath(path, type.embeddedSchemaType);
269
+ }
270
+ if (addedPath != null) {
271
+ addedPaths.push(addedPath);
272
+ }
273
+
274
+ // nested schemas
275
+ if (type.schema) {
276
+ const _addedPaths = analyzeSchema(type.schema, path);
277
+
278
+ // Special case: if discriminator key is the only field that would
279
+ // be projected in, remove it.
280
+ if (exclude === false) {
281
+ checkEmbeddedDiscriminatorKeyProjection(fields, path, type.schema,
282
+ selected, _addedPaths);
283
+ }
284
+ }
285
+ });
286
+ stack.pop();
287
+ return addedPaths;
288
+ }
289
+
290
+ function analyzePath(path, type) {
291
+ if (fields == null) {
292
+ return;
293
+ }
294
+
295
+ // If schema-level selected not set, nothing to do
296
+ if (typeof type.selected !== 'boolean') {
297
+ return;
298
+ }
299
+
300
+ // User overwriting default exclusion
301
+ if (type.selected === false && fields[path]) {
302
+ if (sanitizeProjection) {
303
+ fields[path] = 0;
304
+ }
305
+
306
+ return;
307
+ }
308
+
309
+ // If set to 0, we're explicitly excluding the discriminator key. Can't do this for all fields,
310
+ // because we have tests that assert that using `-path` to exclude schema-level `select: true`
311
+ // fields counts as an exclusive projection. See gh-11546
312
+ if (!exclude && type.selected && path === schema.options.discriminatorKey && fields[path] != null && !fields[path]) {
313
+ delete fields[path];
314
+ return;
315
+ }
316
+
317
+ if (exclude === false && type.selected && fields[path] != null && !fields[path]) {
318
+ delete fields[path];
319
+ return;
320
+ }
321
+
322
+ const plusPath = '+' + path;
323
+ const hasPlusPath = fields && plusPath in fields;
324
+ if (hasPlusPath) {
325
+ // forced inclusion
326
+ delete fields[plusPath];
327
+
328
+ // if there are other fields being included, add this one
329
+ // if no other included fields, leave this out (implied inclusion)
330
+ if (exclude === false && keys.length > 1 && !~keys.indexOf(path) && !sanitizeProjection) {
331
+ fields[path] = 1;
332
+ } else if (exclude == null && sanitizeProjection && type.selected === false) {
333
+ fields[path] = 0;
334
+ }
335
+
336
+ return;
337
+ }
338
+
339
+ // check for parent exclusions
340
+ const pieces = path.split('.');
341
+ let cur = '';
342
+ for (let i = 0; i < pieces.length; ++i) {
343
+ cur += cur.length ? '.' + pieces[i] : pieces[i];
344
+ if (excluded.indexOf(cur) !== -1) {
345
+ return;
346
+ }
347
+ }
348
+
349
+ // Special case: if user has included a parent path of a discriminator key,
350
+ // don't explicitly project in the discriminator key because that will
351
+ // project out everything else under the parent path
352
+ if (!exclude && (type?.options?.$skipDiscriminatorCheck || false)) {
353
+ let cur = '';
354
+ for (let i = 0; i < pieces.length; ++i) {
355
+ cur += (cur.length === 0 ? '' : '.') + pieces[i];
356
+ const projection = get(fields, cur, false) || get(fields, cur + '.$', false);
357
+ if (projection && typeof projection !== 'object') {
358
+ return;
359
+ }
360
+ }
361
+ }
362
+
363
+ (type.selected ? selected : excluded).push(path);
364
+ return path;
365
+ }
366
+ };
367
+
368
+ /**
369
+ * Set each path query option to lean
370
+ *
371
+ * @param {Object} option
372
+ */
373
+
374
+ function makeLean(val) {
375
+ return function(option) {
376
+ option.options || (option.options = {});
377
+
378
+ if (Array.isArray(val?.virtuals)) {
379
+ val = Object.assign({}, val);
380
+ val.virtuals = val.virtuals.
381
+ filter(path => typeof path === 'string' && path.startsWith(option.path + '.')).
382
+ map(path => path.slice(option.path.length + 1));
383
+ }
384
+
385
+ option.options.lean = val;
386
+ };
387
+ }