Skip to content

Commit

Permalink
Merge branch '6.0' into gh-9840
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Feb 9, 2021
2 parents baf3938 + 0089566 commit cd12847
Show file tree
Hide file tree
Showing 31 changed files with 309 additions and 125 deletions.
23 changes: 23 additions & 0 deletions History.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
5.11.15 / 2021-02-03
====================
* fix(document): fix issues with `isSelected` as an path in a nested schema #9884 #9873 [IslandRhythms](https://github.com/IslandRhythms)
* fix(index.d.ts): better support for `SchemaDefinition` generics when creating schema #9863 #9862 #9789
* fix(index.d.ts): allow required function in array definition #9888 [Ugzuzg](https://github.com/Ugzuzg)
* fix(index.d.ts): reorder create typings to allow array desctructuring #9890 [Ugzuzg](https://github.com/Ugzuzg)
* fix(index.d.ts): add missing overload to Model.validate #9878 #9877 [jonamat](https://github.com/jonamat)
* fix(index.d.ts): throw compiler error if schema says path is a String, but interface says path is a number #9857
* fix(index.d.ts): make `Query` a class, allow calling `Query#where()` with object argument and with no arguments #9856
* fix(index.d.ts): support calling `Schema#pre()` and `Schema#post()` with options and array of hooked function names #9844
* docs(faq): mention other debug options than console #9887 [dandv](https://github.com/dandv)
* docs(connections): clarify that Mongoose can emit 'error' both during initial connection and after initial connection #9853

5.11.14 / 2021-01-28
====================
* fix(populate): avoid inferring `justOne` from parent when populating a POJO with a manually populated path #9833 [IslandRhythms](https://github.com/IslandRhythms)
* fix(document): apply setters on each element of the array when setting a populated array #9838
* fix(map): handle change tracking on maps of subdocs #9811 [IslandRhythms](https://github.com/IslandRhythms)
* fix(document): remove dependency on `documentIsSelected` symbol #9841 [IslandRhythms](https://github.com/IslandRhythms)
* fix(error): make ValidationError.toJSON to include the error name correctly #9849 [hanzki](https://github.com/hanzki)
* fix(index.d.ts): indicate that `Document#remove()` returns a promise, not a query #9826
* fix(index.d.ts): allow setting `SchemaType#enum` to TypeScript enum with `required: true` #9546

5.11.13 / 2021-01-20
====================
* fix(map): handle change tracking on map of arrays #9813
Expand Down
7 changes: 3 additions & 4 deletions docs/connections.pug
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ block content

There are two classes of errors that can occur with a Mongoose connection.

- Error on initial connection. If initial connection fails, Mongoose will **not** attempt to reconnect, it will emit an 'error' event, and the promise `mongoose.connect()` returns will reject.
- Error on initial connection. If initial connection fails, Mongoose will emit an 'error' event and the promise `mongoose.connect()` returns will reject. However, Mongoose will **not** automatically try to reconnect.
- Error after initial connection was established. Mongoose will attempt to reconnect, and it will emit an 'error' event.

To handle initial connection errors, you should use `.catch()` or `try/catch` with async/await.
Expand All @@ -145,9 +145,8 @@ block content
});
```

Note that the `error` event in the code above does not fire when mongoose loses
connection after the initial connection was established. You can listen to the
`disconnected` event for that purpose.
Note that Mongoose does not necessarily emit an 'error' event if it loses connectivity to MongoDB. You should
listen to the `disconnected` event to report when Mongoose is disconnected from MongoDB.

<h3 id="options"><a href="#options">Options</a></h3>

Expand Down
6 changes: 3 additions & 3 deletions docs/faq.pug
Original file line number Diff line number Diff line change
Expand Up @@ -293,9 +293,10 @@ block content

<a href="#enable_debugging">**Q**</a>. How can I enable debugging?

**A**. Set the `debug` option to `true`:
**A**. Set the `debug` option:

```javascript
// all executed methods log output to console
mongoose.set('debug', true)

