@zodmon/core 0.5.0 → 0.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.
package/dist/index.d.cts CHANGED
@@ -506,12 +506,11 @@ type DotPathType<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K
506
506
  * // Builder functions mixed with object literals
507
507
  * const filter: TypedFilter<User> = { age: $gte(18), role: $in(['admin', 'mod']) }
508
508
  *
509
- * // Logical composition
510
- * const filter = $and<User>(
511
- * $or<User>({ role: 'admin' }, { role: 'moderator' }),
512
- * { age: $gte(18) },
513
- * { email: $exists() },
514
- * )
509
+ * // Logical composition — T inferred from find() context
510
+ * posts.find($and(
511
+ * $or({ published: true }, { views: $gte(100) }),
512
+ * { title: $regex(/guide/i) },
513
+ * ))
515
514
  *
516
515
  * // Dynamic conditional building
517
516
  * const conditions: TypedFilter<User>[] = []
@@ -855,6 +854,8 @@ declare function extractFieldIndexes(shape: z.core.$ZodShape): FieldIndexDefinit
855
854
  */
856
855
  declare function collection<TShape extends z.core.$ZodShape>(name: string, shape: TShape, options?: CollectionOptions<Extract<keyof TShape, string>>): CollectionDefinition<TShape>;
857
856
 
857
+ type IndexDirection = 1 | -1;
858
+ type CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>;
858
859
  /**
859
860
  * A builder for compound index definitions.
860
861
  *
@@ -874,9 +875,6 @@ declare function collection<TShape extends z.core.$ZodShape>(name: string, shape
874
875
  * index({ email: 1, role: -1 }).unique().name('email_role_idx')
875
876
  * ```
876
877
  */
