Skip to content

Commit

Permalink
Merge branch '7.0' into vkarpov15/gh-12638
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Dec 28, 2022
2 parents a906650 + 13bb983 commit 90d7e45
Show file tree
Hide file tree
Showing 16 changed files with 264 additions and 177 deletions.
25 changes: 16 additions & 9 deletions docs/js/navbar-search.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
document.getElementById('search-button-nav').onclick = function() {
var q = document.getElementById('search-input-nav').value;
window.location.href = '/docs/search.html?q=' + encodeURIComponent(q);
};
(function() {
var versionFromUrl = window.location.pathname.match(/^\/docs\/(\d+\.x)/);
var version = versionFromUrl ? versionFromUrl[1] : defaultVersion;

var q = document.getElementById('search-input-nav').onkeyup = function(ev) {
if (ev.keyCode === 13) {
var searchPrefix = versionFromUrl ? '/docs/' + version + '/docs/' : '/docs/';

document.getElementById('search-button-nav').onclick = function() {
var q = document.getElementById('search-input-nav').value;
window.location.href = '/docs/search.html?q=' + encodeURIComponent(q);
}
};
window.location.href = searchPrefix + 'search.html?q=' + encodeURIComponent(q);
};

document.getElementById('search-input-nav').onkeyup = function(ev) {
if (ev.keyCode === 13) {
var q = document.getElementById('search-input-nav').value;
window.location.href = searchPrefix + 'search.html?q=' + encodeURIComponent(q);
}
};
})();
8 changes: 6 additions & 2 deletions docs/js/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,13 @@ for (var i = 0; i < pairs.length; ++i) {
}
}

var defaultVersion = '6.x';
var versionFromUrl = window.location.pathname.match(/^\/docs\/(\d+\.x)/);
var version = versionFromUrl ? versionFromUrl[1] : defaultVersion;

