mongoose 8.9.1 → 8.9.2
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.
- package/dist/browser.umd.js +1 -1
- package/lib/aggregate.js +21 -4
- package/lib/connection.js +1 -1
- package/lib/document.js +4 -4
- package/lib/helpers/indexes/isIndexSpecEqual.js +32 -0
- package/lib/model.js +10 -7
- package/lib/query.js +1 -4
- package/lib/schema.js +3 -3
- package/lib/types/map.js +8 -1
- package/package.json +1 -1
- package/types/index.d.ts +57 -50
package/lib/aggregate.js
CHANGED
|
@@ -87,6 +87,24 @@ function Aggregate(pipeline, model) {
|
|
|
87
87
|
|
|
88
88
|
Aggregate.prototype.options;
|
|
89
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Returns default options for this aggregate.
|
|
92
|
+
*
|
|
93
|
+
* @param {Model} model
|
|
94
|
+
* @api private
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
Aggregate.prototype._optionsForExec = function() {
|
|
98
|
+
const options = this.options || {};
|
|
99
|
+
|
|
100
|
+
const asyncLocalStorage = this.model()?.db?.base.transactionAsyncLocalStorage?.getStore();
|
|
101
|
+
if (!options.hasOwnProperty('session') && asyncLocalStorage?.session != null) {
|
|
102
|
+
options.session = asyncLocalStorage.session;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return options;
|
|
106
|
+
};
|
|
107
|
+
|
|
90
108
|
/**
|
|
91
109
|
* Get/set the model that this aggregation will execute on.
|
|
92
110
|
*
|
|
@@ -914,6 +932,7 @@ Aggregate.prototype.option = function(value) {
|
|
|
914
932
|
*/
|
|
915
933
|
|
|
916
934
|
Aggregate.prototype.cursor = function(options) {
|
|
935
|
+
this._optionsForExec();
|
|
917
936
|
this.options.cursor = options || {};
|
|
918
937
|
return new AggregationCursor(this); // return this;
|
|
919
938
|
};
|
|
@@ -1022,10 +1041,7 @@ Aggregate.prototype.exec = async function exec() {
|
|
|
1022
1041
|
applyGlobalMaxTimeMS(this.options, model.db.options, model.base.options);
|
|
1023
1042
|
applyGlobalDiskUse(this.options, model.db.options, model.base.options);
|
|
1024
1043
|
|
|
1025
|
-
|
|
1026
|
-
if (!this.options.hasOwnProperty('session') && asyncLocalStorage?.session != null) {
|
|
1027
|
-
this.options.session = asyncLocalStorage.session;
|
|
1028
|
-
}
|
|
1044
|
+
this._optionsForExec();
|
|
1029
1045
|
|
|
1030
1046
|
if (this.options && this.options.cursor) {
|
|
1031
1047
|
return new AggregationCursor(this);
|
|
@@ -1052,6 +1068,7 @@ Aggregate.prototype.exec = async function exec() {
|
|
|
1052
1068
|
}
|
|
1053
1069
|
|
|
1054
1070
|
const options = clone(this.options || {});
|
|
1071
|
+
|
|
1055
1072
|
let result;
|
|
1056
1073
|
try {
|
|
1057
1074
|
const cursor = await collection.aggregate(this._pipeline, options);
|
package/lib/connection.js
CHANGED
|
@@ -663,7 +663,7 @@ Connection.prototype.withSession = async function withSession(executor) {
|
|
|
663
663
|
*
|
|
664
664
|
* const session = await conn.startSession();
|
|
665
665
|
* let doc = await Person.findOne({ name: 'Ned Stark' }, null, { session });
|
|
666
|
-
* await doc.
|
|
666
|
+
* await doc.deleteOne();
|
|
667
667
|
* // `doc` will always be null, even if reading from a replica set
|
|
668
668
|
* // secondary. Without causal consistency, it is possible to
|
|
669
669
|
* // get a doc back from the below query if the query reads from a
|
package/lib/document.js
CHANGED
|
@@ -2357,17 +2357,17 @@ Document.prototype.$isDefault = function(path) {
|
|
|
2357
2357
|
};
|
|
2358
2358
|
|
|
2359
2359
|
/**
|
|
2360
|
-
* Getter/setter, determines whether the document was
|
|
2360
|
+
* Getter/setter, determines whether the document was deleted. The `Model.prototype.deleteOne()` method sets `$isDeleted` if the delete operation succeeded.
|
|
2361
2361
|
*
|
|
2362
2362
|
* #### Example:
|
|
2363
2363
|
*
|
|
2364
|
-
* const product = await product.
|
|
2364
|
+
* const product = await product.deleteOne();
|
|
2365
2365
|
* product.$isDeleted(); // true
|
|
2366
|
-
* product.
|
|
2366
|
+
* product.deleteOne(); // no-op, doesn't send anything to the db
|
|
2367
2367
|
*
|
|
2368
2368
|
* product.$isDeleted(false);
|
|
2369
2369
|
* product.$isDeleted(); // false
|
|
2370
|
-
* product.
|
|
2370
|
+
* product.deleteOne(); // will execute a remove against the db
|
|
2371
2371
|
*
|
|
2372
2372
|
*
|
|
2373
2373
|
* @param {Boolean} [val] optional, overrides whether mongoose thinks the doc is deleted
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Compares two index specifications to determine if they are equal.
|
|
5
|
+
*
|
|
6
|
+
* #### Example:
|
|
7
|
+
* isIndexSpecEqual({ a: 1, b: 1 }, { a: 1, b: 1 }); // true
|
|
8
|
+
* isIndexSpecEqual({ a: 1, b: 1 }, { b: 1, a: 1 }); // false
|
|
9
|
+
* isIndexSpecEqual({ a: 1, b: -1 }, { a: 1, b: 1 }); // false
|
|
10
|
+
*
|
|
11
|
+
* @param {Object} spec1 The first index specification to compare.
|
|
12
|
+
* @param {Object} spec2 The second index specification to compare.
|
|
13
|
+
* @returns {Boolean} Returns true if the index specifications are equal, otherwise returns false.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
module.exports = function isIndexSpecEqual(spec1, spec2) {
|
|
17
|
+
const spec1Keys = Object.keys(spec1);
|
|
18
|
+
const spec2Keys = Object.keys(spec2);
|
|
19
|
+
|
|
20
|
+
if (spec1Keys.length !== spec2Keys.length) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
for (let i = 0; i < spec1Keys.length; i++) {
|
|
25
|
+
const key = spec1Keys[i];
|
|
26
|
+
if (key !== spec2Keys[i] || spec1[key] !== spec2[key]) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return true;
|
|
32
|
+
};
|
package/lib/model.js
CHANGED
|
@@ -694,13 +694,20 @@ Model.prototype.$__where = function _where(where) {
|
|
|
694
694
|
};
|
|
695
695
|
|
|
696
696
|
/**
|
|
697
|
-
* Delete this document from the db.
|
|
697
|
+
* Delete this document from the db. Returns a Query instance containing a `deleteOne` operation by this document's `_id`.
|
|
698
698
|
*
|
|
699
699
|
* #### Example:
|
|
700
700
|
*
|
|
701
701
|
* await product.deleteOne();
|
|
702
702
|
* await Product.findById(product._id); // null
|
|
703
703
|
*
|
|
704
|
+
* Since `deleteOne()` returns a Query, the `deleteOne()` will **not** execute unless you use either `await`, `.then()`, `.catch()`, or [`.exec()`](https://mongoosejs.com/docs/api/query.html#Query.prototype.exec())
|
|
705
|
+
*
|
|
706
|
+
* #### Example:
|
|
707
|
+
*
|
|
708
|
+
* product.deleteOne(); // Doesn't do anything
|
|
709
|
+
* product.deleteOne().exec(); // Deletes the document, returns a promise
|
|
710
|
+
*
|
|
704
711
|
* @return {Query} Query
|
|
705
712
|
* @api public
|
|
706
713
|
*/
|
|
@@ -1879,8 +1886,6 @@ Model.translateAliases = function translateAliases(fields, errorOnDuplicates) {
|
|
|
1879
1886
|
/**
|
|
1880
1887
|
* Deletes the first document that matches `conditions` from the collection.
|
|
1881
1888
|
* It returns an object with the property `deletedCount` indicating how many documents were deleted.
|
|
1882
|
-
* Behaves like `remove()`, but deletes at most one document regardless of the
|
|
1883
|
-
* `single` option.
|
|
1884
1889
|
*
|
|
1885
1890
|
* #### Example:
|
|
1886
1891
|
*
|
|
@@ -1914,8 +1919,6 @@ Model.deleteOne = function deleteOne(conditions, options) {
|
|
|
1914
1919
|
/**
|
|
1915
1920
|
* Deletes all of the documents that match `conditions` from the collection.
|
|
1916
1921
|
* It returns an object with the property `deletedCount` containing the number of documents deleted.
|
|
1917
|
-
* Behaves like `remove()`, but deletes all documents that match `conditions`
|
|
1918
|
-
* regardless of the `single` option.
|
|
1919
1922
|
*
|
|
1920
1923
|
* #### Example:
|
|
1921
1924
|
*
|
|
@@ -2729,7 +2732,7 @@ Model.create = async function create(doc, options) {
|
|
|
2729
2732
|
* // operationType: 'delete',
|
|
2730
2733
|
* // ns: { db: 'mydb', coll: 'Person' },
|
|
2731
2734
|
* // documentKey: { _id: 5a51b125c5500f5aa094c7bd } }
|
|
2732
|
-
* await doc.
|
|
2735
|
+
* await doc.deleteOne();
|
|
2733
2736
|
*
|
|
2734
2737
|
* @param {Array} [pipeline]
|
|
2735
2738
|
* @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/4.9/classes/Collection.html#watch)
|
|
@@ -2777,7 +2780,7 @@ Model.watch = function(pipeline, options) {
|
|
|
2777
2780
|
*
|
|
2778
2781
|
* const session = await Person.startSession();
|
|
2779
2782
|
* let doc = await Person.findOne({ name: 'Ned Stark' }, null, { session });
|
|
2780
|
-
* await doc.
|
|
2783
|
+
* await doc.deleteOne();
|
|
2781
2784
|
* // `doc` will always be null, even if reading from a replica set
|
|
2782
2785
|
* // secondary. Without causal consistency, it is possible to
|
|
2783
2786
|
* // get a doc back from the below query if the query reads from a
|
package/lib/query.js
CHANGED
|
@@ -2247,10 +2247,7 @@ Query.prototype.error = function error(err) {
|
|
|
2247
2247
|
*/
|
|
2248
2248
|
|
|
2249
2249
|
Query.prototype._unsetCastError = function _unsetCastError() {
|
|
2250
|
-
if (this._error == null) {
|
|
2251
|
-
return;
|
|
2252
|
-
}
|
|
2253
|
-
if (this._error != null && !(this._error instanceof CastError)) {
|
|
2250
|
+
if (this._error == null || !(this._error instanceof CastError)) {
|
|
2254
2251
|
return;
|
|
2255
2252
|
}
|
|
2256
2253
|
return this.error(null);
|
package/lib/schema.js
CHANGED
|
@@ -18,13 +18,13 @@ const getConstructorName = require('./helpers/getConstructorName');
|
|
|
18
18
|
const getIndexes = require('./helpers/schema/getIndexes');
|
|
19
19
|
const handleReadPreferenceAliases = require('./helpers/query/handleReadPreferenceAliases');
|
|
20
20
|
const idGetter = require('./helpers/schema/idGetter');
|
|
21
|
+
const isIndexSpecEqual = require('./helpers/indexes/isIndexSpecEqual');
|
|
21
22
|
const merge = require('./helpers/schema/merge');
|
|
22
23
|
const mpath = require('mpath');
|
|
23
24
|
const setPopulatedVirtualValue = require('./helpers/populate/setPopulatedVirtualValue');
|
|
24
25
|
const setupTimestamps = require('./helpers/timestamps/setupTimestamps');
|
|
25
26
|
const utils = require('./utils');
|
|
26
27
|
const validateRef = require('./helpers/populate/validateRef');
|
|
27
|
-
const util = require('util');
|
|
28
28
|
|
|
29
29
|
const hasNumericSubpathRegex = /\.\d+(\.|$)/;
|
|
30
30
|
|
|
@@ -899,7 +899,7 @@ Schema.prototype.removeIndex = function removeIndex(index) {
|
|
|
899
899
|
|
|
900
900
|
if (typeof index === 'object') {
|
|
901
901
|
for (let i = this._indexes.length - 1; i >= 0; --i) {
|
|
902
|
-
if (
|
|
902
|
+
if (isIndexSpecEqual(this._indexes[i][0], index)) {
|
|
903
903
|
this._indexes.splice(i, 1);
|
|
904
904
|
}
|
|
905
905
|
}
|
|
@@ -2147,7 +2147,7 @@ Schema.prototype.index = function(fields, options) {
|
|
|
2147
2147
|
}
|
|
2148
2148
|
|
|
2149
2149
|
for (const existingIndex of this.indexes()) {
|
|
2150
|
-
if (
|
|
2150
|
+
if (options.name == null && existingIndex[1].name == null && isIndexSpecEqual(existingIndex[0], fields)) {
|
|
2151
2151
|
throw new MongooseError(`Schema already has an index on ${JSON.stringify(fields)}`);
|
|
2152
2152
|
}
|
|
2153
2153
|
}
|
package/lib/types/map.js
CHANGED
|
@@ -9,6 +9,7 @@ const handleSpreadDoc = require('../helpers/document/handleSpreadDoc');
|
|
|
9
9
|
const util = require('util');
|
|
10
10
|
const specialProperties = require('../helpers/specialProperties');
|
|
11
11
|
const isBsonType = require('../helpers/isBsonType');
|
|
12
|
+
const cleanModifiedSubpaths = require('../helpers/document/cleanModifiedSubpaths');
|
|
12
13
|
|
|
13
14
|
const populateModelSymbol = require('../helpers/symbols').populateModelSymbol;
|
|
14
15
|
|
|
@@ -157,7 +158,13 @@ class MongooseMap extends Map {
|
|
|
157
158
|
super.set(key, value);
|
|
158
159
|
|
|
159
160
|
if (parent != null && parent.$__ != null && !deepEqual(value, priorVal)) {
|
|
160
|
-
|
|
161
|
+
const path = fullPath.call(this);
|
|
162
|
+
parent.markModified(path);
|
|
163
|
+
// If overwriting the full document array or subdoc, make sure to clean up any paths that were modified
|
|
164
|
+
// before re: #15108
|
|
165
|
+
if (this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested) {
|
|
166
|
+
cleanModifiedSubpaths(parent, path);
|
|
167
|
+
}
|
|
161
168
|
}
|
|
162
169
|
|
|
163
170
|
// Delay calculating full path unless absolutely necessary, because string
|
package/package.json
CHANGED
package/types/index.d.ts
CHANGED
|
@@ -572,7 +572,8 @@ declare module 'mongoose' {
|
|
|
572
572
|
| typeof Schema.Types.Number
|
|
573
573
|
| typeof Schema.Types.String
|
|
574
574
|
| typeof Schema.Types.Buffer
|
|
575
|
-
| typeof Schema.Types.ObjectId
|
|
575
|
+
| typeof Schema.Types.ObjectId
|
|
576
|
+
| typeof Schema.Types.UUID;
|
|
576
577
|
|
|
577
578
|
|
|
578
579
|
export type InferId<T> = T extends { _id?: any } ? T['_id'] : Types.ObjectId;
|
|
@@ -712,76 +713,82 @@ declare module 'mongoose' {
|
|
|
712
713
|
/**
|
|
713
714
|
* Converts any Buffer properties into mongodb.Binary instances, which is what `lean()` returns
|
|
714
715
|
*/
|
|
715
|
-
export type BufferToBinary<T> = T extends
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
: T[K] extends
|
|
716
|
+
export type BufferToBinary<T> = T extends Buffer
|
|
717
|
+
? mongodb.Binary
|
|
718
|
+
: T extends TreatAsPrimitives
|
|
719
|
+
? T
|
|
720
|
+
: T extends Record<string, any> ? {
|
|
721
|
+
[K in keyof T]: T[K] extends Buffer
|
|
722
|
+
? mongodb.Binary
|
|
723
|
+
: T[K] extends Types.DocumentArray<infer ItemType>
|
|
721
724
|
? Types.DocumentArray<BufferToBinary<ItemType>>
|
|
722
725
|
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
723
726
|
? HydratedSingleSubdocument<SubdocType>
|
|
724
727
|
: BufferToBinary<T[K]>;
|
|
725
|
-
|
|
728
|
+
} : T;
|
|
726
729
|
|
|
727
730
|
/**
|
|
728
731
|
* Converts any Buffer properties into { type: 'buffer', data: [1, 2, 3] } format for JSON serialization
|
|
729
732
|
*/
|
|
730
|
-
export type BufferToJSON<T> = T extends
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
: T[K] extends
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
?
|
|
739
|
-
:
|
|
740
|
-
|
|
733
|
+
export type BufferToJSON<T> = T extends Buffer
|
|
734
|
+
? { type: 'buffer', data: number[] }
|
|
735
|
+
: T extends TreatAsPrimitives
|
|
736
|
+
? T
|
|
737
|
+
: T extends Record<string, any> ? {
|
|
738
|
+
[K in keyof T]: T[K] extends Buffer
|
|
739
|
+
? { type: 'buffer', data: number[] }
|
|
740
|
+
: T[K] extends Types.DocumentArray<infer ItemType>
|
|
741
|
+
? Types.DocumentArray<BufferToBinary<ItemType>>
|
|
742
|
+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
743
|
+
? HydratedSingleSubdocument<SubdocType>
|
|
744
|
+
: BufferToBinary<T[K]>;
|
|
745
|
+
} : T;
|
|
741
746
|
|
|
742
747
|
/**
|
|
743
748
|
* Converts any ObjectId properties into strings for JSON serialization
|
|
744
749
|
*/
|
|
745
|
-
export type ObjectIdToString<T> = T extends
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
: T[K] extends
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
?
|
|
754
|
-
:
|
|
755
|
-
|
|
750
|
+
export type ObjectIdToString<T> = T extends mongodb.ObjectId
|
|
751
|
+
? string
|
|
752
|
+
: T extends TreatAsPrimitives
|
|
753
|
+
? T
|
|
754
|
+
: T extends Record<string, any> ? {
|
|
755
|
+
[K in keyof T]: T[K] extends mongodb.ObjectId
|
|
756
|
+
? string
|
|
757
|
+
: T[K] extends Types.DocumentArray<infer ItemType>
|
|
758
|
+
? Types.DocumentArray<ObjectIdToString<ItemType>>
|
|
759
|
+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
760
|
+
? HydratedSingleSubdocument<ObjectIdToString<SubdocType>>
|
|
761
|
+
: ObjectIdToString<T[K]>;
|
|
762
|
+
} : T;
|
|
756
763
|
|
|
757
764
|
/**
|
|
758
765
|
* Converts any Date properties into strings for JSON serialization
|
|
759
766
|
*/
|
|
760
|
-
export type DateToString<T> = T extends
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
: T[K] extends
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
767
|
+
export type DateToString<T> = T extends NativeDate
|
|
768
|
+
? string
|
|
769
|
+
: T extends TreatAsPrimitives
|
|
770
|
+
? T
|
|
771
|
+
: T extends Record<string, any> ? {
|
|
772
|
+
[K in keyof T]: T[K] extends NativeDate
|
|
773
|
+
? string
|
|
774
|
+
: T[K] extends (NativeDate | null | undefined)
|
|
775
|
+
? string | null | undefined
|
|
776
|
+
: T[K] extends Types.DocumentArray<infer ItemType>
|
|
777
|
+
? Types.DocumentArray<DateToString<ItemType>>
|
|
778
|
+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
779
|
+
? HydratedSingleSubdocument<DateToString<SubdocType>>
|
|
780
|
+
: DateToString<T[K]>;
|
|
781
|
+
} : T;
|
|
771
782
|
|
|
772
783
|
/**
|
|
773
784
|
* Converts any Mongoose subdocuments (single nested or doc arrays) into POJO equivalents
|
|
774
785
|
*/
|
|
775
786
|
export type SubdocsToPOJOs<T> = T extends TreatAsPrimitives ? T : T extends Record<string, any> ? {
|
|
776
|
-
[K in keyof T]: T[K] extends
|
|
777
|
-
?
|
|
778
|
-
: T[K] extends
|
|
779
|
-
?
|
|
780
|
-
: T[K]
|
|
781
|
-
? ItemType[]
|
|
782
|
-
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
783
|
-
? SubdocType
|
|
784
|
-
: SubdocsToPOJOs<T[K]>;
|
|
787
|
+
[K in keyof T]: T[K] extends Types.DocumentArray<infer ItemType>
|
|
788
|
+
? ItemType[]
|
|
789
|
+
: T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
|
|
790
|
+
? SubdocType
|
|
791
|
+
: SubdocsToPOJOs<T[K]>;
|
|
785
792
|
} : T;
|
|
786
793
|
|
|
787
794
|
export type JSONSerialized<T> = SubdocsToPOJOs<
|