Skip to content

Commit

Permalink
Merge branch '8.6' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 authored Aug 10, 2024
2 parents baf3ca2 + 80cd6a8 commit 50b26dc
Show file tree
Hide file tree
Showing 32 changed files with 249 additions and 50 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16

Expand All @@ -52,7 +52,7 @@ jobs:
- run: git fetch --depth=1 --tags # download all tags for documentation

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16

Expand Down
8 changes: 4 additions & 4 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 18

Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: ${{ matrix.node }}

Expand Down Expand Up @@ -96,7 +96,7 @@ jobs:
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16
- name: Load MongoDB binary cache
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16
- run: npm install
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/tidelift-alignment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16
- name: Alignment
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/tsd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 18

Expand All @@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7

- name: Setup node
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
with:
node-version: 16

Expand Down
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
8.5.2 / 2024-07-30
==================
* perf(clone): avoid further unnecessary checks if cloning a primitive value #14762 #14394
* fix: allow setting document array default to null #14769 #14717 #6691
* fix(model): support session: null option for save() to opt out of automatic session option with transactionAsyncLocalStorage #14744 #14736
* fix(model+document): avoid depopulating manually populated doc as getter value #14760 #14759
* fix: correct shardkey access in buildBulkWriteOps #14753 #14752 [adf0nt3s](https://github.com/adf0nt3s)
* fix(query): handle casting $switch in $expr #14755 #14751
* types: allow calling SchemaType.cast() without parent and init parameters #14756 #14748 #9076
* docs: fix a wrong example in v6 migration guide #14758 [abdelrahman-elkady](https://github.com/abdelrahman-elkady)

