diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 7f907742423..10df11dc592 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-20.04 name: Benchmark TypeScript Types steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: fetch-depth: 0 - name: Setup node diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ebec4f60e06..efa77ce7fa8 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -21,7 +21,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 8596c0348b4..0fcf2297d28 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest name: Lint Markdown files steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 @@ -48,7 +48,7 @@ jobs: runs-on: ubuntu-20.04 name: Test Generating Docs steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - run: git fetch --depth=1 --tags # download all tags for documentation - name: Setup node diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 90e47fc07e1..d6ff049078a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: runs-on: ubuntu-latest name: Lint JS-Files steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 @@ -58,7 +58,7 @@ jobs: MONGOMS_PREFER_GLOBAL_PATH: 1 FORCE_COLOR: true steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 @@ -94,7 +94,7 @@ jobs: MONGOMS_PREFER_GLOBAL_PATH: 1 FORCE_COLOR: true steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: @@ -122,7 +122,7 @@ jobs: env: FORCE_COLOR: true steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: @@ -139,6 +139,6 @@ jobs: contents: read steps: - name: Check out repo - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Dependency review uses: actions/dependency-review-action@v4 diff --git a/.github/workflows/tidelift-alignment.yml b/.github/workflows/tidelift-alignment.yml index f3a213d1d8d..c151d9114ce 100644 --- a/.github/workflows/tidelift-alignment.yml +++ b/.github/workflows/tidelift-alignment.yml @@ -15,7 +15,7 @@ jobs: if: github.repository == 'Automattic/mongoose' steps: - name: Checkout - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 with: diff --git a/.github/workflows/tsd.yml b/.github/workflows/tsd.yml index e7865152638..cc3d045454d 100644 --- a/.github/workflows/tsd.yml +++ b/.github/workflows/tsd.yml @@ -20,7 +20,7 @@ jobs: runs-on: ubuntu-latest name: Lint TS-Files steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 @@ -38,7 +38,7 @@ jobs: runs-on: ubuntu-latest name: Test Typescript Types steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - name: Setup node uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 707999f7c6d..1da05718451 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +8.4.5 / 2024-07-05 +================== + * types: correct this for validate.validator schematype option #14720 #14696 + * docs(model): note that insertMany() with lean skips applying defaults #14723 #14698 + 8.4.4 / 2024-06-25 ================== * perf: avoid unnecesary get() call and use faster approach for converting to string #14673 #14394 diff --git a/lib/model.js b/lib/model.js index f5de6fb8ead..85393e5cc6d 100644 --- a/lib/model.js +++ b/lib/model.js @@ -3122,16 +3122,23 @@ Model.startSession = function() { * * #### Example: * - * await Movies.insertMany([ + * const docs = await Movies.insertMany([ * { name: 'Star Wars' }, * { name: 'The Empire Strikes Back' } * ]); + * docs[0].name; // 'Star Wars' + * + * // Return raw result from MongoDB + * const result = await Movies.insertMany([ + * { name: 'Star Wars' }, + * { name: 'The Empire Strikes Back' } + * ], { rawResult: true }); * * @param {Array|Object|*} doc(s) * @param {Object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/4.9/classes/Collection.html#insertMany) * @param {Boolean} [options.ordered=true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an "unordered" `insertMany()`. * @param {Boolean} [options.rawResult=false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/4.9/interfaces/InsertManyResult.html) with a `mongoose` property that contains `validationErrors` and `results` if this is an unordered `insertMany`. - * @param {Boolean} [options.lean=false] if `true`, skips hydrating the documents. This means Mongoose will **not** cast or validate any of the documents passed to `insertMany()`. This option is useful if you need the extra performance, but comes with data integrity risk. Consider using with [`castObject()`](https://mongoosejs.com/docs/api/model.html#Model.castObject()). + * @param {Boolean} [options.lean=false] if `true`, skips hydrating the documents. This means Mongoose will **not** cast, validate, or apply defaults to any of the documents passed to `insertMany()`. This option is useful if you need the extra performance, but comes with data integrity risk. Consider using with [`castObject()`](https://mongoosejs.com/docs/api/model.html#Model.castObject()) and [`applyDefaults()`](https://mongoosejs.com/docs/api/model.html#Model.applyDefaults()). * @param {Number} [options.limit=null] this limits the number of documents being processed (validation/casting) by mongoose in parallel, this does **NOT** send the documents in batches to MongoDB. Use this option if you're processing a large number of documents and your app is running out of memory. * @param {String|Object|Array} [options.populate=null] populates the result documents. This option is a no-op if `rawResult` is set. * @param {Boolean} [options.throwOnValidationError=false] If true and `ordered: false`, throw an error if one of the operations failed validation, but all valid operations completed successfully. diff --git a/package.json b/package.json index 3fce3440e94..6dac516c46e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mongoose", "description": "Mongoose MongoDB ODM", - "version": "8.4.4", + "version": "8.4.5", "author": "Guillermo Rauch ", "keywords": [ "mongodb", @@ -28,10 +28,10 @@ "sift": "17.1.3" }, "devDependencies": { - "@babel/core": "7.24.6", - "@babel/preset-env": "7.24.6", - "@typescript-eslint/eslint-plugin": "^6.2.1", - "@typescript-eslint/parser": "^6.2.1", + "@babel/core": "7.24.7", + "@babel/preset-env": "7.24.7", + "@typescript-eslint/eslint-plugin": "^6.21.0", + "@typescript-eslint/parser": "^6.21.0", "acquit": "1.3.0", "acquit-ignore": "0.2.1", "acquit-require": "0.1.1", @@ -47,27 +47,27 @@ "eslint": "8.57.0", "eslint-plugin-markdown": "^5.0.0", "eslint-plugin-mocha-no-only": "1.2.0", - "express": "^4.18.1", + "express": "^4.19.2", "fs-extra": "~11.2.0", - "highlight.js": "11.8.0", + "highlight.js": "11.9.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.4.0", - "moment": "2.x", - "mongodb-memory-server": "9.3.0", + "mocha": "10.6.0", + "moment": "2.30.1", + "mongodb-memory-server": "9.4.0", "ncp": "^2.0.0", "nyc": "15.1.0", "pug": "3.0.3", "q": "1.5.1", "sinon": "18.0.0", "stream-browserify": "3.0.0", - "tsd": "0.31.0", - "typescript": "5.4.5", - "uuid": "9.0.1", - "webpack": "5.91.0" + "tsd": "0.31.1", + "typescript": "5.5.3", + "uuid": "10.0.0", + "webpack": "5.92.1" }, "directories": { "lib": "./lib/mongoose" diff --git a/test/types/schema.test.ts b/test/types/schema.test.ts index bbbcdd5d71f..9dab60d2022 100644 --- a/test/types/schema.test.ts +++ b/test/types/schema.test.ts @@ -18,7 +18,8 @@ import { SchemaType, Types, Query, - model + model, + ValidateOpts } from 'mongoose'; import { expectType, expectError, expectAssignable } from 'tsd'; import { ObtainDocumentPathType, ResolvePathType } from '../../types/inferschematype'; @@ -1511,3 +1512,46 @@ function gh13772() { const doc = new TestModel(); expectAssignable(doc.toObject()); } + +function gh14696() { + interface User { + name: string; + isActive: boolean; + isActiveAsync: boolean; + } + + const x: ValidateOpts = { + validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + }; + + const userSchema = new Schema({ + name: { + type: String, + required: [true, 'Name on card is required'] + }, + isActive: { + type: Boolean, + default: false, + validate: { + validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + } + }, + isActiveAsync: { + type: Boolean, + default: false, + validate: { + async validator(v: any) { + expectAssignable(this); + return !v || this.name === 'super admin'; + } + } + } + }); + +} diff --git a/types/schematypes.d.ts b/types/schematypes.d.ts index 778b83c7ad5..b7f1fc733b9 100644 --- a/types/schematypes.d.ts +++ b/types/schematypes.d.ts @@ -60,7 +60,7 @@ declare module 'mongoose' { alias?: string | string[]; /** Function or object describing how to validate this schematype. See [validation docs](https://mongoosejs.com/docs/validation.html). */ - validate?: SchemaValidator | AnyArray>; + validate?: SchemaValidator | AnyArray>; /** Allows overriding casting logic for this individual path. If a string, the given string overwrites Mongoose's default cast error message. */ cast?: string | diff --git a/types/validation.d.ts b/types/validation.d.ts index 488ead7e588..3310d954435 100644 --- a/types/validation.d.ts +++ b/types/validation.d.ts @@ -1,6 +1,6 @@ declare module 'mongoose' { - type SchemaValidator = RegExp | [RegExp, string] | Function | [Function, string] | ValidateOpts | ValidateOpts[]; + type SchemaValidator = RegExp | [RegExp, string] | Function | [Function, string] | ValidateOpts | ValidateOpts[]; interface ValidatorProps { path: string; @@ -13,23 +13,18 @@ declare module 'mongoose' { (props: ValidatorProps): string; } - interface ValidateFn { - (value: T, props?: ValidatorProps & Record): boolean; - } - - interface LegacyAsyncValidateFn { - (value: T, done: (result: boolean) => void): void; - } + type ValidateFn = + (this: EnforcedDocType, value: any, props?: ValidatorProps & Record) => boolean; - interface AsyncValidateFn { - (value: T, props?: ValidatorProps & Record): Promise; - } + type AsyncValidateFn = + (this: EnforcedDocType, value: any, props?: ValidatorProps & Record) => Promise; - interface ValidateOpts { + interface ValidateOpts { msg?: string; message?: string | ValidatorMessageFn; type?: string; - validator: ValidateFn | LegacyAsyncValidateFn | AsyncValidateFn; + validator: ValidateFn + | AsyncValidateFn; propsParameter?: boolean; } }