877
-
878
- type IndexDirection = 1 | -1;
879
- type CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>;
880
878
  declare class IndexBuilder<TKeys extends string> {
881
879
  readonly fields: Partial<Record<TKeys, IndexDirection>>;
882
880
  readonly options: CompoundIndexOptions;
@@ -1189,16 +1187,14 @@ declare const $not: <O extends Record<string, unknown>>(op: O) => {
1189
1187
  *
1190
1188
  * @example
1191
1189
  * ```ts
1190
+ * // T inferred from collection's find() context
1192
1191
  * users.find($or({ role: 'admin' }, { age: $gte(18) }))
1193
1192
  *
1194
- * // Dynamic composition
1195
- * const conditions: TypedFilter<User>[] = []
1196
- * if (name) conditions.push({ name })
1197
- * if (role) conditions.push({ role })
1198
- * users.find($or(...conditions))
1193
+ * // Explicit generic for standalone usage
1194
+ * const filter = $or<User>({ role: 'admin' }, { age: $gte(18) })
1199
1195
  * ```
1200
1196
  */
1201
- declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1197
+ declare const $or: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1202
1198
  /**
1203
1199
  * Joins filter clauses with a logical AND. Matches documents that satisfy
1204
1200
  * all of the provided filters. Useful for dynamic filter building where
@@ -1206,6 +1202,7 @@ declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1206
1202
  *
1207
1203
  * @example
1208
1204
  * ```ts
1205
+ * // T inferred from collection's find() context
1209
1206
  * users.find($and(
1210
1207
  * $or({ role: 'admin' }, { role: 'moderator' }),
1211
1208
  * { age: $gte(18) },
@@ -1213,7 +1210,7 @@ declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1213
1210
  * ))
1214
1211
  * ```
1215
1212
  */
1216
- declare const $and: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1213
+ declare const $and: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1217
1214
  /**
1218
1215
  * Joins filter clauses with a logical NOR. Matches documents that fail
1219
1216
  * all of the provided filters.
@@ -1224,7 +1221,7 @@ declare const $and: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1224
1221
  * users.find($nor({ role: 'banned' }, { role: 'suspended' }))
1225
1222
  * ```
1226
1223
  */
1227
- declare const $nor: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1224
+ declare const $nor: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1228
1225
  /**
1229
1226
  * Escape hatch for unsupported or raw MongoDB filter operators.
1230
1227
  * Wraps an untyped filter object so it can be passed where `TypedFilter<T>` is expected.
@@ -1237,6 +1234,219 @@ declare const $nor: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1237
1234
  */
1238
1235
  declare const raw: <T = any>(filter: Record<string, unknown>) => TypedFilter<T>;
1239
1236
 
1237
+ /**
1238
+ * Extracts the element type from an array type.
1239
+ *
1240
+ * @example
1241
+ * ```ts
1242
+ * type E = ArrayElement<string[]> // string
1243
+ * type N = ArrayElement<number[]> // number
1244
+ * ```
1245
+ */
1246
+ type ArrayElement<T> = T extends ReadonlyArray<infer E> ? E : never;
1247
+ /**
1248
+ * Fields valid for `$set`, `$setOnInsert`, `$min`, and `$max` operators.
1249
+ *
1250
+ * Allows top-level fields with matching value types plus dot-notation paths
1251
+ * for nested field updates.
1252
+ *
1253
+ * @example
1254
+ * ```ts
1255
+ * const set: SetFields<User> = { name: 'Alice', 'address.city': 'NYC' }
1256
+ * ```
1257
+ */
1258
+ type SetFields<T> = {
1259
+ [K in keyof T]?: T[K];
1260
+ } & {
1261
+ [P in DotPaths<T>]?: DotPathType<T, P>;
1262
+ };
1263
+ /**
1264
+ * Fields valid for the `$inc` operator — only number-typed fields.
1265
+ *
1266
+ * Includes dot-notation paths that resolve to number types.
1267
+ *
1268
+ * @example
1269
+ * ```ts
1270
+ * const inc: IncFields<User> = { age: 1, 'stats.views': 5 }
1271
+ * ```
1272
+ */
1273
+ type IncFields<T> = {
1274
+ [K in keyof T as NonNullable<T[K]> extends number ? K : never]?: number;
1275
+ } & {
1276
+ [P in DotPaths<T> as DotPathType<T, P> extends number ? P : never]?: number;
1277
+ };
1278
+ /**
1279
+ * Modifiers for the `$push` operator.
1280
+ *
1281
+ * Use with `$push` to insert multiple elements and control array position/size.
1282
+ *
1283
+ * @example
1284
+ * ```ts
1285
+ * const push = { tags: { $each: ['a', 'b'], $position: 0, $slice: 10 } }
1286
+ * ```
1287
+ */
1288
+ type PushModifiers<E> = {
1289
+ /** Array of elements to push. */
1290
+ $each: E[];
1291
+ /** Position at which to insert elements. */
1292
+ $position?: number;
1293
+ /** Maximum array length after push. */
1294
+ $slice?: number;
1295
+ /** Sort order applied after push. */
1296
+ $sort?: 1 | -1 | Record<string, 1 | -1>;
1297
+ };
1298
+ /**
1299
+ * Fields valid for the `$push` operator — only array-typed fields.
1300
+ *
1301
+ * Accepts a single element value or a modifier object with `$each`.
1302
+ *
1303
+ * @example
1304
+ * ```ts
1305
+ * const push: PushFields<User> = { tags: 'dev' }
1306
+ * const pushMany: PushFields<User> = { tags: { $each: ['a', 'b'] } }
1307
+ * ```
1308
+ */
1309
+ type PushFields<T> = {
1310
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | PushModifiers<ArrayElement<NonNullable<T[K]>>>;
1311
+ };
1312
+ /**
1313
+ * Fields valid for the `$pull` operator — only array-typed fields.
1314
+ *
1315
+ * For primitive arrays: accepts a value or comparison operators.
1316
+ * For object arrays: also accepts a `TypedFilter` on the element type.
1317
+ *
1318
+ * @example
1319
+ * ```ts
1320
+ * const pull: PullFields<User> = { tags: 'old' }
1321
+ * const pullQuery: PullFields<User> = { scores: { $lt: 50 } }
1322
+ * const pullObj: PullFields<User> = { comments: { author: 'spam' } }
1323
+ * ```
1324
+ */
1325
+ type PullFields<T> = {
1326
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | ComparisonOperators<ArrayElement<NonNullable<T[K]>>> | (ArrayElement<NonNullable<T[K]>> extends Record<string, unknown> ? TypedFilter<ArrayElement<NonNullable<T[K]>>> : unknown);
1327
+ };
1328
+ /**
1329
+ * Modifier for the `$addToSet` operator's `$each` syntax.
1330
+ *
1331
+ * @example
1332
+ * ```ts
1333
+ * const addToSet = { tags: { $each: ['a', 'b'] } }
1334
+ * ```
1335
+ */
1336
+ type AddToSetEach<E> = {
1337
+ $each: E[];
1338
+ };
1339
+ /**
1340
+ * Fields valid for the `$addToSet` operator — only array-typed fields.
1341
+ *
1342
+ * Accepts a single element value or `{ $each: [...] }` for multiple elements.
1343
+ *
1344
+ * @example
1345
+ * ```ts
1346
+ * const add: AddToSetFields<User> = { tags: 'dev' }
1347
+ * const addMany: AddToSetFields<User> = { tags: { $each: ['a', 'b'] } }
1348
+ * ```
1349
+ */
1350
+ type AddToSetFields<T> = {
1351
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | AddToSetEach<ArrayElement<NonNullable<T[K]>>>;
1352
+ };
1353
+ /**
1354
+ * Fields valid for the `$pop` operator — only array-typed fields.
1355
+ *
1356
+ * Value `1` removes the last element, `-1` removes the first.
1357
+ *
1358
+ * @example
1359
+ * ```ts
1360
+ * const pop: PopFields<User> = { tags: -1 } // remove first
1361
+ * ```
1362
+ */
1363
+ type PopFields<T> = {
1364
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: 1 | -1;
1365
+ };
1366
+ /**
1367
+ * Fields valid for the `$unset` operator — any existing field.
1368
+ *
1369
+ * Value is `''`, `true`, or `1` (all mean "remove this field").
1370
+ *
1371
+ * @example
1372
+ * ```ts
1373
+ * const unset: UnsetFields<User> = { middleName: '' }
1374
+ * ```
1375
+ */
1376
+ type UnsetFields<T> = {
1377
+ [K in keyof T]?: '' | true | 1;
1378
+ };
1379
+ /**
1380
+ * Fields valid for the `$currentDate` operator — only Date-typed fields.
1381
+ *
1382
+ * Sets the field to the current date. Value is `true` or `{ $type: 'date' }`.
1383
+ *
1384
+ * @example
1385
+ * ```ts
1386
+ * const cd: CurrentDateFields<User> = { createdAt: true }
1387
+ * ```
1388
+ */
1389
+ type CurrentDateFields<T> = {
1390
+ [K in keyof T as NonNullable<T[K]> extends Date ? K : never]?: true | {
1391
+ $type: 'date';
1392
+ };
1393
+ };
1394
+ /**
1395
+ * Fields valid for the `$rename` operator.
1396
+ *
1397
+ * Renames an existing field to a new name. Key is the current field name,
1398
+ * value is the new name as a string.
1399
+ *
1400
+ * @example
1401
+ * ```ts
1402
+ * const rename: RenameFields<User> = { name: 'fullName' }
1403
+ * ```
1404
+ */
1405
+ type RenameFields<T> = {
1406
+ [K in keyof T & string]?: string;
1407
+ };
1408
+ /**
1409
+ * Strict type-safe MongoDB update filter.
1410
+ *
1411
+ * Validates update operators against field types at compile time. Each operator
1412
+ * constrains which fields it accepts (e.g. `$inc` only on numbers, `$push` only
1413
+ * on arrays). Supports dot-notation paths for nested field access.
1414
+ *
1415
+ * @example
1416
+ * ```ts
1417
+ * const update: TypedUpdateFilter<User> = {
1418
+ * $set: { name: 'Alice' },
1419
+ * $inc: { age: 1 },
1420
+ * }
1421
+ * ```
1422
+ */
1423
+ type TypedUpdateFilter<T> = {
1424
+ /** Sets the value of one or more fields. */
1425
+ $set?: SetFields<T>;
1426
+ /** Sets fields only when inserting (upsert). Same typing as `$set`. */
1427
+ $setOnInsert?: SetFields<T>;
1428
+ /** Increments numeric fields by the given amount. Only accepts number-typed fields. */
1429
+ $inc?: IncFields<T>;
1430
+ /** Updates the field if the given value is less than the current value. */
1431
+ $min?: SetFields<T>;
1432
+ /** Updates the field if the given value is greater than the current value. */
1433
+ $max?: SetFields<T>;
1434
+ /** Appends a value to an array field. Supports `$each`, `$position`, `$slice`, `$sort`. */
1435
+ $push?: PushFields<T>;
1436
+ /** Removes matching values from an array field. */
1437
+ $pull?: PullFields<T>;
1438
+ /** Adds a value to an array only if it doesn't already exist. */
1439
+ $addToSet?: AddToSetFields<T>;
1440
+ /** Removes the first (`-1`) or last (`1`) element of an array. */
1441
+ $pop?: PopFields<T>;
1442
+ /** Removes the specified fields from the document. */
1443
+ $unset?: UnsetFields<T>;
1444
+ /** Sets the field to the current date. Only accepts Date-typed fields. */
1445
+ $currentDate?: CurrentDateFields<T>;
1446
+ /** Renames a field. */
1447
+ $rename?: RenameFields<T>;
1448
+ };
1449
+
1240
1450
  /**
1241
1451
  * Type-level marker that carries the target collection type through the
1242
1452
  * type system. Intersected with the schema return type by `.ref()` so
@@ -1321,4 +1531,4 @@ declare function getRefMetadata(schema: unknown): RefMetadata | undefined;
1321
1531
  */
1322
1532
  declare function installRefExtension(): void;
1323
1533
 
1324
- export { $and, $eq, $exists, $gt, $gte, $in, $lt, $lte, $ne, $nin, $nor, $not, $or, $regex, type AnyCollection, type CollectionDefinition, CollectionHandle, type CollectionOptions, type ComparisonOperators, type CompoundIndexDefinition, Database, type DotPathType, type DotPaths, type FieldIndexDefinition, type FindOneOptions, type FindOptions, IndexBuilder, type IndexMetadata, type IndexOptions, type InferDocument, type InferInsert, type RefMarker, type RefMetadata, type ResolvedShape, type TypedFilter, TypedFindCursor, type TypedSort, type ValidationMode, type ZodObjectId, ZodmonNotFoundError, ZodmonValidationError, collection, createClient, extractDbName, extractFieldIndexes, find, findOne, findOneOrThrow, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, installExtensions, installRefExtension, isOid, objectId, oid, raw };
1534
+ export { $and, $eq, $exists, $gt, $gte, $in, $lt, $lte, $ne, $nin, $nor, $not, $or, $regex, type AddToSetEach, type AddToSetFields, type AnyCollection, type ArrayElement, type CollectionDefinition, CollectionHandle, type CollectionOptions, type ComparisonOperators, type CompoundIndexDefinition, type CurrentDateFields, Database, type DotPathType, type DotPaths, type FieldIndexDefinition, type FindOneOptions, type FindOptions, type IncFields, IndexBuilder, type IndexMetadata, type IndexOptions, type InferDocument, type InferInsert, type PopFields, type PullFields, type PushFields, type PushModifiers, type RefMarker, type RefMetadata, type RenameFields, type ResolvedShape, type SetFields, type TypedFilter, TypedFindCursor, type TypedSort, type TypedUpdateFilter, type UnsetFields, type ValidationMode, type ZodObjectId, ZodmonNotFoundError, ZodmonValidationError, collection, createClient, extractDbName, extractFieldIndexes, find, findOne, findOneOrThrow, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, installExtensions, installRefExtension, isOid, objectId, oid, raw };
package/dist/index.d.ts CHANGED
@@ -506,12 +506,11 @@ type DotPathType<T, P extends string> = P extends `${infer K}.${infer Rest}` ? K
506
506
  * // Builder functions mixed with object literals
507
507
  * const filter: TypedFilter<User> = { age: $gte(18), role: $in(['admin', 'mod']) }
508
508
  *
509
- * // Logical composition
510
- * const filter = $and<User>(
511
- * $or<User>({ role: 'admin' }, { role: 'moderator' }),
512
- * { age: $gte(18) },
513
- * { email: $exists() },
514
- * )
509
+ * // Logical composition — T inferred from find() context
510
+ * posts.find($and(
511
+ * $or({ published: true }, { views: $gte(100) }),
512
+ * { title: $regex(/guide/i) },
513
+ * ))
515
514
  *
516
515
  * // Dynamic conditional building
517
516
  * const conditions: TypedFilter<User>[] = []
@@ -855,6 +854,8 @@ declare function extractFieldIndexes(shape: z.core.$ZodShape): FieldIndexDefinit
855
854
  */
856
855
  declare function collection<TShape extends z.core.$ZodShape>(name: string, shape: TShape, options?: CollectionOptions<Extract<keyof TShape, string>>): CollectionDefinition<TShape>;
857
856
 
857
+ type IndexDirection = 1 | -1;
858
+ type CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>;
858
859
  /**
859
860
  * A builder for compound index definitions.
860
861
  *
@@ -874,9 +875,6 @@ declare function collection<TShape extends z.core.$ZodShape>(name: string, shape
874
875
  * index({ email: 1, role: -1 }).unique().name('email_role_idx')
875
876
  * ```
876
877
  */
877
-
878
- type IndexDirection = 1 | -1;
879
- type CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>;
880
878
  declare class IndexBuilder<TKeys extends string> {
881
879
  readonly fields: Partial<Record<TKeys, IndexDirection>>;
882
880
  readonly options: CompoundIndexOptions;
@@ -1189,16 +1187,14 @@ declare const $not: <O extends Record<string, unknown>>(op: O) => {
1189
1187
  *
1190
1188
  * @example
1191
1189
  * ```ts
1190
+ * // T inferred from collection's find() context
1192
1191
  * users.find($or({ role: 'admin' }, { age: $gte(18) }))
1193
1192
  *
1194
- * // Dynamic composition
1195
- * const conditions: TypedFilter<User>[] = []
1196
- * if (name) conditions.push({ name })
1197
- * if (role) conditions.push({ role })
1198
- * users.find($or(...conditions))
1193
+ * // Explicit generic for standalone usage
1194
+ * const filter = $or<User>({ role: 'admin' }, { age: $gte(18) })
1199
1195
  * ```
1200
1196
  */
1201
- declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1197
+ declare const $or: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1202
1198
  /**
1203
1199
  * Joins filter clauses with a logical AND. Matches documents that satisfy
1204
1200
  * all of the provided filters. Useful for dynamic filter building where
@@ -1206,6 +1202,7 @@ declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1206
1202
  *
1207
1203
  * @example
1208
1204
  * ```ts
1205
+ * // T inferred from collection's find() context
1209
1206
  * users.find($and(
1210
1207
  * $or({ role: 'admin' }, { role: 'moderator' }),
1211
1208
  * { age: $gte(18) },
@@ -1213,7 +1210,7 @@ declare const $or: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1213
1210
  * ))
1214
1211
  * ```
1215
1212
  */
1216
- declare const $and: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1213
+ declare const $and: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1217
1214
  /**
1218
1215
  * Joins filter clauses with a logical NOR. Matches documents that fail
1219
1216
  * all of the provided filters.
@@ -1224,7 +1221,7 @@ declare const $and: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1224
1221
  * users.find($nor({ role: 'banned' }, { role: 'suspended' }))
1225
1222
  * ```
1226
1223
  */
1227
- declare const $nor: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1224
+ declare const $nor: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>;
1228
1225
  /**
1229
1226
  * Escape hatch for unsupported or raw MongoDB filter operators.
1230
1227
  * Wraps an untyped filter object so it can be passed where `TypedFilter<T>` is expected.
@@ -1237,6 +1234,219 @@ declare const $nor: <T>(...filters: TypedFilter<T>[]) => TypedFilter<T>;
1237
1234
  */
1238
1235
  declare const raw: <T = any>(filter: Record<string, unknown>) => TypedFilter<T>;
1239
1236
 
1237
+ /**
1238
+ * Extracts the element type from an array type.
1239
+ *
1240
+ * @example
1241
+ * ```ts
1242
+ * type E = ArrayElement<string[]> // string
1243
+ * type N = ArrayElement<number[]> // number
1244
+ * ```
1245
+ */
1246
+ type ArrayElement<T> = T extends ReadonlyArray<infer E> ? E : never;
1247
+ /**
1248
+ * Fields valid for `$set`, `$setOnInsert`, `$min`, and `$max` operators.
1249
+ *
1250
+ * Allows top-level fields with matching value types plus dot-notation paths
1251
+ * for nested field updates.
1252
+ *
1253
+ * @example
1254
+ * ```ts
1255
+ * const set: SetFields<User> = { name: 'Alice', 'address.city': 'NYC' }
1256
+ * ```
1257
+ */
1258
+ type SetFields<T> = {
1259
+ [K in keyof T]?: T[K];
1260
+ } & {
1261
+ [P in DotPaths<T>]?: DotPathType<T, P>;
1262
+ };
1263
+ /**
1264
+ * Fields valid for the `$inc` operator — only number-typed fields.
1265
+ *
1266
+ * Includes dot-notation paths that resolve to number types.
1267
+ *
1268
+ * @example
1269
+ * ```ts
1270
+ * const inc: IncFields<User> = { age: 1, 'stats.views': 5 }
1271
+ * ```
1272
+ */
1273
+ type IncFields<T> = {
1274
+ [K in keyof T as NonNullable<T[K]> extends number ? K : never]?: number;
1275
+ } & {
1276
+ [P in DotPaths<T> as DotPathType<T, P> extends number ? P : never]?: number;
1277
+ };
1278
+ /**
1279
+ * Modifiers for the `$push` operator.
1280
+ *
1281
+ * Use with `$push` to insert multiple elements and control array position/size.
1282
+ *
1283
+ * @example
1284
+ * ```ts
1285
+ * const push = { tags: { $each: ['a', 'b'], $position: 0, $slice: 10 } }
1286
+ * ```
1287
+ */
1288
+ type PushModifiers<E> = {
1289
+ /** Array of elements to push. */
1290
+ $each: E[];
1291
+ /** Position at which to insert elements. */
1292
+ $position?: number;
1293
+ /** Maximum array length after push. */
1294
+ $slice?: number;
1295
+ /** Sort order applied after push. */
1296
+ $sort?: 1 | -1 | Record<string, 1 | -1>;
1297
+ };
1298
+ /**
1299
+ * Fields valid for the `$push` operator — only array-typed fields.
1300
+ *
1301
+ * Accepts a single element value or a modifier object with `$each`.
1302
+ *
1303
+ * @example
1304
+ * ```ts
1305
+ * const push: PushFields<User> = { tags: 'dev' }
1306
+ * const pushMany: PushFields<User> = { tags: { $each: ['a', 'b'] } }
1307
+ * ```
1308
+ */
1309
+ type PushFields<T> = {
1310
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | PushModifiers<ArrayElement<NonNullable<T[K]>>>;
1311
+ };
1312
+ /**
1313
+ * Fields valid for the `$pull` operator — only array-typed fields.
1314
+ *
1315
+ * For primitive arrays: accepts a value or comparison operators.
1316
+ * For object arrays: also accepts a `TypedFilter` on the element type.
1317
+ *
1318
+ * @example
1319
+ * ```ts
1320
+ * const pull: PullFields<User> = { tags: 'old' }
1321
+ * const pullQuery: PullFields<User> = { scores: { $lt: 50 } }
1322
+ * const pullObj: PullFields<User> = { comments: { author: 'spam' } }
1323
+ * ```
1324
+ */
1325
+ type PullFields<T> = {
1326
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | ComparisonOperators<ArrayElement<NonNullable<T[K]>>> | (ArrayElement<NonNullable<T[K]>> extends Record<string, unknown> ? TypedFilter<ArrayElement<NonNullable<T[K]>>> : unknown);
1327
+ };
1328
+ /**
1329
+ * Modifier for the `$addToSet` operator's `$each` syntax.
1330
+ *
1331
+ * @example
1332
+ * ```ts
1333
+ * const addToSet = { tags: { $each: ['a', 'b'] } }
1334
+ * ```
1335
+ */
1336
+ type AddToSetEach<E> = {
1337
+ $each: E[];
1338
+ };
1339
+ /**
1340
+ * Fields valid for the `$addToSet` operator — only array-typed fields.
1341
+ *
1342
+ * Accepts a single element value or `{ $each: [...] }` for multiple elements.
1343
+ *
1344
+ * @example
1345
+ * ```ts
1346
+ * const add: AddToSetFields<User> = { tags: 'dev' }
1347
+ * const addMany: AddToSetFields<User> = { tags: { $each: ['a', 'b'] } }
1348
+ * ```
1349
+ */
1350
+ type AddToSetFields<T> = {
1351
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: ArrayElement<NonNullable<T[K]>> | AddToSetEach<ArrayElement<NonNullable<T[K]>>>;
1352
+ };
1353
+ /**
1354
+ * Fields valid for the `$pop` operator — only array-typed fields.
1355
+ *
1356
+ * Value `1` removes the last element, `-1` removes the first.
1357
+ *
1358
+ * @example
1359
+ * ```ts
1360
+ * const pop: PopFields<User> = { tags: -1 } // remove first
1361
+ * ```
1362
+ */
1363
+ type PopFields<T> = {
1364
+ [K in keyof T as NonNullable<T[K]> extends ReadonlyArray<unknown> ? K : never]?: 1 | -1;
1365
+ };
1366
+ /**
1367
+ * Fields valid for the `$unset` operator — any existing field.
1368
+ *
1369
+ * Value is `''`, `true`, or `1` (all mean "remove this field").
1370
+ *
1371
+ * @example
1372
+ * ```ts
1373
+ * const unset: UnsetFields<User> = { middleName: '' }
1374
+ * ```
1375
+ */
1376
+ type UnsetFields<T> = {
1377
+ [K in keyof T]?: '' | true | 1;
1378
+ };
1379
+ /**
1380
+ * Fields valid for the `$currentDate` operator — only Date-typed fields.
1381
+ *
1382
+ * Sets the field to the current date. Value is `true` or `{ $type: 'date' }`.
1383
+ *
1384
+ * @example
1385
+ * ```ts
1386
+ * const cd: CurrentDateFields<User> = { createdAt: true }
1387
+ * ```
1388
+ */
1389
+ type CurrentDateFields<T> = {
1390
+ [K in keyof T as NonNullable<T[K]> extends Date ? K : never]?: true | {
1391
+ $type: 'date';
1392
+ };
1393
+ };
1394
+ /**
1395
+ * Fields valid for the `$rename` operator.
1396
+ *
1397
+ * Renames an existing field to a new name. Key is the current field name,
1398
+ * value is the new name as a string.
1399
+ *
1400
+ * @example
1401
+ * ```ts
1402
+ * const rename: RenameFields<User> = { name: 'fullName' }
1403
+ * ```
1404
+ */
1405
+ type RenameFields<T> = {
1406
+ [K in keyof T & string]?: string;
1407
+ };
1408
+ /**
1409
+ * Strict type-safe MongoDB update filter.
1410
+ *
1411
+ * Validates update operators against field types at compile time. Each operator
1412
+ * constrains which fields it accepts (e.g. `$inc` only on numbers, `$push` only
1413
+ * on arrays). Supports dot-notation paths for nested field access.
1414
+ *
1415
+ * @example
1416
+ * ```ts
1417
+ * const update: TypedUpdateFilter<User> = {
1418
+ * $set: { name: 'Alice' },
1419
+ * $inc: { age: 1 },
1420
+ * }
1421
+ * ```
1422
+ */
1423
+ type TypedUpdateFilter<T> = {
1424
+ /** Sets the value of one or more fields. */
1425
+ $set?: SetFields<T>;
1426
+ /** Sets fields only when inserting (upsert). Same typing as `$set`. */
1427
+ $setOnInsert?: SetFields<T>;
1428
+ /** Increments numeric fields by the given amount. Only accepts number-typed fields. */
1429
+ $inc?: IncFields<T>;
1430
+ /** Updates the field if the given value is less than the current value. */
1431
+ $min?: SetFields<T>;
1432
+ /** Updates the field if the given value is greater than the current value. */
1433
+ $max?: SetFields<T>;
1434
+ /** Appends a value to an array field. Supports `$each`, `$position`, `$slice`, `$sort`. */
1435
+ $push?: PushFields<T>;
1436
+ /** Removes matching values from an array field. */
1437
+ $pull?: PullFields<T>;
1438
+ /** Adds a value to an array only if it doesn't already exist. */
1439
+ $addToSet?: AddToSetFields<T>;
1440
+ /** Removes the first (`-1`) or last (`1`) element of an array. */
1441
+ $pop?: PopFields<T>;
1442
+ /** Removes the specified fields from the document. */
1443
+ $unset?: UnsetFields<T>;
1444
+ /** Sets the field to the current date. Only accepts Date-typed fields. */
1445
+ $currentDate?: CurrentDateFields<T>;
1446
+ /** Renames a field. */
1447
+ $rename?: RenameFields<T>;
1448
+ };
1449
+
1240
1450
  /**
1241
1451
  * Type-level marker that carries the target collection type through the
1242
1452
  * type system. Intersected with the schema return type by `.ref()` so
@@ -1321,4 +1531,4 @@ declare function getRefMetadata(schema: unknown): RefMetadata | undefined;
1321
1531
  */
1322
1532
  declare function installRefExtension(): void;
1323
1533
 
1324
- export { $and, $eq, $exists, $gt, $gte, $in, $lt, $lte, $ne, $nin, $nor, $not, $or, $regex, type AnyCollection, type CollectionDefinition, CollectionHandle, type CollectionOptions, type ComparisonOperators, type CompoundIndexDefinition, Database, type DotPathType, type DotPaths, type FieldIndexDefinition, type FindOneOptions, type FindOptions, IndexBuilder, type IndexMetadata, type IndexOptions, type InferDocument, type InferInsert, type RefMarker, type RefMetadata, type ResolvedShape, type TypedFilter, TypedFindCursor, type TypedSort, type ValidationMode, type ZodObjectId, ZodmonNotFoundError, ZodmonValidationError, collection, createClient, extractDbName, extractFieldIndexes, find, findOne, findOneOrThrow, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, installExtensions, installRefExtension, isOid, objectId, oid, raw };
1534
+ export { $and, $eq, $exists, $gt, $gte, $in, $lt, $lte, $ne, $nin, $nor, $not, $or, $regex, type AddToSetEach, type AddToSetFields, type AnyCollection, type ArrayElement, type CollectionDefinition, CollectionHandle, type CollectionOptions, type ComparisonOperators, type CompoundIndexDefinition, type CurrentDateFields, Database, type DotPathType, type DotPaths, type FieldIndexDefinition, type FindOneOptions, type FindOptions, type IncFields, IndexBuilder, type IndexMetadata, type IndexOptions, type InferDocument, type InferInsert, type PopFields, type PullFields, type PushFields, type PushModifiers, type RefMarker, type RefMetadata, type RenameFields, type ResolvedShape, type SetFields, type TypedFilter, TypedFindCursor, type TypedSort, type TypedUpdateFilter, type UnsetFields, type ValidationMode, type ZodObjectId, ZodmonNotFoundError, ZodmonValidationError, collection, createClient, extractDbName, extractFieldIndexes, find, findOne, findOneOrThrow, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, installExtensions, installRefExtension, isOid, objectId, oid, raw };