@zodmon/core 0.8.0 → 0.10.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.cjs +1124 -113
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1619 -163
- package/dist/index.d.ts +1619 -163
- package/dist/index.js +1084 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ObjectId, DeleteResult, FindCursor, Collection, UpdateResult, MongoClientOptions } from 'mongodb';
|
|
1
|
+
import { ObjectId, Document, DeleteResult, FindCursor, Collection, UpdateResult, MongoClientOptions } from 'mongodb';
|
|
2
2
|
import { ZodPipe, ZodCustom, ZodTransform, z, ZodDefault } from 'zod';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -253,11 +253,12 @@ type InferInsert<TDef extends {
|
|
|
253
253
|
* The immutable definition object returned by collection().
|
|
254
254
|
* Holds everything needed to later create a live collection handle.
|
|
255
255
|
*
|
|
256
|
+
* @typeParam TName - The collection name string literal.
|
|
256
257
|
* @typeParam TShape - The Zod shape defining document fields.
|
|
257
258
|
* @typeParam TIndexes - The compound indexes array type, preserving literal name types.
|
|
258
259
|
*/
|
|
259
|
-
type CollectionDefinition<TShape extends z.core.$ZodShape = z.core.$ZodShape, TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]> = {
|
|
260
|
-
readonly name:
|
|
260
|
+
type CollectionDefinition<TName extends string = string, TShape extends z.core.$ZodShape = z.core.$ZodShape, TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]> = {
|
|
261
|
+
readonly name: TName;
|
|
261
262
|
readonly schema: z.ZodObject<ResolvedShape<TShape>>;
|
|
262
263
|
readonly shape: TShape;
|
|
263
264
|
readonly fieldIndexes: FieldIndexDefinition[];
|
|
@@ -265,7 +266,7 @@ type CollectionDefinition<TShape extends z.core.$ZodShape = z.core.$ZodShape, TI
|
|
|
265
266
|
readonly options: Required<Pick<CollectionOptions, 'validation'>> & Omit<CollectionOptions, 'indexes' | 'validation'>;
|
|
266
267
|
};
|
|
267
268
|
/** Erased collection type for use in generic contexts. */
|
|
268
|
-
type AnyCollection = CollectionDefinition<z.core.$ZodShape>;
|
|
269
|
+
type AnyCollection = CollectionDefinition<string, z.core.$ZodShape>;
|
|
269
270
|
/**
|
|
270
271
|
* Extract declared index names from a collection definition.
|
|
271
272
|
*
|
|
@@ -304,80 +305,664 @@ type ExtractNames<T extends readonly {
|
|
|
304
305
|
}[number];
|
|
305
306
|
|
|
306
307
|
/**
|
|
307
|
-
*
|
|
308
|
+
* Forces TypeScript to eagerly expand mapped/intersection types in tooltips.
|
|
309
|
+
*
|
|
310
|
+
* Instead of showing `Omit<{ _id: ObjectId; name: string; salary: number }, "salary">`,
|
|
311
|
+
* the IDE will display the resolved shape `{ _id: ObjectId; name: string }`.
|
|
308
312
|
*
|
|
309
313
|
* @example
|
|
310
314
|
* ```ts
|
|
311
|
-
*
|
|
312
|
-
*
|
|
315
|
+
* type Expanded = Prettify<Pick<User, 'name' | 'role'>>
|
|
316
|
+
* // ^? { name: string; role: string }
|
|
313
317
|
* ```
|
|
314
318
|
*/
|
|
315
|
-
type
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
dropOrphaned?: boolean;
|
|
319
|
+
type Prettify<T> = {
|
|
320
|
+
[K in keyof T]: T[K];
|
|
321
|
+
} & {};
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Type-level marker that carries the target collection type through the
|
|
325
|
+
* type system. Intersected with the schema return type by `.ref()` so
|
|
326
|
+
* that `RefFields<T>` (future) can extract ref relationships.
|
|
327
|
+
*
|
|
328
|
+
* This is a phantom brand — no runtime value has this property.
|
|
329
|
+
*/
|
|
330
|
+
type RefMarker<TCollection extends AnyCollection = AnyCollection> = {
|
|
331
|
+
readonly _ref: TCollection;
|
|
329
332
|
};
|
|
330
333
|
/**
|
|
331
|
-
*
|
|
334
|
+
* Metadata stored in the WeakMap sidecar for schemas marked with `.ref()`.
|
|
335
|
+
* Holds a reference to the target collection definition object.
|
|
336
|
+
*/
|
|
337
|
+
type RefMetadata = {
|
|
338
|
+
readonly collection: AnyCollection;
|
|
339
|
+
};
|
|
340
|
+
/**
|
|
341
|
+
* Module augmentation: adds `.ref()` to all `ZodType` schemas.
|
|
332
342
|
*
|
|
333
|
-
*
|
|
334
|
-
*
|
|
343
|
+
* The intersection constraint `this['_zod']['output'] extends InferDocument<TCollection>['_id']`
|
|
344
|
+
* ensures compile-time type safety: the field's output type must match the
|
|
345
|
+
* target collection's `_id` type. Mismatches produce a type error.
|
|
346
|
+
*
|
|
347
|
+
* Supports both default ObjectId `_id` and custom `_id` types (string, nanoid, etc.):
|
|
348
|
+
* - `objectId().ref(Users)` compiles when Users has ObjectId `_id`
|
|
349
|
+
* - `z.string().ref(Orgs)` compiles when Orgs has string `_id`
|
|
350
|
+
* - `z.string().ref(Users)` is a type error (string ≠ ObjectId)
|
|
351
|
+
* - `objectId().ref(Orgs)` is a type error (ObjectId ≠ string)
|
|
352
|
+
*/
|
|
353
|
+
declare module 'zod' {
|
|
354
|
+
interface ZodType {
|
|
355
|
+
/**
|
|
356
|
+
* Declare a typed foreign key reference to another collection.
|
|
357
|
+
*
|
|
358
|
+
* Stores the target collection definition in metadata for runtime
|
|
359
|
+
* populate resolution, and brands the return type with
|
|
360
|
+
* `RefMarker<TCollection>` so `RefFields<T>` can extract refs
|
|
361
|
+
* at the type level.
|
|
362
|
+
*
|
|
363
|
+
* The field's output type must match the target collection's `_id` type.
|
|
364
|
+
* Mismatched types produce a compile error.
|
|
365
|
+
*
|
|
366
|
+
* Apply `.ref()` before wrapper methods like `.optional()` or `.nullable()`:
|
|
367
|
+
* `objectId().ref(Users).optional()` — not `objectId().optional().ref(Users)`.
|
|
368
|
+
*
|
|
369
|
+
* @param collection - The target collection definition object.
|
|
370
|
+
* @returns The same schema instance, branded with the ref marker.
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```ts
|
|
374
|
+
* const Posts = collection('posts', {
|
|
375
|
+
* authorId: objectId().ref(Users),
|
|
376
|
+
* title: z.string(),
|
|
377
|
+
* })
|
|
378
|
+
* ```
|
|
379
|
+
*/
|
|
380
|
+
ref<TCollection extends AnyCollection>(collection: TCollection & (this['_zod']['output'] extends InferDocument<TCollection>['_id'] ? unknown : never)): this & RefMarker<TCollection>;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Retrieve the ref metadata attached to a Zod schema, if any.
|
|
385
|
+
*
|
|
386
|
+
* Returns `undefined` when the schema was never marked with `.ref()`.
|
|
387
|
+
*
|
|
388
|
+
* @param schema - The Zod schema to inspect. Accepts `unknown` for
|
|
389
|
+
* convenience; non-object values safely return `undefined`.
|
|
390
|
+
* @returns The {@link RefMetadata} for the schema, or `undefined`.
|
|
335
391
|
*
|
|
336
392
|
* @example
|
|
337
393
|
* ```ts
|
|
338
|
-
* const
|
|
339
|
-
*
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
|
|
394
|
+
* const authorId = objectId().ref(Users)
|
|
395
|
+
* const meta = getRefMetadata(authorId)
|
|
396
|
+
* // => { collection: Users }
|
|
397
|
+
* ```
|
|
398
|
+
*/
|
|
399
|
+
declare function getRefMetadata(schema: unknown): RefMetadata | undefined;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Branded wrapper for accumulator expressions used inside `groupBy`.
|
|
403
|
+
*
|
|
404
|
+
* Carries the MongoDB accumulator expression at runtime and the inferred
|
|
405
|
+
* result type `T` at the type level.
|
|
406
|
+
*
|
|
407
|
+
* @example
|
|
408
|
+
* ```ts
|
|
409
|
+
* const acc: Accumulator<number> = {
|
|
410
|
+
* __accum: true,
|
|
411
|
+
* expr: { $sum: '$price' },
|
|
343
412
|
* }
|
|
344
413
|
* ```
|
|
345
414
|
*/
|
|
346
|
-
type
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
/**
|
|
350
|
-
|
|
351
|
-
/** The relevant options currently set on the existing index. */
|
|
352
|
-
existing: Record<string, unknown>;
|
|
353
|
-
/** The options the schema declares for this index. */
|
|
354
|
-
desired: Record<string, unknown>;
|
|
415
|
+
type Accumulator<T = unknown> = {
|
|
416
|
+
readonly __accum: true;
|
|
417
|
+
readonly expr: Document;
|
|
418
|
+
/** @internal Phantom field — carries the result type at the type level. */
|
|
419
|
+
readonly _type?: T;
|
|
355
420
|
};
|
|
356
421
|
/**
|
|
357
|
-
*
|
|
422
|
+
* Extracts the result type from an `Accumulator<T>`.
|
|
358
423
|
*
|
|
359
|
-
*
|
|
360
|
-
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* type Count = InferAccumulator<Accumulator<number>>
|
|
427
|
+
* // ^? number
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
type InferAccumulator<T> = T extends Accumulator<infer R> ? R : never;
|
|
431
|
+
/**
|
|
432
|
+
* Maps an accumulator spec object to its inferred output shape.
|
|
433
|
+
*
|
|
434
|
+
* Given `{ count: Accumulator<number>, names: Accumulator<string[]> }`,
|
|
435
|
+
* produces `{ count: number, names: string[] }`.
|
|
361
436
|
*
|
|
362
437
|
* @example
|
|
363
438
|
* ```ts
|
|
364
|
-
*
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
*
|
|
439
|
+
* type Spec = {
|
|
440
|
+
* count: Accumulator<number>
|
|
441
|
+
* total: Accumulator<number>
|
|
442
|
+
* }
|
|
443
|
+
* type Result = InferAccumulators<Spec>
|
|
444
|
+
* // ^? { count: number; total: number }
|
|
369
445
|
* ```
|
|
370
446
|
*/
|
|
371
|
-
type
|
|
372
|
-
|
|
373
|
-
created: string[];
|
|
374
|
-
/** Names of indexes that were dropped (or would be dropped in dryRun mode). */
|
|
375
|
-
dropped: string[];
|
|
376
|
-
/** Names of indexes that already existed with matching options — no action taken. */
|
|
377
|
-
skipped: string[];
|
|
378
|
-
/** Indexes whose key matches a desired spec but whose options differ. */
|
|
379
|
-
stale: StaleIndex[];
|
|
447
|
+
type InferAccumulators<T extends Record<string, Accumulator>> = {
|
|
448
|
+
[K in keyof T]: InferAccumulator<T[K]>;
|
|
380
449
|
};
|
|
450
|
+
/**
|
|
451
|
+
* Field reference string prefixed with `$`, constrained to keys of `T`.
|
|
452
|
+
*
|
|
453
|
+
* @example
|
|
454
|
+
* ```ts
|
|
455
|
+
* type OrderRef = FieldRef<{ price: number; qty: number }>
|
|
456
|
+
* // ^? '$price' | '$qty'
|
|
457
|
+
* ```
|
|
458
|
+
*/
|
|
459
|
+
type FieldRef<T> = `$${keyof T & string}`;
|
|
460
|
+
/**
|
|
461
|
+
* Typed accumulator factory passed to the `groupBy` callback.
|
|
462
|
+
*
|
|
463
|
+
* Each method constrains field names to `keyof T & string`, providing
|
|
464
|
+
* IDE autocomplete and compile-time validation. Return types resolve
|
|
465
|
+
* to the actual field type (`T[K]`), not `unknown`.
|
|
466
|
+
*
|
|
467
|
+
* @typeParam T - The current pipeline output document type.
|
|
468
|
+
*
|
|
469
|
+
* @example
|
|
470
|
+
* ```ts
|
|
471
|
+
* users.aggregate()
|
|
472
|
+
* .groupBy('role', acc => ({
|
|
473
|
+
* minSalary: acc.min('salary'), // Accumulator<number>
|
|
474
|
+
* firstName: acc.first('name'), // Accumulator<string>
|
|
475
|
+
* allNames: acc.push('name'), // Accumulator<string[]>
|
|
476
|
+
* count: acc.count(), // Accumulator<number>
|
|
477
|
+
* }))
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
type AccumulatorBuilder<T> = {
|
|
481
|
+
/** Count documents in each group. Always returns `Accumulator<number>`. */
|
|
482
|
+
count(): Accumulator<number>;
|
|
483
|
+
/** Sum a numeric field. Always returns `Accumulator<number>`. */
|
|
484
|
+
sum<K extends keyof T & string>(field: K): Accumulator<number>;
|
|
485
|
+
/** Sum a literal number per document. Always returns `Accumulator<number>`. */
|
|
486
|
+
sum(value: number): Accumulator<number>;
|
|
487
|
+
/** Average a numeric field. Always returns `Accumulator<number>`. */
|
|
488
|
+
avg<K extends keyof T & string>(field: K): Accumulator<number>;
|
|
489
|
+
/** Minimum value of a field. Returns `Accumulator<T[K]>`. */
|
|
490
|
+
min<K extends keyof T & string>(field: K): Accumulator<T[K]>;
|
|
491
|
+
/** Maximum value of a field. Returns `Accumulator<T[K]>`. */
|
|
492
|
+
max<K extends keyof T & string>(field: K): Accumulator<T[K]>;
|
|
493
|
+
/** First value in each group (by document order). Returns `Accumulator<T[K]>`. */
|
|
494
|
+
first<K extends keyof T & string>(field: K): Accumulator<T[K]>;
|
|
495
|
+
/** Last value in each group (by document order). Returns `Accumulator<T[K]>`. */
|
|
496
|
+
last<K extends keyof T & string>(field: K): Accumulator<T[K]>;
|
|
497
|
+
/** Collect values into an array (with duplicates). Returns `Accumulator<T[K][]>`. */
|
|
498
|
+
push<K extends keyof T & string>(field: K): Accumulator<T[K][]>;
|
|
499
|
+
/** Collect unique values into an array. Returns `Accumulator<T[K][]>`. */
|
|
500
|
+
addToSet<K extends keyof T & string>(field: K): Accumulator<T[K][]>;
|
|
501
|
+
};
|
|
502
|
+
/**
|
|
503
|
+
* Resolves the document field type from a `$`-prefixed field reference.
|
|
504
|
+
*
|
|
505
|
+
* @example
|
|
506
|
+
* ```ts
|
|
507
|
+
* type Order = { price: number; name: string }
|
|
508
|
+
* type PriceType = FieldRefType<Order, '$price'>
|
|
509
|
+
* // ^? number
|
|
510
|
+
* ```
|
|
511
|
+
*/
|
|
512
|
+
type FieldRefType<T, F extends string> = F extends `$${infer K}` ? K extends keyof T ? T[K] : never : never;
|
|
513
|
+
/**
|
|
514
|
+
* Output shape of a single-field `groupBy` stage.
|
|
515
|
+
*
|
|
516
|
+
* The `_id` field holds the grouped-by field's value, and the rest of the
|
|
517
|
+
* shape comes from the inferred accumulator types.
|
|
518
|
+
*
|
|
519
|
+
* @example
|
|
520
|
+
* ```ts
|
|
521
|
+
* type Result = GroupByResult<Order, 'status', { count: Accumulator<number> }>
|
|
522
|
+
* // ^? { _id: string; count: number }
|
|
523
|
+
* ```
|
|
524
|
+
*/
|
|
525
|
+
type GroupByResult<T, K extends keyof T, TAccum extends Record<string, Accumulator>> = Prettify<{
|
|
526
|
+
_id: T[K];
|
|
527
|
+
} & InferAccumulators<TAccum>>;
|
|
528
|
+
/**
|
|
529
|
+
* Output shape of a compound (multi-field) `groupBy` stage.
|
|
530
|
+
*
|
|
531
|
+
* The `_id` field is an object with one property per grouped field,
|
|
532
|
+
* and the rest of the shape comes from the inferred accumulator types.
|
|
533
|
+
*
|
|
534
|
+
* @example
|
|
535
|
+
* ```ts
|
|
536
|
+
* type Result = GroupByCompoundResult<Order, 'status' | 'region', { count: Accumulator<number> }>
|
|
537
|
+
* // ^? { _id: Pick<Order, 'status' | 'region'>; count: number }
|
|
538
|
+
* ```
|
|
539
|
+
*/
|
|
540
|
+
type GroupByCompoundResult<T, K extends keyof T, TAccum extends Record<string, Accumulator>> = Prettify<{
|
|
541
|
+
_id: Prettify<Pick<T, K>>;
|
|
542
|
+
} & InferAccumulators<TAccum>>;
|
|
543
|
+
/**
|
|
544
|
+
* Output shape after unwinding an array field.
|
|
545
|
+
*
|
|
546
|
+
* The unwound field's type changes from `Array<E>` to `E`; all other
|
|
547
|
+
* fields are preserved as-is.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* ```ts
|
|
551
|
+
* type Order = { items: string[]; total: number }
|
|
552
|
+
* type Unwound = UnwindResult<Order, 'items'>
|
|
553
|
+
* // ^? { items: string; total: number }
|
|
554
|
+
* ```
|
|
555
|
+
*/
|
|
556
|
+
type UnwindResult<T, K extends keyof T> = {
|
|
557
|
+
[P in keyof T]: P extends K ? (T[P] extends ReadonlyArray<infer E> ? E : T[P]) : T[P];
|
|
558
|
+
};
|
|
559
|
+
/**
|
|
560
|
+
* Narrows document field types based on a filter expression.
|
|
561
|
+
*
|
|
562
|
+
* Inspects each field in the filter for value-constraining operators
|
|
563
|
+
* (`$eq`, `$in`, `$ne`, `$nin`, or direct equality) and narrows the
|
|
564
|
+
* corresponding field type in the output. Fields not mentioned in the
|
|
565
|
+
* filter, or filtered with unsupported operators, keep their original type.
|
|
566
|
+
*
|
|
567
|
+
* Used internally by {@link AggregatePipeline.match} for automatic
|
|
568
|
+
* type narrowing (Tier 2). Requires `as const` on array literals
|
|
569
|
+
* for `$in` / `$nin` inference.
|
|
570
|
+
*
|
|
571
|
+
* @example
|
|
572
|
+
* ```ts
|
|
573
|
+
* type Narrowed = NarrowFromFilter<Employee, { role: 'engineer' }>
|
|
574
|
+
* // ^? { ..., role: 'engineer', ... }
|
|
575
|
+
*
|
|
576
|
+
* type Subset = NarrowFromFilter<Employee, { role: { $in: readonly ['engineer', 'designer'] } }>
|
|
577
|
+
* // ^? { ..., role: 'engineer' | 'designer', ... }
|
|
578
|
+
*
|
|
579
|
+
* type Excluded = NarrowFromFilter<Employee, { role: { $ne: 'intern' } }>
|
|
580
|
+
* // ^? { ..., role: 'engineer' | 'manager' | 'designer', ... }
|
|
581
|
+
* ```
|
|
582
|
+
*/
|
|
583
|
+
type NarrowFromFilter<T, F> = {
|
|
584
|
+
[K in keyof T]: K extends keyof F ? F[K] extends T[K] ? F[K] : F[K] extends {
|
|
585
|
+
$eq: infer V extends T[K];
|
|
586
|
+
} ? V : F[K] extends {
|
|
587
|
+
$in: ReadonlyArray<infer V extends T[K]>;
|
|
588
|
+
} ? V : F[K] extends {
|
|
589
|
+
$ne: infer V extends T[K];
|
|
590
|
+
} ? Exclude<T[K], V> : F[K] extends {
|
|
591
|
+
$nin: ReadonlyArray<infer V extends T[K]>;
|
|
592
|
+
} ? Exclude<T[K], V> : T[K] : T[K];
|
|
593
|
+
};
|
|
594
|
+
/**
|
|
595
|
+
* Extract field keys from a collection definition whose schema fields
|
|
596
|
+
* carry `RefMarker` (i.e. fields that have `.ref()` metadata).
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* ```ts
|
|
600
|
+
* type EmpRefs = RefFields<typeof Employees> // → 'departmentId'
|
|
601
|
+
* ```
|
|
602
|
+
*/
|
|
603
|
+
type RefFields<TDef extends AnyCollection> = {
|
|
604
|
+
[K in keyof TDef['shape'] & string]: TDef['shape'][K] extends RefMarker ? K : never;
|
|
605
|
+
}[keyof TDef['shape'] & string];
|
|
606
|
+
/**
|
|
607
|
+
* Given a collection definition and a ref-bearing field key, extract
|
|
608
|
+
* the target collection type from the `RefMarker<TCollection>` phantom.
|
|
609
|
+
*
|
|
610
|
+
* @example
|
|
611
|
+
* ```ts
|
|
612
|
+
* type Target = ExtractRefCollection<typeof Employees, 'departmentId'>
|
|
613
|
+
* // → typeof Departments
|
|
614
|
+
* ```
|
|
615
|
+
*/
|
|
616
|
+
type ExtractRefCollection<TDef extends AnyCollection, K extends RefFields<TDef>> = TDef['shape'][K] extends RefMarker<infer TCol> ? TCol : never;
|
|
617
|
+
/**
|
|
618
|
+
* Extract the collection name string literal from a collection definition.
|
|
619
|
+
*
|
|
620
|
+
* @example
|
|
621
|
+
* ```ts
|
|
622
|
+
* CollectionName<typeof Departments> // → 'departments'
|
|
623
|
+
* ```
|
|
624
|
+
*/
|
|
625
|
+
type CollectionName<TDef extends AnyCollection> = TDef['name'];
|
|
626
|
+
/**
|
|
627
|
+
* Branded wrapper for computed expressions used inside `addFields`.
|
|
628
|
+
*
|
|
629
|
+
* Carries the MongoDB expression at runtime and the inferred
|
|
630
|
+
* result type `T` at the type level.
|
|
631
|
+
*
|
|
632
|
+
* @example
|
|
633
|
+
* ```ts
|
|
634
|
+
* const yearExpr: Expression<number> = {
|
|
635
|
+
* __expr: true,
|
|
636
|
+
* value: { $year: '$hiredAt' },
|
|
637
|
+
* }
|
|
638
|
+
* ```
|
|
639
|
+
*/
|
|
640
|
+
type Expression<T = unknown> = {
|
|
641
|
+
readonly __expr: true;
|
|
642
|
+
readonly value: Document;
|
|
643
|
+
/** @internal Phantom field — carries the result type at the type level. */
|
|
644
|
+
readonly _type?: T;
|
|
645
|
+
};
|
|
646
|
+
/**
|
|
647
|
+
* Unwrap an `Expression<T>` to its result type `T`.
|
|
648
|
+
* Non-Expression values resolve to `unknown`.
|
|
649
|
+
*
|
|
650
|
+
* @example
|
|
651
|
+
* ```ts
|
|
652
|
+
* type N = InferExpression<Expression<number>> // → number
|
|
653
|
+
* type U = InferExpression<{ $year: string }> // → unknown
|
|
654
|
+
* ```
|
|
655
|
+
*/
|
|
656
|
+
type InferExpression<T> = T extends Expression<infer R> ? R : unknown;
|
|
657
|
+
/**
|
|
658
|
+
* Map an added-fields spec to its resolved output shape.
|
|
659
|
+
*
|
|
660
|
+
* `Expression<V>` values unwrap to `V`. Raw expression objects resolve
|
|
661
|
+
* to `unknown`, signaling that type information is lost.
|
|
662
|
+
*
|
|
663
|
+
* @example
|
|
664
|
+
* ```ts
|
|
665
|
+
* type Spec = { year: Expression<number>; raw: { $year: string } }
|
|
666
|
+
* type Result = InferAddedFields<Spec>
|
|
667
|
+
* // ^? { year: number; raw: unknown }
|
|
668
|
+
* ```
|
|
669
|
+
*/
|
|
670
|
+
type InferAddedFields<T extends Record<string, unknown>> = {
|
|
671
|
+
[K in keyof T]: InferExpression<T[K]>;
|
|
672
|
+
};
|
|
673
|
+
/**
|
|
674
|
+
* Typed expression factory passed to the `addFields` callback.
|
|
675
|
+
*
|
|
676
|
+
* Each method constrains field names to `keyof T & string`, providing
|
|
677
|
+
* IDE autocomplete and compile-time validation. Return types resolve
|
|
678
|
+
* to `Expression<R>` where `R` is the MongoDB operator's output type.
|
|
679
|
+
*
|
|
680
|
+
* @typeParam T - The current pipeline output document type.
|
|
681
|
+
*
|
|
682
|
+
* @example
|
|
683
|
+
* ```ts
|
|
684
|
+
* employees.aggregate()
|
|
685
|
+
* .addFields(expr => ({
|
|
686
|
+
* hireYear: expr.year('hiredAt'), // Expression<number>
|
|
687
|
+
* fullName: expr.concat('name', ' '), // Expression<string>
|
|
688
|
+
* isHighPay: expr.gte('salary', 100_000), // Expression<boolean>
|
|
689
|
+
* }))
|
|
690
|
+
* ```
|
|
691
|
+
*/
|
|
692
|
+
type ExpressionBuilder<T> = {
|
|
693
|
+
/** Add a numeric field and a value. Returns `Expression<number>`. */
|
|
694
|
+
add<K extends keyof T & string>(field: K, value: number | (keyof T & string)): Expression<number>;
|
|
695
|
+
/** Subtract a value from a numeric field. Returns `Expression<number>`. */
|
|
696
|
+
subtract<K extends keyof T & string>(field: K, value: number | (keyof T & string)): Expression<number>;
|
|
697
|
+
/** Multiply a numeric field by a value. Returns `Expression<number>`. */
|
|
698
|
+
multiply<K extends keyof T & string>(field: K, value: number | (keyof T & string)): Expression<number>;
|
|
699
|
+
/** Divide a numeric field by a value. Returns `Expression<number>`. */
|
|
700
|
+
divide<K extends keyof T & string>(field: K, value: number | (keyof T & string)): Expression<number>;
|
|
701
|
+
/** Modulo of a numeric field. Returns `Expression<number>`. */
|
|
702
|
+
mod<K extends keyof T & string>(field: K, value: number | (keyof T & string)): Expression<number>;
|
|
703
|
+
/** Absolute value of a numeric field. Returns `Expression<number>`. */
|
|
704
|
+
abs<K extends keyof T & string>(field: K): Expression<number>;
|
|
705
|
+
/** Ceiling of a numeric field. Returns `Expression<number>`. */
|
|
706
|
+
ceil<K extends keyof T & string>(field: K): Expression<number>;
|
|
707
|
+
/** Floor of a numeric field. Returns `Expression<number>`. */
|
|
708
|
+
floor<K extends keyof T & string>(field: K): Expression<number>;
|
|
709
|
+
/** Round a numeric field to N decimal places. Returns `Expression<number>`. */
|
|
710
|
+
round<K extends keyof T & string>(field: K, place?: number): Expression<number>;
|
|
711
|
+
/** Concatenate field values and literal strings. Returns `Expression<string>`. */
|
|
712
|
+
concat(...parts: Array<(keyof T & string) | string>): Expression<string>;
|
|
713
|
+
/** Convert a string field to lowercase. Returns `Expression<string>`. */
|
|
714
|
+
toLower<K extends keyof T & string>(field: K): Expression<string>;
|
|
715
|
+
/** Convert a string field to uppercase. Returns `Expression<string>`. */
|
|
716
|
+
toUpper<K extends keyof T & string>(field: K): Expression<string>;
|
|
717
|
+
/** Trim whitespace from a string field. Returns `Expression<string>`. */
|
|
718
|
+
trim<K extends keyof T & string>(field: K): Expression<string>;
|
|
719
|
+
/** Extract a substring from a string field. Returns `Expression<string>`. */
|
|
720
|
+
substr<K extends keyof T & string>(field: K, start: number, length: number): Expression<string>;
|
|
721
|
+
/** Test equality of a field against a value. Returns `Expression<boolean>`. */
|
|
722
|
+
eq<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
723
|
+
/** Test if a field is greater than a value. Returns `Expression<boolean>`. */
|
|
724
|
+
gt<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
725
|
+
/** Test if a field is greater than or equal to a value. Returns `Expression<boolean>`. */
|
|
726
|
+
gte<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
727
|
+
/** Test if a field is less than a value. Returns `Expression<boolean>`. */
|
|
728
|
+
lt<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
729
|
+
/** Test if a field is less than or equal to a value. Returns `Expression<boolean>`. */
|
|
730
|
+
lte<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
731
|
+
/** Test if a field is not equal to a value. Returns `Expression<boolean>`. */
|
|
732
|
+
ne<K extends keyof T & string>(field: K, value: T[K]): Expression<boolean>;
|
|
733
|
+
/** Extract year from a date field. Returns `Expression<number>`. */
|
|
734
|
+
year<K extends keyof T & string>(field: K): Expression<number>;
|
|
735
|
+
/** Extract month (1-12) from a date field. Returns `Expression<number>`. */
|
|
736
|
+
month<K extends keyof T & string>(field: K): Expression<number>;
|
|
737
|
+
/** Extract day of month (1-31) from a date field. Returns `Expression<number>`. */
|
|
738
|
+
dayOfMonth<K extends keyof T & string>(field: K): Expression<number>;
|
|
739
|
+
/** Count elements in an array field. Returns `Expression<number>`. */
|
|
740
|
+
size<K extends keyof T & string>(field: K): Expression<number>;
|
|
741
|
+
/** Conditional expression. Returns `Expression<TThen | TElse>`. */
|
|
742
|
+
cond<TThen, TElse>(condition: Expression<boolean>, thenValue: TThen, elseValue: TElse): Expression<TThen | TElse>;
|
|
743
|
+
/** Replace null/missing field with a default. Returns `Expression<NonNullable<T[K]> | TDefault>`. */
|
|
744
|
+
ifNull<K extends keyof T & string, TDefault>(field: K, fallback: TDefault): Expression<NonNullable<T[K]> | TDefault>;
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Counts the number of documents in each group.
|
|
749
|
+
*
|
|
750
|
+
* Equivalent to `{ $sum: 1 }` in a MongoDB `$group` stage.
|
|
751
|
+
*
|
|
752
|
+
* @returns An `Accumulator<number>` that counts documents.
|
|
753
|
+
*
|
|
754
|
+
* @example
|
|
755
|
+
* ```ts
|
|
756
|
+
* const pipeline = orders.aggregate()
|
|
757
|
+
* .groupBy('status', { count: $count() })
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
declare const $count: () => Accumulator<number>;
|
|
761
|
+
/**
|
|
762
|
+
* Sums numeric values across documents in each group.
|
|
763
|
+
*
|
|
764
|
+
* Accepts either a `$`-prefixed field reference or a literal number.
|
|
765
|
+
*
|
|
766
|
+
* @param field - A `$field` reference to a numeric field, or a literal number.
|
|
767
|
+
* @returns An `Accumulator<number>`.
|
|
768
|
+
*
|
|
769
|
+
* @example
|
|
770
|
+
* ```ts
|
|
771
|
+
* const pipeline = orders.aggregate()
|
|
772
|
+
* .groupBy('status', {
|
|
773
|
+
* total: $sum('$amount'),
|
|
774
|
+
* fixed: $sum(1),
|
|
775
|
+
* })
|
|
776
|
+
* ```
|
|
777
|
+
*/
|
|
778
|
+
declare const $sum: (field: `$${string}` | number) => Accumulator<number>;
|
|
779
|
+
/**
|
|
780
|
+
* Computes the average of numeric values across documents in each group.
|
|
781
|
+
*
|
|
782
|
+
* @param field - A `$field` reference to a numeric field.
|
|
783
|
+
* @returns An `Accumulator<number>`.
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```ts
|
|
787
|
+
* const pipeline = orders.aggregate()
|
|
788
|
+
* .groupBy('category', { avgPrice: $avg('$price') })
|
|
789
|
+
* ```
|
|
790
|
+
*/
|
|
791
|
+
declare const $avg: (field: `$${string}`) => Accumulator<number>;
|
|
792
|
+
/**
|
|
793
|
+
* Returns the minimum value across documents in each group.
|
|
794
|
+
*
|
|
795
|
+
* For full type safety, prefer the callback builder (`acc.min('price')`).
|
|
796
|
+
* The standalone form accepts an explicit result type `R` for manual typing.
|
|
797
|
+
*
|
|
798
|
+
* @typeParam R - The expected result type (defaults to `unknown`).
|
|
799
|
+
* @param field - A `$field` reference.
|
|
800
|
+
* @returns An `Accumulator<R>`.
|
|
801
|
+
*
|
|
802
|
+
* @example
|
|
803
|
+
* ```ts
|
|
804
|
+
* // Tier 2 — explicit result type
|
|
805
|
+
* const pipeline = orders.aggregate()
|
|
806
|
+
* .groupBy('category', { cheapest: $min<number>('$price') })
|
|
807
|
+
*
|
|
808
|
+
* // Tier 1 — callback builder (recommended)
|
|
809
|
+
* orders.aggregate()
|
|
810
|
+
* .groupBy('category', acc => ({ cheapest: acc.min('price') }))
|
|
811
|
+
* ```
|
|
812
|
+
*/
|
|
813
|
+
declare const $min: <R = unknown>(field: `$${string}`) => Accumulator<R>;
|
|
814
|
+
/**
|
|
815
|
+
* Returns the maximum value across documents in each group.
|
|
816
|
+
*
|
|
817
|
+
* For full type safety, prefer the callback builder (`acc.max('price')`).
|
|
818
|
+
* The standalone form accepts an explicit result type `R` for manual typing.
|
|
819
|
+
*
|
|
820
|
+
* @typeParam R - The expected result type (defaults to `unknown`).
|
|
821
|
+
* @param field - A `$field` reference.
|
|
822
|
+
* @returns An `Accumulator<R>`.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* ```ts
|
|
826
|
+
* // Tier 2 — explicit result type
|
|
827
|
+
* const pipeline = orders.aggregate()
|
|
828
|
+
* .groupBy('category', { priciest: $max<number>('$price') })
|
|
829
|
+
*
|
|
830
|
+
* // Tier 1 — callback builder (recommended)
|
|
831
|
+
* orders.aggregate()
|
|
832
|
+
* .groupBy('category', acc => ({ priciest: acc.max('price') }))
|
|
833
|
+
* ```
|
|
834
|
+
*/
|
|
835
|
+
declare const $max: <R = unknown>(field: `$${string}`) => Accumulator<R>;
|
|
836
|
+
/**
|
|
837
|
+
* Returns the first value in each group according to the document order.
|
|
838
|
+
*
|
|
839
|
+
* For full type safety, prefer the callback builder (`acc.first('name')`).
|
|
840
|
+
* The standalone form accepts an explicit result type `R` for manual typing.
|
|
841
|
+
*
|
|
842
|
+
* @typeParam R - The expected result type (defaults to `unknown`).
|
|
843
|
+
* @param field - A `$field` reference.
|
|
844
|
+
* @returns An `Accumulator<R>`.
|
|
845
|
+
*
|
|
846
|
+
* @example
|
|
847
|
+
* ```ts
|
|
848
|
+
* // Tier 2 — explicit result type
|
|
849
|
+
* const pipeline = orders.aggregate()
|
|
850
|
+
* .sort({ createdAt: 1 })
|
|
851
|
+
* .groupBy('status', { earliest: $first<Date>('$createdAt') })
|
|
852
|
+
*
|
|
853
|
+
* // Tier 1 — callback builder (recommended)
|
|
854
|
+
* orders.aggregate()
|
|
855
|
+
* .sort({ createdAt: 1 })
|
|
856
|
+
* .groupBy('status', acc => ({ earliest: acc.first('createdAt') }))
|
|
857
|
+
* ```
|
|
858
|
+
*/
|
|
859
|
+
declare const $first: <R = unknown>(field: `$${string}`) => Accumulator<R>;
|
|
860
|
+
/**
|
|
861
|
+
* Returns the last value in each group according to the document order.
|
|
862
|
+
*
|
|
863
|
+
* For full type safety, prefer the callback builder (`acc.last('name')`).
|
|
864
|
+
* The standalone form accepts an explicit result type `R` for manual typing.
|
|
865
|
+
*
|
|
866
|
+
* @typeParam R - The expected result type (defaults to `unknown`).
|
|
867
|
+
* @param field - A `$field` reference.
|
|
868
|
+
* @returns An `Accumulator<R>`.
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```ts
|
|
872
|
+
* // Tier 2 — explicit result type
|
|
873
|
+
* const pipeline = orders.aggregate()
|
|
874
|
+
* .sort({ createdAt: -1 })
|
|
875
|
+
* .groupBy('status', { latest: $last<Date>('$createdAt') })
|
|
876
|
+
*
|
|
877
|
+
* // Tier 1 — callback builder (recommended)
|
|
878
|
+
* orders.aggregate()
|
|
879
|
+
* .sort({ createdAt: -1 })
|
|
880
|
+
* .groupBy('status', acc => ({ latest: acc.last('createdAt') }))
|
|
881
|
+
* ```
|
|
882
|
+
*/
|
|
883
|
+
declare const $last: <R = unknown>(field: `$${string}`) => Accumulator<R>;
|
|
884
|
+
/**
|
|
885
|
+
* Pushes values into an array for each group.
|
|
886
|
+
*
|
|
887
|
+
* May contain duplicates. Use `$addToSet` for unique values.
|
|
888
|
+
* For full type safety, prefer the callback builder (`acc.push('name')`).
|
|
889
|
+
*
|
|
890
|
+
* @typeParam R - The element type (defaults to `unknown`).
|
|
891
|
+
* @param field - A `$field` reference.
|
|
892
|
+
* @returns An `Accumulator<R[]>`.
|
|
893
|
+
*
|
|
894
|
+
* @example
|
|
895
|
+
* ```ts
|
|
896
|
+
* // Tier 2 — explicit element type
|
|
897
|
+
* const pipeline = orders.aggregate()
|
|
898
|
+
* .groupBy('status', { items: $push<string>('$name') })
|
|
899
|
+
*
|
|
900
|
+
* // Tier 1 — callback builder (recommended)
|
|
901
|
+
* orders.aggregate()
|
|
902
|
+
* .groupBy('status', acc => ({ items: acc.push('name') }))
|
|
903
|
+
* ```
|
|
904
|
+
*/
|
|
905
|
+
declare const $push: <R = unknown>(field: `$${string}`) => Accumulator<R[]>;
|
|
906
|
+
/**
|
|
907
|
+
* Collects unique values into an array for each group (set semantics).
|
|
908
|
+
*
|
|
909
|
+
* Like `$push` but deduplicates.
|
|
910
|
+
* For full type safety, prefer the callback builder (`acc.addToSet('tag')`).
|
|
911
|
+
*
|
|
912
|
+
* @typeParam R - The element type (defaults to `unknown`).
|
|
913
|
+
* @param field - A `$field` reference.
|
|
914
|
+
* @returns An `Accumulator<R[]>`.
|
|
915
|
+
*
|
|
916
|
+
* @example
|
|
917
|
+
* ```ts
|
|
918
|
+
* // Tier 2 — explicit element type
|
|
919
|
+
* const pipeline = orders.aggregate()
|
|
920
|
+
* .groupBy('category', { uniqueTags: $addToSet<string>('$tag') })
|
|
921
|
+
*
|
|
922
|
+
* // Tier 1 — callback builder (recommended)
|
|
923
|
+
* orders.aggregate()
|
|
924
|
+
* .groupBy('category', acc => ({ uniqueTags: acc.addToSet('tag') }))
|
|
925
|
+
* ```
|
|
926
|
+
*/
|
|
927
|
+
declare const $addToSet: <R = unknown>(field: `$${string}`) => Accumulator<R[]>;
|
|
928
|
+
/**
|
|
929
|
+
* Create a typed accumulator builder for use inside `groupBy` callbacks.
|
|
930
|
+
*
|
|
931
|
+
* The builder adds the `$` prefix to field names automatically and returns
|
|
932
|
+
* properly typed `Accumulator<T[K]>` values. Primarily used internally by
|
|
933
|
+
* `AggregatePipeline.groupBy` — most users interact with the builder via
|
|
934
|
+
* the callback parameter rather than calling this directly.
|
|
935
|
+
*
|
|
936
|
+
* @typeParam T - The current pipeline output document type.
|
|
937
|
+
* @returns An `AccumulatorBuilder<T>` with methods for each MongoDB accumulator.
|
|
938
|
+
*
|
|
939
|
+
* @example
|
|
940
|
+
* ```ts
|
|
941
|
+
* const acc = createAccumulatorBuilder<{ salary: number; name: string }>()
|
|
942
|
+
* acc.min('salary') // { __accum: true, expr: { $min: '$salary' } }
|
|
943
|
+
* acc.push('name') // { __accum: true, expr: { $push: '$name' } }
|
|
944
|
+
* ```
|
|
945
|
+
*/
|
|
946
|
+
declare function createAccumulatorBuilder<T>(): AccumulatorBuilder<T>;
|
|
947
|
+
/**
|
|
948
|
+
* Create a typed expression builder for use inside `addFields` callbacks.
|
|
949
|
+
*
|
|
950
|
+
* The builder adds the `$` prefix to field names automatically and returns
|
|
951
|
+
* properly typed `Expression<T>` values. Primarily used internally by
|
|
952
|
+
* `AggregatePipeline.addFields` — most users interact with the builder via
|
|
953
|
+
* the callback parameter rather than calling this directly.
|
|
954
|
+
*
|
|
955
|
+
* @typeParam T - The current pipeline output document type.
|
|
956
|
+
* @returns An `ExpressionBuilder<T>` with methods for each MongoDB expression operator.
|
|
957
|
+
*
|
|
958
|
+
* @example
|
|
959
|
+
* ```ts
|
|
960
|
+
* const expr = createExpressionBuilder<{ salary: number; name: string; hiredAt: Date }>()
|
|
961
|
+
* expr.year('hiredAt') // { __expr: true, value: { $year: '$hiredAt' } }
|
|
962
|
+
* expr.multiply('salary', 0.9) // { __expr: true, value: { $multiply: ['$salary', 0.9] } }
|
|
963
|
+
* ```
|
|
964
|
+
*/
|
|
965
|
+
declare function createExpressionBuilder<T>(): ExpressionBuilder<T>;
|
|
381
966
|
|
|
382
967
|
/**
|
|
383
968
|
* Comparison operators for a field value of type `V`.
|
|
@@ -409,10 +994,10 @@ type ComparisonOperators<V> = {
|
|
|
409
994
|
$lt?: V;
|
|
410
995
|
/** Matches values less than or equal to the specified value. */
|
|
411
996
|
$lte?: V;
|
|
412
|
-
/** Matches any value in the specified array. */
|
|
413
|
-
$in?: V[];
|
|
414
|
-
/** Matches none of the values in the specified array. */
|
|
415
|
-
$nin?: V[];
|
|
997
|
+
/** Matches any value in the specified array. Accepts `as const` arrays for type narrowing. */
|
|
998
|
+
$in?: readonly V[];
|
|
999
|
+
/** Matches none of the values in the specified array. Accepts `as const` arrays for type narrowing. */
|
|
1000
|
+
$nin?: readonly V[];
|
|
416
1001
|
/** Matches documents where the field exists (`true`) or does not exist (`false`). */
|
|
417
1002
|
$exists?: boolean;
|
|
418
1003
|
/** Negates a comparison operator. */
|
|
@@ -1240,6 +1825,82 @@ declare function updateMany<TDef extends AnyCollection>(handle: CollectionHandle
|
|
|
1240
1825
|
*/
|
|
1241
1826
|
declare function findOneAndUpdate<TDef extends AnyCollection>(handle: CollectionHandle<TDef>, filter: TypedFilter<InferDocument<TDef>>, update: TypedUpdateFilter<InferDocument<TDef>>, options?: FindOneAndUpdateOptions): Promise<InferDocument<TDef> | null>;
|
|
1242
1827
|
|
|
1828
|
+
/**
|
|
1829
|
+
* Options controlling how {@link syncIndexes} behaves.
|
|
1830
|
+
*
|
|
1831
|
+
* @example
|
|
1832
|
+
* ```ts
|
|
1833
|
+
* await users.syncIndexes({ dryRun: true })
|
|
1834
|
+
* await users.syncIndexes({ dropOrphaned: true })
|
|
1835
|
+
* ```
|
|
1836
|
+
*/
|
|
1837
|
+
type SyncIndexesOptions = {
|
|
1838
|
+
/**
|
|
1839
|
+
* When `true`, compute the diff without actually creating, dropping, or
|
|
1840
|
+
* modifying any indexes. The returned {@link SyncIndexesResult} shows what
|
|
1841
|
+
* *would* happen.
|
|
1842
|
+
*/
|
|
1843
|
+
dryRun?: boolean;
|
|
1844
|
+
/**
|
|
1845
|
+
* When `true`, drop indexes that exist in MongoDB but are not declared in
|
|
1846
|
+
* the schema. Also drops and recreates stale indexes (same key, different
|
|
1847
|
+
* options). When `false` (the default), orphaned and stale indexes are
|
|
1848
|
+
* reported but left untouched.
|
|
1849
|
+
*/
|
|
1850
|
+
dropOrphaned?: boolean;
|
|
1851
|
+
};
|
|
1852
|
+
/**
|
|
1853
|
+
* Describes an index whose key matches a desired index but whose options differ.
|
|
1854
|
+
*
|
|
1855
|
+
* Returned in {@link SyncIndexesResult.stale} so the caller can decide whether
|
|
1856
|
+
* to manually reconcile or re-run with `dropOrphaned: true`.
|
|
1857
|
+
*
|
|
1858
|
+
* @example
|
|
1859
|
+
* ```ts
|
|
1860
|
+
* const result = await users.syncIndexes()
|
|
1861
|
+
* for (const s of result.stale) {
|
|
1862
|
+
* console.log(`${s.name}: key=${JSON.stringify(s.key)}`)
|
|
1863
|
+
* console.log(` existing=${JSON.stringify(s.existing)}`)
|
|
1864
|
+
* console.log(` desired=${JSON.stringify(s.desired)}`)
|
|
1865
|
+
* }
|
|
1866
|
+
* ```
|
|
1867
|
+
*/
|
|
1868
|
+
type StaleIndex = {
|
|
1869
|
+
/** The MongoDB index name (e.g. `'email_1'`). */
|
|
1870
|
+
name: string;
|
|
1871
|
+
/** The index key spec (e.g. `{ email: 1 }`). */
|
|
1872
|
+
key: Record<string, 1 | -1 | 'text'>;
|
|
1873
|
+
/** The relevant options currently set on the existing index. */
|
|
1874
|
+
existing: Record<string, unknown>;
|
|
1875
|
+
/** The options the schema declares for this index. */
|
|
1876
|
+
desired: Record<string, unknown>;
|
|
1877
|
+
};
|
|
1878
|
+
/**
|
|
1879
|
+
* The result of a {@link syncIndexes} call.
|
|
1880
|
+
*
|
|
1881
|
+
* Every array contains index names. `stale` contains full details so the
|
|
1882
|
+
* caller can inspect the mismatch.
|
|
1883
|
+
*
|
|
1884
|
+
* @example
|
|
1885
|
+
* ```ts
|
|
1886
|
+
* const result = await users.syncIndexes()
|
|
1887
|
+
* console.log('created:', result.created)
|
|
1888
|
+
* console.log('dropped:', result.dropped)
|
|
1889
|
+
* console.log('skipped:', result.skipped)
|
|
1890
|
+
* console.log('stale:', result.stale.map(s => s.name))
|
|
1891
|
+
* ```
|
|
1892
|
+
*/
|
|
1893
|
+
type SyncIndexesResult = {
|
|
1894
|
+
/** Names of indexes that were created (or would be created in dryRun mode). */
|
|
1895
|
+
created: string[];
|
|
1896
|
+
/** Names of indexes that were dropped (or would be dropped in dryRun mode). */
|
|
1897
|
+
dropped: string[];
|
|
1898
|
+
/** Names of indexes that already existed with matching options — no action taken. */
|
|
1899
|
+
skipped: string[];
|
|
1900
|
+
/** Indexes whose key matches a desired spec but whose options differ. */
|
|
1901
|
+
stale: StaleIndex[];
|
|
1902
|
+
};
|
|
1903
|
+
|
|
1243
1904
|
/**
|
|
1244
1905
|
* Typed wrapper around a MongoDB driver `Collection`.
|
|
1245
1906
|
*
|
|
@@ -1499,14 +2160,578 @@ declare class CollectionHandle<TDef extends AnyCollection = AnyCollection> {
|
|
|
1499
2160
|
*
|
|
1500
2161
|
* @example
|
|
1501
2162
|
* ```ts
|
|
1502
|
-
* // Dry run to preview changes without modifying the database
|
|
1503
|
-
* const diff = await users.syncIndexes({ dryRun: true })
|
|
1504
|
-
* console.log('Would create:', diff.created)
|
|
1505
|
-
* console.log('Would drop:', diff.dropped)
|
|
2163
|
+
* // Dry run to preview changes without modifying the database
|
|
2164
|
+
* const diff = await users.syncIndexes({ dryRun: true })
|
|
2165
|
+
* console.log('Would create:', diff.created)
|
|
2166
|
+
* console.log('Would drop:', diff.dropped)
|
|
2167
|
+
* ```
|
|
2168
|
+
*/
|
|
2169
|
+
syncIndexes(options?: SyncIndexesOptions): Promise<SyncIndexesResult>;
|
|
2170
|
+
/**
|
|
2171
|
+
* Start a type-safe aggregation pipeline on this collection.
|
|
2172
|
+
*
|
|
2173
|
+
* Returns a fluent pipeline builder that tracks the output document
|
|
2174
|
+
* shape through each stage. The pipeline is lazy — no query executes
|
|
2175
|
+
* until a terminal method (`toArray`, `for await`, `explain`) is called.
|
|
2176
|
+
*
|
|
2177
|
+
* @returns A new pipeline builder starting with this collection's document type.
|
|
2178
|
+
*
|
|
2179
|
+
* @example
|
|
2180
|
+
* ```ts
|
|
2181
|
+
* const users = db.use(Users)
|
|
2182
|
+
* const result = await users.aggregate()
|
|
2183
|
+
* .match({ role: 'admin' })
|
|
2184
|
+
* .groupBy('role', { count: $count() })
|
|
2185
|
+
* .toArray()
|
|
2186
|
+
* ```
|
|
2187
|
+
*/
|
|
2188
|
+
aggregate(): AggregatePipeline<TDef, InferDocument<TDef>>;
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
* Immutable aggregation pipeline builder for type-safe MongoDB aggregations.
|
|
2193
|
+
*
|
|
2194
|
+
* Each stage method returns a **new** `AggregatePipeline` instance — the
|
|
2195
|
+
* original is never mutated. This makes it safe to branch from a shared base
|
|
2196
|
+
* pipeline without cross-contamination.
|
|
2197
|
+
*
|
|
2198
|
+
* Use {@link aggregate} to create a pipeline from a {@link CollectionHandle},
|
|
2199
|
+
* or call `raw()` to append arbitrary stages.
|
|
2200
|
+
*
|
|
2201
|
+
* @typeParam TDef - The collection definition type, used to derive document types.
|
|
2202
|
+
* @typeParam TOutput - The current output document type (changes as stages transform the shape).
|
|
2203
|
+
*
|
|
2204
|
+
* @example
|
|
2205
|
+
* ```ts
|
|
2206
|
+
* const results = await aggregate(users)
|
|
2207
|
+
* .raw({ $match: { role: 'admin' } })
|
|
2208
|
+
* .raw({ $sort: { name: 1 } })
|
|
2209
|
+
* .toArray()
|
|
2210
|
+
* ```
|
|
2211
|
+
*/
|
|
2212
|
+
declare class AggregatePipeline<TDef extends AnyCollection, TOutput> {
|
|
2213
|
+
protected readonly definition: TDef;
|
|
2214
|
+
private readonly nativeCollection;
|
|
2215
|
+
private readonly stages;
|
|
2216
|
+
constructor(definition: TDef, nativeCollection: Collection<InferDocument<TDef>>, stages: Document[]);
|
|
2217
|
+
/**
|
|
2218
|
+
* Append an arbitrary aggregation stage to the pipeline (escape hatch).
|
|
2219
|
+
*
|
|
2220
|
+
* Returns a new pipeline instance with the stage appended — the
|
|
2221
|
+
* original pipeline is not modified.
|
|
2222
|
+
*
|
|
2223
|
+
* Optionally accepts a type parameter `TNew` to change the output
|
|
2224
|
+
* type when the stage transforms the document shape.
|
|
2225
|
+
*
|
|
2226
|
+
* @typeParam TNew - The output type after this stage. Defaults to the current output type.
|
|
2227
|
+
* @param stage - A raw MongoDB aggregation stage document (e.g. `{ $match: { ... } }`).
|
|
2228
|
+
* @returns A new pipeline with the stage appended.
|
|
2229
|
+
*
|
|
2230
|
+
* @example
|
|
2231
|
+
* ```ts
|
|
2232
|
+
* const admins = aggregate(users)
|
|
2233
|
+
* .raw({ $match: { role: 'admin' } })
|
|
2234
|
+
* .toArray()
|
|
2235
|
+
* ```
|
|
2236
|
+
*
|
|
2237
|
+
* @example
|
|
2238
|
+
* ```ts
|
|
2239
|
+
* // Change output type with a $project stage
|
|
2240
|
+
* const names = aggregate(users)
|
|
2241
|
+
* .raw<{ name: string }>({ $project: { name: 1, _id: 0 } })
|
|
2242
|
+
* .toArray()
|
|
2243
|
+
* ```
|
|
2244
|
+
*/
|
|
2245
|
+
raw<TNew = TOutput>(stage: Document): AggregatePipeline<TDef, TNew>;
|
|
2246
|
+
/**
|
|
2247
|
+
* Execute the pipeline and return all results as an array.
|
|
2248
|
+
*
|
|
2249
|
+
* @returns A promise resolving to the array of output documents.
|
|
2250
|
+
*
|
|
2251
|
+
* @example
|
|
2252
|
+
* ```ts
|
|
2253
|
+
* const results = await aggregate(users)
|
|
2254
|
+
* .raw({ $match: { age: { $gte: 18 } } })
|
|
2255
|
+
* .toArray()
|
|
2256
|
+
* ```
|
|
2257
|
+
*/
|
|
2258
|
+
toArray(): Promise<TOutput[]>;
|
|
2259
|
+
/**
|
|
2260
|
+
* Stream pipeline results one document at a time via `for await...of`.
|
|
2261
|
+
*
|
|
2262
|
+
* @returns An async generator yielding output documents.
|
|
2263
|
+
*
|
|
2264
|
+
* @example
|
|
2265
|
+
* ```ts
|
|
2266
|
+
* for await (const user of aggregate(users).raw({ $match: { role: 'admin' } })) {
|
|
2267
|
+
* console.log(user.name)
|
|
2268
|
+
* }
|
|
2269
|
+
* ```
|
|
2270
|
+
*/
|
|
2271
|
+
[Symbol.asyncIterator](): AsyncGenerator<TOutput>;
|
|
2272
|
+
/**
|
|
2273
|
+
* Return the query execution plan without running the pipeline.
|
|
2274
|
+
*
|
|
2275
|
+
* Useful for debugging and understanding how MongoDB will process
|
|
2276
|
+
* the pipeline stages.
|
|
2277
|
+
*
|
|
2278
|
+
* @returns A promise resolving to the explain output document.
|
|
2279
|
+
*
|
|
2280
|
+
* @example
|
|
2281
|
+
* ```ts
|
|
2282
|
+
* const plan = await aggregate(users)
|
|
2283
|
+
* .raw({ $match: { role: 'admin' } })
|
|
2284
|
+
* .explain()
|
|
2285
|
+
* console.log(plan)
|
|
2286
|
+
* ```
|
|
2287
|
+
*/
|
|
2288
|
+
explain(): Promise<Document>;
|
|
2289
|
+
/**
|
|
2290
|
+
* Filter documents using a type-safe match expression.
|
|
2291
|
+
*
|
|
2292
|
+
* Appends a `$match` stage to the pipeline. The filter is constrained
|
|
2293
|
+
* to the current output type, so only valid fields and operators are accepted.
|
|
2294
|
+
*
|
|
2295
|
+
* Supports two forms of type narrowing:
|
|
2296
|
+
*
|
|
2297
|
+
* **Tier 1 — Explicit type parameter:**
|
|
2298
|
+
* ```ts
|
|
2299
|
+
* .match<{ role: 'engineer' | 'designer' }>({ role: { $in: ['engineer', 'designer'] } })
|
|
2300
|
+
* // role narrows to 'engineer' | 'designer'
|
|
2301
|
+
* ```
|
|
2302
|
+
*
|
|
2303
|
+
* **Tier 2 — Automatic inference from filter literals:**
|
|
2304
|
+
* ```ts
|
|
2305
|
+
* .match({ role: 'engineer' }) // role narrows to 'engineer'
|
|
2306
|
+
* .match({ role: { $ne: 'intern' } }) // role narrows to Exclude<Role, 'intern'>
|
|
2307
|
+
* .match({ role: { $in: ['engineer', 'designer'] as const } }) // needs as const
|
|
2308
|
+
* ```
|
|
2309
|
+
*
|
|
2310
|
+
* When no type parameter is provided and the filter doesn't contain
|
|
2311
|
+
* inferrable literals, the output type is unchanged (backward compatible).
|
|
2312
|
+
*
|
|
2313
|
+
* @typeParam TNarrow - Optional object mapping field names to narrowed types. Must be a subtype of the corresponding fields in TOutput.
|
|
2314
|
+
* @typeParam F - Inferred from the filter argument. Do not provide explicitly.
|
|
2315
|
+
* @param filter - A type-safe filter for the current output type.
|
|
2316
|
+
* @returns A new pipeline with the `$match` stage appended and output type narrowed.
|
|
2317
|
+
*
|
|
2318
|
+
* @example
|
|
2319
|
+
* ```ts
|
|
2320
|
+
* // Explicit narrowing
|
|
2321
|
+
* const filtered = await users.aggregate()
|
|
2322
|
+
* .match<{ role: 'engineer' }>({ role: 'engineer' })
|
|
2323
|
+
* .toArray()
|
|
2324
|
+
* // filtered[0].role → 'engineer'
|
|
2325
|
+
*
|
|
2326
|
+
* // Automatic narrowing with $in (requires as const)
|
|
2327
|
+
* const subset = await users.aggregate()
|
|
2328
|
+
* .match({ role: { $in: ['engineer', 'designer'] as const } })
|
|
2329
|
+
* .toArray()
|
|
2330
|
+
* // subset[0].role → 'engineer' | 'designer'
|
|
2331
|
+
* ```
|
|
2332
|
+
*/
|
|
2333
|
+
match<TNarrow extends {
|
|
2334
|
+
[K in keyof TNarrow]: K extends keyof TOutput ? TOutput[K] : never;
|
|
2335
|
+
} = {}, F extends TypedFilter<TOutput> = TypedFilter<TOutput>>(filter: F): AggregatePipeline<TDef, Prettify<Omit<NarrowFromFilter<TOutput, F>, keyof TNarrow> & TNarrow>>;
|
|
2336
|
+
/**
|
|
2337
|
+
* Sort documents by one or more fields.
|
|
2338
|
+
*
|
|
2339
|
+
* Appends a `$sort` stage. Keys are constrained to `keyof TOutput & string`
|
|
2340
|
+
* and values must be `1` (ascending) or `-1` (descending).
|
|
2341
|
+
*
|
|
2342
|
+
* @param spec - A sort specification mapping field names to sort direction.
|
|
2343
|
+
* @returns A new pipeline with the `$sort` stage appended.
|
|
2344
|
+
*
|
|
2345
|
+
* @example
|
|
2346
|
+
* ```ts
|
|
2347
|
+
* const sorted = await aggregate(users)
|
|
2348
|
+
* .sort({ age: -1, name: 1 })
|
|
2349
|
+
* .toArray()
|
|
2350
|
+
* ```
|
|
2351
|
+
*/
|
|
2352
|
+
sort(spec: Partial<Record<keyof TOutput & string, 1 | -1>>): AggregatePipeline<TDef, TOutput>;
|
|
2353
|
+
/**
|
|
2354
|
+
* Skip a number of documents in the pipeline.
|
|
2355
|
+
*
|
|
2356
|
+
* Appends a `$skip` stage. Commonly used with {@link limit} for pagination.
|
|
2357
|
+
*
|
|
2358
|
+
* @param n - The number of documents to skip.
|
|
2359
|
+
* @returns A new pipeline with the `$skip` stage appended.
|
|
2360
|
+
*
|
|
2361
|
+
* @example
|
|
2362
|
+
* ```ts
|
|
2363
|
+
* // Page 2 (10 items per page)
|
|
2364
|
+
* const page2 = await aggregate(users)
|
|
2365
|
+
* .sort({ name: 1 })
|
|
2366
|
+
* .skip(10)
|
|
2367
|
+
* .limit(10)
|
|
2368
|
+
* .toArray()
|
|
2369
|
+
* ```
|
|
2370
|
+
*/
|
|
2371
|
+
skip(n: number): AggregatePipeline<TDef, TOutput>;
|
|
2372
|
+
/**
|
|
2373
|
+
* Limit the number of documents passing through the pipeline.
|
|
2374
|
+
*
|
|
2375
|
+
* Appends a `$limit` stage. Commonly used with {@link skip} for pagination,
|
|
2376
|
+
* or after {@link sort} to get top/bottom N results.
|
|
2377
|
+
*
|
|
2378
|
+
* @param n - The maximum number of documents to pass through.
|
|
2379
|
+
* @returns A new pipeline with the `$limit` stage appended.
|
|
2380
|
+
*
|
|
2381
|
+
* @example
|
|
2382
|
+
* ```ts
|
|
2383
|
+
* const top5 = await aggregate(users)
|
|
2384
|
+
* .sort({ score: -1 })
|
|
2385
|
+
* .limit(5)
|
|
2386
|
+
* .toArray()
|
|
2387
|
+
* ```
|
|
2388
|
+
*/
|
|
2389
|
+
limit(n: number): AggregatePipeline<TDef, TOutput>;
|
|
2390
|
+
/**
|
|
2391
|
+
* Include only specified fields in the output.
|
|
2392
|
+
*
|
|
2393
|
+
* Appends a `$project` stage with inclusion (`1`) for each key.
|
|
2394
|
+
* The `_id` field is always included. The output type narrows to
|
|
2395
|
+
* `Pick<TOutput, K | '_id'>`.
|
|
2396
|
+
*
|
|
2397
|
+
* @param spec - An object mapping field names to `1` for inclusion.
|
|
2398
|
+
* @returns A new pipeline with the `$project` stage appended.
|
|
2399
|
+
*
|
|
2400
|
+
* @example
|
|
2401
|
+
* ```ts
|
|
2402
|
+
* const namesOnly = await aggregate(users)
|
|
2403
|
+
* .project({ name: 1 })
|
|
2404
|
+
* .toArray()
|
|
2405
|
+
* // [{ _id: ..., name: 'Ada' }, ...]
|
|
2406
|
+
* ```
|
|
2407
|
+
*/
|
|
2408
|
+
project<K extends keyof TOutput & string>(spec: Record<K, 1>): AggregatePipeline<TDef, Prettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>>;
|
|
2409
|
+
/**
|
|
2410
|
+
* Variadic shorthand for {@link project} — pick fields to include.
|
|
2411
|
+
*
|
|
2412
|
+
* Generates a `$project` stage that includes only the listed fields
|
|
2413
|
+
* (plus `_id`). Equivalent to `.project({ field1: 1, field2: 1 })`.
|
|
2414
|
+
*
|
|
2415
|
+
* @param fields - Field names to include in the output.
|
|
2416
|
+
* @returns A new pipeline with the `$project` stage appended.
|
|
2417
|
+
*
|
|
2418
|
+
* @example
|
|
2419
|
+
* ```ts
|
|
2420
|
+
* const namesAndRoles = await aggregate(users)
|
|
2421
|
+
* .pick('name', 'role')
|
|
2422
|
+
* .toArray()
|
|
2423
|
+
* ```
|
|
2424
|
+
*/
|
|
2425
|
+
pick<K extends keyof TOutput & string>(...fields: K[]): AggregatePipeline<TDef, Prettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>>;
|
|
2426
|
+
/**
|
|
2427
|
+
* Exclude specified fields from the output.
|
|
2428
|
+
*
|
|
2429
|
+
* Appends a `$project` stage with exclusion (`0`) for each key.
|
|
2430
|
+
* All other fields pass through. The output type becomes `Omit<TOutput, K>`.
|
|
2431
|
+
*
|
|
2432
|
+
* @param fields - Field names to exclude from the output.
|
|
2433
|
+
* @returns A new pipeline with the `$project` stage appended.
|
|
2434
|
+
*
|
|
2435
|
+
* @example
|
|
2436
|
+
* ```ts
|
|
2437
|
+
* const noAge = await aggregate(users)
|
|
2438
|
+
* .omit('age')
|
|
2439
|
+
* .toArray()
|
|
2440
|
+
* ```
|
|
2441
|
+
*/
|
|
2442
|
+
omit<K extends keyof TOutput & string>(...fields: K[]): AggregatePipeline<TDef, Prettify<Omit<TOutput, K>>>;
|
|
2443
|
+
/**
|
|
2444
|
+
* Group documents by one or more fields with accumulator expressions.
|
|
2445
|
+
*
|
|
2446
|
+
* Accepts accumulators as either a **callback** (recommended) or a plain object.
|
|
2447
|
+
*
|
|
2448
|
+
* The callback receives a typed `AccumulatorBuilder` with full autocomplete
|
|
2449
|
+
* and compile-time field validation. Builder methods resolve return types
|
|
2450
|
+
* to the actual field type (`T[K]`), not `unknown`.
|
|
2451
|
+
*
|
|
2452
|
+
* @param field - A field name or array of field names to group by.
|
|
2453
|
+
* @param accumulators - A callback `(acc) => ({ ... })` or plain accumulator object.
|
|
2454
|
+
* @returns A new pipeline with the `$group` stage appended.
|
|
2455
|
+
*
|
|
2456
|
+
* @example
|
|
2457
|
+
* ```ts
|
|
2458
|
+
* // Callback style (recommended — full type safety)
|
|
2459
|
+
* const byRole = await aggregate(users)
|
|
2460
|
+
* .groupBy('role', acc => ({
|
|
2461
|
+
* count: acc.count(),
|
|
2462
|
+
* minSalary: acc.min('salary'), // → number
|
|
2463
|
+
* firstName: acc.first('name'), // → string
|
|
2464
|
+
* }))
|
|
2465
|
+
* .toArray()
|
|
2466
|
+
* ```
|
|
2467
|
+
*
|
|
2468
|
+
* @example
|
|
2469
|
+
* ```ts
|
|
2470
|
+
* // Object style (backward compatible)
|
|
2471
|
+
* const byRole = await aggregate(users)
|
|
2472
|
+
* .groupBy('role', { count: $count() })
|
|
2473
|
+
* .toArray()
|
|
2474
|
+
* ```
|
|
2475
|
+
*
|
|
2476
|
+
* @example
|
|
2477
|
+
* ```ts
|
|
2478
|
+
* // Compound groupBy
|
|
2479
|
+
* const byRoleAndDept = await aggregate(users)
|
|
2480
|
+
* .groupBy(['role', 'dept'], acc => ({ count: acc.count() }))
|
|
2481
|
+
* .toArray()
|
|
2482
|
+
* ```
|
|
2483
|
+
*/
|
|
2484
|
+
groupBy<K extends keyof TOutput & string, TAccum extends Record<string, Accumulator>>(field: K, accumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum): AggregatePipeline<TDef, GroupByResult<TOutput, K, TAccum>>;
|
|
2485
|
+
groupBy<K extends keyof TOutput & string, TAccum extends Record<string, Accumulator>>(field: K[], accumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum): AggregatePipeline<TDef, GroupByCompoundResult<TOutput, K, TAccum>>;
|
|
2486
|
+
/**
|
|
2487
|
+
* Add new fields or overwrite existing ones in the output documents.
|
|
2488
|
+
*
|
|
2489
|
+
* **Callback style (recommended)** — the `ExpressionBuilder` provides
|
|
2490
|
+
* autocomplete for field names and infers return types automatically:
|
|
2491
|
+
*
|
|
2492
|
+
* ```ts
|
|
2493
|
+
* employees.aggregate()
|
|
2494
|
+
* .addFields(expr => ({
|
|
2495
|
+
* hireYear: expr.year('hiredAt'), // Expression<number>
|
|
2496
|
+
* isHighPay: expr.gte('salary', 100_000), // Expression<boolean>
|
|
2497
|
+
* }))
|
|
2498
|
+
* ```
|
|
2499
|
+
*
|
|
2500
|
+
* **Raw style** — pass MongoDB expression objects directly. Use an
|
|
2501
|
+
* explicit type parameter to preserve type safety:
|
|
2502
|
+
*
|
|
2503
|
+
* ```ts
|
|
2504
|
+
* // Tier 2: explicit type parameter
|
|
2505
|
+
* .addFields<{ hireYear: number }>({ hireYear: { $year: '$hiredAt' } })
|
|
2506
|
+
*
|
|
2507
|
+
* // Tier 3: no type parameter — fields resolve to unknown
|
|
2508
|
+
* .addFields({ hireYear: { $year: '$hiredAt' } })
|
|
2509
|
+
* ```
|
|
2510
|
+
*
|
|
2511
|
+
* @param fields - A callback `(expr) => ({ ... })` or plain fields object.
|
|
2512
|
+
* @returns A new pipeline with the `$addFields` stage appended.
|
|
2513
|
+
*
|
|
2514
|
+
* @example
|
|
2515
|
+
* ```ts
|
|
2516
|
+
* const enriched = await aggregate(employees)
|
|
2517
|
+
* .addFields(expr => ({
|
|
2518
|
+
* hireYear: expr.year('hiredAt'),
|
|
2519
|
+
* monthlySalary: expr.divide('salary', 12),
|
|
2520
|
+
* }))
|
|
2521
|
+
* .toArray()
|
|
2522
|
+
* ```
|
|
2523
|
+
*/
|
|
2524
|
+
addFields<TFields extends Record<string, Expression>>(fields: (expr: ExpressionBuilder<TOutput>) => TFields): AggregatePipeline<TDef, Prettify<TOutput & InferAddedFields<TFields>>>;
|
|
2525
|
+
addFields<TFields extends Record<string, unknown> = Record<string, unknown>>(fields: TFields): AggregatePipeline<TDef, Prettify<TOutput & TFields>>;
|
|
2526
|
+
/**
|
|
2527
|
+
* Deconstruct an array field, outputting one document per array element.
|
|
2528
|
+
*
|
|
2529
|
+
* Appends an `$unwind` stage. The unwound field's type changes from
|
|
2530
|
+
* `T[]` to `T` in the output type. Documents with empty or missing
|
|
2531
|
+
* arrays are dropped unless `preserveEmpty` is `true`.
|
|
2532
|
+
*
|
|
2533
|
+
* @param field - The name of the array field to unwind.
|
|
2534
|
+
* @param options - Optional settings for the unwind stage.
|
|
2535
|
+
* @param options.preserveEmpty - If `true`, documents with null, missing, or empty arrays are preserved.
|
|
2536
|
+
* @returns A new pipeline with the `$unwind` stage appended.
|
|
2537
|
+
*
|
|
2538
|
+
* @example
|
|
2539
|
+
* ```ts
|
|
2540
|
+
* const flat = await aggregate(orders)
|
|
2541
|
+
* .unwind('items')
|
|
2542
|
+
* .toArray()
|
|
2543
|
+
* // Each result has a single `items` value instead of an array
|
|
2544
|
+
* ```
|
|
2545
|
+
*/
|
|
2546
|
+
unwind<K extends keyof TOutput & string>(field: K, options?: {
|
|
2547
|
+
preserveEmpty?: boolean;
|
|
2548
|
+
}): AggregatePipeline<TDef, UnwindResult<TOutput, K>>;
|
|
2549
|
+
/**
|
|
2550
|
+
* Join documents from another collection via a `$lookup` stage.
|
|
2551
|
+
*
|
|
2552
|
+
* **Forward lookup** — when the field has `.ref()` metadata pointing to
|
|
2553
|
+
* another collection, resolves the target collection and output type
|
|
2554
|
+
* automatically:
|
|
2555
|
+
*
|
|
2556
|
+
* ```ts
|
|
2557
|
+
* books.aggregate().lookup('authorId').toArray()
|
|
2558
|
+
* // Each book gains an `authors: Author[]` array
|
|
2559
|
+
* ```
|
|
2560
|
+
*
|
|
2561
|
+
* **Reverse lookup** — when the foreign key lives on the *other*
|
|
2562
|
+
* collection, pass the collection definition and the `on` field:
|
|
2563
|
+
*
|
|
2564
|
+
* ```ts
|
|
2565
|
+
* users.aggregate().lookup(Books, { on: 'authorId' }).toArray()
|
|
2566
|
+
* // Each user gains a `books: Book[]` array
|
|
2567
|
+
* ```
|
|
2568
|
+
*
|
|
2569
|
+
* Pass `unwind: true` to flatten the joined array into a single object
|
|
2570
|
+
* (adds a `$unwind` stage with `preserveNullAndEmptyArrays: true`).
|
|
2571
|
+
*
|
|
2572
|
+
* @param fieldOrCollection - A ref-bearing field name (forward) or collection definition (reverse).
|
|
2573
|
+
* @param options - `as` alias, `unwind` flag, and `on` (reverse only).
|
|
2574
|
+
* @returns A new pipeline with `$lookup` (and optionally `$unwind`) appended.
|
|
2575
|
+
*
|
|
2576
|
+
* @example
|
|
2577
|
+
* ```ts
|
|
2578
|
+
* // Forward lookup with custom alias and unwind
|
|
2579
|
+
* const results = await aggregate(books)
|
|
2580
|
+
* .lookup('authorId', { as: 'author', unwind: true })
|
|
2581
|
+
* .toArray()
|
|
2582
|
+
* // Each book has a single `author: Author` object
|
|
2583
|
+
* ```
|
|
2584
|
+
*
|
|
2585
|
+
* @example
|
|
2586
|
+
* ```ts
|
|
2587
|
+
* // Reverse lookup: each author gains their books
|
|
2588
|
+
* const results = await aggregate(authors)
|
|
2589
|
+
* .lookup(Books, { on: 'authorId' })
|
|
2590
|
+
* .toArray()
|
|
2591
|
+
* // Each author has a `books: Book[]` array
|
|
2592
|
+
* ```
|
|
2593
|
+
*/
|
|
2594
|
+
lookup<K extends RefFields<TDef>, TAs extends string = CollectionName<ExtractRefCollection<TDef, K>>>(field: K, options: {
|
|
2595
|
+
as?: TAs;
|
|
2596
|
+
unwind: true;
|
|
2597
|
+
}): AggregatePipeline<TDef, Prettify<TOutput & {
|
|
2598
|
+
[P in TAs]: InferDocument<ExtractRefCollection<TDef, K>>;
|
|
2599
|
+
}>>;
|
|
2600
|
+
lookup<K extends RefFields<TDef>, TAs extends string = CollectionName<ExtractRefCollection<TDef, K>>>(field: K, options?: {
|
|
2601
|
+
as?: TAs;
|
|
2602
|
+
unwind?: false;
|
|
2603
|
+
}): AggregatePipeline<TDef, Prettify<TOutput & {
|
|
2604
|
+
[P in TAs]: InferDocument<ExtractRefCollection<TDef, K>>[];
|
|
2605
|
+
}>>;
|
|
2606
|
+
lookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(from: TForeignDef, options: {
|
|
2607
|
+
on: keyof InferDocument<TForeignDef> & string;
|
|
2608
|
+
as?: TAs;
|
|
2609
|
+
unwind: true;
|
|
2610
|
+
}): AggregatePipeline<TDef, Prettify<TOutput & {
|
|
2611
|
+
[P in TAs]: InferDocument<TForeignDef>;
|
|
2612
|
+
}>>;
|
|
2613
|
+
lookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(from: TForeignDef, options: {
|
|
2614
|
+
on: keyof InferDocument<TForeignDef> & string;
|
|
2615
|
+
as?: TAs;
|
|
2616
|
+
unwind?: false;
|
|
2617
|
+
}): AggregatePipeline<TDef, Prettify<TOutput & {
|
|
2618
|
+
[P in TAs]: InferDocument<TForeignDef>[];
|
|
2619
|
+
}>>;
|
|
2620
|
+
/**
|
|
2621
|
+
* Count documents per group, sorted by count descending.
|
|
2622
|
+
*
|
|
2623
|
+
* Shorthand for `.groupBy(field, { count: $count() }).sort({ count: -1 })`.
|
|
2624
|
+
*
|
|
2625
|
+
* @param field - The field to group and count by.
|
|
2626
|
+
* @returns A new pipeline producing `{ _id: TOutput[K], count: number }` results.
|
|
2627
|
+
*
|
|
2628
|
+
* @example
|
|
2629
|
+
* ```ts
|
|
2630
|
+
* const roleCounts = await aggregate(users)
|
|
2631
|
+
* .countBy('role')
|
|
2632
|
+
* .toArray()
|
|
2633
|
+
* // [{ _id: 'user', count: 3 }, { _id: 'admin', count: 2 }]
|
|
2634
|
+
* ```
|
|
2635
|
+
*/
|
|
2636
|
+
countBy<K extends keyof TOutput & string>(field: K): AggregatePipeline<TDef, Prettify<{
|
|
2637
|
+
_id: TOutput[K];
|
|
2638
|
+
count: number;
|
|
2639
|
+
}>>;
|
|
2640
|
+
/**
|
|
2641
|
+
* Sum a numeric field per group, sorted by total descending.
|
|
2642
|
+
*
|
|
2643
|
+
* Shorthand for `.groupBy(field, { total: $sum('$sumField') }).sort({ total: -1 })`.
|
|
2644
|
+
*
|
|
2645
|
+
* @param field - The field to group by.
|
|
2646
|
+
* @param sumField - The numeric field to sum.
|
|
2647
|
+
* @returns A new pipeline producing `{ _id: TOutput[K], total: number }` results.
|
|
2648
|
+
*
|
|
2649
|
+
* @example
|
|
2650
|
+
* ```ts
|
|
2651
|
+
* const revenueByCategory = await aggregate(orders)
|
|
2652
|
+
* .sumBy('category', 'amount')
|
|
2653
|
+
* .toArray()
|
|
2654
|
+
* // [{ _id: 'electronics', total: 5000 }, ...]
|
|
2655
|
+
* ```
|
|
2656
|
+
*/
|
|
2657
|
+
sumBy<K extends keyof TOutput & string, S extends keyof TOutput & string>(field: K, sumField: S): AggregatePipeline<TDef, Prettify<{
|
|
2658
|
+
_id: TOutput[K];
|
|
2659
|
+
total: number;
|
|
2660
|
+
}>>;
|
|
2661
|
+
/**
|
|
2662
|
+
* Sort by a single field with a friendly direction name.
|
|
2663
|
+
*
|
|
2664
|
+
* Shorthand for `.sort({ [field]: direction === 'desc' ? -1 : 1 })`.
|
|
2665
|
+
*
|
|
2666
|
+
* @param field - The field to sort by.
|
|
2667
|
+
* @param direction - Sort direction: `'asc'` (default) or `'desc'`.
|
|
2668
|
+
* @returns A new pipeline with the `$sort` stage appended.
|
|
2669
|
+
*
|
|
2670
|
+
* @example
|
|
2671
|
+
* ```ts
|
|
2672
|
+
* const youngest = await aggregate(users)
|
|
2673
|
+
* .sortBy('age')
|
|
2674
|
+
* .toArray()
|
|
2675
|
+
* ```
|
|
2676
|
+
*/
|
|
2677
|
+
sortBy(field: keyof TOutput & string, direction?: 'asc' | 'desc'): AggregatePipeline<TDef, TOutput>;
|
|
2678
|
+
/**
|
|
2679
|
+
* Return the top N documents sorted by a field descending.
|
|
2680
|
+
*
|
|
2681
|
+
* Shorthand for `.sort({ [by]: -1 }).limit(n)`.
|
|
2682
|
+
*
|
|
2683
|
+
* @param n - The number of documents to return.
|
|
2684
|
+
* @param options - An object with a `by` field specifying the sort key.
|
|
2685
|
+
* @returns A new pipeline with `$sort` and `$limit` stages appended.
|
|
2686
|
+
*
|
|
2687
|
+
* @example
|
|
2688
|
+
* ```ts
|
|
2689
|
+
* const top3 = await aggregate(users)
|
|
2690
|
+
* .top(3, { by: 'score' })
|
|
2691
|
+
* .toArray()
|
|
2692
|
+
* ```
|
|
2693
|
+
*/
|
|
2694
|
+
top(n: number, options: {
|
|
2695
|
+
by: keyof TOutput & string;
|
|
2696
|
+
}): AggregatePipeline<TDef, TOutput>;
|
|
2697
|
+
/**
|
|
2698
|
+
* Return the bottom N documents sorted by a field ascending.
|
|
2699
|
+
*
|
|
2700
|
+
* Shorthand for `.sort({ [by]: 1 }).limit(n)`.
|
|
2701
|
+
*
|
|
2702
|
+
* @param n - The number of documents to return.
|
|
2703
|
+
* @param options - An object with a `by` field specifying the sort key.
|
|
2704
|
+
* @returns A new pipeline with `$sort` and `$limit` stages appended.
|
|
2705
|
+
*
|
|
2706
|
+
* @example
|
|
2707
|
+
* ```ts
|
|
2708
|
+
* const bottom3 = await aggregate(users)
|
|
2709
|
+
* .bottom(3, { by: 'score' })
|
|
2710
|
+
* .toArray()
|
|
1506
2711
|
* ```
|
|
1507
2712
|
*/
|
|
1508
|
-
|
|
2713
|
+
bottom(n: number, options: {
|
|
2714
|
+
by: keyof TOutput & string;
|
|
2715
|
+
}): AggregatePipeline<TDef, TOutput>;
|
|
1509
2716
|
}
|
|
2717
|
+
/**
|
|
2718
|
+
* Create a new aggregation pipeline for a collection.
|
|
2719
|
+
*
|
|
2720
|
+
* Returns an empty pipeline that can be extended with stage methods
|
|
2721
|
+
* like `raw()`, or future typed stages (`match`, `project`, etc.).
|
|
2722
|
+
*
|
|
2723
|
+
* @param handle - A typed collection handle obtained from `db.use()`.
|
|
2724
|
+
* @returns A new empty `AggregatePipeline` whose output type is the collection's document type.
|
|
2725
|
+
*
|
|
2726
|
+
* @example
|
|
2727
|
+
* ```ts
|
|
2728
|
+
* const users = db.use(Users)
|
|
2729
|
+
* const admins = await aggregate(users)
|
|
2730
|
+
* .raw({ $match: { role: 'admin' } })
|
|
2731
|
+
* .toArray()
|
|
2732
|
+
* ```
|
|
2733
|
+
*/
|
|
2734
|
+
declare function aggregate<TDef extends AnyCollection>(handle: CollectionHandle<TDef>): AggregatePipeline<TDef, InferDocument<TDef>>;
|
|
1510
2735
|
|
|
1511
2736
|
/**
|
|
1512
2737
|
* Wraps a MongoDB `MongoClient` and `Db`, providing typed collection access
|
|
@@ -1540,7 +2765,7 @@ declare class Database {
|
|
|
1540
2765
|
* @param def - A collection definition created by `collection()`.
|
|
1541
2766
|
* @returns A typed collection handle for CRUD operations.
|
|
1542
2767
|
*/
|
|
1543
|
-
use<TShape extends z.core.$ZodShape, TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]>(def: CollectionDefinition<TShape, TIndexes>): CollectionHandle<CollectionDefinition<TShape, TIndexes>>;
|
|
2768
|
+
use<TName extends string, TShape extends z.core.$ZodShape, TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]>(def: CollectionDefinition<TName, TShape, TIndexes>): CollectionHandle<CollectionDefinition<TName, TShape, TIndexes>>;
|
|
1544
2769
|
/**
|
|
1545
2770
|
* Synchronize indexes for all registered collections with MongoDB.
|
|
1546
2771
|
*
|
|
@@ -1636,9 +2861,9 @@ declare function extractFieldIndexes(shape: z.core.$ZodShape): FieldIndexDefinit
|
|
|
1636
2861
|
* })
|
|
1637
2862
|
* ```
|
|
1638
2863
|
*/
|
|
1639
|
-
declare function collection<TShape extends z.core.$ZodShape, const TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]>(name:
|
|
2864
|
+
declare function collection<TName extends string, TShape extends z.core.$ZodShape, const TIndexes extends readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[]>(name: TName, shape: TShape, options?: Omit<CollectionOptions<Extract<keyof TShape, string>>, 'indexes'> & {
|
|
1640
2865
|
indexes?: TIndexes;
|
|
1641
|
-
}): CollectionDefinition<TShape, [...TIndexes]>;
|
|
2866
|
+
}): CollectionDefinition<TName, TShape, [...TIndexes]>;
|
|
1642
2867
|
|
|
1643
2868
|
type IndexDirection = 1 | -1;
|
|
1644
2869
|
type CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>;
|
|
@@ -1752,11 +2977,222 @@ declare function insertOne<TDef extends AnyCollection>(handle: CollectionHandle<
|
|
|
1752
2977
|
*/
|
|
1753
2978
|
declare function insertMany<TDef extends AnyCollection>(handle: CollectionHandle<TDef>, docs: InferInsert<TDef>[]): Promise<InferDocument<TDef>[]>;
|
|
1754
2979
|
|
|
2980
|
+
/**
|
|
2981
|
+
* Base error class for all Zodmon errors.
|
|
2982
|
+
*
|
|
2983
|
+
* Every error thrown by Zodmon extends this class, making it easy to catch all
|
|
2984
|
+
* Zodmon-related errors in a single `catch` block while still allowing more
|
|
2985
|
+
* specific handling via subclass checks.
|
|
2986
|
+
*
|
|
2987
|
+
* @example
|
|
2988
|
+
* ```ts
|
|
2989
|
+
* try {
|
|
2990
|
+
* await users.insertOne({ name: 123 })
|
|
2991
|
+
* } catch (err) {
|
|
2992
|
+
* if (err instanceof ZodmonError) {
|
|
2993
|
+
* console.log(err.name) // => 'ZodmonError' (or a subclass name)
|
|
2994
|
+
* console.log(err.collection) // => 'users'
|
|
2995
|
+
* console.log(err.cause) // => original Error, if provided
|
|
2996
|
+
* }
|
|
2997
|
+
* }
|
|
2998
|
+
* ```
|
|
2999
|
+
*/
|
|
3000
|
+
declare class ZodmonError extends Error {
|
|
3001
|
+
readonly name: string;
|
|
3002
|
+
/** The MongoDB collection name associated with this error. */
|
|
3003
|
+
readonly collection: string;
|
|
3004
|
+
/** The underlying error that caused this error, if any. */
|
|
3005
|
+
readonly cause?: Error;
|
|
3006
|
+
constructor(message: string, collection: string, options?: {
|
|
3007
|
+
cause?: Error;
|
|
3008
|
+
});
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
/**
|
|
3012
|
+
* Thrown when MongoDB rejects an operation due to authentication or authorization failure.
|
|
3013
|
+
*
|
|
3014
|
+
* Corresponds to MongoDB error codes 13 (Unauthorized) and 18 (AuthenticationFailed).
|
|
3015
|
+
* Inspect `.code` to distinguish between authorization and authentication failures.
|
|
3016
|
+
*
|
|
3017
|
+
* @example
|
|
3018
|
+
* ```ts
|
|
3019
|
+
* try {
|
|
3020
|
+
* await users.insertOne({ name: 'Alice' })
|
|
3021
|
+
* } catch (err) {
|
|
3022
|
+
* if (err instanceof ZodmonAuthError) {
|
|
3023
|
+
* console.log(err.message) // => 'Not authorized to perform this operation on "users"'
|
|
3024
|
+
* console.log(err.code) // => 13 or 18
|
|
3025
|
+
* console.log(err.collection) // => 'users'
|
|
3026
|
+
* }
|
|
3027
|
+
* }
|
|
3028
|
+
* ```
|
|
3029
|
+
*/
|
|
3030
|
+
declare class ZodmonAuthError extends ZodmonError {
|
|
3031
|
+
readonly name = "ZodmonAuthError";
|
|
3032
|
+
/** The MongoDB error code (13 or 18). */
|
|
3033
|
+
readonly code: number;
|
|
3034
|
+
constructor(collection: string, code: number, cause: Error);
|
|
3035
|
+
}
|
|
3036
|
+
|
|
3037
|
+
/**
|
|
3038
|
+
* Thrown when a bulk write operation partially or fully fails.
|
|
3039
|
+
*
|
|
3040
|
+
* Exposes partial result counts (`.insertedCount`, `.matchedCount`, etc.) alongside
|
|
3041
|
+
* an array of `.writeErrors` describing each individual failure. Use this to determine
|
|
3042
|
+
* which operations succeeded and which failed.
|
|
3043
|
+
*
|
|
3044
|
+
* @example
|
|
3045
|
+
* ```ts
|
|
3046
|
+
* try {
|
|
3047
|
+
* await users.insertMany([{ name: 'Alice' }, { name: 'Alice' }]) // duplicate
|
|
3048
|
+
* } catch (err) {
|
|
3049
|
+
* if (err instanceof ZodmonBulkWriteError) {
|
|
3050
|
+
* console.log(err.insertedCount) // => 1
|
|
3051
|
+
* console.log(err.writeErrors) // => [{ index: 1, code: 11000, message: '...' }]
|
|
3052
|
+
* console.log(err.collection) // => 'users'
|
|
3053
|
+
* }
|
|
3054
|
+
* }
|
|
3055
|
+
* ```
|
|
3056
|
+
*/
|
|
3057
|
+
declare class ZodmonBulkWriteError extends ZodmonError {
|
|
3058
|
+
readonly name = "ZodmonBulkWriteError";
|
|
3059
|
+
/** Number of documents successfully inserted. */
|
|
3060
|
+
readonly insertedCount: number;
|
|
3061
|
+
/** Number of documents matched by update filters. */
|
|
3062
|
+
readonly matchedCount: number;
|
|
3063
|
+
/** Number of documents actually modified. */
|
|
3064
|
+
readonly modifiedCount: number;
|
|
3065
|
+
/** Number of documents deleted. */
|
|
3066
|
+
readonly deletedCount: number;
|
|
3067
|
+
/** Individual write errors with their operation index, code, and message. */
|
|
3068
|
+
readonly writeErrors: Array<{
|
|
3069
|
+
index: number;
|
|
3070
|
+
code: number;
|
|
3071
|
+
message: string;
|
|
3072
|
+
}>;
|
|
3073
|
+
constructor(collection: string, cause: Error, totalOps?: number);
|
|
3074
|
+
}
|
|
3075
|
+
|
|
3076
|
+
/**
|
|
3077
|
+
* Thrown when a document fails server-side JSON Schema validation (MongoDB error code 121).
|
|
3078
|
+
*
|
|
3079
|
+
* This is distinct from {@link ZodmonValidationError}, which validates against Zod schemas
|
|
3080
|
+
* on the client side. This error surfaces when MongoDB's own document validation rejects
|
|
3081
|
+
* a write. Inspect `.errInfo` for the server's detailed validation failure information.
|
|
3082
|
+
*
|
|
3083
|
+
* @example
|
|
3084
|
+
* ```ts
|
|
3085
|
+
* try {
|
|
3086
|
+
* await users.insertOne({ name: 'Alice', age: -1 })
|
|
3087
|
+
* } catch (err) {
|
|
3088
|
+
* if (err instanceof ZodmonDocValidationError) {
|
|
3089
|
+
* console.log(err.message) // => 'Server-side document validation failed for "users": ...'
|
|
3090
|
+
* console.log(err.errInfo) // => { failingDocumentId: ..., details: ... }
|
|
3091
|
+
* console.log(err.collection) // => 'users'
|
|
3092
|
+
* }
|
|
3093
|
+
* }
|
|
3094
|
+
* ```
|
|
3095
|
+
*/
|
|
3096
|
+
declare class ZodmonDocValidationError extends ZodmonError {
|
|
3097
|
+
readonly name = "ZodmonDocValidationError";
|
|
3098
|
+
/** Server-provided validation failure details. */
|
|
3099
|
+
readonly errInfo: unknown;
|
|
3100
|
+
constructor(collection: string, errInfo: unknown, cause: Error);
|
|
3101
|
+
}
|
|
3102
|
+
|
|
3103
|
+
/**
|
|
3104
|
+
* Thrown when a MongoDB insert or update violates a unique index constraint (E11000).
|
|
3105
|
+
*
|
|
3106
|
+
* Parses the duplicate key information from the MongoDB driver error to expose
|
|
3107
|
+
* structured fields: `.field` (first conflicting key), `.value`, `.index` (index name),
|
|
3108
|
+
* `.keyPattern`, and `.keyValue`. Falls back to regex parsing for older drivers.
|
|
3109
|
+
*
|
|
3110
|
+
* @example
|
|
3111
|
+
* ```ts
|
|
3112
|
+
* try {
|
|
3113
|
+
* await users.insertOne({ email: 'alice@example.com' })
|
|
3114
|
+
* } catch (err) {
|
|
3115
|
+
* if (err instanceof ZodmonDuplicateKeyError) {
|
|
3116
|
+
* console.log(err.field) // => 'email'
|
|
3117
|
+
* console.log(err.value) // => 'alice@example.com'
|
|
3118
|
+
* console.log(err.index) // => 'email_1'
|
|
3119
|
+
* console.log(err.keyPattern) // => { email: 1 }
|
|
3120
|
+
* console.log(err.keyValue) // => { email: 'alice@example.com' }
|
|
3121
|
+
* console.log(err.collection) // => 'users'
|
|
3122
|
+
* }
|
|
3123
|
+
* }
|
|
3124
|
+
* ```
|
|
3125
|
+
*/
|
|
3126
|
+
declare class ZodmonDuplicateKeyError extends ZodmonError {
|
|
3127
|
+
readonly name = "ZodmonDuplicateKeyError";
|
|
3128
|
+
/** The first field that caused the duplicate key violation. */
|
|
3129
|
+
readonly field: string;
|
|
3130
|
+
/** The duplicate value, or `undefined` if it could not be extracted. */
|
|
3131
|
+
readonly value: unknown;
|
|
3132
|
+
/** The name of the index that was violated. */
|
|
3133
|
+
readonly index: string;
|
|
3134
|
+
/** The key pattern of the violated index (e.g. `{ email: 1 }`). */
|
|
3135
|
+
readonly keyPattern: Record<string, number>;
|
|
3136
|
+
/** The key values that caused the violation. */
|
|
3137
|
+
readonly keyValue: Record<string, unknown>;
|
|
3138
|
+
constructor(collection: string, cause: Error);
|
|
3139
|
+
}
|
|
3140
|
+
|
|
3141
|
+
/**
|
|
3142
|
+
* Thrown when a MongoDB index operation fails.
|
|
3143
|
+
*
|
|
3144
|
+
* Corresponds to MongoDB error codes 67 (CannotCreateIndex), 85 (IndexOptionsConflict),
|
|
3145
|
+
* and 86 (IndexKeySpecsConflict). Inspect `.code` to determine the specific failure reason.
|
|
3146
|
+
*
|
|
3147
|
+
* @example
|
|
3148
|
+
* ```ts
|
|
3149
|
+
* try {
|
|
3150
|
+
* await syncIndexes(db, [Users])
|
|
3151
|
+
* } catch (err) {
|
|
3152
|
+
* if (err instanceof ZodmonIndexError) {
|
|
3153
|
+
* console.log(err.message) // => 'Index options conflict on "users": ...'
|
|
3154
|
+
* console.log(err.code) // => 67, 85, or 86
|
|
3155
|
+
* console.log(err.collection) // => 'users'
|
|
3156
|
+
* }
|
|
3157
|
+
* }
|
|
3158
|
+
* ```
|
|
3159
|
+
*/
|
|
3160
|
+
declare class ZodmonIndexError extends ZodmonError {
|
|
3161
|
+
readonly name = "ZodmonIndexError";
|
|
3162
|
+
/** The MongoDB error code (67, 85, or 86). */
|
|
3163
|
+
readonly code: number;
|
|
3164
|
+
constructor(collection: string, code: number, errmsg: string, cause: Error);
|
|
3165
|
+
}
|
|
3166
|
+
|
|
3167
|
+
/**
|
|
3168
|
+
* Thrown when a MongoDB operation fails due to a network error.
|
|
3169
|
+
*
|
|
3170
|
+
* Wraps `MongoNetworkError` from the MongoDB driver with the collection name
|
|
3171
|
+
* and the original error message for easier debugging.
|
|
3172
|
+
*
|
|
3173
|
+
* @example
|
|
3174
|
+
* ```ts
|
|
3175
|
+
* try {
|
|
3176
|
+
* await users.find({ status: 'active' })
|
|
3177
|
+
* } catch (err) {
|
|
3178
|
+
* if (err instanceof ZodmonNetworkError) {
|
|
3179
|
+
* console.log(err.message) // => 'Network error on "users": connection refused'
|
|
3180
|
+
* console.log(err.collection) // => 'users'
|
|
3181
|
+
* }
|
|
3182
|
+
* }
|
|
3183
|
+
* ```
|
|
3184
|
+
*/
|
|
3185
|
+
declare class ZodmonNetworkError extends ZodmonError {
|
|
3186
|
+
readonly name = "ZodmonNetworkError";
|
|
3187
|
+
constructor(collection: string, cause: Error);
|
|
3188
|
+
}
|
|
3189
|
+
|
|
1755
3190
|
/**
|
|
1756
3191
|
* Thrown when a query expected to find a document returns no results.
|
|
1757
3192
|
*
|
|
1758
3193
|
* Used by {@link findOneOrThrow} when no document matches the provided filter.
|
|
1759
|
-
* Callers can inspect `.collection` to identify which collection the query targeted
|
|
3194
|
+
* Callers can inspect `.collection` to identify which collection the query targeted,
|
|
3195
|
+
* and `.filter` to see the query that produced no results.
|
|
1760
3196
|
*
|
|
1761
3197
|
* @example
|
|
1762
3198
|
* ```ts
|
|
@@ -1766,15 +3202,68 @@ declare function insertMany<TDef extends AnyCollection>(handle: CollectionHandle
|
|
|
1766
3202
|
* if (err instanceof ZodmonNotFoundError) {
|
|
1767
3203
|
* console.log(err.message) // => 'Document not found in "users"'
|
|
1768
3204
|
* console.log(err.collection) // => 'users'
|
|
3205
|
+
* console.log(err.filter) // => { name: 'nonexistent' }
|
|
1769
3206
|
* }
|
|
1770
3207
|
* }
|
|
1771
3208
|
* ```
|
|
1772
3209
|
*/
|
|
1773
|
-
declare class ZodmonNotFoundError extends
|
|
3210
|
+
declare class ZodmonNotFoundError extends ZodmonError {
|
|
1774
3211
|
readonly name = "ZodmonNotFoundError";
|
|
1775
|
-
/** The
|
|
1776
|
-
readonly
|
|
1777
|
-
constructor(collection: string);
|
|
3212
|
+
/** The filter that produced no results. */
|
|
3213
|
+
readonly filter: unknown;
|
|
3214
|
+
constructor(collection: string, filter: unknown);
|
|
3215
|
+
}
|
|
3216
|
+
|
|
3217
|
+
/**
|
|
3218
|
+
* Thrown when a MongoDB query is malformed or exceeds resource limits.
|
|
3219
|
+
*
|
|
3220
|
+
* Corresponds to MongoDB error codes 2 (BadValue), 9 (FailedToParse), and
|
|
3221
|
+
* 292 (QueryExceededMemoryLimit). Inspect `.code` to determine the specific failure.
|
|
3222
|
+
*
|
|
3223
|
+
* @example
|
|
3224
|
+
* ```ts
|
|
3225
|
+
* try {
|
|
3226
|
+
* await users.find({ $invalid: true })
|
|
3227
|
+
* } catch (err) {
|
|
3228
|
+
* if (err instanceof ZodmonQueryError) {
|
|
3229
|
+
* console.log(err.message) // => 'Bad value in query on "users": ...'
|
|
3230
|
+
* console.log(err.code) // => 2, 9, or 292
|
|
3231
|
+
* console.log(err.collection) // => 'users'
|
|
3232
|
+
* }
|
|
3233
|
+
* }
|
|
3234
|
+
* ```
|
|
3235
|
+
*/
|
|
3236
|
+
declare class ZodmonQueryError extends ZodmonError {
|
|
3237
|
+
readonly name = "ZodmonQueryError";
|
|
3238
|
+
/** The MongoDB error code (2, 9, or 292). */
|
|
3239
|
+
readonly code: number;
|
|
3240
|
+
constructor(collection: string, code: number, errmsg: string, cause: Error);
|
|
3241
|
+
}
|
|
3242
|
+
|
|
3243
|
+
/**
|
|
3244
|
+
* Thrown when a MongoDB operation exceeds its server time limit.
|
|
3245
|
+
*
|
|
3246
|
+
* Corresponds to MongoDB error codes 50 (MaxTimeMSExpired) and
|
|
3247
|
+
* 262 (ExceededTimeLimit). Inspect `.code` to distinguish between the two.
|
|
3248
|
+
*
|
|
3249
|
+
* @example
|
|
3250
|
+
* ```ts
|
|
3251
|
+
* try {
|
|
3252
|
+
* await users.find({ status: 'active' })
|
|
3253
|
+
* } catch (err) {
|
|
3254
|
+
* if (err instanceof ZodmonTimeoutError) {
|
|
3255
|
+
* console.log(err.message) // => 'Operation timed out on "users": ...'
|
|
3256
|
+
* console.log(err.code) // => 50 or 262
|
|
3257
|
+
* console.log(err.collection) // => 'users'
|
|
3258
|
+
* }
|
|
3259
|
+
* }
|
|
3260
|
+
* ```
|
|
3261
|
+
*/
|
|
3262
|
+
declare class ZodmonTimeoutError extends ZodmonError {
|
|
3263
|
+
readonly name = "ZodmonTimeoutError";
|
|
3264
|
+
/** The MongoDB error code (50 or 262). */
|
|
3265
|
+
readonly code: number;
|
|
3266
|
+
constructor(collection: string, code: number, cause: Error);
|
|
1778
3267
|
}
|
|
1779
3268
|
|
|
1780
3269
|
/**
|
|
@@ -1794,17 +3283,62 @@ declare class ZodmonNotFoundError extends Error {
|
|
|
1794
3283
|
* // => 'Validation failed for "users": name (Expected string, received number)'
|
|
1795
3284
|
* console.log(err.collection) // => 'users'
|
|
1796
3285
|
* console.log(err.zodError) // => ZodError with .issues array
|
|
3286
|
+
* console.log(err.document) // => the document that failed validation
|
|
1797
3287
|
* }
|
|
1798
3288
|
* }
|
|
1799
3289
|
* ```
|
|
1800
3290
|
*/
|
|
1801
|
-
declare class ZodmonValidationError extends
|
|
3291
|
+
declare class ZodmonValidationError extends ZodmonError {
|
|
1802
3292
|
readonly name = "ZodmonValidationError";
|
|
1803
|
-
/** The MongoDB collection name where the validation failed. */
|
|
1804
|
-
readonly collection: string;
|
|
1805
3293
|
/** The original Zod validation error with detailed issue information. */
|
|
1806
3294
|
readonly zodError: z.ZodError;
|
|
1807
|
-
|
|
3295
|
+
/** The document that failed validation. */
|
|
3296
|
+
readonly document: unknown;
|
|
3297
|
+
constructor(collection: string, zodError: z.ZodError, document: unknown);
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
/**
|
|
3301
|
+
* Maps a caught MongoDB error to the appropriate Zodmon error subclass and throws it.
|
|
3302
|
+
*
|
|
3303
|
+
* This function always throws — it never returns. Use it in `catch` blocks to convert
|
|
3304
|
+
* raw MongoDB driver errors into structured, typed Zodmon errors. If the error is already
|
|
3305
|
+
* a `ZodmonError`, it is rethrown as-is to prevent double-wrapping.
|
|
3306
|
+
*
|
|
3307
|
+
* @example
|
|
3308
|
+
* ```ts
|
|
3309
|
+
* try {
|
|
3310
|
+
* await db.collection('users').insertOne(doc)
|
|
3311
|
+
* } catch (err) {
|
|
3312
|
+
* wrapMongoError(err, 'users')
|
|
3313
|
+
* }
|
|
3314
|
+
* ```
|
|
3315
|
+
*/
|
|
3316
|
+
declare function wrapMongoError(err: unknown, collection: string): never;
|
|
3317
|
+
|
|
3318
|
+
/**
|
|
3319
|
+
* Thrown when a transaction encounters a write conflict (MongoDB error code 112).
|
|
3320
|
+
*
|
|
3321
|
+
* This occurs when another operation modifies the same document concurrently during
|
|
3322
|
+
* a transaction. The recommended recovery strategy is to retry the transaction.
|
|
3323
|
+
*
|
|
3324
|
+
* @example
|
|
3325
|
+
* ```ts
|
|
3326
|
+
* try {
|
|
3327
|
+
* await db.transaction(async (tx) => {
|
|
3328
|
+
* const users = tx.use(Users)
|
|
3329
|
+
* await users.updateOne({ _id: id }, { $inc: { balance: -100 } })
|
|
3330
|
+
* })
|
|
3331
|
+
* } catch (err) {
|
|
3332
|
+
* if (err instanceof ZodmonWriteConflictError) {
|
|
3333
|
+
* console.log(err.message) // => 'Write conflict in "users": ...'
|
|
3334
|
+
* console.log(err.collection) // => 'users'
|
|
3335
|
+
* }
|
|
3336
|
+
* }
|
|
3337
|
+
* ```
|
|
3338
|
+
*/
|
|
3339
|
+
declare class ZodmonWriteConflictError extends ZodmonError {
|
|
3340
|
+
readonly name = "ZodmonWriteConflictError";
|
|
3341
|
+
constructor(collection: string, cause: Error);
|
|
1808
3342
|
}
|
|
1809
3343
|
|
|
1810
3344
|
/**
|
|
@@ -2111,11 +3645,11 @@ declare const $: {
|
|
|
2111
3645
|
readonly lte: <V>(value: V) => {
|
|
2112
3646
|
$lte: V;
|
|
2113
3647
|
};
|
|
2114
|
-
readonly in: <V>(values: V[]) => {
|
|
2115
|
-
$in: V[];
|
|
3648
|
+
readonly in: <V>(values: readonly V[]) => {
|
|
3649
|
+
$in: readonly V[];
|
|
2116
3650
|
};
|
|
2117
|
-
readonly nin: <V>(values: V[]) => {
|
|
2118
|
-
$nin: V[];
|
|
3651
|
+
readonly nin: <V>(values: readonly V[]) => {
|
|
3652
|
+
$nin: readonly V[];
|
|
2119
3653
|
};
|
|
2120
3654
|
readonly exists: (flag?: boolean) => {
|
|
2121
3655
|
$exists: boolean;
|
|
@@ -2207,8 +3741,8 @@ declare const $lte: <V>(value: V) => {
|
|
|
2207
3741
|
* users.find({ role: $in(['admin', 'moderator']) })
|
|
2208
3742
|
* ```
|
|
2209
3743
|
*/
|
|
2210
|
-
declare const $in: <V>(values: V[]) => {
|
|
2211
|
-
$in: V[];
|
|
3744
|
+
declare const $in: <V>(values: readonly V[]) => {
|
|
3745
|
+
$in: readonly V[];
|
|
2212
3746
|
};
|
|
2213
3747
|
/**
|
|
2214
3748
|
* Matches none of the values in the specified array.
|
|
@@ -2218,8 +3752,8 @@ declare const $in: <V>(values: V[]) => {
|
|
|
2218
3752
|
* users.find({ role: $nin(['banned', 'suspended']) })
|
|
2219
3753
|
* ```
|
|
2220
3754
|
*/
|
|
2221
|
-
declare const $nin: <V>(values: V[]) => {
|
|
2222
|
-
$nin: V[];
|
|
3755
|
+
declare const $nin: <V>(values: readonly V[]) => {
|
|
3756
|
+
$nin: readonly V[];
|
|
2223
3757
|
};
|
|
2224
3758
|
/**
|
|
2225
3759
|
* Matches documents where the field exists (or does not exist).
|
|
@@ -2319,84 +3853,6 @@ declare const $nor: <T>(...filters: NoInfer<TypedFilter<T>>[]) => TypedFilter<T>
|
|
|
2319
3853
|
*/
|
|
2320
3854
|
declare const raw: <T = any>(filter: Record<string, unknown>) => TypedFilter<T>;
|
|
2321
3855
|
|
|
2322
|
-
/**
|
|
2323
|
-
* Type-level marker that carries the target collection type through the
|
|
2324
|
-
* type system. Intersected with the schema return type by `.ref()` so
|
|
2325
|
-
* that `RefFields<T>` (future) can extract ref relationships.
|
|
2326
|
-
*
|
|
2327
|
-
* This is a phantom brand — no runtime value has this property.
|
|
2328
|
-
*/
|
|
2329
|
-
type RefMarker<TCollection extends AnyCollection = AnyCollection> = {
|
|
2330
|
-
readonly _ref: TCollection;
|
|
2331
|
-
};
|
|
2332
|
-
/**
|
|
2333
|
-
* Metadata stored in the WeakMap sidecar for schemas marked with `.ref()`.
|
|
2334
|
-
* Holds a reference to the target collection definition object.
|
|
2335
|
-
*/
|
|
2336
|
-
type RefMetadata = {
|
|
2337
|
-
readonly collection: AnyCollection;
|
|
2338
|
-
};
|
|
2339
|
-
/**
|
|
2340
|
-
* Module augmentation: adds `.ref()` to all `ZodType` schemas.
|
|
2341
|
-
*
|
|
2342
|
-
* The intersection constraint `this['_zod']['output'] extends InferDocument<TCollection>['_id']`
|
|
2343
|
-
* ensures compile-time type safety: the field's output type must match the
|
|
2344
|
-
* target collection's `_id` type. Mismatches produce a type error.
|
|
2345
|
-
*
|
|
2346
|
-
* Supports both default ObjectId `_id` and custom `_id` types (string, nanoid, etc.):
|
|
2347
|
-
* - `objectId().ref(Users)` compiles when Users has ObjectId `_id`
|
|
2348
|
-
* - `z.string().ref(Orgs)` compiles when Orgs has string `_id`
|
|
2349
|
-
* - `z.string().ref(Users)` is a type error (string ≠ ObjectId)
|
|
2350
|
-
* - `objectId().ref(Orgs)` is a type error (ObjectId ≠ string)
|
|
2351
|
-
*/
|
|
2352
|
-
declare module 'zod' {
|
|
2353
|
-
interface ZodType {
|
|
2354
|
-
/**
|
|
2355
|
-
* Declare a typed foreign key reference to another collection.
|
|
2356
|
-
*
|
|
2357
|
-
* Stores the target collection definition in metadata for runtime
|
|
2358
|
-
* populate resolution, and brands the return type with
|
|
2359
|
-
* `RefMarker<TCollection>` so `RefFields<T>` can extract refs
|
|
2360
|
-
* at the type level.
|
|
2361
|
-
*
|
|
2362
|
-
* The field's output type must match the target collection's `_id` type.
|
|
2363
|
-
* Mismatched types produce a compile error.
|
|
2364
|
-
*
|
|
2365
|
-
* Apply `.ref()` before wrapper methods like `.optional()` or `.nullable()`:
|
|
2366
|
-
* `objectId().ref(Users).optional()` — not `objectId().optional().ref(Users)`.
|
|
2367
|
-
*
|
|
2368
|
-
* @param collection - The target collection definition object.
|
|
2369
|
-
* @returns The same schema instance, branded with the ref marker.
|
|
2370
|
-
*
|
|
2371
|
-
* @example
|
|
2372
|
-
* ```ts
|
|
2373
|
-
* const Posts = collection('posts', {
|
|
2374
|
-
* authorId: objectId().ref(Users),
|
|
2375
|
-
* title: z.string(),
|
|
2376
|
-
* })
|
|
2377
|
-
* ```
|
|
2378
|
-
*/
|
|
2379
|
-
ref<TCollection extends AnyCollection>(collection: TCollection & (this['_zod']['output'] extends InferDocument<TCollection>['_id'] ? unknown : never)): this & RefMarker<TCollection>;
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
/**
|
|
2383
|
-
* Retrieve the ref metadata attached to a Zod schema, if any.
|
|
2384
|
-
*
|
|
2385
|
-
* Returns `undefined` when the schema was never marked with `.ref()`.
|
|
2386
|
-
*
|
|
2387
|
-
* @param schema - The Zod schema to inspect. Accepts `unknown` for
|
|
2388
|
-
* convenience; non-object values safely return `undefined`.
|
|
2389
|
-
* @returns The {@link RefMetadata} for the schema, or `undefined`.
|
|
2390
|
-
*
|
|
2391
|
-
* @example
|
|
2392
|
-
* ```ts
|
|
2393
|
-
* const authorId = objectId().ref(Users)
|
|
2394
|
-
* const meta = getRefMetadata(authorId)
|
|
2395
|
-
* // => { collection: Users }
|
|
2396
|
-
* ```
|
|
2397
|
-
*/
|
|
2398
|
-
declare function getRefMetadata(schema: unknown): RefMetadata | undefined;
|
|
2399
|
-
|
|
2400
3856
|
/**
|
|
2401
3857
|
* Shorthand for `CollectionHandle<TDef>`.
|
|
2402
3858
|
*
|
|
@@ -2462,4 +3918,4 @@ type UpdateFilterOf<TDef extends AnyCollection> = TypedUpdateFilter<InferDocumen
|
|
|
2462
3918
|
*/
|
|
2463
3919
|
type SortOf<TDef extends AnyCollection> = TypedSort<InferDocument<TDef>>;
|
|
2464
3920
|
|
|
2465
|
-
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, type CursorPage, type CursorPaginateOptions, Database, type DotPathType, type DotPaths, type FieldIndexDefinition, type FilterOf, type FindOneAndDeleteOptions, type FindOneAndUpdateOptions, type FindOneOptions, type FindOptions, type HandleOf, type IncFields, IndexBuilder, type IndexMetadata, type IndexNames, type IndexOptions, type IndexSpec, type InferDocument, type InferInsert, type OffsetPage, type OffsetPaginateOptions, type PopFields, type PullFields, type PushFields, type PushModifiers, type RefMarker, type RefMetadata, type RenameFields, type ResolvedShape, type SetFields, type SortOf, type StaleIndex, type SyncIndexesOptions, type SyncIndexesResult, type TypedFilter, TypedFindCursor, type TypedSort, type TypedUpdateFilter, type UnsetFields, type UpdateFilterOf, type UpdateOptions, type ValidationMode, type ZodObjectId, ZodmonNotFoundError, ZodmonValidationError, checkUnindexedFields, collection, createClient, deleteMany, deleteOne, extractComparableOptions, extractDbName, extractFieldIndexes, find, findOne, findOneAndDelete, findOneAndUpdate, findOneOrThrow, generateIndexName, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, isOid, objectId, oid, raw, serializeIndexKey, syncIndexes, toCompoundIndexSpec, toFieldIndexSpec, updateMany, updateOne };
|
|
3921
|
+
export { $, $addToSet, $and, $avg, $count, $eq, $exists, $first, $gt, $gte, $in, $last, $lt, $lte, $max, $min, $ne, $nin, $nor, $not, $or, $push, $regex, $sum, type Accumulator, type AccumulatorBuilder, type AddToSetEach, type AddToSetFields, AggregatePipeline, type AnyCollection, type ArrayElement, type CollectionDefinition, CollectionHandle, type CollectionName, type CollectionOptions, type ComparisonOperators, type CompoundIndexDefinition, type CurrentDateFields, type CursorPage, type CursorPaginateOptions, Database, type DotPathType, type DotPaths, type Expression, type ExpressionBuilder, type ExtractRefCollection, type FieldIndexDefinition, type FieldRef, type FieldRefType, type FilterOf, type FindOneAndDeleteOptions, type FindOneAndUpdateOptions, type FindOneOptions, type FindOptions, type GroupByCompoundResult, type GroupByResult, type HandleOf, type IncFields, IndexBuilder, type IndexMetadata, type IndexNames, type IndexOptions, type IndexSpec, type InferAccumulator, type InferAccumulators, type InferAddedFields, type InferDocument, type InferExpression, type InferInsert, type NarrowFromFilter, type OffsetPage, type OffsetPaginateOptions, type PopFields, type Prettify, type PullFields, type PushFields, type PushModifiers, type RefFields, type RefMarker, type RefMetadata, type RenameFields, type ResolvedShape, type SetFields, type SortOf, type StaleIndex, type SyncIndexesOptions, type SyncIndexesResult, type TypedFilter, TypedFindCursor, type TypedSort, type TypedUpdateFilter, type UnsetFields, type UnwindResult, type UpdateFilterOf, type UpdateOptions, type ValidationMode, type ZodObjectId, ZodmonAuthError, ZodmonBulkWriteError, ZodmonDocValidationError, ZodmonDuplicateKeyError, ZodmonError, ZodmonIndexError, ZodmonNetworkError, ZodmonNotFoundError, ZodmonQueryError, ZodmonTimeoutError, ZodmonValidationError, ZodmonWriteConflictError, aggregate, checkUnindexedFields, collection, createAccumulatorBuilder, createClient, createExpressionBuilder, deleteMany, deleteOne, extractComparableOptions, extractDbName, extractFieldIndexes, find, findOne, findOneAndDelete, findOneAndUpdate, findOneOrThrow, generateIndexName, getIndexMetadata, getRefMetadata, index, insertMany, insertOne, isOid, objectId, oid, raw, serializeIndexKey, syncIndexes, toCompoundIndexSpec, toFieldIndexSpec, updateMany, updateOne, wrapMongoError };
|