// disable colors in debug mode
Expand All @@ -305,8 +306,7 @@ block content
mongoose.set('debug', { shell: true })
```

All executed collection methods will log output of their arguments to your
console.
For more debugging options (streams, callbacks), see the ['debug' option under `.set()`](./api.html#mongoose_Mongoose-set).


<hr id="callback_never_executes" />
Expand Down
Binary file added docs/images/fortunegames.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 46 additions & 19 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -630,11 +630,11 @@ declare module 'mongoose' {
countDocuments(filter: FilterQuery<T>, callback?: (err: any, count: number) => void): Query<number, T>;

/** Creates a new document or documents */
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents): Promise<T>;
create<DocContents = T | DocumentDefinition<T>>(docs: DocContents[], options?: SaveOptions): Promise<T[]>;
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents): Promise<T>;
create<DocContents = T | DocumentDefinition<T>>(...docs: DocContents[]): Promise<T[]>;
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents, callback: (err: CallbackError, doc: T) => void): void;
create<DocContents = T | DocumentDefinition<T>>(docs: DocContents[], callback: (err: CallbackError, docs: T[]) => void): void;
create<DocContents = T | DocumentDefinition<T>>(doc: DocContents, callback: (err: CallbackError, doc: T) => void): void;

/**
* Create the collection for this model. By default, if no indexes are specified,
Expand Down Expand Up @@ -753,6 +753,7 @@ declare module 'mongoose' {
/** Casts and validates the given object against this model's schema, passing the given `context` to custom validators. */
validate(callback?: (err: any) => void): Promise<void>;
validate(optional: any, callback?: (err: any) => void): Promise<void>;
validate(optional: any, pathsToValidate: string[], callback?: (err: any) => void): Promise<void>;

/** Watches the underlying collection for changes using [MongoDB change streams](https://docs.mongodb.com/manual/changeStreams/). */
watch(pipeline?: Array<Record<string, unknown>>, options?: mongodb.ChangeStreamOptions): mongodb.ChangeStream;
Expand Down Expand Up @@ -844,6 +845,8 @@ declare module 'mongoose' {

/** Creates a Query, applies the passed conditions, and returns the Query. */
where(path: string, val?: any): Query<Array<T>, T>;
where(obj: object): Query<Array<T>, T>;
where(): Query<Array<T>, T>;
}

interface QueryOptions {
Expand Down Expand Up @@ -1037,16 +1040,20 @@ declare module 'mongoose' {
useProjection?: boolean;
}

type MongooseDocumentMiddleware = 'validate' | 'save' | 'remove' | 'updateOne' | 'deleteOne' | 'init';
type MongooseQueryMiddleware = 'count' | 'deleteMany' | 'deleteOne' | 'find' | 'findOne' | 'findOneAndDelete' | 'findOneAndRemove' | 'findOneAndUpdate' | 'remove' | 'update' | 'updateOne' | 'updateMany';

class Schema<DocType extends Document = Document, M extends Model<DocType> = Model<DocType>> extends events.EventEmitter {
type SchemaPreOptions = { document?: boolean, query?: boolean };
type SchemaPostOptions = { document?: boolean, query?: boolean };

class Schema<DocType extends Document = Document, M extends Model<DocType> = Model<DocType>, SchemaDefinitionType = undefined> extends events.EventEmitter {
/**
* Create a new schema
*/
constructor(definition?: SchemaDefinition, options?: SchemaOptions);
constructor(definition?: SchemaDefinition<DocumentDefinition<SchemaDefinitionType>>, options?: SchemaOptions);

/** Adds key path / schema type pairs to this schema. */
add(obj: SchemaDefinition | Schema, prefix?: string): this;
add(obj: SchemaDefinition<DocumentDefinition<SchemaDefinitionType>> | Schema, prefix?: string): this;

/**
* Array of child schemas (from document arrays and single nested subdocs)
Expand Down Expand Up @@ -1113,21 +1120,33 @@ declare module 'mongoose' {
plugin(fn: (schema: Schema, opts?: any) => void, opts?: any): this;

/** Defines a post hook for the model. */
post<T extends Document = DocType>(method: 'validate' | 'save' | 'remove' | 'updateOne' | 'deleteOne' | 'init' | RegExp, fn: (this: T, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | string | RegExp, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, res: Array<any>, next: (err: CallbackError) => void) => void): this;
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: (this: T, res: Array<any>, next: (err: CallbackError) => void) => void): this;
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: (this: T, res: any, next: (err: CallbackError) => void) => void): this;

post<T extends Document = DocType>(method: 'validate' | 'save' | 'remove' | 'updateOne' | 'deleteOne' | 'init' | RegExp, fn: (this: T, err: NativeError, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | string | RegExp, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, err: NativeError, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err?: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, err: NativeError, res: Array<any>, next: (err: CallbackError) => void) => void): this;
post<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: Array<any>, next: (err: CallbackError) => void) => void): this;
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;
post<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPostOptions, fn: (this: T, err: NativeError, res: any, next: (err: CallbackError) => void) => void): this;

/** Defines a pre hook for the model. */
pre<T extends Document = DocType>(method: 'validate' | 'save' | 'remove' | 'updateOne' | 'deleteOne' | 'init' | RegExp, fn: (this: T, next: (err?: CallbackError) => void) => void): this;
pre<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | string | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, fn: (this: T, next: (err?: CallbackError) => void) => void): this;
pre<T extends Document = DocType>(method: MongooseDocumentMiddleware | MongooseDocumentMiddleware[] | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err?: CallbackError) => void) => void): this;
pre<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Query<any, any> = Query<any, any>>(method: MongooseQueryMiddleware | MongooseQueryMiddleware[] | string | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Aggregate<any> = Aggregate<any>>(method: 'aggregate' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, fn: (this: T, next: (err: CallbackError) => void) => void): this;
pre<T extends Model<DocType> = M>(method: 'insertMany' | RegExp, options: SchemaPreOptions, fn: (this: T, next: (err: CallbackError) => void) => void): this;

/** Object of currently defined query helpers on this schema. */
query: any;
Expand Down Expand Up @@ -1163,19 +1182,25 @@ declare module 'mongoose' {
virtualpath(name: string): VirtualType | null;
}

type SchemaDefinitionWithBuiltInClass<T> = T extends number
? (typeof Number | 'number' | 'Number')
: T extends string
? (typeof String | 'string' | 'String')
: (Function | string);

type SchemaDefinitionProperty<T = undefined> = SchemaTypeOptions<T extends undefined ? any : T> |
Function |
string |
Schema |
Schema[] |
SchemaDefinitionWithBuiltInClass<T> |
typeof SchemaType |
Schema<T extends Document ? T : Document<any>> |
Schema<T extends Document ? T : Document<any>>[] |
SchemaTypeOptions<T extends undefined ? any : T>[] |
Function[] |
SchemaDefinition<T> |
SchemaDefinition<T>[];

type SchemaDefinition<T = undefined> = T extends undefined
? { [path: string]: SchemaDefinitionProperty; }
: { [path in keyof T]-?: SchemaDefinitionProperty<T[path]>; };
: { [path in keyof T]?: SchemaDefinitionProperty<T[path]>; };

interface SchemaOptions {
/**
Expand Down Expand Up @@ -1340,7 +1365,7 @@ declare module 'mongoose' {
}

interface SchemaTypeOptions<T> {
type?: T;
type: T;

/** Defines a virtual with the given name that gets/sets this path. */
alias?: string;
Expand All @@ -1357,7 +1382,7 @@ declare module 'mongoose' {
* path cannot be set to a nullish value. If a function, Mongoose calls the
* function and only checks for nullish values if the function returns a truthy value.
*/
required?: boolean | (() => boolean) | [boolean, string];
required?: boolean | (() => boolean) | [boolean, string] | [() => boolean, string];

/**
* The default value for this path. If a function, Mongoose executes the function
Expand Down Expand Up @@ -1757,7 +1782,7 @@ declare module 'mongoose' {

type ReturnsNewDoc = { new: true } | { returnOriginal: false };

interface Query<ResultType, DocType extends Document> {
class Query<ResultType, DocType extends Document> {
_mongooseOptions: MongooseQueryOptions;

/** Executes the query */
Expand Down Expand Up @@ -2135,6 +2160,8 @@ declare module 'mongoose' {

/** Specifies a path for use with chaining. */
where(path: string, val?: any): this;
where(obj: object): this;
where(): this;

/** Defines a `$within` or `$geoWithin` argument for geo-spatial queries. */
within(val?: any): this;
Expand Down
4 changes: 2 additions & 2 deletions index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,8 @@ html(lang='en')
<a rel="sponsored" href="https://ghostinspector.com/">
<img class="sponsor" src="https://images.opencollective.com/ghostinspector/51b7be8/logo.png" style="height: 100px">
</a>
<a rel="sponsored" href="https://wongagames.co.uk/">
<img class="sponsor" src="https://images.opencollective.com/wongagames/d3eb92f/logo/256.png" style="height: 100px">
<a rel="sponsored" href="https://fortunegames.com/">
<img class="sponsor" src="/docs/images/fortunegames.jpg" style="height: 100px">
</a>
<a rel="sponsored" href="https://medium.com/@niksundin/best-web-design-companies-1872e445775f">
<img class="sponsor" src="https://images.opencollective.com/top-web-design-agencies/d92d747/logo.png" style="height: 100px">
Expand Down
6 changes: 3 additions & 3 deletions lib/aggregate.js
Original file line number Diff line number Diff line change
Expand Up @@ -1099,15 +1099,15 @@ function prepareDiscriminatorPipeline(aggregate) {
// If the first pipeline stage is a match and it doesn't specify a `__t`
// key, add the discriminator key to it. This allows for potential
// aggregation query optimizations not to be disturbed by this feature.
if (originalPipeline[0] && originalPipeline[0].$match && !originalPipeline[0].$match[discriminatorKey]) {
if (originalPipeline[0] != null && originalPipeline[0].$match && !originalPipeline[0].$match[discriminatorKey]) {
originalPipeline[0].$match[discriminatorKey] = discriminatorValue;
// `originalPipeline` is a ref, so there's no need for
// aggregate._pipeline = originalPipeline
} else if (originalPipeline[0] && originalPipeline[0].$geoNear) {
} else if (originalPipeline[0] != null && originalPipeline[0].$geoNear) {
originalPipeline[0].$geoNear.query =
originalPipeline[0].$geoNear.query || {};
originalPipeline[0].$geoNear.query[discriminatorKey] = discriminatorValue;
} else if (originalPipeline[0] && originalPipeline[0].$search) {
} else if (originalPipeline[0] != null && originalPipeline[0].$search) {
if (originalPipeline[1] && originalPipeline[1].$match != null) {
originalPipeline[1].$match[discriminatorKey] = originalPipeline[1].$match[discriminatorKey] || discriminatorValue;
} else {
Expand Down
9 changes: 5 additions & 4 deletions lib/cast.js
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,11 @@ module.exports = function cast(schema, obj, options, context) {
}
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
'schema, strict mode is `true`, and upsert is `true`.');
} else if (options.strictQuery === 'throw') {
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
'schema and strictQuery is \'throw\'.');
} else if (options.strictQuery) {
} else if (options.strict) {
if (options.strict === 'throw') {
throw new StrictModeError(path, 'Path "' + path + '" is not in ' +
'schema and strict is \'throw\'.');
}
delete obj[path];
}
} else if (val == null) {
Expand Down
Loading

0 comments on commit cd12847

Please sign in to comment.