mongoose 9.1.6 → 9.2.1

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "9.1.6",
4
+ "version": "9.2.1",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -20,7 +20,7 @@
20
20
  "type": "commonjs",
21
21
  "license": "MIT",
22
22
  "dependencies": {
23
- "kareem": "3.0.0",
23
+ "kareem": "3.2.0",
24
24
  "mongodb": "~7.0",
25
25
  "mpath": "0.9.0",
26
26
  "mquery": "6.0.0",
@@ -48,16 +48,15 @@
48
48
  "markdownlint-cli2": "^0.20.0",
49
49
  "marked": "15.x",
50
50
  "mkdirp": "^3.0.1",
51
- "mocha": "11.3.0",
51
+ "mocha": "11.7.5",
52
52
  "moment": "2.30.1",
53
+ "mongodb-client-encryption": "~7.0",
53
54
  "mongodb-memory-server": "11.0.1",
54
55
  "mongodb-runner": "^6.0.0",
55
- "mongodb-client-encryption": "~7.0",
56
56
  "ncp": "^2.0.0",
57
57
  "c8": "10.1.3",
58
58
  "pug": "3.0.3",
59
59
  "sinon": "21.0.1",
60
- "tsd": "0.33.0",
61
60
  "typescript": "5.9.3",
62
61
  "typescript-eslint": "^8.31.1",
63
62
  "uuid": "11.1.0"
@@ -99,7 +98,7 @@
99
98
  "test-deno:ci": "npm run test-deno -- --reporter min",
100
99
  "test-rs": "START_REPLICA_SET=1 mocha --timeout 30000 --exit ./test/*.test.js",
101
100
  "test-rs:ci": "npm run test-rs -- --reporter min",
102
- "test-tsd": "node ./test/types/check-types-filename && tsd --full",
101
+ "test:types": "tsc --project test/types/tsconfig.json",
103
102
  "setup-test-encryption": "node scripts/setup-encryption-tests.js",
104
103
  "test-encryption": "mocha --exit ./test/encryption/*.test.js",
105
104
  "test-encryption:ci": "npm run test-encryption -- --reporter min",
@@ -131,18 +130,5 @@
131
130
  "funding": {
132
131
  "type": "opencollective",
133
132
  "url": "https://opencollective.com/mongoose"
134
- },
135
- "tsd": {
136
- "directory": "test/types",
137
- "compilerOptions": {
138
- "esModuleInterop": false,
139
- "strict": true,
140
- "allowSyntheticDefaultImports": true,
141
- "strictPropertyInitialization": false,
142
- "noImplicitAny": false,
143
- "strictNullChecks": true,
144
- "module": "commonjs",
145
- "target": "ES2022"
146
- }
147
133
  }
148
134
  }