if (q != null) {
document.getElementById('search-input').value = decodeURIComponent(q);
fetch(root + '/search?search=' + q).
fetch(root + '/search?search=' + q + '&version=' + version).
then(function(res) { return res.json(); }).
then(
function(result) {
Expand All @@ -22,7 +26,7 @@ if (q != null) {
var html = '';
for (var i = 0; i < result.results.length; ++i) {
var res = result.results[i];
var url = res.url.replace(/^\//, '');
var url = res.url;
html += '<li>' +
'<a class="title" href="' + url + '">' +
res.title +
Expand Down
11 changes: 9 additions & 2 deletions docs/search.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,15 @@ async function run() {

await Content.deleteMany({ version });
for (const content of contents) {
if (version !== '6.x') {
content.url = `/docs/${version}/docs${content.url}`;
if (version === '6.x') {
let url = content.url.startsWith('/') ? content.url : `/${content.url}`;
if (!url.startsWith('/docs')) {
url = '/docs' + url;
}
content.url = url;
} else {
const url = content.url.startsWith('/') ? content.url : `/${content.url}`;
content.url = `/docs/${version}/docs${url}`;
}
await content.save();
}
Expand Down
24 changes: 16 additions & 8 deletions docs/typescript/schemas.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
# Schemas in TypeScript

Mongoose [schemas](../guide.html) are how you tell Mongoose what your documents look like.
Mongoose schemas are separate from TypeScript interfaces, so you need to define both a _document interface_ and a _schema_ until V6.3.1.
Mongoose supports auto typed schemas so you don't need to define additional typescript interface anymore but you are still able to do so.
Mongoose provides a `InferSchemaType`, which infers the type of the auto typed schema document when needed.
Mongoose schemas are separate from TypeScript interfaces, so you need to either define both a _document interface_ and a _schema_; or rely on Mongoose to automatically infer the type from the schema definition.

`Until mongoose V6.3.1:`
### Separate document interface definition

```typescript
import { Schema } from 'mongoose';
Expand All @@ -25,7 +23,12 @@ const schema = new Schema<User>({
});
```

`another approach:`
By default, Mongoose does **not** check if your document interface lines up with your schema.
For example, the above code won't throw an error if `email` is optional in the document interface, but `required` in `schema`.

### Automatic type inference

Mongoose can also automatically infer the document type from your schema definition as follows.

```typescript
import { Schema, InferSchemaType } from 'mongoose';
Expand Down Expand Up @@ -53,11 +56,16 @@ type User = InferSchemaType<typeof schema>;
// avatar?: string;
// }


// `UserModel` will have `name: string`, etc.
const UserModel = mongoose.model('User', schema);
```

By default, Mongoose does **not** check if your document interface lines up with your schema.
For example, the above code won't throw an error if `email` is optional in the document interface, but `required` in `schema`.
There are a few caveats for using automatic type inference:

1. You need to set `strictNullChecks: true` or `strict: true` in your `tsconfig.json`. Or, if you're setting flags at the command line, `--strictNullChecks` or `--strict`. There are [known issues](https:/Automattic/mongoose/issues/12420) with automatic type inference with strict mode disabled.
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.

If automatic type inference doesn't work for you, you can always fall back to document interface definitions.

## Generic parameters

Expand Down
3 changes: 3 additions & 0 deletions lib/helpers/model/discriminator.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const Mixed = require('../../schema/mixed');
const applyBuiltinPlugins = require('../schema/applyBuiltinPlugins');
const clone = require('../clone');
const defineKey = require('../document/compile').defineKey;
const get = require('../get');
Expand Down Expand Up @@ -41,6 +42,8 @@ module.exports = function discriminator(model, name, schema, tiedValue, applyPlu
model.base._applyPlugins(schema, {
skipTopLevel: !applyPluginsToDiscriminators
});
} else if (!mergeHooks) {
applyBuiltinPlugins(schema);
}

const key = model.schema.options.discriminatorKey;
Expand Down
12 changes: 12 additions & 0 deletions lib/helpers/schema/applyBuiltinPlugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
'use strict';

const builtinPlugins = require('../../plugins');

module.exports = function applyBuiltinPlugins(schema) {
for (const plugin of Object.values(builtinPlugins)) {
plugin(schema, { deduplicate: true });
}
schema.plugins = Object.values(builtinPlugins).
map(fn => ({ fn, opts: { deduplicate: true } })).
concat(schema.plugins);
};
14 changes: 2 additions & 12 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,17 @@ const Types = require('./types');
const Query = require('./query');
const Model = require('./model');
const applyPlugins = require('./helpers/schema/applyPlugins');
const builtinPlugins = require('./plugins');
const driver = require('./driver');
const promiseOrCallback = require('./helpers/promiseOrCallback');
const legacyPluralize = require('./helpers/pluralize');
const utils = require('./utils');
const pkg = require('../package.json');
const cast = require('./cast');
const removeSubdocs = require('./plugins/removeSubdocs');
const saveSubdocs = require('./plugins/saveSubdocs');
const trackTransaction = require('./plugins/trackTransaction');
const validateBeforeSave = require('./plugins/validateBeforeSave');

const Aggregate = require('./aggregate');
const PromiseProvider = require('./promise_provider');
const printStrictQueryWarning = require('./helpers/printStrictQueryWarning');
const shardingPlugin = require('./plugins/sharding');
const trusted = require('./helpers/query/trusted').trusted;
const sanitizeFilter = require('./helpers/query/sanitizeFilter');
const isBsonType = require('./helpers/isBsonType');
Expand Down Expand Up @@ -108,13 +104,7 @@ function Mongoose(options) {
configurable: false,
enumerable: true,
writable: false,
value: [
[saveSubdocs, { deduplicate: true }],
[validateBeforeSave, { deduplicate: true }],
[shardingPlugin, { deduplicate: true }],
[removeSubdocs, { deduplicate: true }],
[trackTransaction, { deduplicate: true }]
]
value: Object.values(builtinPlugins).map(plugin => ([plugin, { deduplicate: true }]))
});
}

Expand Down
7 changes: 6 additions & 1 deletion lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ const castBulkWrite = require('./helpers/model/castBulkWrite');
const clone = require('./helpers/clone');
const createPopulateQueryFilter = require('./helpers/populate/createPopulateQueryFilter');
const getDefaultBulkwriteResult = require('./helpers/getDefaultBulkwriteResult');
const getSchemaDiscriminatorByValue = require('./helpers/discriminator/getSchemaDiscriminatorByValue');
const discriminator = require('./helpers/model/discriminator');
const firstKey = require('./helpers/firstKey');
const each = require('./helpers/each');
Expand Down Expand Up @@ -4475,7 +4476,11 @@ Model.validate = function validate(obj, pathsToValidate, context, callback) {
}

return this.db.base._promiseOrCallback(callback, cb => {
const schema = this.schema;
let schema = this.schema;
const discriminatorKey = schema.options.discriminatorKey;
if (schema.discriminators != null && obj != null && obj[discriminatorKey] != null) {
schema = getSchemaDiscriminatorByValue(schema, obj[discriminatorKey]) || schema;
}
let paths = Object.keys(schema.paths);

if (pathsToValidate != null) {
Expand Down
28 changes: 0 additions & 28 deletions lib/plugins/clearValidating.js

This file was deleted.

7 changes: 7 additions & 0 deletions lib/plugins/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

exports.removeSubdocs = require('./removeSubdocs');
exports.saveSubdocs = require('./saveSubdocs');
exports.sharding = require('./sharding');
exports.trackTransaction = require('./trackTransaction');
exports.validateBeforeSave = require('./validateBeforeSave');
3 changes: 3 additions & 0 deletions lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,9 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
if (options.hasOwnProperty('strict')) {
childSchemaOptions.strict = options.strict;
}
if (options.hasOwnProperty('strictQuery')) {
childSchemaOptions.strictQuery = options.strictQuery;
}

if (this._userProvidedOptions.hasOwnProperty('_id')) {
childSchemaOptions._id = this._userProvidedOptions._id;
Expand Down
24 changes: 24 additions & 0 deletions test/model.discriminator.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2077,4 +2077,28 @@ describe('model', function() {
schema.pre('save', function testHook12604() {});
}
});

it('applies built-in plugins if mergePlugins and mergeHooks disabled (gh-12696) (gh-12604)', async function() {
const shapeDef = { name: String };
const shapeSchema = Schema(shapeDef, { discriminatorKey: 'kind' });

const Shape = db.model('Test', shapeSchema);

let subdocSaveCalls = 0;
const nestedSchema = Schema({ test: String });
nestedSchema.pre('save', function() {
++subdocSaveCalls;
});

const squareSchema = Schema({ ...shapeDef, nested: nestedSchema });
const Square = Shape.discriminator(
'Square',
squareSchema,
{ mergeHooks: false, mergePlugins: false }
);

assert.equal(subdocSaveCalls, 0);
await Square.create({ nested: { test: 'foo' } });
assert.equal(subdocSaveCalls, 1);
});
});
Loading

0 comments on commit 90d7e45

Please sign in to comment.