mongoose 9.5.0 → 9.6.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.
@@ -30,6 +30,7 @@ msg.DocumentNotFoundError = null;
30
30
  msg.general = {};
31
31
  msg.general.default = 'Validator failed for path `{PATH}` with value `{VALUE}`';
32
32
  msg.general.required = 'Path `{PATH}` is required.';
33
+ msg.general.allowNull = 'Path `{PATH}` does not allow null values.';
33
34
 
34
35
  msg.Number = {};
35
36
  msg.Number.min = 'Path `{PATH}` ({VALUE}) is less than minimum allowed value ({MIN}).';
@@ -94,6 +94,20 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'cast', opts);
94
94
 
95
95
  Object.defineProperty(SchemaTypeOptions.prototype, 'required', opts);
96
96
 
97
+ /**
98
+ * Controls whether this path may be set to `null`. By default, Mongoose allows
99
+ * `null` for non-required paths. Set `allowNull: false` to allow `undefined`
100
+ * but disallow `null`.
101
+ *
102
+ * @api public
103
+ * @property allowNull
104
+ * @memberOf SchemaTypeOptions
105
+ * @type {boolean}
106
+ * @instance
107
+ */
108
+
109
+ Object.defineProperty(SchemaTypeOptions.prototype, 'allowNull', opts);
110
+
97
111
  /**
98
112
  * The default value for this path. If a function, Mongoose executes the function
99
113
  * and uses the return value as the default.
package/lib/schemaType.js CHANGED
@@ -200,15 +200,16 @@ SchemaType.prototype._createJSONSchemaTypeDefinition = function _createJSONSchem
200
200
  (this.options.required == null ?
201
201
  (options?._defaultRequired === true || this.path === '_id') :
202
202
  this.options.required && typeof this.options.required !== 'function');
203
+ const allowNull = this.options.allowNull !== false;
203
204
 
204
205
  if (useBsonType) {
205
- if (isRequired) {
206
+ if (isRequired || !allowNull) {
206
207
  return { bsonType };
207
208
  }
208
209
  return { bsonType: [bsonType, 'null'] };
209
210
  }
210
211
 
211
- if (isRequired) {
212
+ if (isRequired || !allowNull) {
212
213
  return { type };
213
214
  }
214
215
  return { type: [type, 'null'] };
@@ -1142,6 +1143,12 @@ SchemaType.prototype.required = function(required, message) {
1142
1143
 
1143
1144
  const _this = this;
1144
1145
  this.isRequired = true;
1146
+ this.originalRequiredValue = required;
1147
+
1148
+ if (typeof this.originalRequiredValue !== 'function' &&
1149
+ (utils.hasUserDefinedProperty(this.options, 'allowNull') || this.allowNullValidator != null)) {
1150
+ throw new MongooseError('Path "' + this.path + '" may not have `allowNull` specified when `required` is true');
1151
+ }
1145
1152
 
1146
1153
  this.requiredValidator = function(v) {
1147
1154
  const cachedRequired = this?.$__?.cachedRequired;
@@ -1166,8 +1173,6 @@ SchemaType.prototype.required = function(required, message) {
1166
1173
 
1167
1174
  return _this.checkRequired(v, this);
1168
1175
  };
1169
- this.originalRequiredValue = required;
1170
-
1171
1176
  if (typeof required === 'string') {
1172
1177
  message = required;
1173
1178
  required = undefined;
@@ -1183,6 +1188,53 @@ SchemaType.prototype.required = function(required, message) {
1183
1188
  return this;
1184
1189
  };
1185
1190
 
1191
+ /**
1192
+ * Adds a validator that disallows `null` for this path without making the path
1193
+ * required. `undefined` values still pass validation.
1194
+ *
1195
+ * #### Example:
1196
+ *
1197
+ * const schema = new Schema({
1198
+ * name: { type: String, allowNull: false }
1199
+ * });
1200
+ *
1201
+ * new Model({ name: undefined }).validateSync(); // OK
1202
+ * new Model({ name: null }).validateSync(); // ValidationError
1203
+ *
1204
+ * @param {boolean} allowNull
1205
+ * @return {SchemaType} this
1206
+ * @api public
1207
+ */
1208
+
1209
+ SchemaType.prototype.allowNull = function(allowNull) {
1210
+ if (arguments.length > 0 && this.isRequired && typeof this.originalRequiredValue !== 'function') {
1211
+ throw new MongooseError('Path "' + this.path + '" may not have `allowNull` specified when `required` is true');
1212
+ }
1213
+
1214
+ this.validators = this.validators.filter(function(v) {
1215
+ return v.validator !== this.allowNullValidator;
1216
+ }, this);
1217
+
1218
+ if (allowNull !== false) {
1219
+ delete this.options.allowNull;
1220
+ delete this.allowNullValidator;
1221
+ return this;
1222
+ }
1223
+
1224
+ this.options.allowNull = false;
1225
+ this.allowNullValidator = function(v) {
1226
+ return v !== null;
1227
+ };
1228
+
1229
+ this.validators.push({
1230
+ validator: this.allowNullValidator,
1231
+ message: MongooseError.messages.general.allowNull,
1232
+ type: 'allowNull'
1233
+ });
1234
+
1235
+ return this;
1236
+ };
1237
+
1186
1238
  /**
1187
1239
  * Set the model that this path refers to. This is the option that [populate](https://mongoosejs.com/docs/populate.html)
1188
1240
  * looks at to determine the foreign collection it should query.
@@ -1802,6 +1854,7 @@ SchemaType.prototype.clone = function() {
1802
1854
  const schematype = new this.constructor(this.path, options, this.instance, this.parentSchema);
1803
1855
  schematype.validators = this.validators.slice();
1804
1856
  if (this.requiredValidator !== undefined) schematype.requiredValidator = this.requiredValidator;
1857
+ if (this.allowNullValidator !== undefined) schematype.allowNullValidator = this.allowNullValidator;
1805
1858
  if (this.defaultValue !== undefined) schematype.defaultValue = this.defaultValue;
1806
1859
  if (this.$immutable !== undefined && this.options.immutable === undefined) {
1807
1860
  schematype.$immutable = this.$immutable;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "9.5.0",
4
+ "version": "9.6.0",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -21,7 +21,7 @@
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
23
  "kareem": "3.3.0",
24
- "mongodb": "~7.1",
24
+ "mongodb": "~7.2",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "6.0.0",
27
27
  "ms": "2.1.3",
@@ -52,7 +52,7 @@
52
52
  "markdownlint-cli2": "0.22.0",
53
53
  "marked": "17.0.5",
54
54
  "mkdirp": "^3.0.1",
55
- "mocha": "11.7.5",
55
+ "mocha": "12.0.0-beta-9.2",
56
56
  "moment": "2.30.1",
57
57
  "mongodb-client-encryption": "~7.0",
58
58
  "mongodb-memory-server": "11.0.1",
@@ -63,7 +63,7 @@
63
63
  "tstyche": "^7.0.0",
64
64
  "typescript": "5.9.3",
65
65
  "typescript-eslint": "^8.31.1",
66
- "uuid": "11.1.0"
66
+ "uuid": "14.0.0"
67
67
  },
68
68
  "directories": {
69
69
  "lib": "./lib/mongoose"
package/types/index.d.ts CHANGED
@@ -819,12 +819,12 @@ declare module 'mongoose' {
819
819
 
820
820
  export type ReturnsNewDoc = { new: true } | { returnOriginal: false } | { returnDocument: 'after' };
821
821
 
822
- type ArrayOperators = { $slice: number | [number, number]; $elemMatch?: never } | { $elemMatch: Record<string, any>; $slice?: never };
822
+ export type ArrayProjectionOperators = { $slice: number | [number, number]; $elemMatch?: never } | { $elemMatch: Record<string, any>; $slice?: never };
823
823
  /**
824
824
  * This Type Assigns `Element | undefined` recursively to the `T` type.
825
825
  * if it is an array it will do this to the element of the array, if it is an object it will do this for the properties of the object.
826
826
  * `Element` is the truthy or falsy values that are going to be used as the value of the projection.(1 | true or 0 | false)
827
- * For the elements of the array we will use: `Element | `undefined` | `ArrayOperators`
827
+ * For the elements of the array we will use: `Element | `undefined` | `ArrayProjectionOperators`
828
828
  * @example
829
829
  * type CalculatedType = Projector<{ a: string, b: number, c: { d: string }, d: string[] }, true>
830
830
  * type CalculatedType = {
@@ -833,11 +833,11 @@ declare module 'mongoose' {
833
833
  c?: true | {
834
834
  d?: true | undefined;
835
835
  } | undefined;
836
- d?: true | ArrayOperators | undefined;
836
+ d?: true | ArrayProjectionOperators | undefined;
837
837
  }
838
838
  */
