@depup/mongoose 9.4.1-depup.0 → 9.8.1-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 (60) hide show
  1. package/README.md +3 -9
  2. package/changes.json +3 -8
  3. package/eslint.config.mjs +4 -1
  4. package/lib/aggregate.js +54 -24
  5. package/lib/cast.js +1 -1
  6. package/lib/connection.js +1 -1
  7. package/lib/cursor/aggregationCursor.js +47 -16
  8. package/lib/cursor/queryCursor.js +23 -7
  9. package/lib/document.js +140 -61
  10. package/lib/drivers/node-mongodb-native/collection.js +10 -4
  11. package/lib/error/cast.js +18 -9
  12. package/lib/error/divergentArray.js +1 -1
  13. package/lib/error/messages.js +1 -0
  14. package/lib/helpers/clone.js +22 -5
  15. package/lib/helpers/document/applyDefaults.js +5 -0
  16. package/lib/helpers/populate/createPopulateQueryFilter.js +9 -1
  17. package/lib/helpers/populate/getModelsMapForPopulate.js +8 -6
  18. package/lib/helpers/populate/splitPopulateQuery.js +81 -0
  19. package/lib/helpers/query/castUpdate.js +31 -10
  20. package/lib/helpers/schema/getKeysInSchemaOrder.js +13 -16
  21. package/lib/helpers/update/applyTimestampsToUpdate.js +4 -2
  22. package/lib/model.js +153 -38
  23. package/lib/mongoose.js +3 -3
  24. package/lib/options/schemaTypeOptions.js +14 -0
  25. package/lib/plugins/saveSubdocs.js +16 -13
  26. package/lib/query.js +208 -102
  27. package/lib/queryHelpers.js +13 -12
  28. package/lib/schema/array.js +3 -3
  29. package/lib/schema/date.js +7 -5
  30. package/lib/schema/documentArray.js +1 -1
  31. package/lib/schema/objectId.js +7 -1
  32. package/lib/schema/string.js +19 -2
  33. package/lib/schema/subdocument.js +1 -1
  34. package/lib/schema/union.js +2 -2
  35. package/lib/schema.js +38 -12
  36. package/lib/schemaType.js +58 -10
  37. package/lib/standardSchema/convertErrorToIssues.js +20 -0
  38. package/lib/stateMachine.js +11 -6
  39. package/lib/tracing.js +38 -0
  40. package/lib/types/documentArray/methods/index.js +117 -3
  41. package/lib/types/subdocument.js +4 -2
  42. package/lib/utils.js +3 -2
  43. package/lib/validOptions.js +1 -0
  44. package/package.json +27 -30
  45. package/tstyche.json +2 -1
  46. package/types/augmentations.d.ts +2 -2
  47. package/types/document.d.ts +21 -4
  48. package/types/expressions.d.ts +16 -0
  49. package/types/index.d.ts +15 -10
  50. package/types/inferhydrateddoctype.d.ts +1 -1
  51. package/types/inferrawdoctype.d.ts +6 -3
  52. package/types/inferschematype.d.ts +10 -2
  53. package/types/models.d.ts +38 -12
  54. package/types/mongooseoptions.d.ts +9 -1
  55. package/types/populate.d.ts +8 -0
  56. package/types/query.d.ts +13 -3
  57. package/types/schemaoptions.d.ts +5 -0
  58. package/types/schematypes.d.ts +10 -0
  59. package/types/tracing.d.ts +10 -0
  60. package/types/utility.d.ts +9 -0
package/README.md CHANGED
@@ -13,16 +13,10 @@ npm install @depup/mongoose
13
13
 
14
14
  | Field | Value |
15
15
  |-------|-------|