@@ -5,6 +5,8 @@ declare module 'mongoose' {
5
5
  type AggregateExtract<P> = P extends Aggregate<infer T> ? T : never;
6
6
 
7
7
  interface AggregateOptions extends Omit<mongodb.AggregateOptions & mongodb.Abortable, 'session'>, SessionOption {
8
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
9
+ middleware?: boolean | SkipMiddlewareOptions;
8
10
  [key: string]: any;
9
11
  }
10
12
 
@@ -4,6 +4,13 @@ declare module 'mongoose' {
4
4
  /** A list of paths to skip. If set, Mongoose will validate every modified path that is not in this list. */
5
5
  type pathsToSkip = string[] | string;
6
6
 
7
+ interface ValidateOptions {
8
+ /** List of paths to skip. If set, Mongoose will validate every modified path that is not in this list. */
9
+ pathsToSkip?: pathsToSkip;
10
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
11
+ middleware?: boolean | SkipMiddlewareOptions;
12
+ }
13
+
7
14
  interface DocumentSetOptions {
8
15
  merge?: boolean;
9
16
 
@@ -255,105 +262,13 @@ declare module 'mongoose' {
255
262
  toBSON(): Require_id<DocType>;
256
263
 
257
264
  /** The return value of this method is used in calls to JSON.stringify(doc). */
258
- // Consistently handle combinations of flattenMaps, flattenObjectIds, virtuals, and versionKey
259
-
260
- // All combinations, including with and without TVirtuals when virtuals is true/false,
261
- // and proper nesting/order: flattenMaps -> ObjectIdToString -> Omit<..., '__v'> when needed.
262
-
263
- // flattenMaps: false (default) cases
264
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: true, versionKey: false }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
265
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Require_id<DocType & TVirtuals>>;
266
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: true, versionKey: false }): Omit<Require_id<DocType & TVirtuals>, '__v'>;
267
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: true }): Require_id<DocType & TVirtuals>;
268
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: false, versionKey: false }): ObjectIdToString<Omit<Require_id<DocType>, '__v'>>;
269
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: false }): ObjectIdToString<Require_id<DocType>>;
270
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: false, versionKey: false }): Omit<Require_id<DocType>, '__v'>;
271
- toJSON(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: false }): Require_id<DocType>;
272
-
273
- // flattenMaps: true cases
274
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true, versionKey: false }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>>;
275
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<FlattenMaps<Require_id<DocType & TVirtuals>>>;
276
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: true, versionKey: false }): Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>;
277
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: true }): FlattenMaps<Require_id<DocType & TVirtuals>>;
278
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: false, versionKey: false }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType>>, '__v'>>;
279
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: false }): ObjectIdToString<FlattenMaps<Require_id<DocType>>>;
280
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: false, versionKey: false }): Omit<FlattenMaps<Require_id<DocType>>, '__v'>;
281
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: false }): FlattenMaps<Require_id<DocType>>;
282
-
283
- // Handle "at least" short cross-combinations
284
- // (Some permutations above will catch these, but make some explicit for clarity)
285
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<FlattenMaps<Require_id<DocType & TVirtuals>>>;
286
- toJSON(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true }): ObjectIdToString<FlattenMaps<Require_id<DocType>>>;
287
- toJSON(options: ToObjectOptions & { flattenObjectIds: true, virtuals: true }): ObjectIdToString<Require_id<DocType & TVirtuals>>;
288
- toJSON(options: ToObjectOptions & { flattenObjectIds: true }): ObjectIdToString<Require_id<DocType>>;
289
- toJSON(options: ToObjectOptions & { flattenMaps: true, virtuals: true }): FlattenMaps<Require_id<DocType & TVirtuals>>;
290
- toJSON(options: ToObjectOptions & { flattenMaps: true }): FlattenMaps<Require_id<DocType>>;
291
-
292
- // Handle versionKey: false (regardless of the others - most specific overloads should come first)
293
- toJSON(options: ToObjectOptions & { versionKey: false, flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>>;
294
- toJSON(options: ToObjectOptions & { versionKey: false, flattenMaps: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
295
- toJSON(options: ToObjectOptions & { versionKey: false, flattenMaps: true, virtuals: true }): Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>;
296
- toJSON(options: ToObjectOptions & { versionKey: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
297
- toJSON(options: ToObjectOptions & { versionKey: false, virtuals: true }): Omit<Require_id<DocType & TVirtuals>, '__v'>;
298
- toJSON(options: ToObjectOptions & { versionKey: false, flattenMaps: true, flattenObjectIds: true }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType>>, '__v'>>;
299
- toJSON(options: ToObjectOptions & { versionKey: false, flattenObjectIds: true }): ObjectIdToString<Omit<Require_id<DocType>, '__v'>>;
300
- toJSON(options: ToObjectOptions & { versionKey: false, flattenMaps: true }): Omit<FlattenMaps<Require_id<DocType>>, '__v'>;
301
- toJSON(options: ToObjectOptions & { versionKey: false }): Omit<Require_id<DocType>, '__v'>;
302
-
303
- // Handle virtuals: true
304
- toJSON(options: ToObjectOptions & { virtuals: true }): Require_id<DocType & TVirtuals>;
305
-
306
- // Default - no special options
265
+ toJSON<O extends ToObjectOptions>(options: O): ToObjectReturnType<DocType, TVirtuals, O, TSchemaOptions>;
307
266
  toJSON(options?: ToObjectOptions): Default__v<Require_id<DocType>, TSchemaOptions>;
308
-
309
267
  toJSON<T>(options?: ToObjectOptions): Default__v<Require_id<T>, ResolveSchemaOptions<TSchemaOptions>>;
310
268
 
311
269
  /** Converts this document into a plain-old JavaScript object ([POJO](https://masteringjs.io/tutorials/fundamentals/pojo)). */
312
- // flattenMaps: false (default) cases
313
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: true, versionKey: false }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
314
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Require_id<DocType & TVirtuals>>;
315
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: true, versionKey: false }): Omit<Require_id<DocType & TVirtuals>, '__v'>;
316
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: true }): Require_id<DocType & TVirtuals>;
317
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: false, versionKey: false }): ObjectIdToString<Omit<Require_id<DocType>, '__v'>>;
318
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: true, virtuals: false }): ObjectIdToString<Require_id<DocType>>;
319
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: false, versionKey: false }): Omit<Require_id<DocType>, '__v'>;
320
- toObject(options: ToObjectOptions & { flattenMaps: false, flattenObjectIds: false, virtuals: false }): Require_id<DocType>;
321
-
322
- // flattenMaps: true cases
323
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true, versionKey: false }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>>;
324
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<FlattenMaps<Require_id<DocType & TVirtuals>>>;
325
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: true, versionKey: false }): Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>;
326
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: true }): FlattenMaps<Require_id<DocType & TVirtuals>>;
327
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: false, versionKey: false }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType>>, '__v'>>;
328
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: false }): ObjectIdToString<FlattenMaps<Require_id<DocType>>>;
329
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: false, versionKey: false }): Omit<FlattenMaps<Require_id<DocType>>, '__v'>;
330
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: false, virtuals: false }): FlattenMaps<Require_id<DocType>>;
331
-
332
- // Handle "at least" short cross-combinations
333
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<FlattenMaps<Require_id<DocType & TVirtuals>>>;
334
- toObject(options: ToObjectOptions & { flattenMaps: true, flattenObjectIds: true }): ObjectIdToString<FlattenMaps<Require_id<DocType>>>;
335
- toObject(options: ToObjectOptions & { flattenObjectIds: true, virtuals: true }): ObjectIdToString<Require_id<DocType & TVirtuals>>;
336
- toObject(options: ToObjectOptions & { flattenObjectIds: true }): ObjectIdToString<Require_id<DocType>>;
337
- toObject(options: ToObjectOptions & { flattenMaps: true, virtuals: true }): FlattenMaps<Require_id<DocType & TVirtuals>>;
338
- toObject(options: ToObjectOptions & { flattenMaps: true }): FlattenMaps<Require_id<DocType>>;
339
-
340
- // Handle versionKey: false (regardless of the others - most specific overloads should come first)
341
- toObject(options: ToObjectOptions & { versionKey: false, flattenMaps: true, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>>;
342
- toObject(options: ToObjectOptions & { versionKey: false, flattenMaps: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
343
- toObject(options: ToObjectOptions & { versionKey: false, flattenMaps: true, virtuals: true }): Omit<FlattenMaps<Require_id<DocType & TVirtuals>>, '__v'>;
344
- toObject(options: ToObjectOptions & { versionKey: false, flattenObjectIds: true, virtuals: true }): ObjectIdToString<Omit<Require_id<DocType & TVirtuals>, '__v'>>;
345
- toObject(options: ToObjectOptions & { versionKey: false, virtuals: true }): Omit<Require_id<DocType & TVirtuals>, '__v'>;
346
- toObject(options: ToObjectOptions & { versionKey: false, flattenMaps: true, flattenObjectIds: true }): ObjectIdToString<Omit<FlattenMaps<Require_id<DocType>>, '__v'>>;
347
- toObject(options: ToObjectOptions & { versionKey: false, flattenObjectIds: true }): ObjectIdToString<Omit<Require_id<DocType>, '__v'>>;
348
- toObject(options: ToObjectOptions & { versionKey: false, flattenMaps: true }): Omit<FlattenMaps<Require_id<DocType>>, '__v'>;
349
- toObject(options: ToObjectOptions & { versionKey: false }): Omit<Require_id<DocType>, '__v'>;
350
-
351
- // Handle virtuals: true
352
- toObject(options: ToObjectOptions & { virtuals: true }): Require_id<DocType & TVirtuals>;
353
-
354
- // Default - no special options
270
+ toObject<O extends ToObjectOptions>(options: O): ToObjectReturnType<DocType, TVirtuals, O, TSchemaOptions>;
355
271
  toObject(options?: ToObjectOptions): Default__v<Require_id<DocType>, TSchemaOptions>;
356
-
357
272
  toObject<T>(options?: ToObjectOptions): Default__v<Require_id<T>, ResolveSchemaOptions<TSchemaOptions>>;
358
273
 
359
274
  /** Clears the modified state on the specified path. */
@@ -364,13 +279,13 @@ declare module 'mongoose' {
364
279
  updateOne(update?: UpdateQuery<this> | UpdateWithAggregationPipeline, options?: QueryOptions | null): Query<any, this>;
365
280
 
366
281
  /** Executes registered validation rules for this document. */
367
- validate<T extends keyof DocType>(pathsToValidate?: T | T[], options?: AnyObject): Promise<void>;
368
- validate(pathsToValidate?: pathsToValidate, options?: AnyObject): Promise<void>;
369
- validate(options: { pathsToSkip?: pathsToSkip }): Promise<void>;
282
+ validate<T extends keyof DocType>(pathsToValidate?: T | T[], options?: Omit<ValidateOptions, 'pathsToSkip'> & AnyObject): Promise<void>;
283
+ validate(pathsToValidate?: pathsToValidate, options?: Omit<ValidateOptions, 'pathsToSkip'> & AnyObject): Promise<void>;
284
+ validate(options: ValidateOptions): Promise<void>;
370
285
 
371
286
  /** Executes registered validation rules (skipping asynchronous validators) for this document. */
372
- validateSync(options: { pathsToSkip?: pathsToSkip, [k: string]: any }): Error.ValidationError | null;
373
- validateSync<T extends keyof DocType>(pathsToValidate?: T | T[], options?: AnyObject): Error.ValidationError | null;
374
- validateSync(pathsToValidate?: pathsToValidate, options?: AnyObject): Error.ValidationError | null;
287
+ validateSync(options: ValidateOptions & { [k: string]: any }): Error.ValidationError | null;
288
+ validateSync<T extends keyof DocType>(pathsToValidate?: T | T[], options?: Omit<ValidateOptions, 'pathsToSkip'> & AnyObject): Error.ValidationError | null;
289
+ validateSync(pathsToValidate?: pathsToValidate, options?: Omit<ValidateOptions, 'pathsToSkip'> & AnyObject): Error.ValidationError | null;
375
290
  }
376
291
  }
package/types/index.d.ts CHANGED
@@ -242,6 +242,8 @@ declare module 'mongoose' {
242
242
  flattenMaps?: boolean;
243
243
  /** if true, convert any ObjectIds in the result to 24 character hex strings. */
244
244
  flattenObjectIds?: boolean;
245
+ /** if true, convert any UUIDs in the result to 36 character hex strings. */
246
+ flattenUUIDs?: boolean;
245
247
  /** apply all getters (path and virtual getters) */
246
248
  getters?: boolean;
247
249
  /** remove empty objects (defaults to true) */
@@ -943,25 +945,35 @@ declare module 'mongoose' {
943
945
  : BufferToBinary<T[K]>;
944
946
  } : T;
945
947
 
946
- /**
947
- * Converts any Buffer properties into "{ type: 'buffer', data: [1, 2, 3] }" format for JSON serialization
948
- */
949
- export type UUIDToJSON<T> = T extends mongodb.UUID
948
+ /**
949
+ * Converts any UUID properties into strings for JSON serialization
950
+ */
951
+ export type UUIDToString<T> = T extends Types.UUID
952
+ ? string
953
+ : T extends mongodb.UUID
950
954
  ? string
951
955
  : T extends Document
952
956
  ? T
953
957
  : T extends TreatAsPrimitives
954
958
  ? T
955
959
  : T extends Record<string, any> ? {
956
- [K in keyof T]: T[K] extends mongodb.UUID
960
+ [K in keyof T]: T[K] extends Types.UUID
957
961
  ? string
958
- : T[K] extends Types.DocumentArray<infer ItemType>
959
- ? Types.DocumentArray<UUIDToJSON<ItemType>>
960
- : T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
961
- ? HydratedSingleSubdocument<SubdocType>
962
- : UUIDToJSON<T[K]>;
962
+ : T[K] extends mongodb.UUID
963
+ ? string
964
+ : T[K] extends Types.DocumentArray<infer ItemType>
965
+ ? Types.DocumentArray<UUIDToString<ItemType>>
966
+ : T[K] extends Types.Subdocument<unknown, unknown, infer SubdocType>
967
+ ? HydratedSingleSubdocument<UUIDToString<SubdocType>>
968
+ : UUIDToString<T[K]>;
963
969
  } : T;
964
970
 
971
+ /**
972
+ * Alias for UUIDToString for backwards compatibility.
973
+ * @deprecated Use UUIDToString instead.
974
+ */
975
+ export type UUIDToJSON<T> = UUIDToString<T>;
976
+
965
977
  /**
966
978
  * Converts any ObjectId properties into strings for JSON serialization
967
979
  */
@@ -1029,6 +1041,77 @@ declare module 'mongoose' {
1029
1041
  >
1030
1042
  >;
1031
1043
 
1044
+ /**
1045
+ * Helper types for computing toObject/toJSON return types based on options.
1046
+ * These compose transforms conditionally to avoid combinatorial explosion of overloads.
1047
+ */
1048
+ type ApplyVirtuals<T, TVirtuals, O> =
1049
+ O extends { virtuals: true } ? T & TVirtuals : T;
1050
+
1051
+ type GetVersionKeyName<TSchemaOptions> =
1052
+ TSchemaOptions extends { versionKey: infer VK }
1053
+ ? VK extends string ? VK : '__v'
1054
+ : '__v';
1055
+
1056
+ type ApplyVersionKey<T, O, TSchemaOptions = {}> =
1057
+ O extends { versionKey: false } ? Omit<T, GetVersionKeyName<TSchemaOptions>> : T;
1058
+
1059
+ /**
1060
+ * Single-pass type that applies all flatten transforms (flattenMaps, flattenObjectIds, flattenUUIDs)
1061
+ * in one recursive traversal. This avoids TypeScript's "union type too complex" error that occurs
1062
+ * when nesting separate recursive transform types.
1063
+ *
1064
+ * By handling all transforms in one pass, we correctly handle ObjectIds/UUIDs nested inside Maps
1065
+ * since we recurse into Map values during the same traversal that converts ObjectIds/UUIDs.
1066
+ */
1067
+ type ApplyFlattenTransforms<T, O> =
1068
+ // Handle ObjectId first (before TreatAsPrimitives since ObjectId is in TreatAsPrimitives)
1069
+ T extends mongodb.ObjectId
1070
+ ? O extends { flattenObjectIds: true } ? string : T
1071
+ // Handle UUID (both Types.UUID and mongodb.UUID)
1072
+ : T extends Types.UUID
1073
+ ? O extends { flattenUUIDs: true } ? string : T
1074
+ : T extends mongodb.UUID
1075
+ ? O extends { flattenUUIDs: true } ? string : T
1076
+ // Handle Map - flatten to Record and recurse into values
1077
+ : T extends Map<any, infer V>
1078
+ ? O extends { flattenMaps: true }
1079
+ ? Record<string, ApplyFlattenTransforms<V, O>>
1080
+ : T
1081
+ // Don't recurse into Documents
1082
+ : T extends Document
1083
+ ? T
1084
+ // Don't modify primitives
1085
+ : T extends TreatAsPrimitives
1086
+ ? T
1087
+ // Handle DocumentArray - recurse into items
1088
+ : T extends Types.DocumentArray<infer ItemType>
1089
+ ? Types.DocumentArray<ApplyFlattenTransforms<ItemType, O>>
1090
+ // Handle Subdocument - recurse into subdoc type
1091
+ : T extends Types.Subdocument<unknown, unknown, infer SubdocType>
1092
+ ? HydratedSingleSubdocument<ApplyFlattenTransforms<SubdocType, O>>
1093
+ // Handle regular objects - recurse into properties
1094
+ : T extends Record<string, any>
1095
+ ? { [K in keyof T]: ApplyFlattenTransforms<T[K], O> }
1096
+ : T;
1097
+
1098
+ /**
1099
+ * Computes the return type of toObject/toJSON based on the provided options.
1100
+ * Uses a single-pass transform for flatten operations to correctly handle all combinations.
1101
+ */
1102
+ export type ToObjectReturnType<DocType, TVirtuals, O extends ToObjectOptions, TSchemaOptions = {}> =
1103
+ ApplyVersionKey<
1104
+ Default__v<
1105
+ ApplyFlattenTransforms<
1106
+ ApplyVirtuals<Require_id<DocType>, TVirtuals, O>,
1107
+ O
1108
+ >,
1109
+ TSchemaOptions
1110
+ >,
1111
+ O,
1112
+ TSchemaOptions
1113
+ >;
1114
+
1032
1115
  /**
1033
1116
  * Separate type is needed for properties of union type (for example, Types.DocumentArray | undefined) to apply conditional check to each member of it
1034
1117
  * https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types
@@ -63,7 +63,8 @@ declare module 'mongoose' {
63
63
  : {},
64
64
  TypeKey,
65
65
  TTransformOptions,
66
- RawDocTypeHint<PathValueType>
66
+ RawDocTypeHint<PathValueType>,
67
+ TypeKey extends keyof PathValueType ? false : true
67
68
  >;
68
69
 
69
70
  type neverOrAny = ' ~neverOrAny~';
@@ -86,7 +87,8 @@ declare module 'mongoose' {
86
87
  Options extends SchemaTypeOptions<PathValueType> = {},
87
88
  TypeKey extends string = DefaultSchemaOptions['typeKey'],
88
89
  TTransformOptions = { bufferToBinary: false },
89
- TypeHint = never
90
+ TypeHint = never,
91
+ IsNestedPath extends boolean = false
90
92
  > =
91
93
  IsNotNever<TypeHint> extends true ? TypeHint
92
94
  : [PathValueType] extends [neverOrAny] ? PathValueType
@@ -145,6 +147,14 @@ declare module 'mongoose' {
145
147
  : IfEquals<PathValueType, ObjectConstructor> extends true ? any
146
148
  : IfEquals<PathValueType, {}> extends true ? any
147
149
  : PathValueType extends typeof SchemaType ? PathValueType['prototype']
148
- : PathValueType extends Record<string, any> ? InferRawDocType<PathValueType>
150
+ : PathValueType extends Record<string, any> ?
151
+ IsNestedPath extends true ?
152
+ // Nested path (no type key) - no _id
153
+ InferRawDocTypeWithout_id<PathValueType, { typeKey: TypeKey }, TTransformOptions>
154
+ : Options extends { _id: false } ?
155
+ // Subdocument with _id: false
156
+ InferRawDocTypeWithout_id<PathValueType, { typeKey: TypeKey }, TTransformOptions>
157
+ : // Subdocument with _id (default)
158
+ InferRawDocType<PathValueType, { typeKey: TypeKey }, TTransformOptions>
149
159
  : unknown;
150
160
  }
@@ -112,7 +112,12 @@ declare module 'mongoose' {
112
112
  }[alias]
113
113
  : unknown;
114
114
 
115
- type ResolveSchemaOptions<T> = MergeType<DefaultSchemaOptions, T>;
115
+ type TypesAreEqual<A, B> = [A] extends [B] ? [B] extends [A] ? true : false : false;
116
+
117
+ type ResolveSchemaOptions<T> =
118
+ keyof T extends never ? DefaultSchemaOptions :
119
+ TypesAreEqual<T, DefaultSchemaOptions> extends true ? DefaultSchemaOptions :
120
+ MergeType<DefaultSchemaOptions, T>;
116
121
 
117
122
  type ApplySchemaOptions<T, O = DefaultSchemaOptions> = ResolveTimestamps<T, O>;
118
123
 
@@ -34,6 +34,13 @@ declare module 'mongoose' {
34
34
  type SchemaPreOptions = MiddlewareOptions;
35
35
  type SchemaPostOptions = MiddlewareOptions;
36
36
 
37
+ interface SkipMiddlewareOptions {
38
+ /** If `false`, skip pre middleware. */
39
+ pre?: boolean;
40
+ /** If `false`, skip post middleware. */
41
+ post?: boolean;
42
+ }
43
+
37
44
  type PreMiddlewareFunction<ThisType = any> = (
38
45
  this: ThisType,
39
46
  opts?: Record<string, any>
package/types/models.d.ts CHANGED
@@ -37,12 +37,16 @@ declare module 'mongoose' {
37
37
  strict?: boolean | 'throw';
38
38
  /** When false, do not add timestamps to documents. Can be overridden at the operation level. */
39
39
  timestamps?: boolean;
40
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
41
+ middleware?: boolean | SkipMiddlewareOptions;
40
42
  }
41
43
 
42
44
  interface MongooseBulkSaveOptions extends mongodb.BulkWriteOptions {
43
45
  timestamps?: boolean;
44
46
  session?: ClientSession;
45
47
  validateBeforeSave?: boolean;
48
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
49
+ middleware?: boolean | SkipMiddlewareOptions;
46
50
  }
47
51
 
48
52
  /**
@@ -59,7 +63,7 @@ declare module 'mongoose' {
59
63
  setters?: boolean;
60
64
  hydratedPopulatedDocs?: boolean;
61
65
  virtuals?: boolean;
62
- // strict?: boolean | 'throw';
66
+ strict?: boolean | 'throw';
63
67
  }
64
68
 
65
69
  interface InsertManyOptions extends
@@ -72,6 +76,8 @@ declare module 'mongoose' {
72
76
  ordered?: boolean;
73
77
  lean?: boolean;
74
78
  throwOnValidationError?: boolean;
79
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
80
+ middleware?: boolean | SkipMiddlewareOptions;
75
81
  timestamps?: boolean | QueryTimestampsConfig;
76
82
  }
77
83
 
@@ -83,59 +89,6 @@ declare module 'mongoose' {
83
89
  type UpdateResult = mongodb.UpdateResult;
84
90
  type DeleteResult = mongodb.DeleteResult;
85
91
 
86
- interface MapReduceOptions<T, K, R> {
87
- map: Function | string;
88
- reduce: (key: K, vals: T[]) => R;
89
- /** query filter object. */
90
- query?: any;
91
- /** sort input objects using this key */
92
- sort?: any;
93
- /** max number of documents */
94
- limit?: number;
95
- /** keep temporary data default: false */
96
- keeptemp?: boolean;
97
- /** finalize function */
98
- finalize?: (key: K, val: R) => R;
99
- /** scope variables exposed to map/reduce/finalize during execution */
100
- scope?: any;
101
- /** it is possible to make the execution stay in JS. Provided in MongoDB > 2.0.X default: false */
102
- jsMode?: boolean;
103
- /** provide statistics on job execution time. default: false */
104
- verbose?: boolean;
105
- readPreference?: string;
106
- /** sets the output target for the map reduce job. default: {inline: 1} */
107
- out?: {
108
- /** the results are returned in an array */
109
- inline?: number;
110
- /**
111
- * {replace: 'collectionName'} add the results to collectionName: the
112
- * results replace the collection
113
- */
114
- replace?: string;
115
- /**
116
- * {reduce: 'collectionName'} add the results to collectionName: if
117
- * dups are detected, uses the reducer / finalize functions
118
- */
119
- reduce?: string;
120
- /**
121
- * {merge: 'collectionName'} add the results to collectionName: if
122
- * dups exist the new docs overwrite the old
123
- */
124
- merge?: string;
125
- };
126
- }
127
-
128
- interface GeoSearchOptions {
129
- /** x,y point to search for */
130
- near: number[];
131
- /** the maximum distance from the point near that a result can be */
132
- maxDistance: number;
133
- /** The maximum number of results to return */
134
- limit?: number;
135
- /** return the raw object instead of the Mongoose Model */
136
- lean?: boolean;
137
- }
138
-
139
92
  interface ModifyResult<T> {
140
93
  value: Default__v<Require_id<T>> | null;
141
94
  /** see https://www.mongodb.com/docs/manual/reference/command/findAndModify/#lasterrorobject */
@@ -165,6 +118,8 @@ declare module 'mongoose' {
165
118
  validateModifiedOnly?: boolean;
166
119
  w?: number | string;
167
120
  wtimeout?: number;
121
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
122
+ middleware?: boolean | SkipMiddlewareOptions;
168
123
  }
169
124
 
170
125
  interface CreateOptions extends SaveOptions {
@@ -361,7 +316,7 @@ declare module 'mongoose' {
361
316
  * mongoose will not create the collection for the model until any documents are
362
317
  * created. Use this method to create the collection explicitly.
363
318
  */
364
- createCollection<T extends mongodb.Document>(options?: mongodb.CreateCollectionOptions & Pick<SchemaOptions, 'expires'>): Promise<mongodb.Collection<T>>;
319
+ createCollection<T extends mongodb.Document>(options?: mongodb.CreateCollectionOptions & Pick<SchemaOptions, 'expires'> & { middleware?: boolean | SkipMiddlewareOptions }): Promise<mongodb.Collection<T>>;
365
320
 
366
321
  /**
367
322
  * Create an [Atlas search index](https://www.mongodb.com/docs/atlas/atlas-search/create-index/).
@@ -120,13 +120,17 @@ declare module 'mongoose' {
120
120
  overwriteModels?: boolean;
121
121
 
122
122
  /**
123
- * If `false`, changes the default `returnOriginal` option to `findOneAndUpdate()`,
124
- * `findByIdAndUpdate`, and `findOneAndReplace()` to false. This is equivalent to
125
- * setting the `new` option to `true` for `findOneAndX()` calls by default. Read our
126
- * `findOneAndUpdate()` [tutorial](https://mongoosejs.com/docs/tutorials/findoneandupdate.html)
127
- * for more information.
123
+ * Set the default value for the `returnDocument` option to `findOneAndUpdate()`,
124
+ * `findByIdAndUpdate()`, and `findOneAndReplace()`.
125
+ * - `'before'`: Return the document before the update was applied.
126
+ * - `'after'`: Return the document after the update was applied.
128
127
  *
129
- * @default true
128
+ * @default 'before'
129
+ */
130
+ returnDocument?: 'before' | 'after';
131
+
132
+ /**
133
+ * @deprecated Use `returnDocument` instead.
130
134
  */
131
135
  returnOriginal?: boolean;
132
136
 
package/types/query.d.ts CHANGED
@@ -20,11 +20,22 @@ declare module 'mongoose' {
20
20
 
21
21
  export type ApplyBasicQueryCasting<T> = QueryTypeCasting<T> | QueryTypeCasting<T[]> | (T extends (infer U)[] ? QueryTypeCasting<U> : T) | null;
22
22
 
23
- type _QueryFilter<T> = ({ [P in keyof T]?: mongodb.Condition<ApplyBasicQueryCasting<T[P]>>; } & mongodb.RootFilterOperators<{ [P in keyof mongodb.WithId<T>]?: ApplyBasicQueryCasting<mongodb.WithId<T>[P]>; }>);
24
- type QueryFilter<T> = IsItRecordAndNotAny<T> extends true ? _QueryFilter<WithLevel1NestedPaths<T>> : _QueryFilter<Record<string, any>>;
23
+ type _QueryFilter<T> = (
24
+ { [P in keyof T]?: mongodb.Condition<ApplyBasicQueryCasting<T[P]>>; } &
25
+ mongodb.RootFilterOperators<{ [P in keyof mongodb.WithId<T>]?: ApplyBasicQueryCasting<mongodb.WithId<T>[P]>; }>
26
+ );
27
+ type _QueryFilterLooseId<T> = (
28
+ { [P in keyof T]?: mongodb.Condition<ApplyBasicQueryCasting<T[P]>>; } &
29
+ mongodb.RootFilterOperators<
30
+ { [P in keyof T]?: ApplyBasicQueryCasting<T[P]>; } &
31
+ { _id?: any; }
32
+ >
33
+ );
34
+ type QueryFilter<T> = IsItRecordAndNotAny<T> extends true ? _QueryFilter<WithLevel1NestedPaths<T>> : _QueryFilterLooseId<Record<string, any>>;
25
35
 
26
36
  type MongooseBaseQueryOptionKeys =
27
37
  | 'context'
38
+ | 'middleware'
28
39
  | 'multipleCastError'
29
40
  | 'overwriteDiscriminatorKey'
30
41
  | 'overwriteImmutable'
@@ -95,6 +106,9 @@ declare module 'mongoose' {
95
106
  * By default, `findOneAndUpdate()` returns the document as it was **before**
96
107
  * `update` was applied. If you set `new: true`, `findOneAndUpdate()` will
97
108
  * instead give you the object after `update` was applied.
109
+ * Use `returnDocument: 'after'` instead of `new: true`, or `returnDocument: 'before'` instead of `new: false`.
110
+ *
111
+ * @deprecated
98
112
  */
99
113
  new?: boolean;
100
114
 
@@ -112,10 +126,14 @@ declare module 'mongoose' {
112
126
  readPreference?: string | mongodb.ReadPreferenceMode;
113
127
  /**
114
128
  * An alias for the `new` option. `returnOriginal: false` is equivalent to `new: true`.
129
+ * Use `returnDocument: 'after'` instead of `returnOriginal: false`, or `returnDocument: 'before'` instead of `returnOriginal: true`.
130
+ *
131
+ * @deprecated
115
132
  */
116
133
  returnOriginal?: boolean;
117
134
  /**
118
- * Another alias for the `new` option. `returnOriginal` is deprecated so this should be used.
135
+ * Has two possible values, `'before'` and `'after'`. By default, it will return the document before the update was applied.
136
+ * @default 'before'
119
137
  */
120
138
  returnDocument?: 'before' | 'after';
121
139
  /**
@@ -166,6 +184,9 @@ declare module 'mongoose' {
166
184
  updatePipeline?: boolean;
167
185
  writeConcern?: mongodb.WriteConcern;
168
186
 
187
+ /** set to `false` to skip all user-defined middleware, or `{ pre: false }` / `{ post: false }` to skip only pre or post hooks */
188
+ middleware?: boolean | SkipMiddlewareOptions;
189
+
169
190
  [other: string]: any;
170
191
  }
171
192
 
package/types/types.d.ts CHANGED
@@ -84,7 +84,7 @@ declare module 'mongoose' {
84
84
  class ObjectId extends mongodb.ObjectId {
85
85
  }
86
86
 
87
- class Subdocument<IdType = any, TQueryHelpers = any, DocType = any> extends Document<IdType, TQueryHelpers, DocType> {
87
+ class Subdocument<IdType = any, TQueryHelpers = any, DocType = any, TVirtuals = {}, TSchemaOptions = {}> extends Document<IdType, TQueryHelpers, DocType, TVirtuals, TSchemaOptions> {
88
88
  $isSingleNested: true;
89
89
 
90
90
  /** Returns the top level document of this sub-document. */
@@ -97,7 +97,7 @@ declare module 'mongoose' {
97
97
  $parent(): Document;
98
98
  }
99
99
 
100
- class ArraySubdocument<IdType = any, TQueryHelpers = unknown, DocType = unknown> extends Subdocument<IdType, TQueryHelpers, DocType> {
100
+ class ArraySubdocument<IdType = any, TQueryHelpers = unknown, DocType = unknown, TVirtuals = {}, TSchemaOptions = {}> extends Subdocument<IdType, TQueryHelpers, DocType, TVirtuals, TSchemaOptions> {
101
101
  /** Returns this sub-documents parent array. */
102
102
  parentArray(): Types.DocumentArray<unknown>;
103
103
  }
@@ -131,7 +131,7 @@ declare module 'mongoose' {
131
131
  /**
132
132
  * @summary Checks if two types are identical.
133
133
  * @param {T} T The first type to be compared with {@link U}.
134
- * @param {U} U The seconde type to be compared with {@link T}.
134
+ * @param {U} U The second type to be compared with {@link T}.
135
135
  * @param {Y} Y A type to be returned if {@link T} & {@link U} are identical.
136
136
  * @param {N} N A type to be returned if {@link T} & {@link U} are not identical.
137
137
  */