839
- type Projector<T, Element> = T extends Array<infer U>
840
- ? Projector<U, Element> | ArrayOperators
839
+ export type Projector<T, Element> = T extends Array<infer U>
840
+ ? Projector<U, Element> | ArrayProjectionOperators
841
841
  : T extends TreatAsPrimitives
842
842
  ? Element
843
843
  : T extends Record<string, any>
@@ -3,7 +3,8 @@ import {
3
3
  PathEnumOrString,
4
4
  OptionalPaths,
5
5
  RequiredPaths,
6
- IsPathRequired
6
+ IsPathRequired,
7
+ PathAllowsNull
7
8
  } from './inferschematype';
8
9
  import { Binary, UUID } from 'mongodb';
9
10
 
@@ -24,7 +25,9 @@ declare module 'mongoose' {
24
25
  OptionalPaths<SchemaDefinition, TSchemaOptions['typeKey']>)
25
26
  ]: IsPathRequired<SchemaDefinition[K], TSchemaOptions['typeKey']> extends true
26
27
  ? ObtainRawDocumentPathType<SchemaDefinition[K], TSchemaOptions['typeKey'], TTransformOptions>
27
- : ObtainRawDocumentPathType<SchemaDefinition[K], TSchemaOptions['typeKey'], TTransformOptions> | null;
28
+ : PathAllowsNull<SchemaDefinition[K]> extends true
29
+ ? ObtainRawDocumentPathType<SchemaDefinition[K], TSchemaOptions['typeKey'], TTransformOptions> | null
30
+ : ObtainRawDocumentPathType<SchemaDefinition[K], TSchemaOptions['typeKey'], TTransformOptions>;
28
31
  }, TSchemaOptions>;