16
- | Original | [mongoose](https://www.npmjs.com/package/mongoose) @ 9.4.1 |
17
- | Processed | 2026-04-03 |
16
+ | Original | [mongoose](https://www.npmjs.com/package/mongoose) @ 9.8.1 |
17
+ | Processed | 2026-07-28 |
18
18
  | Smoke test | passed |
19
- | Deps updated | 1 |
20
-
21
- ## Dependency Changes
22
-
23
- | Dependency | From | To |
24
- |------------|------|-----|
25
- | mongodb | ~7.1 | ^7.1.1 |
19
+ | Deps updated | 0 |
26
20
 
27
21
  ---
28
22
 
package/changes.json CHANGED
@@ -1,10 +1,5 @@
1
1
  {
2
- "bumped": {
3
- "mongodb": {
4
- "from": "~7.1",
5
- "to": "^7.1.1"
6
- }
7
- },
8
- "timestamp": "2026-04-03T20:13:40.524Z",
9
- "totalUpdated": 1
2
+ "bumped": {},
3
+ "timestamp": "2026-07-28T00:38:49.300Z",
4
+ "totalUpdated": 0
10
5
  }
package/eslint.config.mjs CHANGED
@@ -15,7 +15,10 @@ export default defineConfig([
15
15
  '!**/.*',
16
16
  '**/node_modules',
17
17
  '**/.git',
18
- '**/data'
18
+ '**/data',
19
+ '**/docs/3.*/**',
20
+ '**/docs/5.*/**',
21
+ '**/docs/vendor/*'
19
22
  ]),
20
23
  js.configs.recommended,
21
24
  // general options
package/lib/aggregate.js CHANGED
@@ -15,6 +15,8 @@ const { buildMiddlewareFilter } = require('./helpers/buildMiddlewareFilter');
15
15
  const stringifyFunctionOperators = require('./helpers/aggregate/stringifyFunctionOperators');
16
16
  const utils = require('./utils');
17
17
  const { modelSymbol } = require('./helpers/symbols');
18
+ const { createTracedChannel } = require('./tracing');
19
+ const { trace: traceAggregate } = createTracedChannel('mongoose:aggregate');
18
20
  const read = Query.prototype.read;
19
21
  const readConcern = Query.prototype.readConcern;
20
22
 
@@ -613,6 +615,9 @@ Aggregate.prototype.graphLookup = function(options) {
613
615
  *
614
616
  * aggregate.sample(3); // Add a pipeline that picks 3 random documents
615
617
  *
618
+ * // `$match` before `$sample` samples from the filtered subset
619
+ * aggregate.match({ difficulty: 'easy' }).sample(3);
620
+ *
616
621
  * @see $sample https://www.mongodb.com/docs/manual/reference/operator/aggregation/sample/#pipe._S_sample
617
622
  * @param {number} size number of random documents to pick
618
623
  * @return {Aggregate}
@@ -1032,7 +1037,7 @@ Aggregate.prototype.pipeline = function() {
1032
1037
  * const base = MyModel.aggregate().match({ test: 1 });
1033
1038
  * base.pipelineForUnionWith(); // [{ $match: { test: 1 } }]
1034
1039
  *
1035
- * @return {Array} The current pipeline with `$unionWith` stage restrictions
1040
+ * @return {PipelineStage[]} The current pipeline with `$unionWith` stage restrictions
1036
1041
  * @api public
1037
1042
  */
1038
1043
 
@@ -1071,8 +1076,20 @@ Aggregate.prototype.exec = async function exec() {
1071
1076
 
1072
1077
  this._optionsForExec();
1073
1078
 
1074
- const cursor = await this._connection.client.db().aggregate(this._pipeline, this.options);
1075
- return await cursor.toArray();
1079
+ const _this = this;
1080
+ return traceAggregate(async function maybeTracedConnectionAggregate() {
1081
+ const cursor = await _this._connection.client.db().aggregate(_this._pipeline, _this.options);
1082
+ return await cursor.toArray();
1083
+ }, () => ({
1084
+ operation: 'aggregate',
1085
+ database: _this._connection.name,
1086
+ serverAddress: _this._connection.host,
1087
+ serverPort: _this._connection.port,
1088
+ args: {
1089
+ pipeline: _this._pipeline,
1090
+ options: _this.options
1091
+ }
1092
+ }));
1076
1093
  }
1077
1094
 
1078
1095
  const model = this._model;
@@ -1090,32 +1107,45 @@ Aggregate.prototype.exec = async function exec() {
1090
1107
  prepareDiscriminatorPipeline(this._pipeline, this._model.schema);
1091
1108
  stringifyFunctionOperators(this._pipeline);
1092
1109
 
1093
- const preFilter = buildMiddlewareFilter(this.options, 'pre');
1094
- const postFilter = buildMiddlewareFilter(this.options, 'post');
1110
+ const _this = this;
1111
+ return traceAggregate(async function maybeTracedAggregateExec() {
1112
+ const preFilter = buildMiddlewareFilter(_this.options, 'pre');
1113
+ const postFilter = buildMiddlewareFilter(_this.options, 'post');
1095
1114
 
1096
- try {
1097
- await model.hooks.execPre('aggregate', this, [], { filter: preFilter });
1098
- } catch (error) {
1099
- return await model.hooks.execPost('aggregate', this, [null], { error, filter: postFilter });
1100
- }
1115
+ try {
1116
+ await model.hooks.execPre('aggregate', _this, [], { filter: preFilter });
1117
+ } catch (error) {
1118
+ return await model.hooks.execPost('aggregate', _this, [null], { error, filter: postFilter });
1119
+ }
1101
1120
 
1102
- if (!this._pipeline.length) {
1103
- throw new MongooseError('Aggregate has empty pipeline');
1104
- }
1121
+ if (!_this._pipeline.length) {
1122
+ throw new MongooseError('Aggregate has empty pipeline');
1123
+ }
1105
1124
 
1106
- const options = clone(this.options || {});
1107
- delete options.middleware;
1125
+ const options = clone(_this.options || {});
1126
+ delete options.middleware;
1108
1127
 
1109
- let result;
1110
- try {
1111
- const cursor = await collection.aggregate(this._pipeline, options);
1112
- result = await cursor.toArray();
1113
- } catch (error) {
1114
- return await model.hooks.execPost('aggregate', this, [null], { error, filter: postFilter });
1115
- }
1128
+ let result;
1129
+ try {
1130
+ const cursor = await collection.aggregate(_this._pipeline, options);
1131
+ result = await cursor.toArray();
1132
+ } catch (error) {
1133
+ return await model.hooks.execPost('aggregate', _this, [null], { error, filter: postFilter });
1134
+ }
1116
1135
 
1117
- await model.hooks.execPost('aggregate', this, [result], { error: null, filter: postFilter });
1118
- return result;
1136
+ await model.hooks.execPost('aggregate', _this, [result], { error: null, filter: postFilter });
1137
+ return result;
1138
+ }, () => ({
1139
+ operation: 'aggregate',
1140
+ collection: collection.name,
1141
+ database: model.db?.name,
1142
+ serverAddress: model.db?.host,
1143
+ serverPort: model.db?.port,
1144
+ args: {
1145
+ pipeline: _this._pipeline,
1146
+ options: _this.options
1147
+ }
1148
+ }));
1119
1149
  };
1120
1150
 
1121
1151
  /**
package/lib/cast.js CHANGED
@@ -413,7 +413,7 @@ function _cast(val, numbertype, context) {
413
413
  _cast(item, numbertype, context);
414
414
  val[nkey] = item;
415
415
  } else {
416
- val[nkey] = numbertype.castForQuery({ val: item, context: context });
416
+ val[nkey] = numbertype.castForQuery(null, item, context);
417
417
  }
418
418
  }
419
419
  }
package/lib/connection.js CHANGED
@@ -1354,7 +1354,7 @@ Connection.prototype.onClose = function onClose(force) {
1354
1354
 
1355
1355
  /**
1356
1356
  * Retrieves a raw collection instance, creating it if not cached.
1357
- * This method returns a thin wrapper around a [MongoDB Node.js driver collection]([MongoDB Node.js driver collection](https://mongodb.github.io/node-mongodb-native/Next/classes/Collection.html)).
1357
+ * This method returns a thin wrapper around a [MongoDB Node.js driver collection](https://mongodb.github.io/node-mongodb-native/Next/classes/Collection.html).
1358
1358
  * Using a Collection bypasses Mongoose middleware, validation, and casting,
1359
1359
  * letting you use [MongoDB Node.js driver](https://mongodb.github.io/node-mongodb-native/) functionality directly.
1360
1360
  *
@@ -10,6 +10,7 @@ const eachAsync = require('../helpers/cursor/eachAsync');
10
10
  const immediate = require('../helpers/immediate');
11
11
  const kareem = require('kareem');
12
12
  const util = require('util');
13
+ const { cursorNextChannel } = require('../tracing');
13
14
 
14
15
  /**
15
16
  * An AggregationCursor is a concurrency primitive for processing aggregation
@@ -62,13 +63,7 @@ util.inherits(AggregationCursor, Readable);
62
63
  */
63
64
 
64
65
  function _init(model, c, agg) {
65
- if (!model.collection.buffer) {
66
- model.hooks.execPre('aggregate', agg).then(() => onPreComplete(null), err => onPreComplete(err));
67
- } else {
68
- model.collection.emitter.once('queue', function() {
69
- model.hooks.execPre('aggregate', agg).then(() => onPreComplete(null), err => onPreComplete(err));
70
- });
71
- }
66
+ model.hooks.execPre('aggregate', agg).then(() => onPreComplete(null), err => onPreComplete(err));
72
67
 
73
68
  function onPreComplete(err) {
74
69
  if (err != null) {
@@ -79,8 +74,28 @@ function _init(model, c, agg) {
79
74
  c._transforms.push(agg.options.cursor.transform);
80
75
  }
81
76
 
82
- c.cursor = model.collection.aggregate(agg._pipeline, agg.options || {});
83
- c.emit('cursor', c.cursor);
77
+ if (model.collection._shouldBufferCommands() && model.collection.buffer) {
78
+ model.collection.queue.push([
79
+ () => _getRawCursor(model, c, agg)
80
+ ]);
81
+ } else {
82
+ _getRawCursor(model, c, agg);
83
+ }
84
+ }
85
+ }
86
+
87
+ /*!
88
+ * ignore
89
+ */
90
+
91
+ function _getRawCursor(model, aggregationCursor, agg) {
92
+ try {
93
+ const cursor = model.collection.aggregate(agg._pipeline, agg.options || {});
94
+ aggregationCursor.cursor = cursor;
95
+ aggregationCursor.emit('cursor', cursor);
96
+ } catch (err) {
97
+ aggregationCursor._markError(err);
98
+ aggregationCursor.listeners('error').length > 0 && aggregationCursor.emit('error', aggregationCursor._error);
84
99
  }
85
100
  }
86
101
 
@@ -277,14 +292,30 @@ AggregationCursor.prototype.next = async function next() {
277
292
  if (typeof arguments[0] === 'function') {
278
293
  throw new MongooseError('AggregationCursor.prototype.next() no longer accepts a callback');
279
294
  }
280
- return new Promise((resolve, reject) => {
281
- _next(this, (err, res) => {
282
- if (err != null) {
283
- return reject(err);
284
- }
285
- resolve(res);
295
+ const _this = this;
296
+ const model = this.agg._model;
297
+ return cursorNextChannel.trace(function maybeTracedAggCursorNext() {
298
+ return new Promise((resolve, reject) => {
299
+ _next(_this, (err, res) => {
300
+ if (err != null) {
301
+ return reject(err);
302
+ }
303
+ resolve(res);
304
+ });
286
305
  });
287
- });
306
+ }, () => ({
307
+ operation: 'aggregate',
308
+ collection: model?.collection?.name,
309
+ database: model?.db?.name,
310
+ serverAddress: model?.db?.host,
311
+ serverPort: model?.db?.port,
312
+ batchSize: _this.agg.options?.cursor?.batchSize,
313
+ tailable: false,
314
+ args: {
315
+ pipeline: _this.agg._pipeline,
316
+ options: _this.agg.options
317
+ }
318
+ }));
288
319
  };
289
320
 
290
321
  /**
@@ -12,6 +12,7 @@ const kareem = require('kareem');
12
12
  const immediate = require('../helpers/immediate');
13
13
  const { once } = require('events');
14
14
  const util = require('util');
15
+ const { cursorNextChannel } = require('../tracing');
15
16
 
16
17
  /**
17
18
  * A QueryCursor is a concurrency primitive for processing query results
@@ -310,14 +311,29 @@ QueryCursor.prototype.next = async function next() {
310
311
  if (this._closed) {
311
312
  throw new MongooseError('Cannot call `next()` on a closed cursor');
312
313
  }
313
- return new Promise((resolve, reject) => {
314
- _next(this, function(error, doc) {
315
- if (error) {
316
- return reject(error);
317
- }
318
- resolve(doc);
314
+ const _this = this;
315
+ return cursorNextChannel.trace(function maybeTracedQueryCursorNext() {
316
+ return new Promise((resolve, reject) => {
317
+ _next(_this, function(error, doc) {
318
+ if (error) {
319
+ return reject(error);
320
+ }
321
+ resolve(doc);
322
+ });
319
323
  });
320
- });
324
+ }, () => ({
325
+ operation: _this.query.op || 'find',
326
+ collection: _this.query.mongooseCollection.name,
327
+ database: _this.model.db?.name,
328
+ serverAddress: _this.model.db?.host,
329
+ serverPort: _this.model.db?.port,
330
+ batchSize: _this.options.batchSize || _this.query.options?.batchSize,
331
+ tailable: _this.options.tailable || _this.query.options?.tailable || false,
332
+ args: {
333
+ filter: _this.query.getFilter(),
334
+ options: _this.query._mongooseOptions
335
+ }
336
+ }));
321
337
  };
322
338
 
323
339
  /**