Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ module.exports = {
'!.*',
'node_modules',
'.git',
'data'
'data',
'.config'
],
overrides: [
{
Expand Down
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@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

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@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/encryption-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ jobs:
env:
FORCE_COLOR: true
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup node
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22
- name: Install Dependencies
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

Expand Down Expand Up @@ -61,7 +61,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: ${{ matrix.node }}

Expand Down Expand Up @@ -96,7 +96,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22
- name: Load MongoDB binary cache
Expand Down Expand Up @@ -124,7 +124,7 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22
- 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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22
- 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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

Expand All @@ -41,7 +41,7 @@ jobs:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

- name: Setup node
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
with:
node-version: 22

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,4 @@ list.out

data
*.pid
mo-expansion*
67 changes: 65 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
8.12.1 / 2025-03-04
===================
* fix: match bson version with mongodb's bson version #15297 [hasezoey](https://github.com/hasezoey)

8.12.0 / 2025-03-03
===================
* feat: bump mongodb driver to 6.14
* feat: expose "SchemaTypeOptions" in browser #15277 [hasezoey](https://github.com/hasezoey)
* docs: update field-level-encryption.md #15272 [dphrag](https://github.com/dphrag)

8.11.0 / 2025-02-26
===================
* feat(model): make bulkWrite results include MongoDB bulk write errors as well as validation errors #15271 #15265
* feat(document): add schemaFieldsOnly option to toObject() and toJSON() #15259 #15218
* feat: introduce populate ordered option for populating in series rather than in parallel for transactions #15239 #15231 #15210
* fix(bigint): throw error when casting BigInt that's outside of the bounds of what MongoDB can safely store #15230 #15200

8.10.2 / 2025-02-25
===================
* fix(model+connection): return MongoDB BulkWriteResult instance even if no valid ops #15266 #15265
* fix(debug): avoid printing trusted symbol in debug output #15267 #15263
* types: make type inference logic resilient to no Buffer type due to missing @types/node #15261

8.10.1 / 2025-02-14
===================
* perf(document): only call undoReset() 1x/document #15257 #15255
* perf(schema): clear childSchemas when overwriting existing path to avoid performance degradations #15256 #15253
* perf: some more micro optimizations for find() and findOne() #14906 #15250
* fix(model): avoid adding timeout on Model.init() buffering to avoid unintentional dangling open handles #15251 #15241
* fix: avoid connection buffering on init if autoCreate: false #15247 #15241
* fix: infer discriminator key if set in $set with overwriteDiscriminatorKey #15243 #15218
* types(middleware): make this in document middleware the hydrated doc type, not raw doc type #15246 #15242
* types(schema): support options parameter to Schema.prototype.discriminator() #15249 #15244
* types(schema): allow calling Schema.prototype.number() with no message arg #15237 #15236
* docs(typescript): recommend using HydratedSingleSubdocument over Types.Subdocument #15240 #15211

8.10.0 / 2025-02-05
===================
* feat(schema+schematype): add toJSONSchema() method to convert schemas and schematypes to JSON schema #15184 #11162
* feat(connection): make connection helpers respect bufferTimeoutMS #15229 #15201
* feat(document): support schematype-level transform option #15163 #15084
* feat(model): add insertOne() function to insert a single doc #15162 #14843
* feat(connection): support Connection.prototype.aggregate() for db-level aggregations #15153
* feat(model): make syncIndexes() not call createIndex() on indexes that already exist #15175 #12250
* feat(model): useConnection(connection) function #14802
* fix(model): disallow updateMany(update) and fix TypeScript types re: updateMany() #15199 #15190
* fix(collection): avoid buffering if creating a collection during a connection interruption #15187 #14971
* fix(model): throw error if calling create() with multiple docs in a transaction unless ordered: true #15100
* fix(model): skip createCollection() in syncIndexes() if autoCreate: false #15155
* fix(model): make `hydrate()` handle hydrating deeply nested populated docs with hydratedPopulatedDocs #15130
* types(document): make sure toObject() and toJSON() apply versionKey __v #15097
* ci(NODE-6505): CI Setup for Encryption Support #15139 [aditi-khare-mongoDB](https://github.com/aditi-khare-mongoDB)

8.9.7 / 2025-02-04
==================
* fix: avoid applying defaults on map embedded paths #15217 #15196
* types: add missing $median operator to aggregation types #15233 #15209
* docs(document): clarify that toObject() returns a POJO that may contain non-POJO values #15232 #15208

8.9.6 / 2025-01-31
==================
* fix(document): allow setting values to undefined with set(obj) syntax with strict: false #15207 #15192
* fix(schema): improve reason for UUID cast error, currently a TypeError #15215 #15202
* fix(aggregate): improve error when calling near() with invalid coordinates #15206 #15188

7.8.6 / 2025-01-20
===================
* chore: remove coverage output from bundle
Expand Down Expand Up @@ -94,8 +159,6 @@
* fix: disallow using $where in match
* perf: cache results from getAllSubdocs() on saveOptions, only loop through known subdoc properties #15055 #15029
* fix(model+query): support overwriteDiscriminatorKey for bulkWrite updateOne and updateMany, allow inferring discriminator key from update #15046 #15040
=======
>>>>>>> 7.x

7.8.3 / 2024-11-26
==================
Expand Down
57 changes: 53 additions & 4 deletions docs/field-level-encryption.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ Keep in mind that the following example is a simple example to help you get star
The encryption key in the following example is insecure; MongoDB recommends using a [KMS](https://www.mongodb.com/docs/v5.0/core/security-client-side-encryption-key-management/).

```javascript
const { ClientEncryption } = require('mongodb-client-encryption');
const { ClientEncryption } = require('mongodb');
const mongoose = require('mongoose');
const { Binary } = require('mongodb');

run().catch(err => console.log(err));

Expand All @@ -66,12 +65,14 @@ async function run() {
kmsProviders
}
}).asPromise();
const encryption = new ClientEncryption(conn.client, {
const encryption = new ClientEncryption(conn.getClient(), {
keyVaultNamespace,
kmsProviders,
});

const _key = await encryption.createDataKey('local');
const _key = await encryption.createDataKey('local', {
keyAltNames: ['exampleKeyName'],
});
}
```

Expand Down Expand Up @@ -112,3 +113,51 @@ With the above connection, if you create a model named 'Test' that uses the 'tes
const Model = mongoose.model('Test', mongoose.Schema({ name: String }));
await Model.create({ name: 'super secret' });
```

## Automatic FLE in Mongoose

Mongoose supports the declaration of encrypted schemas - schemas that, when connected to a model, utilize MongoDB's Client Side
Field Level Encryption or Queryable Encryption under the hood. Mongoose automatically generates either an `encryptedFieldsMap` or a
`schemaMap` when instantiating a MongoClient and encrypts fields on write and decrypts fields on reads.

### Encryption types

MongoDB has two different automatic encryption implementations: client side field level encryption (CSFLE) and queryable encryption (QE).
See [choosing an in-use encryption approach](https://www.mongodb.com/docs/v7.3/core/queryable-encryption/about-qe-csfle/#choosing-an-in-use-encryption-approach).

### Declaring Encrypted Schemas

The following schema declares two properties, `name` and `ssn`. `ssn` is encrypted using queryable encryption, and
is configured for equality queries:

```javascript
const encryptedUserSchema = new Schema({
name: String,
ssn: {
type: String,
// 1
encrypt: {
keyId: '<uuid string of key id>',
queries: 'equality'
}
}
// 2
}, { encryptionType: 'queryableEncryption' });
```

To declare a field as encrypted, you must:

1. Annotate the field with encryption metadata in the schema definition
2. Choose an encryption type for the schema and configure the schema for the encryption type

Not all schematypes are supported for CSFLE and QE. For an overview of valid schema types, refer to MongoDB's documentation.

### Registering Models

Encrypted schemas must be registered on a connection, not the Mongoose global:

```javascript

const connection = mongoose.createConnection();
const UserModel = connection.model('User', encryptedUserSchema);
```
20 changes: 10 additions & 10 deletions docs/schematypes.md
Original file line number Diff line number Diff line change
Expand Up @@ -654,16 +654,16 @@ typeof question.answer; // 'bigint'
### Double {#double}

Mongoose supports [64-bit IEEE 754-2008 floating point numbers](https://en.wikipedia.org/wiki/IEEE_754-2008_revision) as a SchemaType.
Int32s are stored as [BSON type "double" in MongoDB](https://www.mongodb.com/docs/manual/reference/bson-types/).
Doubles are stored as [BSON type "double" in MongoDB](https://www.mongodb.com/docs/manual/reference/bson-types/).

```javascript
const studentsSchema = new Schema({
id: Int32
const temperatureSchema = new Schema({
celsius: Double
});
const Student = mongoose.model('Student', schema);
const Temperature = mongoose.model('Temperature', temperatureSchema);

const student = new Temperature({ celsius: 1339 });
typeof student.id; // 'number'
const temperature = new Temperature({ celsius: 1339 });
temperature.celsius instanceof bson.Double; // true
```

There are several types of values that will be successfully cast to a Double.
Expand All @@ -673,7 +673,7 @@ new Temperature({ celsius: '1.2e12' }).celsius; // 15 as a Double
new Temperature({ celsius: true }).celsius; // 1 as a Double
new Temperature({ celsius: false }).celsius; // 0 as a Double
new Temperature({ celsius: { valueOf: () => 83.0033 } }).celsius; // 83 as a Double
new Temperature({ celsius: '' }).celsius; // null as a Double
new Temperature({ celsius: '' }).celsius; // null
```

The following inputs will result will all result in a [CastError](validation.html#cast-errors) once validated, meaning that it will not throw on initialization, only when validated:
Expand All @@ -688,12 +688,12 @@ Mongoose supports 32-bit integers as a SchemaType.
Int32s are stored as [32-bit integers in MongoDB (BSON type "int")](https://www.mongodb.com/docs/manual/reference/bson-types/).

```javascript
const studentsSchema = new Schema({
const studentSchema = new Schema({
id: Int32
});
const Student = mongoose.model('Student', schema);
const Student = mongoose.model('Student', studentSchema);

const student = new Temperature({ celsius: 1339 });
const student = new Student({ id: 1339 });
typeof student.id; // 'number'
```

Expand Down
6 changes: 5 additions & 1 deletion docs/typescript/subdocuments.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ Define a separate `THydratedDocumentType` and pass it as the 5th generic param t
`THydratedDocumentType` controls what type Mongoose uses for "hydrated documents", that is, what `await UserModel.findOne()`, `UserModel.hydrate()`, and `new UserModel()` return.

```ts
import { HydratedSingleSubdocument } from 'mongoose';

// Define property overrides for hydrated documents
type THydratedUserDocument = {
names?: mongoose.Types.Subdocument<Names>
names?: HydratedSingleSubdocument<Names>
}
type UserModelType = mongoose.Model<User, {}, {}, {}, THydratedUserDocument>;

Expand All @@ -51,6 +53,7 @@ const UserModel = mongoose.model<User, UserModelType>('User', userSchema);

const doc = new UserModel({ names: { _id: '0'.repeat(24), firstName: 'foo' } });
doc.names!.ownerDocument(); // Works, `names` is a subdocument!
doc.names!.firstName; // 'foo'
```

## Subdocument Arrays
Expand Down Expand Up @@ -81,4 +84,5 @@ const UserModel = model<User, UserModelType>('User', new Schema<User, UserModelT

const doc = new UserModel({});
doc.names[0].ownerDocument(); // Works!
doc.names[0].firstName; // string
```
12 changes: 12 additions & 0 deletions lib/aggregate.js
Original file line number Diff line number Diff line change
Expand Up @@ -397,11 +397,23 @@ Aggregate.prototype.project = function(arg) {
* @memberOf Aggregate
* @instance
* @param {Object} arg
* @param {Object|Array<Number>} arg.near GeoJSON point or coordinates array
* @return {Aggregate}
* @api public
*/

Aggregate.prototype.near = function(arg) {
if (arg == null) {
throw new MongooseError('Aggregate `near()` must be called with non-nullish argument');
}
if (arg.near == null) {
throw new MongooseError('Aggregate `near()` argument must have a `near` property');
}
const coordinates = Array.isArray(arg.near) ? arg.near : arg.near.coordinates;
if (typeof arg.near === 'object' && (!Array.isArray(coordinates) || coordinates.length < 2 || coordinates.find(c => typeof c !== 'number'))) {
throw new MongooseError(`Aggregate \`near()\` argument has invalid coordinates, got "${coordinates}"`);
}

const op = {};
op.$geoNear = arg;
return this.append(op);
Expand Down
9 changes: 9 additions & 0 deletions lib/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,15 @@ exports.VirtualType = require('./virtualType');

exports.SchemaType = require('./schemaType.js');

/**
* The constructor used for schematype options
*
* @method SchemaTypeOptions
* @api public
*/

exports.SchemaTypeOptions = require('./options/schemaTypeOptions');

/**
* Internal utils
*
Expand Down
Loading
Loading