29
32
 
30
33
  export type InferRawDocType<
@@ -47,7 +47,9 @@ declare module 'mongoose' {
47
47
  TSchemaOptions['typeKey']
48
48
  > extends true ?
49
49
  ObtainDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']>
50
- : ObtainDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']> | null;
50
+ : PathAllowsNull<DocDefinition[K]> extends true ?
51
+ ObtainDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']> | null
52
+ : ObtainDocumentPathType<DocDefinition[K], TSchemaOptions['typeKey']>;
51
53
  };
52
54
 
53
55
  /**
@@ -222,6 +224,12 @@ type OptionalPaths<T, TypeKey extends string = DefaultTypeKey> = Pick<
222
224
  OptionalPathKeys<T, TypeKey>
223
225
  >;
224
226
 
227
+ /**
228
+ * @summary Checks if a document path allows `null` values.
229
+ * @param {P} P Document path.
230
+ */
231
+ export type PathAllowsNull<P> = P extends { allowNull: false } ? false : true;
232
+
225
233
  /**
226
234
  * @summary Allows users to optionally choose their own type for a schema field for stronger typing.
227
235
  */
package/types/query.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  declare module 'mongoose' {
2
2
  import mongodb = require('mongodb');
3
3
 
4
- type StringQueryTypeCasting = string | RegExp;
4
+ type StringQueryTypeCasting<T> = string extends T ? string | RegExp : T | RegExp;
5
5
  type ObjectIdQueryTypeCasting = Types.ObjectId | string;
6
6
  type DateQueryTypeCasting = string | number | NativeDate;
7
7
  type UUIDQueryTypeCasting = Types.UUID | string;
8
8
  type BufferQueryCasting = Buffer | mongodb.Binary | number[] | string | { $binary: string | mongodb.Binary };
9
9
  type QueryTypeCasting<T> = T extends string
10
- ? StringQueryTypeCasting
10
+ ? StringQueryTypeCasting<T>
11
11
  : T extends Types.ObjectId
12
12
  ? ObjectIdQueryTypeCasting
13
13
  : T extends Types.UUID
@@ -104,6 +104,13 @@ declare module 'mongoose' {
104
104
  | [boolean, string]
105
105
  | [(this: THydratedDocumentType) => boolean, string];
106
106
 
107
+ /**
108
+ * Controls whether this path may be set to `null`. By default, Mongoose allows
109
+ * `null` for non-required paths. Set `allowNull: false` to allow `undefined`
110
+ * but disallow `null`.
111
+ */
112
+ allowNull?: boolean;
113
+
107
114
  /**
108
115
  * The default value for this path. If a function, Mongoose executes the function
109
116
  * and uses the return value as the default.
@@ -355,6 +362,9 @@ declare module 'mongoose' {
355
362
  */
356
363
  required(required: boolean, message?: string): this;
357
364
 
365
+ /** Adds or removes a validator that disallows `null` without making this path required. */
366
+ allowNull(allowNull: boolean): this;
367
+
358
368
  /** If the SchemaType is a subdocument or document array, this is the schema of that subdocument */
359
369
  schema?: Schema<any>;
360
370