8.5.1 / 2024-07-12
==================
* perf(model): performance improvements for insertMany() #14724
Expand Down
2 changes: 2 additions & 0 deletions docs/typescript/schemas.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ There are a few caveats for using automatic type inference:
2. You need to define your schema in the `new Schema()` call. Don't assign your schema definition to a temporary variable. Doing something like `const schemaDefinition = { name: String }; const schema = new Schema(schemaDefinition);` will not work.
3. Mongoose adds `createdAt` and `updatedAt` to your schema if you specify the `timestamps` option in your schema, *except* if you also specify `methods`, `virtuals`, or `statics`. There is a [known issue](https://github.com/Automattic/mongoose/issues/12807) with type inference with timestamps and methods/virtuals/statics options. If you use methods, virtuals, and statics, you're responsible for adding `createdAt` and `updatedAt` to your schema definition.

If you must define your schema separately, use [as const](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions) (`const schemaDefinition = { ... } as const;`) to prevent *type widening*. TypeScript will automatically widen types like `required: false` to `required: boolean`, which will cause Mongoose to assume the field is required. Using `as const` forces TypeScript to retain these types.

If you need to explicitly get the raw document type (the value returned from `doc.toObject()`, `await Model.findOne().lean()`, etc.) from your schema definition, you can use Mongoose's `inferRawDocType` helper as follows:

```ts
Expand Down
20 changes: 20 additions & 0 deletions lib/cursor/queryCursor.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const eachAsync = require('../helpers/cursor/eachAsync');
const helpers = require('../queryHelpers');
const kareem = require('kareem');
const immediate = require('../helpers/immediate');
const { once } = require('node:events');
const util = require('util');

/**
Expand Down Expand Up @@ -135,6 +136,25 @@ QueryCursor.prototype._read = function() {
});
};

/**
* Returns the underlying cursor from the MongoDB Node driver that this cursor uses.
*
* @method getDriverCursor
* @memberOf QueryCursor
* @returns {Cursor} MongoDB Node driver cursor instance
* @instance
* @api public
*/

QueryCursor.prototype.getDriverCursor = async function getDriverCursor() {
if (this.cursor) {
return this.cursor;
}

await once(this, 'cursor');
return this.cursor;
};

/**
* Registers a transform function which subsequently maps documents retrieved
* via the streams interface or `.next()`
Expand Down
12 changes: 9 additions & 3 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -3801,7 +3801,7 @@ Document.prototype.$__handleReject = function handleReject(err) {
};

/**
* Internal helper for toObject() and toJSON() that doesn't manipulate options
* Internal common logic for toObject() and toJSON()
*
* @return {Object}
* @api private
Expand Down Expand Up @@ -3834,14 +3834,17 @@ Document.prototype.$toObject = function(options, json) {
}

const depopulate = options._calledWithOptions.depopulate
?? options._parentOptions?.depopulate
?? defaultOptions?.depopulate
?? options.depopulate
?? false;
// _isNested will only be true if this is not the top level document, we
// should never depopulate the top-level document
if (depopulate && options._isNested && this.$__.wasPopulated) {
return clone(this.$__.wasPopulated.value || this._doc._id, options);
}
if (depopulate) {
options.depopulate = true;
}

// merge default options with input options.
if (defaultOptions != null) {
Expand All @@ -3855,7 +3858,9 @@ Document.prototype.$toObject = function(options, json) {
options.json = json;
options.minimize = _minimize;

options._parentOptions = options;
const parentOptions = options._parentOptions;
// Parent options should only bubble down for subdocuments, not populated docs
options._parentOptions = this.$isSubdocument ? options : null;

options._skipSingleNestedGetters = false;
// remember the root transform function
Expand Down Expand Up @@ -3886,6 +3891,7 @@ Document.prototype.$toObject = function(options, json) {

const virtuals = options._calledWithOptions.virtuals
?? defaultOptions.virtuals
?? parentOptions?.virtuals
?? undefined;

if (virtuals || (getters && virtuals !== false)) {
Expand Down
8 changes: 6 additions & 2 deletions lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -2115,17 +2115,21 @@ Model.countDocuments = function countDocuments(conditions, options) {
*
* @param {String} field
* @param {Object} [conditions] optional
* @param {Object} [options] optional
* @return {Query}
* @api public
*/

Model.distinct = function distinct(field, conditions) {
Model.distinct = function distinct(field, conditions, options) {
_checkContext(this, 'distinct');
if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function') {
if (typeof arguments[0] === 'function' || typeof arguments[1] === 'function' || typeof arguments[2] === 'function') {
throw new MongooseError('Model.distinct() no longer accepts a callback');
}

const mq = new this.Query({}, {}, this, this.$__collection);
if (options != null) {
mq.setOptions(options);
}

return mq.distinct(field, conditions);
};
Expand Down
15 changes: 11 additions & 4 deletions lib/query.js
Original file line number Diff line number Diff line change
Expand Up @@ -2773,7 +2773,7 @@ Query.prototype.estimatedDocumentCount = function(options) {
this.op = 'estimatedDocumentCount';
this._validateOp();

if (typeof options === 'object' && options != null) {
if (options != null) {
this.setOptions(options);
}

Expand Down Expand Up @@ -2832,7 +2832,7 @@ Query.prototype.countDocuments = function(conditions, options) {
this.merge(conditions);
}

if (typeof options === 'object' && options != null) {
if (options != null) {
this.setOptions(options);
}

Expand Down Expand Up @@ -2870,21 +2870,24 @@ Query.prototype.__distinct = async function __distinct() {
*
* #### Example:
*
* distinct(field, conditions, options)
* distinct(field, conditions)
* distinct(field)
* distinct()
*
* @param {String} [field]
* @param {Object|Query} [filter]
* @param {Object} [options]
* @return {Query} this
* @see distinct https://www.mongodb.com/docs/manual/reference/method/db.collection.distinct/
* @api public
*/

Query.prototype.distinct = function(field, conditions) {
Query.prototype.distinct = function(field, conditions, options) {
if (typeof field === 'function' ||
typeof conditions === 'function' ||
typeof arguments[2] === 'function') {
typeof options === 'function' ||
typeof arguments[3] === 'function') {
throw new MongooseError('Query.prototype.distinct() no longer accepts a callback');
}

Expand All @@ -2903,6 +2906,10 @@ Query.prototype.distinct = function(field, conditions) {
this._distinct = field;
}

if (options != null) {
this.setOptions(options);
}

return this;
};

Expand Down
2 changes: 1 addition & 1 deletion lib/schema/documentArray.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function SchemaDocumentArray(key, schema, options, schemaOptions) {

const fn = this.defaultValue;

if (!('defaultValue' in this) || fn !== void 0) {
if (!('defaultValue' in this) || fn != null) {
this.default(function() {
let arr = fn.call(this);
if (arr != null && !Array.isArray(arr)) {
Expand Down
7 changes: 7 additions & 0 deletions lib/types/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,17 @@ class MongooseMap extends Map {
* and change tracking. Note that Mongoose maps _only_ support strings and
* ObjectIds as keys.
*
* Keys also cannot:
* - be named after special properties `prototype`, `constructor`, and `__proto__`
* - start with a dollar sign (`$`)
* - contain any dots (`.`)
*
* #### Example:
*
* doc.myMap.set('test', 42); // works
* doc.myMap.set({ obj: 42 }, 42); // Throws "Mongoose maps only support string keys"
* doc.myMap.set(10, 42); // Throws "Mongoose maps only support string keys"
* doc.myMap.set("$test", 42); // Throws "Mongoose maps do not support keys that start with "$", got "$test""
*
* @api public
* @method set
Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "mongoose",
"description": "Mongoose MongoDB ODM",
"version": "8.5.1",
"version": "8.5.2",
"author": "Guillermo Rauch <guillermo@learnboost.com>",
"keywords": [
"mongodb",
Expand Down Expand Up @@ -29,7 +29,7 @@
},
"devDependencies": {
"@babel/core": "7.24.7",
"@babel/preset-env": "7.24.7",
"@babel/preset-env": "7.25.3",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"acquit": "1.3.0",
Expand All @@ -49,13 +49,13 @@
"eslint-plugin-mocha-no-only": "1.2.0",
"express": "^4.19.2",
"fs-extra": "~11.2.0",
"highlight.js": "11.9.0",
"highlight.js": "11.10.0",
"lodash.isequal": "4.5.0",
"lodash.isequalwith": "4.4.0",
"markdownlint-cli2": "^0.13.0",
"marked": "4.3.0",
"mkdirp": "^3.0.1",
"mocha": "10.6.0",
"mocha": "10.7.0",
"moment": "2.30.1",
"mongodb-memory-server": "10.0.0",
"ncp": "^2.0.0",
Expand All @@ -65,9 +65,9 @@
"sinon": "18.0.0",
"stream-browserify": "3.0.0",
"tsd": "0.31.1",
"typescript": "5.5.3",
"typescript": "5.5.4",
"uuid": "10.0.0",
"webpack": "5.92.1"
"webpack": "5.93.0"
},
"directories": {
"lib": "./lib/mongoose"
Expand Down
19 changes: 19 additions & 0 deletions test/docs/transactions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,25 @@ describe('transactions', function() {
assert.deepEqual(fromDb, { name: 'Tyrion Lannister' });
});

it('distinct (gh-8006)', async function() {
const Character = db.model('gh8006_Character', new Schema({ name: String, rank: String }, { versionKey: false }));

const session = await db.startSession();

session.startTransaction();
await Character.create([{ name: 'Will Riker', rank: 'Commander' }, { name: 'Jean-Luc Picard', rank: 'Captain' }], { session });

let names = await Character.distinct('name', {}, { session });
assert.deepStrictEqual(names.sort(), ['Jean-Luc Picard', 'Will Riker']);

names = await Character.distinct('name', { rank: 'Captain' }, { session });
assert.deepStrictEqual(names.sort(), ['Jean-Luc Picard']);

// Undo both update and delete since doc should pull from `$session()`
await session.abortTransaction();
session.endSession();
});

it('save() with no changes (gh-8571)', async function() {
db.deleteModel(/Test/);
const Test = db.model('Test', Schema({ name: String }));
Expand Down
Loading

0 comments on commit 50b26dc

Please sign in to comment.