mongoose 6.6.7 → 6.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,329 @@
1
+ /*!
2
+ * Module dependencies.
3
+ */
4
+
5
+ 'use strict';
6
+
7
+ const MongooseBuffer = require('../types/buffer');
8
+ const SchemaType = require('../schematype');
9
+ const CastError = SchemaType.CastError;
10
+ const utils = require('../utils');
11
+ const isBsonType = require('../helpers/isBsonType');
12
+ const handleBitwiseOperator = require('./operators/bitwise');
13
+
14
+ const UUID_FORMAT = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}/i;
15
+ const Binary = MongooseBuffer.Binary;
16
+
17
+ /**
18
+ * Helper function to convert the input hex-string to a buffer
19
+ * @param {String} hex The hex string to convert
20
+ * @returns {Buffer} The hex as buffer
21
+ * @api private
22
+ */
23
+
24
+ function hex2buffer(hex) {
25
+ // use buffer built-in function to convert from hex-string to buffer
26
+ const buff = Buffer.from(hex, 'hex');
27
+ return buff;
28
+ }
29
+
30
+ /**
31
+ * Helper function to convert the buffer input to a string
32
+ * @param {Buffer} buf The buffer to convert to a hex-string
33
+ * @returns {String} The buffer as a hex-string
34
+ * @api private
35
+ */
36
+
37
+ function binary2hex(buf) {
38
+ // use buffer built-in function to convert from buffer to hex-string
39
+ const hex = buf.toString('hex');
40
+ return hex;
41
+ }
42
+
43
+ /**
44
+ * Convert a String to Binary
45
+ * @param {String} uuidStr The value to process
46
+ * @returns {MongooseBuffer} The binary to store
47
+ * @api private
48
+ */
49
+
50
+ function stringToBinary(uuidStr) {
51
+ // Protect against undefined & throwing err
52
+ if (typeof uuidStr !== 'string') uuidStr = '';
53
+ const hex = uuidStr.replace(/[{}-]/g, ''); // remove extra characters
54
+ const bytes = hex2buffer(hex);
55
+ const buff = new MongooseBuffer(bytes);
56
+ buff._subtype = 4;
57
+
58
+ return buff;
59
+ }
60
+
61
+ /**
62
+ * Convert binary to a uuid string
63
+ * @param {Buffer|Binary|String} uuidBin The value to process
64
+ * @returns {String} The completed uuid-string
65
+ * @api private
66
+ */
67
+ function binaryToString(uuidBin) {
68
+ // i(hasezoey) dont quite know why, but "uuidBin" may sometimes also be the already processed string
69
+ let hex;
70
+ if (typeof uuidBin !== 'string') {
71
+ hex = binary2hex(uuidBin);
72
+ const uuidStr = hex.substring(0, 8) + '-' + hex.substring(8, 8 + 4) + '-' + hex.substring(12, 12 + 4) + '-' + hex.substring(16, 16 + 4) + '-' + hex.substring(20, 20 + 12);
73
+ return uuidStr;
74
+ }
75
+ return uuidBin;
76
+ }
77
+
78
+ /**
79
+ * UUIDv1 SchemaType constructor.
80
+ *
81
+ * @param {String} key
82
+ * @param {Object} options
83
+ * @inherits SchemaType
84
+ * @api public
85
+ */
86
+
87
+ function SchemaUUID(key, options) {
88
+ SchemaType.call(this, key, options, 'UUID');
89
+ this.getters.push(binaryToString);
90
+ }
91
+
92
+ /**
93
+ * This schema type's name, to defend against minifiers that mangle
94
+ * function names.
95
+ *
96
+ * @api public
97
+ */
98
+ SchemaUUID.schemaName = 'UUID';
99
+
100
+ SchemaUUID.defaultOptions = {};
101
+
102
+ /*!
103
+ * Inherits from SchemaType.
104
+ */
105
+ SchemaUUID.prototype = Object.create(SchemaType.prototype);
106
+ SchemaUUID.prototype.constructor = SchemaUUID;
107
+
108
+ /*!
109
+ * ignore
110
+ */
111
+
112
+ SchemaUUID._cast = function(value) {
113
+ if (value === null) {
114
+ return value;
115
+ }
116
+
117
+ function newBuffer(initbuff) {
118
+ const buff = new MongooseBuffer(initbuff);
119
+ buff._subtype = 4;
120
+ return buff;
121
+ }
122
+
123
+ if (typeof value === 'string') {
124
+ if (UUID_FORMAT.test(value)) {
125
+ return stringToBinary(value);
126
+ } else {
127
+ throw new CastError(SchemaUUID.schemaName, value, this.path);
128
+ }
129
+ }
130
+
131
+ if (Buffer.isBuffer(value)) {
132
+ return newBuffer(value);
133
+ }
134
+
135
+ if (value instanceof Binary) {
136
+ return newBuffer(value.value(true));
137
+ }
138
+
139
+ // Re: gh-647 and gh-3030, we're ok with casting using `toString()`
140
+ // **unless** its the default Object.toString, because "[object Object]"
141
+ // doesn't really qualify as useful data
142
+ if (value.toString && value.toString !== Object.prototype.toString) {
143
+ if (UUID_FORMAT.test(value.toString())) {
144
+ return stringToBinary(value.toString());
145
+ }
146
+ }
147
+
148
+ throw new CastError(SchemaUUID.schemaName, value, this.path);
149
+ };
150
+
151
+ /**
152
+ * Sets a default option for all UUID instances.
153
+ *
154
+ * #### Example:
155
+ *
156
+ * // Make all UUIDs have `required` of true by default.
157
+ * mongoose.Schema.UUID.set('required', true);
158
+ *
159
+ * const User = mongoose.model('User', new Schema({ test: mongoose.UUID }));
160
+ * new User({ }).validateSync().errors.test.message; // Path `test` is required.
161
+ *
162
+ * @param {String} option The option you'd like to set the value for
163
+ * @param {Any} value value for option
164
+ * @return {undefined}
165
+ * @function set
166
+ * @static
167
+ * @api public
168
+ */
169
+
170
+ SchemaUUID.set = SchemaType.set;
171
+
172
+ /**
173
+ * Get/set the function used to cast arbitrary values to UUIDs.
174
+ *
175
+ * #### Example:
176
+ *
177
+ * // Make Mongoose refuse to cast UUIDs with 0 length
178
+ * const original = mongoose.Schema.Types.UUID.cast();
179
+ * mongoose.UUID.cast(v => {
180
+ * assert.ok(typeof v === "string" && v.length > 0);
181
+ * return original(v);
182
+ * });
183
+ *
184
+ * // Or disable casting entirely
185
+ * mongoose.UUID.cast(false);
186
+ *
187
+ * @param {Function} [caster]
188
+ * @return {Function}
189
+ * @function get
190
+ * @static
191
+ * @api public
192
+ */
193
+
194
+ SchemaUUID.cast = function cast(caster) {
195
+ if (arguments.length === 0) {
196
+ return this._cast;
197
+ }
198
+ if (caster === false) {
199
+ caster = this._defaultCaster;
200
+ }
201
+ this._cast = caster;
202
+
203
+ return this._cast;
204
+ };
205
+
206
+ /*!
207
+ * ignore
208
+ */
209
+
210
+ SchemaUUID._checkRequired = v => v != null;
211
+
212
+ /**
213
+ * Override the function the required validator uses to check whether a string
214
+ * passes the `required` check.
215
+ *
216
+ * @param {Function} fn
217
+ * @return {Function}
218
+ * @function checkRequired
219
+ * @static
220
+ * @api public
221
+ */
222
+
223
+ SchemaUUID.checkRequired = SchemaType.checkRequired;
224
+
225
+ /**
226
+ * Check if the given value satisfies a required validator.
227
+ *
228
+ * @param {Any} value
229
+ * @return {Boolean}
230
+ * @api public
231
+ */
232
+
233
+ SchemaUUID.prototype.checkRequired = function checkRequired(value) {
234
+ return UUID_FORMAT.test(value);
235
+ };
236
+
237
+ /**
238
+ * Casts to UUID
239
+ *
240
+ * @param {Object} value
241
+ * @param {Object} doc
242
+ * @param {Boolean} init whether this is an initialization cast
243
+ * @api private
244
+ */
245
+
246
+ SchemaUUID.prototype.cast = function(value, doc, init) {
247
+ if (SchemaType._isRef(this, value, doc, init)) {
248
+ if (isBsonType(value, 'UUID')) {
249
+ return value;
250
+ }
251
+
252
+ return this._castRef(value, doc, init);
253
+ }
254
+
255
+ let castFn;
256
+ if (typeof this._castFunction === 'function') {
257
+ castFn = this._castFunction;
258
+ } else if (typeof this.constructor.cast === 'function') {
259
+ castFn = this.constructor.cast();
260
+ } else {
261
+ castFn = SchemaUUID.cast();
262
+ }
263
+
264
+ try {
265
+ return castFn(value);
266
+ } catch (error) {
267
+ throw new CastError(SchemaUUID.schemaName, value, this.path, error, this);
268
+ }
269
+ };
270
+
271
+ /*!
272
+ * ignore
273
+ */
274
+
275
+ function handleSingle(val) {
276
+ return this.cast(val);
277
+ }
278
+
279
+ /*!
280
+ * ignore
281
+ */
282
+
283
+ function handleArray(val) {
284
+ return val.map((m) => {
285
+ return this.cast(m);
286
+ });
287
+ }
288
+
289
+ SchemaUUID.prototype.$conditionalHandlers =
290
+ utils.options(SchemaType.prototype.$conditionalHandlers, {
291
+ $bitsAllClear: handleBitwiseOperator,
292
+ $bitsAnyClear: handleBitwiseOperator,
293
+ $bitsAllSet: handleBitwiseOperator,
294
+ $bitsAnySet: handleBitwiseOperator,
295
+ $all: handleArray,
296
+ $gt: handleSingle,
297
+ $gte: handleSingle,
298
+ $in: handleArray,
299
+ $lt: handleSingle,
300
+ $lte: handleSingle,
301
+ $ne: handleSingle,
302
+ $nin: handleArray
303
+ });
304
+
305
+ /**
306
+ * Casts contents for queries.
307
+ *
308
+ * @param {String} $conditional
309
+ * @param {any} val
310
+ * @api private
311
+ */
312
+
313
+ SchemaUUID.prototype.castForQuery = function($conditional, val) {
314
+ let handler;
315
+ if (arguments.length === 2) {
316
+ handler = this.$conditionalHandlers[$conditional];
317
+ if (!handler)
318
+ throw new Error('Can\'t use ' + $conditional + ' with UUID.');
319
+ return handler.call(this, val);
320
+ } else {
321
+ return this.cast($conditional);
322
+ }
323
+ };
324
+
325
+ /*!
326
+ * Module exports.
327
+ */
328
+
329
+ module.exports = SchemaUUID;
package/lib/schema.js CHANGED
@@ -170,17 +170,49 @@ function Schema(obj, options) {
170
170
  * @api private
171
171
  */
172
172
  function aliasFields(schema, paths) {
173
- paths = paths || Object.keys(schema.paths);
174
- for (const path of paths) {
175
- const options = get(schema.paths[path], 'options');
176
- if (options == null) {
173
+ for (const path of Object.keys(paths)) {
174
+ let alias = null;
175
+ if (paths[path] != null) {
176
+ alias = paths[path];
177
+ } else {
178
+ const options = get(schema.paths[path], 'options');
179
+ if (options == null) {
180
+ continue;
181
+ }
182
+
183
+ alias = options.alias;
184
+ }
185
+
186
+ if (!alias) {
177
187
  continue;
178
188
  }
179
189
 
180
190
  const prop = schema.paths[path].path;
181
- const alias = options.alias;
191
+ if (Array.isArray(alias)) {
192
+ for (const a of alias) {
193
+ if (typeof a !== 'string') {
194
+ throw new Error('Invalid value for alias option on ' + prop + ', got ' + a);
195
+ }
196
+
197
+ schema.aliases[a] = prop;
198
+
199
+ schema.
200
+ virtual(a).
201
+ get((function(p) {
202
+ return function() {
203
+ if (typeof this.get === 'function') {
204
+ return this.get(p);
205
+ }
206
+ return this[p];
207
+ };
208
+ })(prop)).
209
+ set((function(p) {
210
+ return function(v) {
211
+ return this.$set(p, v);
212
+ };
213
+ })(prop));
214
+ }
182
215
 
183
- if (!alias) {
184
216
  continue;
185
217
  }
186
218
 
@@ -659,9 +691,44 @@ Schema.prototype.add = function add(obj, prefix) {
659
691
  }
660
692
  }
661
693
 
662
- const addedKeys = Object.keys(obj).
663
- map(key => prefix ? prefix + key : key);
664
- aliasFields(this, addedKeys);
694
+ const aliasObj = Object.fromEntries(
695
+ Object.entries(obj).map(([key]) => ([prefix + key, null]))
696
+ );
697
+ aliasFields(this, aliasObj);
698
+ return this;
699
+ };
700
+
701
+ /**
702
+ * Add an alias for `path`. This means getting or setting the `alias`
703
+ * is equivalent to getting or setting the `path`.
704
+ *
705
+ * #### Example:
706
+ *
707
+ * const toySchema = new Schema({ n: String });
708
+ *
709
+ * // Make 'name' an alias for 'n'
710
+ * toySchema.alias('n', 'name');
711
+ *
712
+ * const Toy = mongoose.model('Toy', toySchema);
713
+ * const turboMan = new Toy({ n: 'Turbo Man' });
714
+ *
715
+ * turboMan.name; // 'Turbo Man'
716
+ * turboMan.n; // 'Turbo Man'
717
+ *
718
+ * turboMan.name = 'Turbo Man Action Figure';
719
+ * turboMan.n; // 'Turbo Man Action Figure'
720
+ *
721
+ * await turboMan.save(); // Saves { _id: ..., n: 'Turbo Man Action Figure' }
722
+ *
723
+ *
724
+ * @param {String} path real path to alias
725
+ * @param {String|String[]} alias the path(s) to use as an alias for `path`
726
+ * @return {Schema} the Schema instance
727
+ * @api public
728
+ */
729
+
730
+ Schema.prototype.alias = function alias(path, alias) {
731
+ aliasFields(this, { [path]: alias });
665
732
  return this;
666
733
  };
667
734
 
@@ -1106,6 +1173,7 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1106
1173
  // If this schema has an associated Mongoose object, use the Mongoose object's
1107
1174
  // copy of SchemaTypes re: gh-7158 gh-6933
1108
1175
  const MongooseTypes = this.base != null ? this.base.Schema.Types : Schema.Types;
1176
+ const Types = this.base != null ? this.base.Types : require('./types');
1109
1177
 
1110
1178
  if (!utils.isPOJO(obj) && !(obj instanceof SchemaTypeOptions)) {
1111
1179
  const constructorName = utils.getFunctionName(obj.constructor);
@@ -1240,6 +1308,10 @@ Schema.prototype.interpretAsType = function(path, obj, options) {
1240
1308
  name = 'Buffer';
1241
1309
  } else if (typeof type === 'function' || typeof type === 'object') {
1242
1310
  name = type.schemaName || utils.getFunctionName(type);
1311
+ } else if (type === Types.ObjectId) {
1312
+ name = 'ObjectId';
1313
+ } else if (type === Types.Decimal128) {
1314
+ name = 'Decimal128';
1243
1315
  } else {
1244
1316
  name = type == null ? '' + type : type.toString();
1245
1317
  }
@@ -1717,6 +1789,7 @@ Schema.prototype.post = function(name) {
1717
1789
  *
1718
1790
  * @param {Function} plugin The Plugin's callback
1719
1791
  * @param {Object} [opts] Options to pass to the plugin
1792
+ * @param {Boolean} [opts.deduplicate=false] If true, ignore duplicate plugins (same `fn` argument using `===`)
1720
1793
  * @see plugins /docs/plugins.html
1721
1794
  * @api public
1722
1795
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.6.7",
4
+ "version": "6.7.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "bson": "^4.6.5",
23
23
  "kareem": "2.4.1",
24
- "mongodb": "4.9.1",
24
+ "mongodb": "4.11.0",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "4.0.3",
27
27
  "ms": "2.1.3",
@@ -133,6 +133,9 @@ declare module 'mongoose' {
133
133
  /** Combines multiple aggregation pipelines. */
134
134
  facet(options: PipelineStage.Facet['$facet']): this;
135
135
 
136
+ /** Appends a new $fill operator to this aggregate pipeline */
137
+ fill(arg: PipelineStage.Fill['$fill']): this;
138
+
136
139
  /** Appends new custom $graphLookup operator(s) to this aggregate pipeline, performing a recursive search on a collection. */
137
140
  graphLookup(options: PipelineStage.GraphLookup['$graphLookup']): this;
138
141
 
@@ -1190,6 +1190,26 @@ declare module 'mongoose' {
1190
1190
  $last: Expression;
1191
1191
  }
1192
1192
 
1193
+ export interface LinearFill {
1194
+ /**
1195
+ * Fills null and missing fields in a window using linear interpolation based on surrounding field values.
1196
+ *
1197
+ * @version 5.3
1198
+ * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/linearFill
1199
+ */
1200
+ $linearFill: Expression
1201
+ }
1202
+
1203
+ export interface Locf {
1204
+ /**
1205
+ * Last observation carried forward. Sets values for null and missing fields in a window to the last non-null value for the field.
1206
+ *
1207
+ * @version 5.2
1208
+ * @see https://www.mongodb.com/docs/manual/reference/operator/aggregation/locf
1209
+ */
1210
+ $locf: Expression
1211
+ }
1212
+
1193
1213
  export interface Map {
1194
1214
  /**
1195
1215
  * Applies a subexpression to each element of an array and returns the array of resulting values in order. Accepts named parameters.
@@ -2745,6 +2765,8 @@ declare module 'mongoose' {
2745
2765
  Expression.First |
2746
2766
  Expression.Integral |
2747
2767
  Expression.Last |
2768
+ Expression.LinearFill |
2769
+ Expression.Locf |
2748
2770
  Expression.Max |
2749
2771
  Expression.Min |
2750
2772
  Expression.Push |
package/types/index.d.ts CHANGED
@@ -109,6 +109,7 @@ declare module 'mongoose' {
109
109
 
110
110
  /** Sets mongoose options */
111
111
  export function set<K extends keyof MongooseOptions>(key: K, value: MongooseOptions[K]): Mongoose;
112
+ export function set(options: { [K in keyof MongooseOptions]: MongooseOptions[K] }): Mongoose;
112
113
 
113
114
  /** The Mongoose version */
114
115
  export const version: string;
@@ -195,6 +196,12 @@ declare module 'mongoose' {
195
196
  /** Adds key path / schema type pairs to this schema. */
196
197
  add(obj: SchemaDefinition<SchemaDefinitionType<EnforcedDocType>> | Schema, prefix?: string): this;
197
198
 
199
+ /**
200
+ * Add an alias for `path`. This means getting or setting the `alias`
201
+ * is equivalent to getting or setting the `path`.
202
+ */
203
+ alias(path: string, alias: string | string[]): this;
204
+
198
205
  /**
199
206
  * Array of child schemas (from document arrays and single nested subdocs)
200
207
  * and their corresponding compiled models. Each element of the array is
@@ -31,14 +31,14 @@ declare module 'mongoose' {
31
31
 
32
32
  /**
33
33
  * @summary Obtains document schema type from Schema instance.
34
- * @param {SchemaType} SchemaType A generic of schema type instance.
34
+ * @param {Schema} TSchema `typeof` a schema instance.
35
35
  * @example
36
36
  * const userSchema = new Schema({userName:String});
37
37
  * type UserType = InferSchemaType<typeof userSchema>;
38
38
  * // result
39
39
  * type UserType = {userName?: string}
40
40
  */
41
- type InferSchemaType<SchemaType> = ObtainSchemaGeneric<SchemaType, 'DocType'>;
41
+ type InferSchemaType<TSchema> = ObtainSchemaGeneric<TSchema, 'DocType'>;
42
42
 
43
43
  /**
44
44
  * @summary Obtains schema Generic type by using generic alias.
@@ -65,7 +65,7 @@ declare module 'mongoose' {
65
65
  * @param {P} P Document path.
66
66
  * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
67
67
  */
68
- type IsPathRequired<P, TypeKey extends TypeKeyBaseType> =
68
+ type IsPathRequired<P, TypeKey extends TypeKeyBaseType = DefaultTypeKey> =
69
69
  P extends { required: true | [true, string | undefined] } | ArrayConstructor | any[]
70
70
  ? true
71
71
  : P extends (Record<TypeKey, ArrayConstructor | any[]>)
@@ -83,7 +83,7 @@ type IsPathRequired<P, TypeKey extends TypeKeyBaseType> =
83
83
  * @description It helps to check if a path is defined by TypeKey OR not.
84
84
  * @param {TypeKey} TypeKey A literal string refers to path type property key.
85
85
  */
86
- type PathWithTypePropertyBaseType<TypeKey extends TypeKeyBaseType> = { [k in TypeKey]: any };
86
+ type PathWithTypePropertyBaseType<TypeKey extends TypeKeyBaseType = DefaultTypeKey> = { [k in TypeKey]: any };
87
87
 
88
88
  /**
89
89
  * @summary A Utility to obtain schema's required path keys.
@@ -91,7 +91,7 @@ type PathWithTypePropertyBaseType<TypeKey extends TypeKeyBaseType> = { [k in Typ
91
91
  * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
92
92
  * @returns required paths keys of document definition.
93
93
  */
94
- type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType> = {
94
+ type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = {
95
95
  [K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? IfEquals<T[K], any, never, K> : never;
96
96
  }[keyof T];
97
97
 
@@ -101,7 +101,7 @@ type RequiredPathKeys<T, TypeKey extends TypeKeyBaseType> = {
101
101
  * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
102
102
  * @returns a record contains required paths with the corresponding type.
103
103
  */
104
- type RequiredPaths<T, TypeKey extends TypeKeyBaseType> = {
104
+ type RequiredPaths<T, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = {
105
105
  [K in RequiredPathKeys<T, TypeKey>]: T[K];
106
106
  };
107
107
 
@@ -111,7 +111,7 @@ type RequiredPaths<T, TypeKey extends TypeKeyBaseType> = {
111
111
  * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
112
112
  * @returns optional paths keys of document definition.
113
113
  */
114
- type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType> = {
114
+ type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = {
115
115
  [K in keyof T]: IsPathRequired<T[K], TypeKey> extends true ? never : K;
116
116
  }[keyof T];
117
117
 
@@ -121,7 +121,7 @@ type OptionalPathKeys<T, TypeKey extends TypeKeyBaseType> = {
121
121
  * @param {TypeKey} TypeKey A generic of literal string type."Refers to the property used for path type definition".
122
122
  * @returns a record contains optional paths with the corresponding type.
123
123
  */
124
- type OptionalPaths<T, TypeKey extends TypeKeyBaseType> = {
124
+ type OptionalPaths<T, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = {
125
125
  [K in OptionalPathKeys<T, TypeKey>]?: T[K];
126
126
  };
127
127
 
@@ -131,7 +131,7 @@ type OptionalPaths<T, TypeKey extends TypeKeyBaseType> = {
131
131
  * @param {PathValueType} PathValueType Document definition path type.
132
132
  * @param {TypeKey} TypeKey A generic refers to document definition.
133
133
  */
134
- type ObtainDocumentPathType<PathValueType, TypeKey extends TypeKeyBaseType> = PathValueType extends Schema<any>
134
+ type ObtainDocumentPathType<PathValueType, TypeKey extends TypeKeyBaseType = DefaultTypeKey> = PathValueType extends Schema<any>
135
135
  ? InferSchemaType<PathValueType>
136
136
  : ResolvePathType<
137
137
  PathValueType extends PathWithTypePropertyBaseType<TypeKey> ? PathValueType[TypeKey] : PathValueType,
@@ -154,19 +154,28 @@ type PathEnumOrString<T extends SchemaTypeOptions<string>['enum']> = T extends (
154
154
  */
155
155
  type ResolvePathType<PathValueType, Options extends SchemaTypeOptions<PathValueType> = {}, TypeKey extends TypeKeyBaseType = DefaultTypeKey> =
156
156
  PathValueType extends Schema ? InferSchemaType<PathValueType> :
157
- PathValueType extends (infer Item)[] ? IfEquals<Item, never, any[], Item extends Schema ? Types.DocumentArray<ResolvePathType<Item>> : ResolvePathType<Item>[]> :
157
+ PathValueType extends (infer Item)[] ? IfEquals<Item, never, any[], Item extends Schema ? Types.DocumentArray<ObtainDocumentPathType<Item, TypeKey>> : ObtainDocumentPathType<Item, TypeKey>[]> :
158
158
  PathValueType extends StringSchemaDefinition ? PathEnumOrString<Options['enum']> :
159
- PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
160
- PathValueType extends DateSchemaDefinition ? Date :
161
- PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
162
- PathValueType extends BooleanSchemaDefinition ? boolean :
163
- PathValueType extends ObjectIdSchemaDefinition ? Types.ObjectId :
164
- PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 :
165
- PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
166
- PathValueType extends ArrayConstructor ? any[] :
167
- PathValueType extends typeof Schema.Types.Mixed ? any:
168
- IfEquals<PathValueType, ObjectConstructor> extends true ? any:
169
- IfEquals<PathValueType, {}> extends true ? any:
170
- PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
171
- PathValueType extends Record<string, any> ? ObtainDocumentType<PathValueType, any, TypeKey> :
172
- unknown;
159
+ IfEquals<PathValueType, Schema.Types.String> extends true ? PathEnumOrString<Options['enum']> :
160
+ IfEquals<PathValueType, String> extends true ? PathEnumOrString<Options['enum']> :
161
+ PathValueType extends NumberSchemaDefinition ? Options['enum'] extends ReadonlyArray<any> ? Options['enum'][number] : number :
162
+ IfEquals<PathValueType, Schema.Types.Number> extends true ? number :
163
+ PathValueType extends DateSchemaDefinition ? Date :
164
+ IfEquals<PathValueType, Schema.Types.Date> extends true ? Date :
165
+ PathValueType extends typeof Buffer | 'buffer' | 'Buffer' | typeof Schema.Types.Buffer ? Buffer :
166
+ PathValueType extends BooleanSchemaDefinition ? boolean :
167
+ IfEquals<PathValueType, Schema.Types.Boolean> extends true ? boolean :
168
+ PathValueType extends ObjectIdSchemaDefinition ? Types.ObjectId :
169
+ IfEquals<PathValueType, Types.ObjectId> extends true ? Types.ObjectId :
170
+ IfEquals<PathValueType, Schema.Types.ObjectId> extends true ? Types.ObjectId :
171
+ PathValueType extends 'decimal128' | 'Decimal128' | typeof Schema.Types.Decimal128 ? Types.Decimal128 :
172
+ IfEquals<PathValueType, Schema.Types.Decimal128> extends true ? Types.Decimal128 :
173
+ IfEquals<PathValueType, Types.Decimal128> extends true ? Types.Decimal128 :
174
+ PathValueType extends MapConstructor ? Map<string, ResolvePathType<Options['of']>> :
175
+ PathValueType extends ArrayConstructor ? any[] :
176
+ PathValueType extends typeof Schema.Types.Mixed ? any:
177
+ IfEquals<PathValueType, ObjectConstructor> extends true ? any:
178
+ IfEquals<PathValueType, {}> extends true ? any:
179
+ PathValueType extends typeof SchemaType ? PathValueType['prototype'] :
180
+ PathValueType extends Record<string, any> ? ObtainDocumentType<PathValueType, any, TypeKey> :
181
+ unknown;
package/types/models.d.ts CHANGED
@@ -1,10 +1,17 @@
1
1
  declare module 'mongoose' {
2
2
  import mongodb = require('mongodb');
3
3
 
4
+ export interface DiscriminatorOptions {
5
+ value?: string | number | ObjectId;
6
+ clone?: boolean;
7
+ overwriteModels?: boolean;
8
+ mergeHooks?: boolean;
9
+ }
10
+
4
11
  export interface AcceptsDiscriminator {
5
12
  /** Adds a discriminator type. */
6
- discriminator<D>(name: string | number, schema: Schema, value?: string | number | ObjectId): Model<D>;
7
- discriminator<T, U>(name: string | number, schema: Schema<T, U>, value?: string | number | ObjectId): U;
13
+ discriminator<D>(name: string | number, schema: Schema, value?: string | number | ObjectId | DiscriminatorOptions): Model<D>;
14
+ discriminator<T, U>(name: string | number, schema: Schema<T, U>, value?: string | number | ObjectId | DiscriminatorOptions): U;
8
15
  }
9
16
 
10
17
  interface MongooseBulkWriteOptions {