Skip to content

Commit faecfd2

Browse files
Merge branch 'Automattic:master' into master
2 parents a63f599 + 59ed89e commit faecfd2

File tree

13 files changed

+123
-41
lines changed

13 files changed

+123
-41
lines changed

docs/compatibility.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
}
1212
</style>
1313

14-
Mongoose relies on the [MongoDB Node.js Driver](http://mongodb.github.io/node-mongodb-native/) to talk to MongoDB.
15-
You can refer to [this table](https://www.mongodb.com/docs/drivers/node/current/compatibility/) for up-to-date information as to which version of the MongoDB driver supports which version of MongoDB.
14+
Mongoose relies on the [MongoDB Node.js Driver](https://www.mongodb.com/docs/drivers/node/current/) to communicate with MongoDB.
1615

17-
Below are the [semver](http://semver.org/) ranges representing which versions of mongoose are compatible with the listed versions of MongoDB server.
16+
You can refer to [this table](https://www.mongodb.com/docs/drivers/compatibility/?driver-language=javascript&javascript-driver-framework=nodejs) for up-to-date information as to which version of the MongoDB driver supports which version of the MongoDB server.
17+
18+
Below are the [SemVer](http://semver.org/) ranges representing which versions of mongoose are compatible with the listed versions of MongoDB server.
1819

1920
| MongoDB Server | Mongoose |
2021
| :------------: | :--------------------------------------------: |
21-
| `8.x` | `^8.7.0 | ^9.0.0` |
22+
| `8.x` | `^8.7.0 \| ^9.0.0` |
2223
| `7.x` | `^7.4.0 \| ^8.0.0 \| ^9.0.0` |
2324
| `6.x` | `^7.0.0 \| ^8.0.0 \| ^9.0.0` |
2425
| `5.x` | `^6.0.0 \| ^7.0.0 \| ^8.0.0` |
@@ -27,4 +28,4 @@ Below are the [semver](http://semver.org/) ranges representing which versions of
2728
| `4.0.x` | `^6.0.0 \| ^7.0.0 \| ^8.0.0 <8.16.0` |
2829
| `3.6.x` | `^6.0.0 \| ^7.0.0 \| ^8.0.0 <8.8.0` |
2930

30-
Mongoose `^6.5.0` also works with MongoDB server 7.x. But not all new MongoDB server 7.x features are supported by Mongoose 6.x.
31+
Mongoose `^6.5.0` also works with MongoDB server 7.x. But not all new MongoDB server 7.x features are supported by Mongoose 6.x. To verify that your version of Mongoose is compatible based on the table above, use the [online SemVer checker](https://jubianchi.github.io/semver-check/#/).

docs/source/api.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ function processFile(props) {
269269
if ('constructor' in ctx && ctx.constructor === undefined) {
270270
ctx.constructorWasUndefined = true;
271271
}
272-
272+
if (!prop.tags) continue;
273273
for (const __tag of prop.tags) {
274274
// the following has been done, because otherwise no type could be applied for intellisense
275275
/** @type {TagObject} */

lib/connection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1782,7 +1782,7 @@ Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
17821782
};
17831783

17841784
/**
1785-
* Switches to a different database using the same [connection pool](https://mongoosejs.com/docs/api/connectionshtml#connection_pools).
1785+
* Switches to a different database using the same [connection pool](https://mongoosejs.com/docs/connections.html#connection_pools).
17861786
*
17871787
* Returns a new connection object, with the new db.
17881788
*

lib/helpers/model/castBulkWrite.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ module.exports.castUpdateOne = function castUpdateOne(originalModel, updateOne,
118118
if (model.schema.$timestamps != null && doInitTimestamps) {
119119
const createdAt = model.schema.$timestamps.createdAt;
120120
const updatedAt = model.schema.$timestamps.updatedAt;
121-
applyTimestampsToUpdate(now, createdAt, updatedAt, update, {});
121+
applyTimestampsToUpdate(now, createdAt, updatedAt, update, {
122+
timestamps: updateOne.timestamps
123+
});
122124
}
123125

124126
if (doInitTimestamps) {
@@ -150,7 +152,8 @@ module.exports.castUpdateOne = function castUpdateOne(originalModel, updateOne,
150152
strict: strict,
151153
upsert: updateOne.upsert,
152154
arrayFilters: updateOne.arrayFilters,
153-
overwriteDiscriminatorKey: updateOne.overwriteDiscriminatorKey
155+
overwriteDiscriminatorKey: updateOne.overwriteDiscriminatorKey,
156+
overwriteImmutable: updateOne.overwriteImmutable
154157
}, model, updateOne['filter']);
155158

156159
return updateOne;
@@ -185,7 +188,9 @@ module.exports.castUpdateMany = function castUpdateMany(originalModel, updateMan
185188
if (model.schema.$timestamps != null && doInitTimestamps) {
186189
const createdAt = model.schema.$timestamps.createdAt;
187190
const updatedAt = model.schema.$timestamps.updatedAt;
188-
applyTimestampsToUpdate(now, createdAt, updatedAt, updateMany['update'], {});
191+
applyTimestampsToUpdate(now, createdAt, updatedAt, updateMany['update'], {
192+
timestamps: updateMany.timestamps
193+
});
189194
}
190195
if (doInitTimestamps) {
191196
applyTimestampsToChildren(now, updateMany['update'], model.schema);
@@ -208,7 +213,8 @@ module.exports.castUpdateMany = function castUpdateMany(originalModel, updateMan
208213
strict: strict,
209214
upsert: updateMany.upsert,
210215
arrayFilters: updateMany.arrayFilters,
211-
overwriteDiscriminatorKey: updateMany.overwriteDiscriminatorKey
216+
overwriteDiscriminatorKey: updateMany.overwriteDiscriminatorKey,
217+
overwriteImmutable: updateMany.overwriteImmutable
212218
}, model, updateMany['filter']);
213219
};
214220

lib/utils.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ exports.deepEqual = function deepEqual(a, b) {
190190
*/
191191

192192
exports.last = function(arr) {
193+
if (arr == null) {
194+
return void 0;
195+
}
193196
if (arr.length > 0) {
194197
return arr[arr.length - 1];
195198
}
@@ -272,6 +275,10 @@ exports.clonePOJOsAndArrays = function clonePOJOsAndArrays(val) {
272275
exports.merge = function merge(to, from, options, path) {
273276
options = options || {};
274277

278+
if (from == null) {
279+
return to;
280+
}
281+
275282
const keys = Object.keys(from);
276283
let i = 0;
277284
const len = keys.length;
@@ -690,6 +697,9 @@ exports.setValue = function(path, val, obj, map, _copying) {
690697

691698
exports.object = {};
692699
exports.object.vals = function vals(o) {
700+
if (o == null) {
701+
return [];
702+
}
693703
const keys = Object.keys(o);
694704
let i = keys.length;
695705
const ret = [];

scripts/generateSearch.js

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,17 @@ function generateContents() {
6363
content.validateSync();
6464

6565
const $ = cheerio.load(text);
66-
6766
contents.push(content);
6867

69-
// Break up individual h3's into separate content for more fine grained search
68+
// Break up h3's into additional content entries
7069
$('h3').each((index, el) => {
7170
el = $(el);
7271
const title = el.text();
7372
const html = el.nextUntil('h3').html();
73+
74+
// *** FIXED: Skip empty HTML blocks ***
75+
if (!html || html.trim() === '') return;
76+
7477
const id = el.prop('id');
7578
const baseUrl = filename.replace('.md', '.html').replace(/^docs/, '');
7679
const content = new Content({
@@ -82,6 +85,7 @@ function generateContents() {
8285
content.validateSync();
8386
contents.push(content);
8487
});
88+
8589
} else if (file.guide) {
8690
let text = fs.readFileSync(filename, 'utf8');
8791
text = text.substring(text.indexOf('block content') + 'block content\n'.length);
@@ -96,14 +100,17 @@ function generateContents() {
96100
content.validateSync();
97101

98102
const $ = cheerio.load(text);
99-
100103
contents.push(content);
101104

102-
// Break up individual h3's into separate content for more fine grained search
105+
// Break up h3's into additional content entries
103106
$('h3').each((index, el) => {
104107
el = $(el);
105108
const title = el.text();
106109
const html = el.nextUntil('h3').html();
110+
111+
// *** FIXED: Skip empty HTML blocks ***
112+
if (!html || html.trim() === '') return;
113+
107114
const id = el.prop('id');
108115
const baseUrl = filename.replace('.pug', '.html').replace(/^docs/, '');
109116
const content = new Content({
@@ -137,56 +144,47 @@ async function generateSearch(config) {
137144

138145
const promises = [];
139146
let lastPrint = 0;
140-
141147
let doneCount = 0;
148+
142149
console.log('Search Content to save:', contents.length);
150+
143151
for (const content of contents) {
144-
if (version === '9.x') {
145-
let url = content.url.startsWith('/') ? content.url : `/${content.url}`;
146-
if (!url.startsWith('/docs')) {
147-
url = '/docs' + url;
148-
}
149-
content.url = url;
150-
} else {
151-
let url = content.url.startsWith('/') ? content.url : `/${content.url}`;
152-
if (!url.startsWith('/docs')) {
153-
url = '/docs' + url;
154-
}
155-
content.url = `/docs/${version}${url}`;
152+
let url = content.url.startsWith('/') ? content.url : `/${content.url}`;
153+
if (!url.startsWith('/docs')) {
154+
url = '/docs' + url;
156155
}
156+
content.url = version === '9.x' ? url : `/docs/${version}${url}`;
157+
157158
const promise = content.save().then(() => {
158159
doneCount += 1;
159160
const nowDate = Date.now();
160-
// only print every 2 seconds, or if it is the first or last element
161161
if (nowDate - lastPrint > 2000 || doneCount === contents.length || doneCount === 1) {
162162
lastPrint = nowDate;
163163
console.log(`${doneCount} / ${contents.length}`);
164164
}
165165
});
166+
166167
promises.push(promise);
167168
}
168169

169170
await Promise.allSettled(promises);
170171

171-
const results = await Content.
172-
find({ $text: { $search: 'validate' }, version }, { score: { $meta: 'textScore' } }).
173-
sort({ score: { $meta: 'textScore' } }).
174-
limit(10);
172+
const results = await Content
173+
.find({ $text: { $search: 'validate' }, version }, { score: { $meta: 'textScore' } })
174+
.sort({ score: { $meta: 'textScore' } })
175+
.limit(10);
175176

176177
console.log(results.map(res => res.url));
177178

178179
console.log(`Added ${contents.length} Search Content`);
179-
180-
// this likely should not be done as part of this script, but by the caller,
181-
// but this script is currently the only one that connects in the website generation.
182180
await mongoose.disconnect();
183181
}
184182

185183
function getConfig() {
186184
const config = require('../.config.js');
187185

188186
if (!config || !config.uri) {
189-
throw new Error('No Config or config.URI given, please create a .config.js file with those values in the root of the repository');
187+
throw new Error('No Config or config.uri given, please create a .config.js file with those values in the root of the repository');
190188
}
191189

192190
return config;
@@ -195,7 +193,6 @@ function getConfig() {
195193
module.exports.generateSearch = generateSearch;
196194
module.exports.getConfig = getConfig;
197195

198-
// only run the following code if this file is the main module / entry file
199196
if (isMain) {
200197
(async function main() {
201198
const config = getConfig();

test/model.updateOne.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2680,6 +2680,36 @@ describe('model: updateOne: ', function() {
26802680
assert.equal(doc.age, 20);
26812681
});
26822682

2683+
it('overwriting immutable createdAt with bulkWrite (gh-15781)', async function() {
2684+
const start = new Date().valueOf();
2685+
const schema = Schema({
2686+
createdAt: {
2687+
type: mongoose.Schema.Types.Date,
2688+
immutable: true
2689+
},
2690+
name: String
2691+
}, { timestamps: true });
2692+
2693+
const Model = db.model('Test', schema);
2694+
2695+
await Model.create({ name: 'gh-15781' });
2696+
let doc = await Model.collection.findOne({ name: 'gh-15781' });
2697+
assert.ok(doc.createdAt.valueOf() >= start);
2698+
2699+
const createdAt = new Date('2011-06-01');
2700+
assert.ok(createdAt.valueOf() < start.valueOf());
2701+
await Model.bulkWrite([{
2702+
updateOne: {
2703+
filter: { _id: doc._id },
2704+
update: { name: 'gh-15781 update', createdAt },
2705+
overwriteImmutable: true,
2706+
timestamps: false
2707+
}
2708+
}]);
2709+
doc = await Model.collection.findOne({ name: 'gh-15781 update' });
2710+
assert.equal(doc.createdAt.valueOf(), createdAt.valueOf());
2711+
});
2712+
26832713
it('updates buffers with `runValidators` successfully (gh-8580)', async function() {
26842714
const Test = db.model('Test', Schema({
26852715
data: { type: Buffer, required: true }

test/types/connection.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,5 +167,6 @@ async function gh15359() {
167167
{ model: 'Test', name: 'updateOne', filter: { name: 'test4' }, update: { $set: { num: 'not a number' } } }
168168
], { ordered: false });
169169
expectType<number>(res3.insertedCount);
170+
expectError(res3.validationErrors);
170171
expectType<Error[] | undefined>(res3.mongoose?.validationErrors);
171172
}

test/types/document.test.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,6 @@ function gh11085(): void {
166166

167167
const newUser = new UserModel();
168168

169-
let _id: number;
170-
expectError(_id = newUser._id);
171169
const _id2: Types.ObjectId = newUser._id;
172170
}
173171

test/types/queries.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,3 +826,17 @@ function gh15671() {
826826
};
827827
};
828828
}
829+
830+
async function gh15786() {
831+
interface IDoc {
832+
nmae: string;
833+
}
834+
835+
interface DocStatics {
836+
m1(): void;
837+
m2(): void;
838+
}
839+
840+
const schema = new Schema<IDoc, Model<IDoc>, {}, {}, {}, DocStatics>({});
841+
schema.static({ m1() {} } as DocStatics);
842+
}

0 commit comments

Comments
 (0)