@zodmon/core 0.10.0 → 0.12.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 +991 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1914 -344
- package/dist/index.d.ts +1914 -344
- package/dist/index.js +980 -234
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/aggregate/expressions.ts","../src/errors/wrap.ts","../src/errors/base.ts","../src/errors/auth.ts","../src/errors/bulk-write.ts","../src/errors/doc-validation.ts","../src/errors/duplicate-key.ts","../src/errors/index-error.ts","../src/errors/network.ts","../src/errors/query.ts","../src/errors/timeout.ts","../src/errors/write-conflict.ts","../src/schema/ref.ts","../src/aggregate/pipeline.ts","../src/client/client.ts","../src/indexes/spec.ts","../src/indexes/sync.ts","../src/crud/delete.ts","../src/errors/validation.ts","../src/crud/find.ts","../src/errors/not-found.ts","../src/indexes/warn.ts","../src/query/cursor.ts","../src/crud/paginate.ts","../src/crud/insert.ts","../src/crud/update.ts","../src/client/handle.ts","../src/collection/collection.ts","../src/schema/extensions.ts","../src/schema/object-id.ts","../src/collection/index-def.ts","../src/helpers/oid.ts","../src/query/operators.ts","../src/query/namespace.ts"],"sourcesContent":["export type {\n\tAccumulator,\n\tAccumulatorBuilder,\n\tCollectionName,\n\tExpression,\n\tExpressionBuilder,\n\tExtractRefCollection,\n\tFieldRef,\n\tFieldRefType,\n\tGroupByCompoundResult,\n\tGroupByResult,\n\tInferAccumulator,\n\tInferAccumulators,\n\tInferAddedFields,\n\tInferExpression,\n\tNarrowFromFilter,\n\tRefFields,\n\tUnwindResult,\n} from './aggregate'\nexport {\n\t$addToSet,\n\t$avg,\n\t$count,\n\t$first,\n\t$last,\n\t$max,\n\t$min,\n\t$push,\n\t$sum,\n\tAggregatePipeline,\n\taggregate,\n\tcreateAccumulatorBuilder,\n\tcreateExpressionBuilder,\n} from './aggregate'\nexport { CollectionHandle, createClient, Database, extractDbName } from './client'\nexport type {\n\tAnyCollection,\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tIndexNames,\n\tInferDocument,\n\tInferInsert,\n\tResolvedShape,\n\tValidationMode,\n} from './collection'\nexport { collection, extractFieldIndexes, IndexBuilder, index } from './collection'\nexport type {\n\tCursorPage,\n\tCursorPaginateOptions,\n\tFindOneAndDeleteOptions,\n\tFindOneAndUpdateOptions,\n\tFindOneOptions,\n\tFindOptions,\n\tOffsetPage,\n\tOffsetPaginateOptions,\n\tUpdateOptions,\n} from './crud'\nexport {\n\tdeleteMany,\n\tdeleteOne,\n\tfind,\n\tfindOne,\n\tfindOneAndDelete,\n\tfindOneAndUpdate,\n\tfindOneOrThrow,\n\tinsertMany,\n\tinsertOne,\n\tupdateMany,\n\tupdateOne,\n} from './crud'\nexport {\n\twrapMongoError,\n\tZodmonAuthError,\n\tZodmonBulkWriteError,\n\tZodmonDocValidationError,\n\tZodmonDuplicateKeyError,\n\tZodmonError,\n\tZodmonIndexError,\n\tZodmonNetworkError,\n\tZodmonNotFoundError,\n\tZodmonQueryError,\n\tZodmonTimeoutError,\n\tZodmonValidationError,\n\tZodmonWriteConflictError,\n} from './errors'\nexport { isOid, oid } from './helpers/oid'\nexport type { Prettify } from './helpers/types'\nexport type { IndexSpec, StaleIndex, SyncIndexesOptions, SyncIndexesResult } from './indexes'\nexport {\n\tcheckUnindexedFields,\n\textractComparableOptions,\n\tgenerateIndexName,\n\tserializeIndexKey,\n\tsyncIndexes,\n\ttoCompoundIndexSpec,\n\ttoFieldIndexSpec,\n} from './indexes'\nexport type {\n\tAddToSetEach,\n\tAddToSetFields,\n\tArrayElement,\n\tComparisonOperators,\n\tCurrentDateFields,\n\tDotPaths,\n\tDotPathType,\n\tIncFields,\n\tPopFields,\n\tPullFields,\n\tPushFields,\n\tPushModifiers,\n\tRenameFields,\n\tSetFields,\n\tTypedFilter,\n\tTypedSort,\n\tTypedUpdateFilter,\n\tUnsetFields,\n} from './query'\nexport {\n\t$,\n\t$and,\n\t$eq,\n\t$exists,\n\t$gt,\n\t$gte,\n\t$in,\n\t$lt,\n\t$lte,\n\t$ne,\n\t$nin,\n\t$nor,\n\t$not,\n\t$or,\n\t$regex,\n\traw,\n\tTypedFindCursor,\n} from './query'\nexport {\n\tgetIndexMetadata,\n\tgetRefMetadata,\n\ttype IndexMetadata,\n\ttype IndexOptions,\n\tobjectId,\n\ttype RefMarker,\n\ttype RefMetadata,\n\ttype ZodObjectId,\n} from './schema'\nexport type { FilterOf, HandleOf, SortOf, UpdateFilterOf } from './types'\n","import type { Accumulator, AccumulatorBuilder, Expression, ExpressionBuilder } from './types'\n\n/**\n * Counts the number of documents in each group.\n *\n * Equivalent to `{ $sum: 1 }` in a MongoDB `$group` stage.\n *\n * @returns An `Accumulator<number>` that counts documents.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('status', { count: $count() })\n * ```\n */\nexport const $count = (): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $sum: 1 },\n})\n\n/**\n * Sums numeric values across documents in each group.\n *\n * Accepts either a `$`-prefixed field reference or a literal number.\n *\n * @param field - A `$field` reference to a numeric field, or a literal number.\n * @returns An `Accumulator<number>`.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('status', {\n * \t\ttotal: $sum('$amount'),\n * \t\tfixed: $sum(1),\n * \t})\n * ```\n */\nexport const $sum = (field: `$${string}` | number): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $sum: field },\n})\n\n/**\n * Computes the average of numeric values across documents in each group.\n *\n * @param field - A `$field` reference to a numeric field.\n * @returns An `Accumulator<number>`.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('category', { avgPrice: $avg('$price') })\n * ```\n */\nexport const $avg = (field: `$${string}`): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $avg: field },\n})\n\n/**\n * Returns the minimum value across documents in each group.\n *\n * For full type safety, prefer the callback builder (`acc.min('price')`).\n * The standalone form accepts an explicit result type `R` for manual typing.\n *\n * @typeParam R - The expected result type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit result type\n * const pipeline = orders.aggregate()\n * \t.groupBy('category', { cheapest: $min<number>('$price') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.groupBy('category', acc => ({ cheapest: acc.min('price') }))\n * ```\n */\nexport const $min = <R = unknown>(field: `$${string}`): Accumulator<R> => ({\n\t__accum: true,\n\texpr: { $min: field },\n})\n\n/**\n * Returns the maximum value across documents in each group.\n *\n * For full type safety, prefer the callback builder (`acc.max('price')`).\n * The standalone form accepts an explicit result type `R` for manual typing.\n *\n * @typeParam R - The expected result type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit result type\n * const pipeline = orders.aggregate()\n * \t.groupBy('category', { priciest: $max<number>('$price') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.groupBy('category', acc => ({ priciest: acc.max('price') }))\n * ```\n */\nexport const $max = <R = unknown>(field: `$${string}`): Accumulator<R> => ({\n\t__accum: true,\n\texpr: { $max: field },\n})\n\n/**\n * Returns the first value in each group according to the document order.\n *\n * For full type safety, prefer the callback builder (`acc.first('name')`).\n * The standalone form accepts an explicit result type `R` for manual typing.\n *\n * @typeParam R - The expected result type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit result type\n * const pipeline = orders.aggregate()\n * \t.sort({ createdAt: 1 })\n * \t.groupBy('status', { earliest: $first<Date>('$createdAt') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.sort({ createdAt: 1 })\n * \t.groupBy('status', acc => ({ earliest: acc.first('createdAt') }))\n * ```\n */\nexport const $first = <R = unknown>(field: `$${string}`): Accumulator<R> => ({\n\t__accum: true,\n\texpr: { $first: field },\n})\n\n/**\n * Returns the last value in each group according to the document order.\n *\n * For full type safety, prefer the callback builder (`acc.last('name')`).\n * The standalone form accepts an explicit result type `R` for manual typing.\n *\n * @typeParam R - The expected result type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit result type\n * const pipeline = orders.aggregate()\n * \t.sort({ createdAt: -1 })\n * \t.groupBy('status', { latest: $last<Date>('$createdAt') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.sort({ createdAt: -1 })\n * \t.groupBy('status', acc => ({ latest: acc.last('createdAt') }))\n * ```\n */\nexport const $last = <R = unknown>(field: `$${string}`): Accumulator<R> => ({\n\t__accum: true,\n\texpr: { $last: field },\n})\n\n/**\n * Pushes values into an array for each group.\n *\n * May contain duplicates. Use `$addToSet` for unique values.\n * For full type safety, prefer the callback builder (`acc.push('name')`).\n *\n * @typeParam R - The element type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R[]>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit element type\n * const pipeline = orders.aggregate()\n * \t.groupBy('status', { items: $push<string>('$name') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.groupBy('status', acc => ({ items: acc.push('name') }))\n * ```\n */\nexport const $push = <R = unknown>(field: `$${string}`): Accumulator<R[]> => ({\n\t__accum: true,\n\texpr: { $push: field },\n})\n\n/**\n * Collects unique values into an array for each group (set semantics).\n *\n * Like `$push` but deduplicates.\n * For full type safety, prefer the callback builder (`acc.addToSet('tag')`).\n *\n * @typeParam R - The element type (defaults to `unknown`).\n * @param field - A `$field` reference.\n * @returns An `Accumulator<R[]>`.\n *\n * @example\n * ```ts\n * // Tier 2 — explicit element type\n * const pipeline = orders.aggregate()\n * \t.groupBy('category', { uniqueTags: $addToSet<string>('$tag') })\n *\n * // Tier 1 — callback builder (recommended)\n * orders.aggregate()\n * \t.groupBy('category', acc => ({ uniqueTags: acc.addToSet('tag') }))\n * ```\n */\nexport const $addToSet = <R = unknown>(field: `$${string}`): Accumulator<R[]> => ({\n\t__accum: true,\n\texpr: { $addToSet: field },\n})\n\n/**\n * Create a typed accumulator builder for use inside `groupBy` callbacks.\n *\n * The builder adds the `$` prefix to field names automatically and returns\n * properly typed `Accumulator<T[K]>` values. Primarily used internally by\n * `AggregatePipeline.groupBy` — most users interact with the builder via\n * the callback parameter rather than calling this directly.\n *\n * @typeParam T - The current pipeline output document type.\n * @returns An `AccumulatorBuilder<T>` with methods for each MongoDB accumulator.\n *\n * @example\n * ```ts\n * const acc = createAccumulatorBuilder<{ salary: number; name: string }>()\n * acc.min('salary') // { __accum: true, expr: { $min: '$salary' } }\n * acc.push('name') // { __accum: true, expr: { $push: '$name' } }\n * ```\n */\nexport function createAccumulatorBuilder<T>(): AccumulatorBuilder<T> {\n\treturn {\n\t\tcount: () => ({ __accum: true, expr: { $sum: 1 } }),\n\t\tsum: (field: string | number) => ({\n\t\t\t__accum: true,\n\t\t\texpr: { $sum: typeof field === 'number' ? field : `$${field}` },\n\t\t}),\n\t\tavg: (field: string) => ({ __accum: true, expr: { $avg: `$${field}` } }),\n\t\tmin: (field: string) => ({ __accum: true, expr: { $min: `$${field}` } }),\n\t\tmax: (field: string) => ({ __accum: true, expr: { $max: `$${field}` } }),\n\t\tfirst: (field: string) => ({ __accum: true, expr: { $first: `$${field}` } }),\n\t\tlast: (field: string) => ({ __accum: true, expr: { $last: `$${field}` } }),\n\t\tpush: (field: string) => ({ __accum: true, expr: { $push: `$${field}` } }),\n\t\taddToSet: (field: string) => ({ __accum: true, expr: { $addToSet: `$${field}` } }),\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Runtime implementation uses string field names and returns plain objects — TypeScript cannot verify that the runtime Accumulator objects match the generic AccumulatorBuilder<T> return types. Safe because type resolution happens at compile time via AccumulatorBuilder<T>, and runtime values are identical to what the standalone $min/$max/etc. produce.\n\t} as any\n}\n\n/**\n * Create a typed expression builder for use inside `addFields` callbacks.\n *\n * The builder adds the `$` prefix to field names automatically and returns\n * properly typed `Expression<T>` values. Primarily used internally by\n * `AggregatePipeline.addFields` — most users interact with the builder via\n * the callback parameter rather than calling this directly.\n *\n * @typeParam T - The current pipeline output document type.\n * @returns An `ExpressionBuilder<T>` with methods for each MongoDB expression operator.\n *\n * @example\n * ```ts\n * const expr = createExpressionBuilder<{ salary: number; name: string; hiredAt: Date }>()\n * expr.year('hiredAt') // { __expr: true, value: { $year: '$hiredAt' } }\n * expr.multiply('salary', 0.9) // { __expr: true, value: { $multiply: ['$salary', 0.9] } }\n * ```\n */\nexport function createExpressionBuilder<T>(): ExpressionBuilder<T> {\n\tconst $ = (field: string) => `$${field}`\n\tconst val = (v: string | number) => (typeof v === 'number' ? v : `$${v}`)\n\tconst expr = <R>(value: unknown): Expression<R> => ({ __expr: true, value }) as Expression<R>\n\n\treturn {\n\t\t// Arithmetic\n\t\tadd: (field: string, value: string | number) => expr({ $add: [$(field), val(value)] }),\n\t\tsubtract: (field: string, value: string | number) =>\n\t\t\texpr({ $subtract: [$(field), val(value)] }),\n\t\tmultiply: (field: string, value: string | number) =>\n\t\t\texpr({ $multiply: [$(field), val(value)] }),\n\t\tdivide: (field: string, value: string | number) => expr({ $divide: [$(field), val(value)] }),\n\t\tmod: (field: string, value: string | number) => expr({ $mod: [$(field), val(value)] }),\n\t\tabs: (field: string) => expr({ $abs: $(field) }),\n\t\tceil: (field: string) => expr({ $ceil: $(field) }),\n\t\tfloor: (field: string) => expr({ $floor: $(field) }),\n\t\tround: (field: string, place = 0) => expr({ $round: [$(field), place] }),\n\n\t\t// String\n\t\tconcat: (...parts: string[]) => {\n\t\t\tconst resolved = parts.map((p) => {\n\t\t\t\t// If it looks like a quoted literal (contains spaces, punctuation, etc.) keep as-is\n\t\t\t\t// Otherwise treat as field name and add $ prefix\n\t\t\t\t// Heuristic: field names are single words matching [a-zA-Z_][a-zA-Z0-9_]*\n\t\t\t\tif (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(p)) return $(p)\n\t\t\t\treturn p\n\t\t\t})\n\t\t\treturn expr({ $concat: resolved })\n\t\t},\n\t\ttoLower: (field: string) => expr({ $toLower: $(field) }),\n\t\ttoUpper: (field: string) => expr({ $toUpper: $(field) }),\n\t\ttrim: (field: string) => expr({ $trim: { input: $(field) } }),\n\t\tsubstr: (field: string, start: number, length: number) =>\n\t\t\texpr({ $substrBytes: [$(field), start, length] }),\n\n\t\t// Comparison\n\t\teq: (field: string, value: unknown) => expr({ $eq: [$(field), value] }),\n\t\tgt: (field: string, value: unknown) => expr({ $gt: [$(field), value] }),\n\t\tgte: (field: string, value: unknown) => expr({ $gte: [$(field), value] }),\n\t\tlt: (field: string, value: unknown) => expr({ $lt: [$(field), value] }),\n\t\tlte: (field: string, value: unknown) => expr({ $lte: [$(field), value] }),\n\t\tne: (field: string, value: unknown) => expr({ $ne: [$(field), value] }),\n\n\t\t// Date\n\t\tyear: (field: string) => expr({ $year: $(field) }),\n\t\tmonth: (field: string) => expr({ $month: $(field) }),\n\t\tdayOfMonth: (field: string) => expr({ $dayOfMonth: $(field) }),\n\n\t\t// Array\n\t\tsize: (field: string) => expr({ $size: $(field) }),\n\n\t\t// Conditional\n\t\tcond: (condition: Expression<boolean>, thenValue: unknown, elseValue: unknown) =>\n\t\t\texpr({ $cond: [condition.value, thenValue, elseValue] }),\n\t\tifNull: (field: string, fallback: unknown) => expr({ $ifNull: [$(field), fallback] }),\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Runtime implementation uses string field names — TypeScript cannot verify generic ExpressionBuilder<T> return types match. Safe because type resolution happens at compile time.\n\t} as any\n}\n","import { MongoBulkWriteError, MongoNetworkError, MongoServerError } from 'mongodb'\nimport { ZodmonAuthError } from './auth'\nimport { ZodmonError } from './base'\nimport { ZodmonBulkWriteError } from './bulk-write'\nimport { ZodmonDocValidationError } from './doc-validation'\nimport { ZodmonDuplicateKeyError } from './duplicate-key'\nimport { ZodmonIndexError } from './index-error'\nimport { ZodmonNetworkError } from './network'\nimport { ZodmonQueryError } from './query'\nimport { ZodmonTimeoutError } from './timeout'\nimport { ZodmonWriteConflictError } from './write-conflict'\n\n/**\n * Maps a caught MongoDB error to the appropriate Zodmon error subclass and throws it.\n *\n * This function always throws — it never returns. Use it in `catch` blocks to convert\n * raw MongoDB driver errors into structured, typed Zodmon errors. If the error is already\n * a `ZodmonError`, it is rethrown as-is to prevent double-wrapping.\n *\n * @example\n * ```ts\n * try {\n * await db.collection('users').insertOne(doc)\n * } catch (err) {\n * wrapMongoError(err, 'users')\n * }\n * ```\n */\nexport function wrapMongoError(err: unknown, collection: string): never {\n\t// 1. Already a ZodmonError — rethrow as-is (no double-wrap)\n\tif (err instanceof ZodmonError) {\n\t\tthrow err\n\t}\n\n\t// 2. MongoBulkWriteError (extends MongoServerError, so check first)\n\tif (err instanceof MongoBulkWriteError) {\n\t\tthrow new ZodmonBulkWriteError(collection, err)\n\t}\n\n\t// 3. MongoNetworkError\n\tif (err instanceof MongoNetworkError) {\n\t\tthrow new ZodmonNetworkError(collection, err)\n\t}\n\n\t// 4. MongoServerError — switch on error code\n\tif (err instanceof MongoServerError) {\n\t\tswitch (err.code) {\n\t\t\tcase 11000:\n\t\t\tcase 11001:\n\t\t\t\tthrow new ZodmonDuplicateKeyError(collection, err)\n\t\t\tcase 112:\n\t\t\t\tthrow new ZodmonWriteConflictError(collection, err)\n\t\t\tcase 50:\n\t\t\tcase 262:\n\t\t\t\tthrow new ZodmonTimeoutError(collection, err.code, err)\n\t\t\tcase 13:\n\t\t\tcase 18:\n\t\t\t\tthrow new ZodmonAuthError(collection, err.code, err)\n\t\t\tcase 67:\n\t\t\tcase 85:\n\t\t\tcase 86:\n\t\t\t\tthrow new ZodmonIndexError(collection, err.code, err.message, err)\n\t\t\tcase 2:\n\t\t\tcase 9:\n\t\t\tcase 292:\n\t\t\t\tthrow new ZodmonQueryError(collection, err.code, err.message, err)\n\t\t\tcase 121:\n\t\t\t\tthrow new ZodmonDocValidationError(\n\t\t\t\t\tcollection,\n\t\t\t\t\t(err as MongoServerError & { errInfo?: unknown }).errInfo,\n\t\t\t\t\terr,\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\tthrow new ZodmonError(`MongoDB error on \"${collection}\": ${err.message}`, collection, {\n\t\t\t\t\tcause: err,\n\t\t\t\t})\n\t\t}\n\t}\n\n\t// 5. Any other Error\n\tif (err instanceof Error) {\n\t\tthrow new ZodmonError(`Unexpected error on \"${collection}\": ${err.message}`, collection, {\n\t\t\tcause: err,\n\t\t})\n\t}\n\n\t// 6. Non-Error value\n\tthrow new ZodmonError(`Unexpected error on \"${collection}\": ${String(err)}`, collection)\n}\n","/**\n * Base error class for all Zodmon errors.\n *\n * Every error thrown by Zodmon extends this class, making it easy to catch all\n * Zodmon-related errors in a single `catch` block while still allowing more\n * specific handling via subclass checks.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 123 })\n * } catch (err) {\n * if (err instanceof ZodmonError) {\n * console.log(err.name) // => 'ZodmonError' (or a subclass name)\n * console.log(err.collection) // => 'users'\n * console.log(err.cause) // => original Error, if provided\n * }\n * }\n * ```\n */\nexport class ZodmonError extends Error {\n\toverride readonly name: string = 'ZodmonError'\n\n\t/** The MongoDB collection name associated with this error. */\n\treadonly collection: string\n\n\t/** The underlying error that caused this error, if any. */\n\toverride readonly cause?: Error\n\n\tconstructor(message: string, collection: string, options?: { cause?: Error }) {\n\t\tsuper(message)\n\t\tthis.collection = collection\n\t\tif (options?.cause) {\n\t\t\tthis.cause = options.cause\n\t\t}\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when MongoDB rejects an operation due to authentication or authorization failure.\n *\n * Corresponds to MongoDB error codes 13 (Unauthorized) and 18 (AuthenticationFailed).\n * Inspect `.code` to distinguish between authorization and authentication failures.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 'Alice' })\n * } catch (err) {\n * if (err instanceof ZodmonAuthError) {\n * console.log(err.message) // => 'Not authorized to perform this operation on \"users\"'\n * console.log(err.code) // => 13 or 18\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonAuthError extends ZodmonError {\n\toverride readonly name = 'ZodmonAuthError'\n\n\t/** The MongoDB error code (13 or 18). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, cause: Error) {\n\t\tconst message =\n\t\t\tcode === 18\n\t\t\t\t? `Authentication failed for \"${collection}\": check connection credentials`\n\t\t\t\t: `Not authorized to perform this operation on \"${collection}\"`\n\t\tsuper(message, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a bulk write operation partially or fully fails.\n *\n * Exposes partial result counts (`.insertedCount`, `.matchedCount`, etc.) alongside\n * an array of `.writeErrors` describing each individual failure. Use this to determine\n * which operations succeeded and which failed.\n *\n * @example\n * ```ts\n * try {\n * await users.insertMany([{ name: 'Alice' }, { name: 'Alice' }]) // duplicate\n * } catch (err) {\n * if (err instanceof ZodmonBulkWriteError) {\n * console.log(err.insertedCount) // => 1\n * console.log(err.writeErrors) // => [{ index: 1, code: 11000, message: '...' }]\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonBulkWriteError extends ZodmonError {\n\toverride readonly name = 'ZodmonBulkWriteError'\n\n\t/** Number of documents successfully inserted. */\n\treadonly insertedCount: number\n\n\t/** Number of documents matched by update filters. */\n\treadonly matchedCount: number\n\n\t/** Number of documents actually modified. */\n\treadonly modifiedCount: number\n\n\t/** Number of documents deleted. */\n\treadonly deletedCount: number\n\n\t/** Individual write errors with their operation index, code, and message. */\n\treadonly writeErrors: Array<{ index: number; code: number; message: string }>\n\n\tconstructor(collection: string, cause: Error, totalOps?: number) {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: accessing MongoBulkWriteError properties not on Error type\n\t\tconst bulkErr = cause as any\n\t\tconst result = (bulkErr['result'] ?? {}) as Record<string, unknown>\n\t\tconst rawErrors = (bulkErr['writeErrors'] ?? []) as Array<Record<string, unknown>>\n\n\t\tconst writeErrors = rawErrors.map((e) => ({\n\t\t\tindex: (e['index'] as number) ?? 0,\n\t\t\tcode: (e['code'] as number) ?? 0,\n\t\t\tmessage: ((e['errmsg'] ?? e['message']) as string) ?? 'unknown error',\n\t\t}))\n\n\t\tconst failedMsg =\n\t\t\ttotalOps !== undefined\n\t\t\t\t? `${writeErrors.length} of ${totalOps} operations failed`\n\t\t\t\t: `${writeErrors.length} operations failed`\n\t\tsuper(`Bulk write failed on \"${collection}\": ${failedMsg}`, collection, { cause })\n\n\t\tthis.insertedCount = (result['insertedCount'] as number) ?? 0\n\t\tthis.matchedCount = (result['matchedCount'] as number) ?? 0\n\t\tthis.modifiedCount = (result['modifiedCount'] as number) ?? 0\n\t\tthis.deletedCount = (result['deletedCount'] as number) ?? 0\n\t\tthis.writeErrors = writeErrors\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a document fails server-side JSON Schema validation (MongoDB error code 121).\n *\n * This is distinct from {@link ZodmonValidationError}, which validates against Zod schemas\n * on the client side. This error surfaces when MongoDB's own document validation rejects\n * a write. Inspect `.errInfo` for the server's detailed validation failure information.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 'Alice', age: -1 })\n * } catch (err) {\n * if (err instanceof ZodmonDocValidationError) {\n * console.log(err.message) // => 'Server-side document validation failed for \"users\": ...'\n * console.log(err.errInfo) // => { failingDocumentId: ..., details: ... }\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonDocValidationError extends ZodmonError {\n\toverride readonly name = 'ZodmonDocValidationError'\n\n\t/** Server-provided validation failure details. */\n\treadonly errInfo: unknown\n\n\tconstructor(collection: string, errInfo: unknown, cause: Error) {\n\t\tsuper(\n\t\t\t`Server-side document validation failed for \"${collection}\": ${cause.message}`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\t\tthis.errInfo = errInfo\n\t}\n}\n","import { ZodmonError } from './base'\n\nconst INDEX_REGEX = /index:\\s+(\\S+)/\nconst DUP_KEY_FIELD_REGEX = /dup key:\\s*\\{\\s*(\\w+):/\n\n/**\n * Thrown when a MongoDB insert or update violates a unique index constraint (E11000).\n *\n * Parses the duplicate key information from the MongoDB driver error to expose\n * structured fields: `.field` (first conflicting key), `.value`, `.index` (index name),\n * `.keyPattern`, and `.keyValue`. Falls back to regex parsing for older drivers.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ email: 'alice@example.com' })\n * } catch (err) {\n * if (err instanceof ZodmonDuplicateKeyError) {\n * console.log(err.field) // => 'email'\n * console.log(err.value) // => 'alice@example.com'\n * console.log(err.index) // => 'email_1'\n * console.log(err.keyPattern) // => { email: 1 }\n * console.log(err.keyValue) // => { email: 'alice@example.com' }\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonDuplicateKeyError extends ZodmonError {\n\toverride readonly name = 'ZodmonDuplicateKeyError'\n\n\t/** The first field that caused the duplicate key violation. */\n\treadonly field: string\n\n\t/** The duplicate value, or `undefined` if it could not be extracted. */\n\treadonly value: unknown\n\n\t/** The name of the index that was violated. */\n\treadonly index: string\n\n\t/** The key pattern of the violated index (e.g. `{ email: 1 }`). */\n\treadonly keyPattern: Record<string, number>\n\n\t/** The key values that caused the violation. */\n\treadonly keyValue: Record<string, unknown>\n\n\tconstructor(collection: string, cause: Error) {\n\t\t// Extract from keyPattern/keyValue properties (MongoDB 4.2+)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: accessing MongoServerError properties not on Error type\n\t\tconst serverErr = cause as any\n\t\tconst kp = serverErr['keyPattern'] as Record<string, number> | undefined\n\t\tconst kv = serverErr['keyValue'] as Record<string, unknown> | undefined\n\n\t\tlet field: string\n\t\tlet value: unknown\n\t\tlet keyPattern: Record<string, number>\n\t\tlet keyValue: Record<string, unknown>\n\n\t\tif (kp && kv) {\n\t\t\tconst firstKey = Object.keys(kp)[0] ?? 'unknown'\n\t\t\tfield = firstKey\n\t\t\tvalue = kv[firstKey]\n\t\t\tkeyPattern = kp\n\t\t\tkeyValue = kv\n\t\t} else {\n\t\t\t// Fallback: regex parse from errmsg\n\t\t\tconst fieldMatch = cause.message.match(DUP_KEY_FIELD_REGEX)\n\t\t\tfield = fieldMatch?.[1] ?? 'unknown'\n\t\t\tvalue = undefined\n\t\t\tkeyPattern = field !== 'unknown' ? { [field]: 1 } : {}\n\t\t\tkeyValue = {}\n\t\t}\n\n\t\tconst indexMatch = cause.message.match(INDEX_REGEX)\n\t\tconst index = indexMatch?.[1] ?? 'unknown'\n\n\t\tconst valueStr = typeof value === 'string' ? `\"${value}\"` : String(value)\n\t\tsuper(\n\t\t\t`Duplicate key in \"${collection}\": ${field} = ${valueStr} (index: ${index})`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\n\t\tthis.field = field\n\t\tthis.value = value\n\t\tthis.index = index\n\t\tthis.keyPattern = keyPattern\n\t\tthis.keyValue = keyValue\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB index operation fails.\n *\n * Corresponds to MongoDB error codes 67 (CannotCreateIndex), 85 (IndexOptionsConflict),\n * and 86 (IndexKeySpecsConflict). Inspect `.code` to determine the specific failure reason.\n *\n * @example\n * ```ts\n * try {\n * await syncIndexes(db, [Users])\n * } catch (err) {\n * if (err instanceof ZodmonIndexError) {\n * console.log(err.message) // => 'Index options conflict on \"users\": ...'\n * console.log(err.code) // => 67, 85, or 86\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonIndexError extends ZodmonError {\n\toverride readonly name = 'ZodmonIndexError'\n\n\t/** The MongoDB error code (67, 85, or 86). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, errmsg: string, cause: Error) {\n\t\tconst prefix =\n\t\t\tcode === 67\n\t\t\t\t? 'Cannot create index'\n\t\t\t\t: code === 85\n\t\t\t\t\t? 'Index options conflict'\n\t\t\t\t\t: 'Index key specs conflict'\n\t\tsuper(`${prefix} on \"${collection}\": ${errmsg}`, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB operation fails due to a network error.\n *\n * Wraps `MongoNetworkError` from the MongoDB driver with the collection name\n * and the original error message for easier debugging.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ status: 'active' })\n * } catch (err) {\n * if (err instanceof ZodmonNetworkError) {\n * console.log(err.message) // => 'Network error on \"users\": connection refused'\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonNetworkError extends ZodmonError {\n\toverride readonly name = 'ZodmonNetworkError'\n\n\tconstructor(collection: string, cause: Error) {\n\t\tsuper(`Network error on \"${collection}\": ${cause.message}`, collection, { cause })\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB query is malformed or exceeds resource limits.\n *\n * Corresponds to MongoDB error codes 2 (BadValue), 9 (FailedToParse), and\n * 292 (QueryExceededMemoryLimit). Inspect `.code` to determine the specific failure.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ $invalid: true })\n * } catch (err) {\n * if (err instanceof ZodmonQueryError) {\n * console.log(err.message) // => 'Bad value in query on \"users\": ...'\n * console.log(err.code) // => 2, 9, or 292\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonQueryError extends ZodmonError {\n\toverride readonly name = 'ZodmonQueryError'\n\n\t/** The MongoDB error code (2, 9, or 292). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, errmsg: string, cause: Error) {\n\t\tconst message =\n\t\t\tcode === 292\n\t\t\t\t? `Query exceeded memory limit on \"${collection}\": enable allowDiskUse for large sorts or aggregations`\n\t\t\t\t: code === 9\n\t\t\t\t\t? `Failed to parse query on \"${collection}\": ${errmsg}`\n\t\t\t\t\t: `Bad value in query on \"${collection}\": ${errmsg}`\n\t\tsuper(message, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB operation exceeds its server time limit.\n *\n * Corresponds to MongoDB error codes 50 (MaxTimeMSExpired) and\n * 262 (ExceededTimeLimit). Inspect `.code` to distinguish between the two.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ status: 'active' })\n * } catch (err) {\n * if (err instanceof ZodmonTimeoutError) {\n * console.log(err.message) // => 'Operation timed out on \"users\": ...'\n * console.log(err.code) // => 50 or 262\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonTimeoutError extends ZodmonError {\n\toverride readonly name = 'ZodmonTimeoutError'\n\n\t/** The MongoDB error code (50 or 262). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, cause: Error) {\n\t\tsuper(`Operation timed out on \"${collection}\": exceeded server time limit`, collection, {\n\t\t\tcause,\n\t\t})\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a transaction encounters a write conflict (MongoDB error code 112).\n *\n * This occurs when another operation modifies the same document concurrently during\n * a transaction. The recommended recovery strategy is to retry the transaction.\n *\n * @example\n * ```ts\n * try {\n * await db.transaction(async (tx) => {\n * const users = tx.use(Users)\n * await users.updateOne({ _id: id }, { $inc: { balance: -100 } })\n * })\n * } catch (err) {\n * if (err instanceof ZodmonWriteConflictError) {\n * console.log(err.message) // => 'Write conflict in \"users\": ...'\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonWriteConflictError extends ZodmonError {\n\toverride readonly name = 'ZodmonWriteConflictError'\n\n\tconstructor(collection: string, cause: Error) {\n\t\tsuper(\n\t\t\t`Write conflict in \"${collection}\": another operation modified this document concurrently — retry the transaction`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\t}\n}\n","import { z } from 'zod'\nimport type { AnyCollection, InferDocument } from '../collection/types'\n\n/**\n * Type-level marker that carries the target collection type through the\n * type system. Intersected with the schema return type by `.ref()` so\n * that `RefFields<T>` (future) can extract ref relationships.\n *\n * This is a phantom brand — no runtime value has this property.\n */\nexport type RefMarker<TCollection extends AnyCollection = AnyCollection> = {\n\treadonly _ref: TCollection\n}\n\n/**\n * Metadata stored in the WeakMap sidecar for schemas marked with `.ref()`.\n * Holds a reference to the target collection definition object.\n */\nexport type RefMetadata = {\n\treadonly collection: AnyCollection\n}\n\n/**\n * Module augmentation: adds `.ref()` to all `ZodType` schemas.\n *\n * The intersection constraint `this['_zod']['output'] extends InferDocument<TCollection>['_id']`\n * ensures compile-time type safety: the field's output type must match the\n * target collection's `_id` type. Mismatches produce a type error.\n *\n * Supports both default ObjectId `_id` and custom `_id` types (string, nanoid, etc.):\n * - `objectId().ref(Users)` compiles when Users has ObjectId `_id`\n * - `z.string().ref(Orgs)` compiles when Orgs has string `_id`\n * - `z.string().ref(Users)` is a type error (string ≠ ObjectId)\n * - `objectId().ref(Orgs)` is a type error (ObjectId ≠ string)\n */\ndeclare module 'zod' {\n\tinterface ZodType {\n\t\t/**\n\t\t * Declare a typed foreign key reference to another collection.\n\t\t *\n\t\t * Stores the target collection definition in metadata for runtime\n\t\t * populate resolution, and brands the return type with\n\t\t * `RefMarker<TCollection>` so `RefFields<T>` can extract refs\n\t\t * at the type level.\n\t\t *\n\t\t * The field's output type must match the target collection's `_id` type.\n\t\t * Mismatched types produce a compile error.\n\t\t *\n\t\t * Apply `.ref()` before wrapper methods like `.optional()` or `.nullable()`:\n\t\t * `objectId().ref(Users).optional()` — not `objectId().optional().ref(Users)`.\n\t\t *\n\t\t * @param collection - The target collection definition object.\n\t\t * @returns The same schema instance, branded with the ref marker.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const Posts = collection('posts', {\n\t\t * authorId: objectId().ref(Users),\n\t\t * title: z.string(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tref<TCollection extends AnyCollection>(\n\t\t\tcollection: TCollection &\n\t\t\t\t(this['_zod']['output'] extends InferDocument<TCollection>['_id'] ? unknown : never),\n\t\t): this & RefMarker<TCollection>\n\t}\n}\n\n/**\n * WeakMap sidecar that associates a Zod schema instance with its\n * {@link RefMetadata}. Uses WeakMap so ref metadata does not prevent\n * garbage collection of schema instances.\n */\nconst refMetadata = new WeakMap<object, RefMetadata>()\n\n/**\n * Retrieve the ref metadata attached to a Zod schema, if any.\n *\n * Returns `undefined` when the schema was never marked with `.ref()`.\n *\n * @param schema - The Zod schema to inspect. Accepts `unknown` for\n * convenience; non-object values safely return `undefined`.\n * @returns The {@link RefMetadata} for the schema, or `undefined`.\n *\n * @example\n * ```ts\n * const authorId = objectId().ref(Users)\n * const meta = getRefMetadata(authorId)\n * // => { collection: Users }\n * ```\n */\nexport function getRefMetadata(schema: unknown): RefMetadata | undefined {\n\tif (typeof schema !== 'object' || schema === null) return undefined\n\treturn refMetadata.get(schema)\n}\n\n/**\n * Symbol guard to prevent double-registration of the `.ref()` extension.\n * Uses `Symbol.for` so it is shared across realms / duplicate module loads.\n */\nconst REF_GUARD = Symbol.for('zodmon_ref')\n\n/**\n * Install the `.ref()` extension method on `ZodType.prototype`.\n *\n * Idempotent — safe to call multiple times.\n */\nexport function installRefExtension(): void {\n\tconst proto = z.ZodType.prototype\n\tif (REF_GUARD in proto) return\n\n\tObject.defineProperty(proto, 'ref', {\n\t\tvalue(this: typeof proto, collection: AnyCollection): typeof proto {\n\t\t\trefMetadata.set(this, { collection })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, REF_GUARD, {\n\t\tvalue: true,\n\t\tenumerable: false,\n\t\tconfigurable: false,\n\t\twritable: false,\n\t})\n}\n","import type { Collection, Document } from 'mongodb'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument } from '../collection/types'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { Prettify } from '../helpers/types'\nimport type { TypedFilter } from '../query/filter'\nimport { getRefMetadata } from '../schema/ref'\nimport { createAccumulatorBuilder, createExpressionBuilder } from './expressions'\nimport type {\n\tAccumulator,\n\tAccumulatorBuilder,\n\tCollectionName,\n\tExpression,\n\tExpressionBuilder,\n\tExtractRefCollection,\n\tGroupByCompoundResult,\n\tGroupByResult,\n\tInferAddedFields,\n\tNarrowFromFilter,\n\tRefFields,\n\tUnwindResult,\n} from './types'\n\n/**\n * Immutable aggregation pipeline builder for type-safe MongoDB aggregations.\n *\n * Each stage method returns a **new** `AggregatePipeline` instance — the\n * original is never mutated. This makes it safe to branch from a shared base\n * pipeline without cross-contamination.\n *\n * Use {@link aggregate} to create a pipeline from a {@link CollectionHandle},\n * or call `raw()` to append arbitrary stages.\n *\n * @typeParam TDef - The collection definition type, used to derive document types.\n * @typeParam TOutput - The current output document type (changes as stages transform the shape).\n *\n * @example\n * ```ts\n * const results = await aggregate(users)\n * .raw({ $match: { role: 'admin' } })\n * .raw({ $sort: { name: 1 } })\n * .toArray()\n * ```\n */\nexport class AggregatePipeline<TDef extends AnyCollection, TOutput> {\n\tprotected readonly definition: TDef\n\tprivate readonly nativeCollection: Collection<InferDocument<TDef>>\n\tprivate readonly stages: Document[]\n\n\tconstructor(\n\t\tdefinition: TDef,\n\t\tnativeCollection: Collection<InferDocument<TDef>>,\n\t\tstages: Document[],\n\t) {\n\t\tthis.definition = definition\n\t\tthis.nativeCollection = nativeCollection\n\t\tthis.stages = stages\n\t}\n\n\t/**\n\t * Append an arbitrary aggregation stage to the pipeline (escape hatch).\n\t *\n\t * Returns a new pipeline instance with the stage appended — the\n\t * original pipeline is not modified.\n\t *\n\t * Optionally accepts a type parameter `TNew` to change the output\n\t * type when the stage transforms the document shape.\n\t *\n\t * @typeParam TNew - The output type after this stage. Defaults to the current output type.\n\t * @param stage - A raw MongoDB aggregation stage document (e.g. `{ $match: { ... } }`).\n\t * @returns A new pipeline with the stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const admins = aggregate(users)\n\t * .raw({ $match: { role: 'admin' } })\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Change output type with a $project stage\n\t * const names = aggregate(users)\n\t * .raw<{ name: string }>({ $project: { name: 1, _id: 0 } })\n\t * .toArray()\n\t * ```\n\t */\n\traw<TNew = TOutput>(stage: Document): AggregatePipeline<TDef, TNew> {\n\t\treturn new AggregatePipeline<TDef, TNew>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\tstage,\n\t\t])\n\t}\n\n\t/**\n\t * Execute the pipeline and return all results as an array.\n\t *\n\t * @returns A promise resolving to the array of output documents.\n\t *\n\t * @example\n\t * ```ts\n\t * const results = await aggregate(users)\n\t * .raw({ $match: { age: { $gte: 18 } } })\n\t * .toArray()\n\t * ```\n\t */\n\tasync toArray(): Promise<TOutput[]> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(this.stages)\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB aggregate() returns AggregationCursor<Document>; casting to TOutput[] is safe because the pipeline stages determine the output shape\n\t\t\treturn (await cursor.toArray()) as any as TOutput[]\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t/**\n\t * Stream pipeline results one document at a time via `for await...of`.\n\t *\n\t * @returns An async generator yielding output documents.\n\t *\n\t * @example\n\t * ```ts\n\t * for await (const user of aggregate(users).raw({ $match: { role: 'admin' } })) {\n\t * console.log(user.name)\n\t * }\n\t * ```\n\t */\n\tasync *[Symbol.asyncIterator](): AsyncGenerator<TOutput> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(this.stages)\n\t\t\tfor await (const doc of cursor) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB aggregate() yields Document; casting to TOutput is safe because the pipeline stages determine the output shape\n\t\t\t\tyield doc as any as TOutput\n\t\t\t}\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t/**\n\t * Return the query execution plan without running the pipeline.\n\t *\n\t * Useful for debugging and understanding how MongoDB will process\n\t * the pipeline stages.\n\t *\n\t * @returns A promise resolving to the explain output document.\n\t *\n\t * @example\n\t * ```ts\n\t * const plan = await aggregate(users)\n\t * .raw({ $match: { role: 'admin' } })\n\t * .explain()\n\t * console.log(plan)\n\t * ```\n\t */\n\tasync explain(): Promise<Document> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(this.stages)\n\t\t\treturn await cursor.explain()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t// ── Shape-preserving stages ──────────────────────────────────────\n\n\t/**\n\t * Filter documents using a type-safe match expression.\n\t *\n\t * Appends a `$match` stage to the pipeline. The filter is constrained\n\t * to the current output type, so only valid fields and operators are accepted.\n\t *\n\t * Supports two forms of type narrowing:\n\t *\n\t * **Tier 1 — Explicit type parameter:**\n\t * ```ts\n\t * .match<{ role: 'engineer' | 'designer' }>({ role: { $in: ['engineer', 'designer'] } })\n\t * // role narrows to 'engineer' | 'designer'\n\t * ```\n\t *\n\t * **Tier 2 — Automatic inference from filter literals:**\n\t * ```ts\n\t * .match({ role: 'engineer' }) // role narrows to 'engineer'\n\t * .match({ role: { $ne: 'intern' } }) // role narrows to Exclude<Role, 'intern'>\n\t * .match({ role: { $in: ['engineer', 'designer'] as const } }) // needs as const\n\t * ```\n\t *\n\t * When no type parameter is provided and the filter doesn't contain\n\t * inferrable literals, the output type is unchanged (backward compatible).\n\t *\n\t * @typeParam TNarrow - Optional object mapping field names to narrowed types. Must be a subtype of the corresponding fields in TOutput.\n\t * @typeParam F - Inferred from the filter argument. Do not provide explicitly.\n\t * @param filter - A type-safe filter for the current output type.\n\t * @returns A new pipeline with the `$match` stage appended and output type narrowed.\n\t *\n\t * @example\n\t * ```ts\n\t * // Explicit narrowing\n\t * const filtered = await users.aggregate()\n\t * .match<{ role: 'engineer' }>({ role: 'engineer' })\n\t * .toArray()\n\t * // filtered[0].role → 'engineer'\n\t *\n\t * // Automatic narrowing with $in (requires as const)\n\t * const subset = await users.aggregate()\n\t * .match({ role: { $in: ['engineer', 'designer'] as const } })\n\t * .toArray()\n\t * // subset[0].role → 'engineer' | 'designer'\n\t * ```\n\t */\n\tmatch<\n\t\tTNarrow extends {\n\t\t\t[K in keyof TNarrow]: K extends keyof TOutput ? TOutput[K] : never\n\t\t\t// biome-ignore lint/complexity/noBannedTypes: {} is the correct default for TNarrow — it means \"no explicit narrowing\", which produces Omit<NarrowFromFilter<TOutput, F>, never> & {} ≡ NarrowFromFilter<TOutput, F>\n\t\t} = {},\n\t\tF extends TypedFilter<TOutput> = TypedFilter<TOutput>,\n\t>(\n\t\tfilter: F,\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Omit<NarrowFromFilter<TOutput, F>, keyof TNarrow> & TNarrow>\n\t> {\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $match: filter },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The narrowed output type is computed from generic params TNarrow and F — TypeScript cannot prove the structural equivalence after $match. Safe because $match only filters documents; it does not change field shapes.\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sort documents by one or more fields.\n\t *\n\t * Appends a `$sort` stage. Keys are constrained to `keyof TOutput & string`\n\t * and values must be `1` (ascending) or `-1` (descending).\n\t *\n\t * @param spec - A sort specification mapping field names to sort direction.\n\t * @returns A new pipeline with the `$sort` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const sorted = await aggregate(users)\n\t * .sort({ age: -1, name: 1 })\n\t * .toArray()\n\t * ```\n\t */\n\tsort(spec: Partial<Record<keyof TOutput & string, 1 | -1>>): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $sort: spec },\n\t\t])\n\t}\n\n\t/**\n\t * Skip a number of documents in the pipeline.\n\t *\n\t * Appends a `$skip` stage. Commonly used with {@link limit} for pagination.\n\t *\n\t * @param n - The number of documents to skip.\n\t * @returns A new pipeline with the `$skip` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Page 2 (10 items per page)\n\t * const page2 = await aggregate(users)\n\t * .sort({ name: 1 })\n\t * .skip(10)\n\t * .limit(10)\n\t * .toArray()\n\t * ```\n\t */\n\tskip(n: number): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $skip: n },\n\t\t])\n\t}\n\n\t/**\n\t * Limit the number of documents passing through the pipeline.\n\t *\n\t * Appends a `$limit` stage. Commonly used with {@link skip} for pagination,\n\t * or after {@link sort} to get top/bottom N results.\n\t *\n\t * @param n - The maximum number of documents to pass through.\n\t * @returns A new pipeline with the `$limit` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const top5 = await aggregate(users)\n\t * .sort({ score: -1 })\n\t * .limit(5)\n\t * .toArray()\n\t * ```\n\t */\n\tlimit(n: number): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $limit: n },\n\t\t])\n\t}\n\n\t// ── Shape-transforming projection stages ─────────────────────────\n\n\t/**\n\t * Include only specified fields in the output.\n\t *\n\t * Appends a `$project` stage with inclusion (`1`) for each key.\n\t * The `_id` field is always included. The output type narrows to\n\t * `Pick<TOutput, K | '_id'>`.\n\t *\n\t * @param spec - An object mapping field names to `1` for inclusion.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const namesOnly = await aggregate(users)\n\t * .project({ name: 1 })\n\t * .toArray()\n\t * // [{ _id: ..., name: 'Ada' }, ...]\n\t * ```\n\t */\n\tproject<K extends keyof TOutput & string>(\n\t\tspec: Record<K, 1>,\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>\n\t> {\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $project: spec },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Pick<TOutput, K | '_id'> is assignable to the generic parameter after $project reshapes the output — safe because the MongoDB $project stage produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Variadic shorthand for {@link project} — pick fields to include.\n\t *\n\t * Generates a `$project` stage that includes only the listed fields\n\t * (plus `_id`). Equivalent to `.project({ field1: 1, field2: 1 })`.\n\t *\n\t * @param fields - Field names to include in the output.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const namesAndRoles = await aggregate(users)\n\t * .pick('name', 'role')\n\t * .toArray()\n\t * ```\n\t */\n\tpick<K extends keyof TOutput & string>(\n\t\t...fields: K[]\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>\n\t> {\n\t\tconst spec = Object.fromEntries(fields.map((f) => [f, 1]))\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $project: spec },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Pick<TOutput, K | '_id'> is assignable to the generic parameter after $project reshapes the output — safe because the MongoDB $project stage produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Exclude specified fields from the output.\n\t *\n\t * Appends a `$project` stage with exclusion (`0`) for each key.\n\t * All other fields pass through. The output type becomes `Omit<TOutput, K>`.\n\t *\n\t * @param fields - Field names to exclude from the output.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const noAge = await aggregate(users)\n\t * .omit('age')\n\t * .toArray()\n\t * ```\n\t */\n\tomit<K extends keyof TOutput & string>(\n\t\t...fields: K[]\n\t): AggregatePipeline<TDef, Prettify<Omit<TOutput, K>>> {\n\t\tconst spec = Object.fromEntries(fields.map((f) => [f, 0]))\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $project: spec },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Omit<TOutput, K> is assignable after $project exclusion reshapes the output — safe because MongoDB $project exclusion produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t// ── groupBy stage ────────────────────────────────────────────────\n\n\t/**\n\t * Group documents by one or more fields with accumulator expressions.\n\t *\n\t * Accepts accumulators as either a **callback** (recommended) or a plain object.\n\t *\n\t * The callback receives a typed `AccumulatorBuilder` with full autocomplete\n\t * and compile-time field validation. Builder methods resolve return types\n\t * to the actual field type (`T[K]`), not `unknown`.\n\t *\n\t * @param field - A field name or array of field names to group by.\n\t * @param accumulators - A callback `(acc) => ({ ... })` or plain accumulator object.\n\t * @returns A new pipeline with the `$group` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Callback style (recommended — full type safety)\n\t * const byRole = await aggregate(users)\n\t * .groupBy('role', acc => ({\n\t * count: acc.count(),\n\t * minSalary: acc.min('salary'), // → number\n\t * firstName: acc.first('name'), // → string\n\t * }))\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Object style (backward compatible)\n\t * const byRole = await aggregate(users)\n\t * .groupBy('role', { count: $count() })\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Compound groupBy\n\t * const byRoleAndDept = await aggregate(users)\n\t * .groupBy(['role', 'dept'], acc => ({ count: acc.count() }))\n\t * .toArray()\n\t * ```\n\t */\n\tgroupBy<K extends keyof TOutput & string, TAccum extends Record<string, Accumulator>>(\n\t\tfield: K,\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t): AggregatePipeline<TDef, GroupByResult<TOutput, K, TAccum>>\n\tgroupBy<K extends keyof TOutput & string, TAccum extends Record<string, Accumulator>>(\n\t\tfield: K[],\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t): AggregatePipeline<TDef, GroupByCompoundResult<TOutput, K, TAccum>>\n\tgroupBy<K extends keyof TOutput & string, TAccum extends Record<string, Accumulator>>(\n\t\tfield: K | K[],\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t):\n\t\t| AggregatePipeline<TDef, GroupByResult<TOutput, K, TAccum>>\n\t\t| AggregatePipeline<TDef, GroupByCompoundResult<TOutput, K, TAccum>> {\n\t\tconst resolved =\n\t\t\ttypeof accumulators === 'function'\n\t\t\t\t? accumulators(createAccumulatorBuilder<TOutput>())\n\t\t\t\t: accumulators\n\n\t\tconst _id = Array.isArray(field)\n\t\t\t? Object.fromEntries(field.map((f) => [f, `$${f}`]))\n\t\t\t: `$${field}`\n\n\t\tconst accumExprs = Object.fromEntries(\n\t\t\tObject.entries(resolved).map(([key, acc]) => [key, acc.expr]),\n\t\t)\n\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $group: { _id, ...accumExprs } },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The output type depends on whether `field` is a string or array — TypeScript cannot narrow the overloaded return type from the union, so we cast. Safe because $group produces exactly GroupByResult or GroupByCompoundResult.\n\t\treturn pipeline as any\n\t}\n\n\t// ── addFields stage ──────────────────────────────────────────────\n\n\t/**\n\t * Add new fields or overwrite existing ones in the output documents.\n\t *\n\t * **Callback style (recommended)** — the `ExpressionBuilder` provides\n\t * autocomplete for field names and infers return types automatically:\n\t *\n\t * ```ts\n\t * employees.aggregate()\n\t * .addFields(expr => ({\n\t * hireYear: expr.year('hiredAt'), // Expression<number>\n\t * isHighPay: expr.gte('salary', 100_000), // Expression<boolean>\n\t * }))\n\t * ```\n\t *\n\t * **Raw style** — pass MongoDB expression objects directly. Use an\n\t * explicit type parameter to preserve type safety:\n\t *\n\t * ```ts\n\t * // Tier 2: explicit type parameter\n\t * .addFields<{ hireYear: number }>({ hireYear: { $year: '$hiredAt' } })\n\t *\n\t * // Tier 3: no type parameter — fields resolve to unknown\n\t * .addFields({ hireYear: { $year: '$hiredAt' } })\n\t * ```\n\t *\n\t * @param fields - A callback `(expr) => ({ ... })` or plain fields object.\n\t * @returns A new pipeline with the `$addFields` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const enriched = await aggregate(employees)\n\t * .addFields(expr => ({\n\t * hireYear: expr.year('hiredAt'),\n\t * monthlySalary: expr.divide('salary', 12),\n\t * }))\n\t * .toArray()\n\t * ```\n\t */\n\t// Overload 1: Callback with ExpressionBuilder\n\taddFields<TFields extends Record<string, Expression>>(\n\t\tfields: (expr: ExpressionBuilder<TOutput>) => TFields,\n\t): AggregatePipeline<TDef, Prettify<TOutput & InferAddedFields<TFields>>>\n\t// Overload 2: Raw object (with optional explicit type parameter)\n\taddFields<TFields extends Record<string, unknown> = Record<string, unknown>>(\n\t\tfields: TFields,\n\t): AggregatePipeline<TDef, Prettify<TOutput & TFields>>\n\t// Implementation\n\taddFields(\n\t\tfields:\n\t\t\t| ((expr: ExpressionBuilder<TOutput>) => Record<string, unknown>)\n\t\t\t| Record<string, unknown>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Implementation must be wide enough for both overloads\n\t): AggregatePipeline<TDef, any> {\n\t\tconst resolved =\n\t\t\ttypeof fields === 'function' ? fields(createExpressionBuilder<TOutput>()) : fields\n\n\t\t// Unwrap Expression wrappers — extract .value for the MongoDB stage\n\t\tconst stage = Object.fromEntries(\n\t\t\tObject.entries(resolved).map(([k, v]) => [\n\t\t\t\tk,\n\t\t\t\tv && typeof v === 'object' && '__expr' in v ? (v as Expression).value : v,\n\t\t\t]),\n\t\t)\n\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $addFields: stage },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that TOutput & InferAddedFields<TFields> is assignable after $addFields merges — safe because $addFields preserves existing fields and adds new ones\n\t\treturn pipeline as any\n\t}\n\n\t// ── unwind stage ─────────────────────────────────────────────────\n\n\t/**\n\t * Deconstruct an array field, outputting one document per array element.\n\t *\n\t * Appends an `$unwind` stage. The unwound field's type changes from\n\t * `T[]` to `T` in the output type. Documents with empty or missing\n\t * arrays are dropped unless `preserveEmpty` is `true`.\n\t *\n\t * @param field - The name of the array field to unwind.\n\t * @param options - Optional settings for the unwind stage.\n\t * @param options.preserveEmpty - If `true`, documents with null, missing, or empty arrays are preserved.\n\t * @returns A new pipeline with the `$unwind` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const flat = await aggregate(orders)\n\t * .unwind('items')\n\t * .toArray()\n\t * // Each result has a single `items` value instead of an array\n\t * ```\n\t */\n\tunwind<K extends keyof TOutput & string>(\n\t\tfield: K,\n\t\toptions?: { preserveEmpty?: boolean },\n\t): AggregatePipeline<TDef, UnwindResult<TOutput, K>> {\n\t\tconst stage: Document = options?.preserveEmpty\n\t\t\t? { $unwind: { path: `$${field}`, preserveNullAndEmptyArrays: true } }\n\t\t\t: { $unwind: `$${field}` }\n\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\tstage,\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that UnwindResult<TOutput, K> is assignable after $unwind transforms the array field to its element type — safe because $unwind produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t// ── lookup stage ────────────────────────────────────────────────\n\n\t/**\n\t * Join documents from another collection via a `$lookup` stage.\n\t *\n\t * **Forward lookup** — when the field has `.ref()` metadata pointing to\n\t * another collection, resolves the target collection and output type\n\t * automatically:\n\t *\n\t * ```ts\n\t * books.aggregate().lookup('authorId').toArray()\n\t * // Each book gains an `authors: Author[]` array\n\t * ```\n\t *\n\t * **Reverse lookup** — when the foreign key lives on the *other*\n\t * collection, pass the collection definition and the `on` field:\n\t *\n\t * ```ts\n\t * users.aggregate().lookup(Books, { on: 'authorId' }).toArray()\n\t * // Each user gains a `books: Book[]` array\n\t * ```\n\t *\n\t * Pass `unwind: true` to flatten the joined array into a single object\n\t * (adds a `$unwind` stage with `preserveNullAndEmptyArrays: true`).\n\t *\n\t * @param fieldOrCollection - A ref-bearing field name (forward) or collection definition (reverse).\n\t * @param options - `as` alias, `unwind` flag, and `on` (reverse only).\n\t * @returns A new pipeline with `$lookup` (and optionally `$unwind`) appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Forward lookup with custom alias and unwind\n\t * const results = await aggregate(books)\n\t * .lookup('authorId', { as: 'author', unwind: true })\n\t * .toArray()\n\t * // Each book has a single `author: Author` object\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Reverse lookup: each author gains their books\n\t * const results = await aggregate(authors)\n\t * .lookup(Books, { on: 'authorId' })\n\t * .toArray()\n\t * // Each author has a `books: Book[]` array\n\t * ```\n\t */\n\tlookup<\n\t\tK extends RefFields<TDef>,\n\t\tTAs extends string = CollectionName<ExtractRefCollection<TDef, K>>,\n\t>(\n\t\tfield: K,\n\t\toptions: { as?: TAs; unwind: true },\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<TOutput & { [P in TAs]: InferDocument<ExtractRefCollection<TDef, K>> }>\n\t>\n\tlookup<\n\t\tK extends RefFields<TDef>,\n\t\tTAs extends string = CollectionName<ExtractRefCollection<TDef, K>>,\n\t>(\n\t\tfield: K,\n\t\toptions?: { as?: TAs; unwind?: false },\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<TOutput & { [P in TAs]: InferDocument<ExtractRefCollection<TDef, K>>[] }>\n\t>\n\tlookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(\n\t\tfrom: TForeignDef,\n\t\toptions: { on: keyof InferDocument<TForeignDef> & string; as?: TAs; unwind: true },\n\t): AggregatePipeline<TDef, Prettify<TOutput & { [P in TAs]: InferDocument<TForeignDef> }>>\n\tlookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(\n\t\tfrom: TForeignDef,\n\t\toptions: { on: keyof InferDocument<TForeignDef> & string; as?: TAs; unwind?: false },\n\t): AggregatePipeline<TDef, Prettify<TOutput & { [P in TAs]: InferDocument<TForeignDef>[] }>>\n\tlookup(\n\t\tfieldOrFrom: string | AnyCollection,\n\t\toptions?: { on?: string; as?: string; unwind?: boolean },\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Implementation signature must be wide enough to cover all four overloads — TypeScript cannot unify the generic return types across overloads, so `any` is the standard escape hatch for overloaded method implementations.\n\t): AggregatePipeline<TDef, any> {\n\t\tconst stages = [...this.stages]\n\n\t\tif (typeof fieldOrFrom === 'object') {\n\t\t\t// Reverse lookup: fieldOrFrom is a collection definition\n\t\t\tconst foreignName = fieldOrFrom.name\n\t\t\tconst foreignField = options?.on\n\t\t\tif (!foreignField) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[zodmon] lookup: reverse lookup on '${foreignName}' requires an 'on' option ` +\n\t\t\t\t\t\t'specifying which field on the foreign collection references this collection.',\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst asField = options?.as ?? foreignName\n\t\t\tstages.push({\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: foreignName,\n\t\t\t\t\tlocalField: '_id',\n\t\t\t\t\tforeignField,\n\t\t\t\t\tas: asField,\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (options?.unwind) {\n\t\t\t\tstages.push({ $unwind: { path: `$${asField}`, preserveNullAndEmptyArrays: true } })\n\t\t\t}\n\t\t} else {\n\t\t\t// Forward lookup: field has .ref() metadata\n\t\t\tconst shape = this.definition.shape\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: shape values are z.core.$ZodType but getRefMetadata accepts unknown — the cast is a no-op at runtime\n\t\t\tconst fieldSchema = (shape as any)[fieldOrFrom]\n\t\t\tconst ref = getRefMetadata(fieldSchema)\n\t\t\tif (!ref) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[zodmon] lookup: field '${fieldOrFrom}' has no .ref() metadata. ` +\n\t\t\t\t\t\t'Use .lookup(CollectionDef, { on: foreignKey }) for reverse lookups, ' +\n\t\t\t\t\t\t'or add .ref(TargetCollection) to the field schema.',\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst targetName = ref.collection.name\n\t\t\tconst asField = options?.as ?? targetName\n\t\t\tstages.push({\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: targetName,\n\t\t\t\t\tlocalField: fieldOrFrom,\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: asField,\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (options?.unwind) {\n\t\t\t\tstages.push({ $unwind: { path: `$${asField}`, preserveNullAndEmptyArrays: true } })\n\t\t\t}\n\t\t}\n\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, stages)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The lookup output type is TOutput intersected with a dynamic record — TypeScript cannot prove the structural equivalence after $lookup reshapes the document. Safe because $lookup preserves all existing fields and adds the joined field.\n\t\treturn pipeline as any\n\t}\n\n\t// ── Convenience shortcuts ────────────────────────────────────────\n\n\t/**\n\t * Count documents per group, sorted by count descending.\n\t *\n\t * Shorthand for `.groupBy(field, { count: $count() }).sort({ count: -1 })`.\n\t *\n\t * @param field - The field to group and count by.\n\t * @returns A new pipeline producing `{ _id: TOutput[K], count: number }` results.\n\t *\n\t * @example\n\t * ```ts\n\t * const roleCounts = await aggregate(users)\n\t * .countBy('role')\n\t * .toArray()\n\t * // [{ _id: 'user', count: 3 }, { _id: 'admin', count: 2 }]\n\t * ```\n\t */\n\tcountBy<K extends keyof TOutput & string>(\n\t\tfield: K,\n\t): AggregatePipeline<TDef, Prettify<{ _id: TOutput[K]; count: number }>> {\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $group: { _id: `$${field}`, count: { $sum: 1 } } },\n\t\t\t{ $sort: { count: -1 } },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The shortcut composes $group + $sort stages; TypeScript cannot infer the combined output type — safe because the stages produce exactly { _id, count } sorted by count descending\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sum a numeric field per group, sorted by total descending.\n\t *\n\t * Shorthand for `.groupBy(field, { total: $sum('$sumField') }).sort({ total: -1 })`.\n\t *\n\t * @param field - The field to group by.\n\t * @param sumField - The numeric field to sum.\n\t * @returns A new pipeline producing `{ _id: TOutput[K], total: number }` results.\n\t *\n\t * @example\n\t * ```ts\n\t * const revenueByCategory = await aggregate(orders)\n\t * .sumBy('category', 'amount')\n\t * .toArray()\n\t * // [{ _id: 'electronics', total: 5000 }, ...]\n\t * ```\n\t */\n\tsumBy<K extends keyof TOutput & string, S extends keyof TOutput & string>(\n\t\tfield: K,\n\t\tsumField: S,\n\t): AggregatePipeline<TDef, Prettify<{ _id: TOutput[K]; total: number }>> {\n\t\tconst pipeline = new AggregatePipeline(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $group: { _id: `$${field}`, total: { $sum: `$${sumField}` } } },\n\t\t\t{ $sort: { total: -1 } },\n\t\t])\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The shortcut composes $group + $sort stages; TypeScript cannot infer the combined output type — safe because the stages produce exactly { _id, total } sorted by total descending\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sort by a single field with a friendly direction name.\n\t *\n\t * Shorthand for `.sort({ [field]: direction === 'desc' ? -1 : 1 })`.\n\t *\n\t * @param field - The field to sort by.\n\t * @param direction - Sort direction: `'asc'` (default) or `'desc'`.\n\t * @returns A new pipeline with the `$sort` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const youngest = await aggregate(users)\n\t * .sortBy('age')\n\t * .toArray()\n\t * ```\n\t */\n\tsortBy(\n\t\tfield: keyof TOutput & string,\n\t\tdirection: 'asc' | 'desc' = 'asc',\n\t): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $sort: { [field]: direction === 'desc' ? -1 : 1 } },\n\t\t])\n\t}\n\n\t/**\n\t * Return the top N documents sorted by a field descending.\n\t *\n\t * Shorthand for `.sort({ [by]: -1 }).limit(n)`.\n\t *\n\t * @param n - The number of documents to return.\n\t * @param options - An object with a `by` field specifying the sort key.\n\t * @returns A new pipeline with `$sort` and `$limit` stages appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const top3 = await aggregate(users)\n\t * .top(3, { by: 'score' })\n\t * .toArray()\n\t * ```\n\t */\n\ttop(n: number, options: { by: keyof TOutput & string }): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $sort: { [options.by]: -1 } },\n\t\t\t{ $limit: n },\n\t\t])\n\t}\n\n\t/**\n\t * Return the bottom N documents sorted by a field ascending.\n\t *\n\t * Shorthand for `.sort({ [by]: 1 }).limit(n)`.\n\t *\n\t * @param n - The number of documents to return.\n\t * @param options - An object with a `by` field specifying the sort key.\n\t * @returns A new pipeline with `$sort` and `$limit` stages appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const bottom3 = await aggregate(users)\n\t * .bottom(3, { by: 'score' })\n\t * .toArray()\n\t * ```\n\t */\n\tbottom(n: number, options: { by: keyof TOutput & string }): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(this.definition, this.nativeCollection, [\n\t\t\t...this.stages,\n\t\t\t{ $sort: { [options.by]: 1 } },\n\t\t\t{ $limit: n },\n\t\t])\n\t}\n}\n\n/**\n * Create a new aggregation pipeline for a collection.\n *\n * Returns an empty pipeline that can be extended with stage methods\n * like `raw()`, or future typed stages (`match`, `project`, etc.).\n *\n * @param handle - A typed collection handle obtained from `db.use()`.\n * @returns A new empty `AggregatePipeline` whose output type is the collection's document type.\n *\n * @example\n * ```ts\n * const users = db.use(Users)\n * const admins = await aggregate(users)\n * .raw({ $match: { role: 'admin' } })\n * .toArray()\n * ```\n */\nexport function aggregate<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n): AggregatePipeline<TDef, InferDocument<TDef>> {\n\treturn new AggregatePipeline<TDef, InferDocument<TDef>>(handle.definition, handle.native, [])\n}\n","import type { Db, MongoClientOptions } from 'mongodb'\nimport { MongoClient } from 'mongodb'\nimport type { z } from 'zod'\nimport type {\n\tCollectionDefinition,\n\tCompoundIndexDefinition,\n\tInferDocument,\n} from '../collection/types'\nimport { syncIndexes as _syncCollectionIndexes } from '../indexes/sync'\nimport type { SyncIndexesOptions, SyncIndexesResult } from '../indexes/types'\nimport { CollectionHandle } from './handle'\n\n/**\n * Wraps a MongoDB `MongoClient` and `Db`, providing typed collection access\n * through {@link CollectionHandle}s.\n *\n * Connection is lazy — the driver connects on the first operation, not at\n * construction time. Call {@link close} for graceful shutdown.\n *\n * @example\n * ```ts\n * const db = createClient('mongodb://localhost:27017', 'myapp')\n * const users = db.use(UsersCollection)\n * await users.native.insertOne({ _id: oid(), name: 'Ada' })\n * await db.close()\n * ```\n */\nexport class Database {\n\tprivate readonly _client: MongoClient\n\tprivate readonly _db: Db\n\t/** Registered collection definitions, keyed by name. Used by syncIndexes(). */\n\tprivate readonly _collections = new Map<string, CollectionDefinition>()\n\n\tconstructor(uri: string, dbName: string, options?: MongoClientOptions) {\n\t\tthis._client = new MongoClient(uri, options)\n\t\tthis._db = this._client.db(dbName)\n\t}\n\n\t/**\n\t * Register a collection definition and return a typed {@link CollectionHandle}.\n\t *\n\t * The handle's `native` property is a MongoDB `Collection<TDoc>` where `TDoc`\n\t * is the document type inferred from the definition's Zod schema. Calling\n\t * `use()` multiple times with the same definition is safe — each call returns\n\t * a new lightweight handle backed by the same underlying driver collection.\n\t *\n\t * @param def - A collection definition created by `collection()`.\n\t * @returns A typed collection handle for CRUD operations.\n\t */\n\tuse<\n\t\tTName extends string,\n\t\tTShape extends z.core.$ZodShape,\n\t\tTIndexes extends readonly CompoundIndexDefinition<\n\t\t\tExtract<keyof TShape, string>\n\t\t>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[],\n\t>(\n\t\tdef: CollectionDefinition<TName, TShape, TIndexes>,\n\t): CollectionHandle<CollectionDefinition<TName, TShape, TIndexes>> {\n\t\t// Safe cast: erasing generics for internal collection tracking.\n\t\t// Stored definitions are only iterated in syncIndexes() where\n\t\t// index metadata is accessed structurally.\n\t\tthis._collections.set(def.name, def as unknown as CollectionDefinition)\n\t\tconst native = this._db.collection<\n\t\t\tInferDocument<CollectionDefinition<TName, TShape, TIndexes>>\n\t\t>(def.name)\n\t\t// Safe cast: CollectionDefinition<TName, TShape, TIndexes> → AnyCollection for the\n\t\t// constructor. The generic is preserved through the return type annotation.\n\t\treturn new CollectionHandle(\n\t\t\tdef as unknown as CollectionDefinition<TName, TShape, TIndexes>,\n\t\t\tnative,\n\t\t) as CollectionHandle<CollectionDefinition<TName, TShape, TIndexes>>\n\t}\n\n\t/**\n\t * Synchronize indexes for all registered collections with MongoDB.\n\t *\n\t * Iterates every collection registered via {@link use} and calls\n\t * {@link syncIndexes} on each one. Returns a record keyed by collection\n\t * name with the sync result for each.\n\t *\n\t * @param options - Optional sync behavior (dryRun, dropOrphaned).\n\t * @returns A record mapping collection names to their sync results.\n\t *\n\t * @example\n\t * ```ts\n\t * const db = createClient('mongodb://localhost:27017', 'myapp')\n\t * db.use(Users)\n\t * db.use(Posts)\n\t * const results = await db.syncIndexes()\n\t * console.log(results['users'].created) // ['email_1']\n\t * console.log(results['posts'].created) // ['title_1']\n\t * ```\n\t */\n\tasync syncIndexes(options?: SyncIndexesOptions): Promise<Record<string, SyncIndexesResult>> {\n\t\tconst results: Record<string, SyncIndexesResult> = {}\n\t\tfor (const [name, def] of this._collections) {\n\t\t\tconst native = this._db.collection(name)\n\t\t\tconst handle = new CollectionHandle(def, native)\n\t\t\tresults[name] = await _syncCollectionIndexes(handle, options)\n\t\t}\n\t\treturn results\n\t}\n\n\t/**\n\t * Execute a function within a MongoDB transaction with auto-commit/rollback.\n\t *\n\t * Stub — full implementation in TASK-106.\n\t */\n\ttransaction<T>(_fn: () => Promise<T>): Promise<T> {\n\t\tthrow new Error('Not implemented')\n\t}\n\n\t/**\n\t * Close the underlying `MongoClient` connection. Safe to call even if\n\t * no connection was established (the driver handles this gracefully).\n\t */\n\tasync close(): Promise<void> {\n\t\tawait this._client.close()\n\t}\n}\n\n/**\n * Extract the database name from a MongoDB connection URI.\n *\n * Handles standard URIs, multi-host/replica set, SRV (`mongodb+srv://`),\n * auth credentials, query parameters, and percent-encoded database names.\n * Returns `undefined` when no database name is present.\n */\nexport function extractDbName(uri: string): string | undefined {\n\tconst withoutProtocol = uri.replace(/^mongodb(?:\\+srv)?:\\/\\//, '')\n\t// Safe cast: split() always returns at least one element, but noUncheckedIndexedAccess\n\t// types [0] as string | undefined.\n\tconst withoutQuery = withoutProtocol.split('?')[0] as string\n\t// Skip past auth credentials (user:pass@) before searching for the path separator\n\tconst atIndex = withoutQuery.lastIndexOf('@')\n\tconst hostAndPath = atIndex === -1 ? withoutQuery : withoutQuery.slice(atIndex + 1)\n\tconst slashIndex = hostAndPath.indexOf('/')\n\tif (slashIndex === -1) return undefined\n\tconst dbName = decodeURIComponent(hostAndPath.slice(slashIndex + 1))\n\treturn dbName || undefined\n}\n\n/**\n * Create a new {@link Database} instance wrapping a MongoDB connection.\n *\n * The connection is lazy — the driver connects on the first operation.\n * Pass any `MongoClientOptions` to configure connection pooling, timeouts, etc.\n *\n * When `dbName` is omitted, the database name is extracted from the URI path\n * (e.g. `mongodb://localhost:27017/myapp` → `'myapp'`). If no database name\n * is found in either the arguments or the URI, a warning is logged and\n * MongoDB's default `'test'` database is used.\n *\n * @param uri - MongoDB connection string (e.g. `mongodb://localhost:27017`).\n * @param dbName - The database name to use.\n * @param options - Optional MongoDB driver client options.\n * @returns A new `Database` instance.\n */\nexport function createClient(uri: string, dbName: string, options?: MongoClientOptions): Database\nexport function createClient(uri: string, options?: MongoClientOptions): Database\nexport function createClient(\n\turi: string,\n\tdbNameOrOptions?: string | MongoClientOptions,\n\tmaybeOptions?: MongoClientOptions,\n): Database {\n\tif (typeof dbNameOrOptions === 'string') {\n\t\treturn new Database(uri, dbNameOrOptions, maybeOptions)\n\t}\n\tconst parsed = extractDbName(uri)\n\tif (!parsed) {\n\t\tconsole.warn('[zodmon] No database name provided — using MongoDB default \"test\"')\n\t}\n\treturn new Database(uri, parsed ?? 'test', dbNameOrOptions)\n}\n","import type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\n\n/**\n * A normalized index specification ready for comparison and creation.\n *\n * `key` maps field paths to direction (`1`, `-1`, or `'text'`).\n * `options` holds MongoDB index options (`unique`, `sparse`, etc.).\n *\n * @example\n * ```ts\n * const spec: IndexSpec = {\n * key: { email: 1 },\n * options: { unique: true },\n * }\n * ```\n */\nexport type IndexSpec = {\n\tkey: Record<string, 1 | -1 | 'text'>\n\toptions: Record<string, unknown>\n}\n\n/**\n * Convert a field-level index definition to a normalized {@link IndexSpec}.\n *\n * Maps schema metadata (`text`, `descending`, `unique`, `sparse`, `expireAfter`,\n * `partial`) to their MongoDB driver equivalents.\n *\n * @param def - A field index definition extracted from schema metadata.\n * @returns A normalized index spec with key and options.\n *\n * @example\n * ```ts\n * const spec = toFieldIndexSpec({ field: 'email', indexed: true, unique: true })\n * // => { key: { email: 1 }, options: { unique: true } }\n *\n * const ttl = toFieldIndexSpec({ field: 'expiresAt', indexed: true, expireAfter: 3600 })\n * // => { key: { expiresAt: 1 }, options: { expireAfterSeconds: 3600 } }\n * ```\n */\nexport function toFieldIndexSpec(def: FieldIndexDefinition): IndexSpec {\n\tconst direction: 1 | -1 | 'text' = def.text ? 'text' : def.descending ? -1 : 1\n\tconst key: Record<string, 1 | -1 | 'text'> = { [def.field]: direction }\n\n\tconst options: Record<string, unknown> = {}\n\tif (def.unique) options['unique'] = true\n\tif (def.sparse) options['sparse'] = true\n\tif (def.expireAfter !== undefined) options['expireAfterSeconds'] = def.expireAfter\n\tif (def.partial) options['partialFilterExpression'] = def.partial\n\n\treturn { key, options }\n}\n\n/**\n * Convert a compound index definition to a normalized {@link IndexSpec}.\n *\n * Copies the `fields` map directly to `key` and maps builder options\n * (`unique`, `sparse`, `name`, `partial`) to MongoDB driver equivalents.\n *\n * @param def - A compound index definition from the collection options.\n * @returns A normalized index spec with key and options.\n *\n * @example\n * ```ts\n * const spec = toCompoundIndexSpec({\n * fields: { email: 1, role: -1 },\n * options: { unique: true, name: 'email_role_idx' },\n * })\n * // => { key: { email: 1, role: -1 }, options: { unique: true, name: 'email_role_idx' } }\n * ```\n */\nexport function toCompoundIndexSpec(def: CompoundIndexDefinition): IndexSpec {\n\t// Compound fields are Partial<Record<K, 1|-1>> structurally, but all keys\n\t// are present at runtime. Cast to the concrete key type for IndexSpec.\n\tconst key = { ...def.fields } as Record<string, 1 | -1 | 'text'>\n\n\tconst options: Record<string, unknown> = {}\n\tif (def.options?.unique) options['unique'] = true\n\tif (def.options?.sparse) options['sparse'] = true\n\tif (def.options?.name) options['name'] = def.options.name\n\tif (def.options?.partial) options['partialFilterExpression'] = def.options.partial\n\n\treturn { key, options }\n}\n\n/**\n * Produce a stable, deterministic string from an index key for comparison.\n *\n * Entries are sorted alphabetically by field name and formatted as\n * `field:direction` pairs joined by commas. Two index keys that should be\n * considered the same will always produce the same string.\n *\n * @param key - An index key mapping field names to direction.\n * @returns A string like `'email:1,role:-1'`.\n *\n * @example\n * ```ts\n * serializeIndexKey({ email: 1, role: -1 })\n * // => 'email:1,role:-1'\n *\n * serializeIndexKey({ name: 'text' })\n * // => 'name:text'\n * ```\n */\nexport function serializeIndexKey(key: Record<string, 1 | -1 | 'text'>): string {\n\t// Field order is preserved intentionally — in MongoDB, { a: 1, b: 1 } and\n\t// { b: 1, a: 1 } are distinct compound indexes (order determines prefix matching).\n\treturn Object.entries(key)\n\t\t.map(([field, dir]) => `${field}:${dir}`)\n\t\t.join(',')\n}\n","import type { Collection } from 'mongodb'\nimport type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { IndexSpec } from './spec'\nimport { serializeIndexKey, toCompoundIndexSpec, toFieldIndexSpec } from './spec'\nimport type { StaleIndex, SyncIndexesOptions, SyncIndexesResult } from './types'\n\n/**\n * Structural constraint for the handle argument of {@link syncIndexes}.\n *\n * Uses a structural type rather than `CollectionHandle<AnyCollection>` to avoid\n * TypeScript variance issues with `exactOptionalPropertyTypes`. Any collection\n * handle returned by `db.use()` satisfies this constraint.\n */\ntype SyncableHandle = {\n\treadonly definition: {\n\t\treadonly fieldIndexes: FieldIndexDefinition[]\n\t\treadonly compoundIndexes: readonly CompoundIndexDefinition[]\n\t}\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\treadonly native: Collection<any>\n}\n\n/**\n * Relevant option keys extracted from MongoDB index info for comparison.\n *\n * When checking whether an existing index matches a desired spec, only these\n * keys are compared — other MongoDB-internal properties (v, ns, etc.) are\n * ignored.\n */\nconst COMPARABLE_OPTION_KEYS = [\n\t'unique',\n\t'sparse',\n\t'expireAfterSeconds',\n\t'partialFilterExpression',\n] as const\n\n/**\n * Extract the comparable options from a MongoDB index info object.\n *\n * Pulls only the keys listed in {@link COMPARABLE_OPTION_KEYS} from the raw\n * index info returned by `listIndexes()`. Keys whose value is `undefined`\n * are omitted so that JSON comparison works correctly.\n *\n * @param info - A raw MongoDB index info object.\n * @returns A plain object with only the relevant option keys.\n *\n * @example\n * ```ts\n * const opts = extractComparableOptions({ v: 2, unique: true, key: { email: 1 } })\n * // => { unique: true }\n * ```\n */\nexport function extractComparableOptions(info: Record<string, unknown>): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {}\n\tfor (const key of COMPARABLE_OPTION_KEYS) {\n\t\tif (info[key] !== undefined) {\n\t\t\tresult[key] = info[key]\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Generate the default MongoDB index name from a key spec.\n *\n * MongoDB names indexes by joining `field_direction` pairs with underscores.\n * For example, `{ email: 1, role: -1 }` becomes `'email_1_role_-1'`.\n *\n * @param key - An index key mapping field names to direction.\n * @returns The generated index name string.\n *\n * @example\n * ```ts\n * generateIndexName({ email: 1 })\n * // => 'email_1'\n *\n * generateIndexName({ email: 1, role: -1 })\n * // => 'email_1_role_-1'\n * ```\n */\nexport function generateIndexName(key: Record<string, 1 | -1 | 'text'>): string {\n\treturn Object.entries(key)\n\t\t.map(([field, dir]) => `${field}_${dir}`)\n\t\t.join('_')\n}\n\n/**\n * Sort an object's keys alphabetically for deterministic JSON comparison.\n *\n * @param obj - A plain object.\n * @returns A new object with keys sorted alphabetically.\n */\nfunction sortKeys(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst sorted: Record<string, unknown> = {}\n\tfor (const key of Object.keys(obj).sort()) {\n\t\tsorted[key] = obj[key]\n\t}\n\treturn sorted\n}\n\n/** Resolve the name for an index spec, preferring an explicit name. */\nfunction resolveSpecName(spec: IndexSpec): string {\n\tconst specName = spec.options['name']\n\treturn typeof specName === 'string' ? specName : generateIndexName(spec.key)\n}\n\n/** Resolve the name from a raw MongoDB index info object. */\nfunction resolveExistingName(\n\tinfo: Record<string, unknown>,\n\tkey: Record<string, 1 | -1 | 'text'>,\n): string {\n\tconst infoName = info['name']\n\tif (typeof infoName === 'string') return infoName\n\treturn generateIndexName(key)\n}\n\n/**\n * Check whether two option objects are equivalent via sorted JSON.\n * The `name` key is excluded from comparison since it identifies\n * the index rather than defining its behavior.\n */\nfunction optionsMatch(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n\treturn JSON.stringify(sortKeys(stripName(a))) === JSON.stringify(sortKeys(stripName(b)))\n}\n\n/** Remove the `name` key from an options object for comparison purposes. */\nfunction stripName(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst { name: _, ...rest } = obj\n\treturn rest\n}\n\n/** Mutable accumulator for sync results. */\ntype SyncAccumulator = {\n\tcreated: string[]\n\tdropped: string[]\n\tskipped: string[]\n\tstale: StaleIndex[]\n\tmatchedKeys: Set<string>\n}\n\n/** Process a single desired spec against the existing index map. */\nasync function processDesiredSpec(\n\tspec: IndexSpec,\n\texistingByKey: Map<string, Record<string, unknown>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tdryRun: boolean,\n\tdropOrphaned: boolean,\n\tacc: SyncAccumulator,\n): Promise<void> {\n\tconst serialized = serializeIndexKey(spec.key)\n\tconst existing = existingByKey.get(serialized)\n\n\tif (!existing) {\n\t\tif (!dryRun) await safeCreateIndex(native, spec.key, spec.options)\n\t\tacc.created.push(resolveSpecName(spec))\n\t\treturn\n\t}\n\n\tacc.matchedKeys.add(serialized)\n\tconst existingName = resolveExistingName(existing, spec.key)\n\tconst existingOpts = extractComparableOptions(existing)\n\n\tif (optionsMatch(existingOpts, spec.options)) {\n\t\tacc.skipped.push(existingName)\n\t\treturn\n\t}\n\n\tif (dropOrphaned) {\n\t\tif (!dryRun) {\n\t\t\tawait safeDropIndex(native, existingName)\n\t\t\tawait safeCreateIndex(native, spec.key, spec.options)\n\t\t}\n\t\tacc.dropped.push(existingName)\n\t\tacc.created.push(resolveSpecName(spec))\n\t\treturn\n\t}\n\n\tacc.stale.push({\n\t\tname: existingName,\n\t\tkey: spec.key,\n\t\texisting: existingOpts,\n\t\tdesired: spec.options,\n\t})\n}\n\n/** Create a single index, wrapping driver errors into ZodmonError. */\nasync function safeCreateIndex(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tkey: Record<string, 1 | -1 | 'text'>,\n\toptions: Record<string, unknown>,\n): Promise<void> {\n\ttry {\n\t\tawait native.createIndex(key, options)\n\t} catch (err) {\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/** Drop a single index, wrapping driver errors into ZodmonError. */\nasync function safeDropIndex(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tname: string,\n): Promise<void> {\n\ttry {\n\t\tawait native.dropIndex(name)\n\t} catch (err) {\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/** Collect orphaned indexes that exist in MongoDB but are not in the desired set. */\nasync function processOrphanedIndexes(\n\texistingIndexes: Record<string, unknown>[],\n\tdesiredKeys: Set<string>,\n\tmatchedKeys: Set<string>,\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tdryRun: boolean,\n\tdropOrphaned: boolean,\n\tdropped: string[],\n): Promise<void> {\n\tfor (const idx of existingIndexes) {\n\t\tconst rawName = idx['name']\n\t\tconst name = typeof rawName === 'string' ? rawName : ''\n\t\tif (name === '_id_') continue\n\n\t\tconst serialized = serializeIndexKey(idx['key'] as Record<string, 1 | -1 | 'text'>)\n\t\tif (matchedKeys.has(serialized) || desiredKeys.has(serialized)) continue\n\n\t\tif (dropOrphaned) {\n\t\t\tif (!dryRun) await safeDropIndex(native, name)\n\t\t\tdropped.push(name)\n\t\t}\n\t}\n}\n\n/**\n * Fetch existing indexes, returning an empty array when the collection\n * does not exist yet (MongoDB throws \"ns does not exist\" in that case).\n */\nasync function listIndexesSafe(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n): Promise<Record<string, unknown>[]> {\n\ttry {\n\t\treturn (await native.listIndexes().toArray()) as unknown as Record<string, unknown>[]\n\t} catch (err) {\n\t\t// MongoDB 7 throws when the namespace (collection) doesn't exist\n\t\tif (err instanceof Error && err.message.includes('ns does not exist')) {\n\t\t\treturn []\n\t\t}\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/**\n * Synchronize the indexes declared in a collection's schema with MongoDB.\n *\n * Compares the desired indexes (from field-level and compound index definitions)\n * with the indexes that currently exist in MongoDB, then creates, drops, or\n * reports differences depending on the options.\n *\n * **Algorithm:**\n * 1. Build desired specs from field indexes and compound indexes.\n * 2. Fetch existing indexes from MongoDB via `listIndexes()`.\n * 3. For each desired spec, compare against existing:\n * - Missing → create (unless `dryRun`).\n * - Present with same options → skip.\n * - Present with different options → stale (or drop+recreate if `dropOrphaned`).\n * 4. For each existing index not in desired set (excluding `_id_`):\n * - If `dropOrphaned` → drop (unless `dryRun`).\n * 5. Return a summary of all actions taken.\n *\n * @param handle - A collection handle created by `db.use()`.\n * @param options - Optional sync behavior (dryRun, dropOrphaned).\n * @returns A summary of created, dropped, skipped, and stale indexes.\n *\n * @example\n * ```ts\n * import { syncIndexes } from '@zodmon/core'\n *\n * const users = db.use(Users)\n * const result = await syncIndexes(users)\n * console.log('Created:', result.created)\n * console.log('Stale:', result.stale.map(s => s.name))\n * ```\n *\n * @example\n * ```ts\n * // Dry run — no changes made\n * const diff = await syncIndexes(users, { dryRun: true })\n * console.log('Would create:', diff.created)\n * console.log('Would drop:', diff.dropped)\n * ```\n */\nexport async function syncIndexes(\n\thandle: SyncableHandle,\n\toptions?: SyncIndexesOptions,\n): Promise<SyncIndexesResult> {\n\tconst { dryRun = false, dropOrphaned = false } = options ?? {}\n\tconst native = handle.native\n\tconst def = handle.definition\n\n\t// 1. Build desired specs\n\tconst desiredSpecs: IndexSpec[] = [\n\t\t...def.fieldIndexes.map(toFieldIndexSpec),\n\t\t...def.compoundIndexes.map(toCompoundIndexSpec),\n\t]\n\n\t// 2. Fetch existing indexes (empty array when collection doesn't exist yet)\n\tconst existingIndexes = await listIndexesSafe(native)\n\n\t// 3. Build map of existing indexes keyed by serialized key\n\tconst existingByKey = new Map<string, Record<string, unknown>>()\n\tfor (const idx of existingIndexes) {\n\t\tconst serialized = serializeIndexKey(idx['key'] as Record<string, 1 | -1 | 'text'>)\n\t\texistingByKey.set(serialized, idx)\n\t}\n\n\tconst acc: SyncAccumulator = {\n\t\tcreated: [],\n\t\tdropped: [],\n\t\tskipped: [],\n\t\tstale: [],\n\t\tmatchedKeys: new Set<string>(),\n\t}\n\n\t// 4. Process desired specs\n\tfor (const spec of desiredSpecs) {\n\t\tawait processDesiredSpec(spec, existingByKey, native, dryRun, dropOrphaned, acc)\n\t}\n\n\t// 5. Handle orphaned indexes\n\tconst desiredKeys = new Set(desiredSpecs.map((s) => serializeIndexKey(s.key)))\n\tawait processOrphanedIndexes(\n\t\texistingIndexes,\n\t\tdesiredKeys,\n\t\tacc.matchedKeys,\n\t\tnative,\n\t\tdryRun,\n\t\tdropOrphaned,\n\t\tacc.dropped,\n\t)\n\n\treturn {\n\t\tcreated: acc.created,\n\t\tdropped: acc.dropped,\n\t\tskipped: acc.skipped,\n\t\tstale: acc.stale,\n\t}\n}\n","import type { DeleteResult } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { TypedFilter } from '../query/filter'\n\n/**\n * Options for {@link findOneAndDelete}.\n */\nexport type FindOneAndDeleteOptions = {\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Delete a single document matching the filter.\n *\n * Removes the first document that matches the filter from the collection.\n * No validation is performed — the document is deleted directly through\n * the MongoDB driver.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @returns The MongoDB `DeleteResult` with the deleted count.\n *\n * @example\n * ```ts\n * const result = await deleteOne(users, { name: 'Ada' })\n * console.log(result.deletedCount) // 1\n * ```\n */\nexport async function deleteOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n): Promise<DeleteResult> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\treturn await handle.native.deleteOne(filter as any)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Delete all documents matching the filter.\n *\n * Removes every document that matches the filter from the collection.\n * No validation is performed — documents are deleted directly through\n * the MongoDB driver.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @returns The MongoDB `DeleteResult` with the deleted count.\n *\n * @example\n * ```ts\n * const result = await deleteMany(users, { role: 'guest' })\n * console.log(result.deletedCount) // number of guests removed\n * ```\n */\nexport async function deleteMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n): Promise<DeleteResult> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\treturn await handle.native.deleteMany(filter as any)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Find a single document matching the filter, delete it, and return the document.\n *\n * Returns the deleted document, or `null` if no document matches the filter.\n * The returned document is validated against the collection's Zod schema\n * using the same resolution logic as {@link findOne}.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional settings: `validate`.\n * @returns The deleted document, or `null` if no document matches.\n * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneAndDelete(users, { name: 'Ada' })\n * if (user) console.log(user.name) // 'Ada' (the deleted document)\n * ```\n *\n * @example\n * ```ts\n * const user = await findOneAndDelete(\n * users,\n * { role: 'guest' },\n * { validate: false },\n * )\n * ```\n */\nexport async function findOneAndDelete<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneAndDeleteOptions,\n): Promise<InferDocument<TDef> | null> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\t// The options object uses includeResultMetadata: false to return the\n\t// document directly instead of a ModifyResult wrapper.\n\t// biome-ignore lint/suspicious/noExplicitAny: declaring result before try/catch for driver error wrapping; the actual value is assigned inside try and is non-null after the catch (wrapMongoError is never-returning)\n\tlet result: any\n\ttry {\n\t\tresult = await handle.native.findOneAndDelete(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\t{ includeResultMetadata: false },\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!result) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\t// Safe cast: raw document from MongoDB matches the collection's document\n\t\t// shape at runtime. Skipping validation per user request.\n\t\treturn result as InferDocument<TDef>\n\t}\n\n\ttry {\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\treturn handle.definition.schema.parse(result) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, result)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { z } from 'zod'\nimport { ZodmonError } from './base'\n\n/**\n * Thrown when a document fails Zod schema validation before a MongoDB write.\n *\n * Wraps the original `ZodError` with the collection name and a human-readable\n * message listing each invalid field and its error. Callers can inspect\n * `.zodError.issues` for programmatic access to individual failures.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 123 })\n * } catch (err) {\n * if (err instanceof ZodmonValidationError) {\n * console.log(err.message)\n * // => 'Validation failed for \"users\": name (Expected string, received number)'\n * console.log(err.collection) // => 'users'\n * console.log(err.zodError) // => ZodError with .issues array\n * console.log(err.document) // => the document that failed validation\n * }\n * }\n * ```\n */\nexport class ZodmonValidationError extends ZodmonError {\n\toverride readonly name = 'ZodmonValidationError'\n\n\t/** The original Zod validation error with detailed issue information. */\n\treadonly zodError: z.ZodError\n\n\t/** The document that failed validation. */\n\treadonly document: unknown\n\n\tconstructor(collection: string, zodError: z.ZodError, document: unknown) {\n\t\tconst fields = zodError.issues\n\t\t\t.map((issue) => {\n\t\t\t\tconst path = issue.path.join('.') || '(root)'\n\t\t\t\treturn `${path} (${issue.message})`\n\t\t\t})\n\t\t\t.join(', ')\n\t\tsuper(`Validation failed for \"${collection}\": ${fields}`, collection, { cause: zodError })\n\t\tthis.zodError = zodError\n\t\tthis.document = document\n\t}\n}\n","import type { FindCursor } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, IndexNames, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonNotFoundError } from '../errors/not-found'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport { checkUnindexedFields } from '../indexes/warn'\nimport { TypedFindCursor } from '../query/cursor'\nimport type { TypedFilter } from '../query/filter'\n\n/**\n * Options for {@link findOne} and {@link findOneOrThrow}.\n */\nexport type FindOneOptions = {\n\t/** MongoDB projection — include (`1`) or exclude (`0`) fields. Typed projections deferred to v1.0. */\n\tproject?: Record<string, 0 | 1>\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Find a single document matching the filter.\n *\n * Queries MongoDB, then validates the fetched document against the collection's\n * Zod schema. Validation mode is resolved from the per-query option, falling\n * back to the collection-level default (which defaults to `'strict'`).\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional projection and validation overrides.\n * @returns The matched document, or `null` if no document matches.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOne(users, { name: 'Ada' })\n * if (user) console.log(user.role) // typed as 'admin' | 'user'\n * ```\n */\nexport async function findOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneOptions,\n): Promise<InferDocument<TDef> | null> {\n\t// Safe cast: TypedFilter's top-level keys are string field names and $-operators,\n\t// both of which are captured by Record<string, unknown>.\n\tcheckUnindexedFields(handle.definition, filter as Record<string, unknown>)\n\tconst findOptions = options?.project ? { projection: options.project } : undefined\n\t// Safe cast: TypedFilter<InferDocument<TDef>> is a strict subset of\n\t// MongoDB's Filter<T>, but the intersection-based mapped type cannot\n\t// be structurally matched by the driver's looser Filter type.\n\tlet raw: Awaited<ReturnType<typeof handle.native.findOne>>\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\traw = await handle.native.findOne(filter as any, findOptions)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!raw) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\t// Safe cast: raw document from MongoDB matches the collection's document\n\t\t// shape at runtime. Skipping validation per user request.\n\t\treturn raw as InferDocument<TDef>\n\t}\n\n\ttry {\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\treturn handle.definition.schema.parse(raw) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, raw)\n\t\t}\n\t\tthrow err\n\t}\n}\n\n/**\n * Find a single document matching the filter, or throw if none exists.\n *\n * Behaves identically to {@link findOne} but throws {@link ZodmonNotFoundError}\n * instead of returning `null` when no document matches the filter.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional projection and validation overrides.\n * @returns The matched document (never null).\n * @throws {ZodmonNotFoundError} When no document matches the filter.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneOrThrow(users, { name: 'Ada' })\n * console.log(user.role) // typed as 'admin' | 'user', guaranteed non-null\n * ```\n */\nexport async function findOneOrThrow<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneOptions,\n): Promise<InferDocument<TDef>> {\n\tconst doc = await findOne(handle, filter, options)\n\tif (!doc) {\n\t\tthrow new ZodmonNotFoundError(handle.definition.name, filter)\n\t}\n\treturn doc\n}\n\n/**\n * Options for {@link find}.\n */\nexport type FindOptions = {\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Find all documents matching the filter, returning a chainable typed cursor.\n *\n * The cursor is lazy — no query is executed until a terminal method\n * (`toArray`, `for await`) is called. Use `sort`, `skip`, and `limit`\n * to shape the query before executing.\n *\n * Each document is validated against the collection's Zod schema when\n * a terminal method consumes it.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional validation overrides.\n * @returns A typed cursor for chaining query modifiers.\n *\n * @example\n * ```ts\n * const admins = await find(users, { role: 'admin' })\n * .sort({ name: 1 })\n * .limit(10)\n * .toArray()\n * ```\n *\n * @example\n * ```ts\n * for await (const user of find(users, {})) {\n * console.log(user.name)\n * }\n * ```\n */\nexport function find<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOptions,\n): TypedFindCursor<TDef, IndexNames<TDef>> {\n\t// Safe cast: TypedFilter's top-level keys are string field names and $-operators,\n\t// both of which are captured by Record<string, unknown>.\n\tcheckUnindexedFields(handle.definition, filter as Record<string, unknown>)\n\t// Safe cast: TypedFilter<InferDocument<TDef>> is a strict subset of\n\t// MongoDB's Filter<T>, but the intersection-based mapped type cannot\n\t// be structurally matched by the driver's looser Filter type.\n\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\tconst raw = handle.native.find(filter as any)\n\t// Safe cast: Collection.find() returns FindCursor<WithId<T>>, but our schemas\n\t// always include _id so WithId<InferDocument<TDef>> is structurally identical\n\t// to InferDocument<TDef>. TypeScript cannot prove this with exactOptionalPropertyTypes.\n\tconst cursor = raw as unknown as FindCursor<InferDocument<TDef>>\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\treturn new TypedFindCursor(cursor, handle.definition, mode, handle.native, filter)\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a query expected to find a document returns no results.\n *\n * Used by {@link findOneOrThrow} when no document matches the provided filter.\n * Callers can inspect `.collection` to identify which collection the query targeted,\n * and `.filter` to see the query that produced no results.\n *\n * @example\n * ```ts\n * try {\n * await users.findOneOrThrow({ name: 'nonexistent' })\n * } catch (err) {\n * if (err instanceof ZodmonNotFoundError) {\n * console.log(err.message) // => 'Document not found in \"users\"'\n * console.log(err.collection) // => 'users'\n * console.log(err.filter) // => { name: 'nonexistent' }\n * }\n * }\n * ```\n */\nexport class ZodmonNotFoundError extends ZodmonError {\n\toverride readonly name = 'ZodmonNotFoundError'\n\n\t/** The filter that produced no results. */\n\treadonly filter: unknown\n\n\tconstructor(collection: string, filter: unknown) {\n\t\tsuper(`Document not found in \"${collection}\"`, collection)\n\t\tthis.filter = filter\n\t}\n}\n","import type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\n\n/**\n * Structural constraint for the definition argument of {@link checkUnindexedFields}.\n *\n * Uses a structural type rather than `CollectionDefinition<z.core.$ZodShape>` to avoid\n * TypeScript variance issues with `exactOptionalPropertyTypes`. Any collection\n * definition returned by `collection()` satisfies this constraint.\n */\ntype WarnableDefinition = {\n\treadonly name: string\n\treadonly fieldIndexes: FieldIndexDefinition[]\n\treadonly compoundIndexes: readonly CompoundIndexDefinition[]\n\treadonly options: {\n\t\twarnUnindexedQueries?: boolean\n\t}\n}\n\n/** MongoDB query operators that should be skipped during unindexed field checks. */\nconst SKIP_OPERATORS = new Set(['$or', '$and', '$nor', '$text', '$where', '$expr', '$comment'])\n\n/**\n * Warn about unindexed fields used in a query filter.\n *\n * When `warnUnindexedQueries` is enabled on a collection definition, this\n * function checks each top-level field in the filter against the collection's\n * declared indexes. Fields that are not covered by any index produce a\n * `console.warn` message to help identify queries that may cause full\n * collection scans in development.\n *\n * **Covered fields:**\n * - `_id` (always indexed by MongoDB)\n * - Fields with `.index()`, `.unique()`, `.text()`, or `.expireAfter()` (field-level indexes)\n * - The **first** field of each compound index (prefix matching)\n *\n * **Skipped keys:**\n * - MongoDB operators: `$or`, `$and`, `$nor`, `$text`, `$where`, `$expr`, `$comment`\n *\n * This function is a no-op (zero overhead) when `warnUnindexedQueries` is not\n * explicitly set to `true`.\n *\n * @param definition - The collection definition containing index metadata.\n * @param filter - The query filter to check for unindexed fields.\n *\n * @example\n * ```ts\n * import { collection, checkUnindexedFields } from '@zodmon/core'\n *\n * const Users = collection('users', {\n * email: z.string().unique(),\n * name: z.string(),\n * }, { warnUnindexedQueries: true })\n *\n * // No warning — email is indexed\n * checkUnindexedFields(Users, { email: 'ada@example.com' })\n *\n * // Warns: \"[zodmon] warn: query on 'users' uses unindexed field 'name'\"\n * checkUnindexedFields(Users, { name: 'Ada' })\n * ```\n */\nexport function checkUnindexedFields(\n\tdefinition: WarnableDefinition,\n\tfilter: Record<string, unknown>,\n): void {\n\tif (definition.options.warnUnindexedQueries !== true) return\n\n\tconst covered = new Set<string>()\n\n\tfor (const fi of definition.fieldIndexes) {\n\t\tcovered.add(fi.field)\n\t}\n\n\tfor (const ci of definition.compoundIndexes) {\n\t\tconst firstField = Object.keys(ci.fields)[0]\n\t\tif (firstField !== undefined) {\n\t\t\tcovered.add(firstField)\n\t\t}\n\t}\n\n\tfor (const key of Object.keys(filter)) {\n\t\tif (key === '_id') continue\n\t\tif (SKIP_OPERATORS.has(key)) continue\n\t\tif (!covered.has(key)) {\n\t\t\tconsole.warn(`[zodmon] warn: query on '${definition.name}' uses unindexed field '${key}'`)\n\t\t}\n\t}\n}\n","import type { Collection, FindCursor, Sort } from 'mongodb'\nimport { z } from 'zod'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport {\n\tbuildCursorFilter,\n\ttype CursorPage,\n\ttype CursorPaginateOptions,\n\tdecodeCursor,\n\tencodeCursor,\n\ttype OffsetPage,\n\ttype OffsetPaginateOptions,\n\tresolveSortKeys,\n\ttype SortEntry,\n} from '../crud/paginate'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\n\n/**\n * Type-safe sort specification for a document type.\n *\n * Constrains sort keys to top-level fields of `T` with direction `1` (ascending)\n * or `-1` (descending). Dot-path sorts deferred to v1.0.\n *\n * @example\n * ```ts\n * const sort: TypedSort<User> = { name: 1, createdAt: -1 }\n * ```\n */\nexport type TypedSort<T> = Partial<Record<keyof T & string, 1 | -1>>\n\n/**\n * Type-safe cursor wrapping MongoDB's `FindCursor`.\n *\n * Provides chainable query modifiers (`sort`, `skip`, `limit`, `hint`) that return\n * `this` for fluent chaining, and terminal methods (`toArray`,\n * `[Symbol.asyncIterator]`) that validate each document against the\n * collection's Zod schema before returning.\n *\n * Created by {@link find} — do not construct directly.\n *\n * @typeParam TDef - The collection definition type, used to infer the document type.\n * @typeParam TIndexNames - Union of declared index names accepted by `.hint()`.\n *\n * @example\n * ```ts\n * const docs = await find(users, { role: 'admin' })\n * .sort({ name: 1 })\n * .limit(10)\n * .toArray()\n * ```\n */\nexport class TypedFindCursor<TDef extends AnyCollection, TIndexNames extends string = string> {\n\t/** @internal */\n\tprivate cursor: FindCursor<InferDocument<TDef>>\n\t/** @internal */\n\tprivate schema: z.ZodType\n\t/** @internal */\n\tprivate collectionName: string\n\t/** @internal */\n\tprivate mode: ValidationMode | false\n\t/** @internal */\n\tprivate readonly nativeCollection: Collection<InferDocument<TDef>>\n\t/** @internal */\n\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter is not assignable to MongoDB's Filter; stored opaquely for paginate\n\tprivate readonly filter: any\n\t/** @internal */\n\tprivate sortSpec: TypedSort<InferDocument<TDef>> | null\n\n\t/** @internal */\n\tconstructor(\n\t\tcursor: FindCursor<InferDocument<TDef>>,\n\t\tdefinition: TDef,\n\t\tmode: ValidationMode | false,\n\t\tnativeCollection: Collection<InferDocument<TDef>>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter is not assignable to MongoDB's Filter; stored opaquely for paginate\n\t\tfilter: any,\n\t) {\n\t\tthis.cursor = cursor\n\t\tthis.schema = definition.schema\n\t\tthis.collectionName = definition.name\n\t\tthis.mode = mode\n\t\tthis.nativeCollection = nativeCollection\n\t\tthis.filter = filter\n\t\tthis.sortSpec = null\n\t}\n\n\t/**\n\t * Set the sort order for the query.\n\t *\n\t * Only top-level document fields are accepted as sort keys.\n\t * Values must be `1` (ascending) or `-1` (descending).\n\t *\n\t * @param spec - Sort specification mapping field names to sort direction.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).sort({ name: 1, age: -1 }).toArray()\n\t * ```\n\t */\n\tsort(spec: TypedSort<InferDocument<TDef>>): this {\n\t\tthis.sortSpec = spec\n\t\t// Safe cast: TypedSort is a strict subset of MongoDB's Sort type,\n\t\t// but Record<keyof T & string, 1 | -1> is not assignable to Sort\n\t\t// due to index signature differences.\n\t\tthis.cursor.sort(spec as Sort)\n\t\treturn this\n\t}\n\n\t/**\n\t * Skip the first `n` documents in the result set.\n\t *\n\t * @param n - Number of documents to skip.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).skip(10).limit(10).toArray() // page 2\n\t * ```\n\t */\n\tskip(n: number): this {\n\t\tthis.cursor.skip(n)\n\t\treturn this\n\t}\n\n\t/**\n\t * Limit the number of documents returned.\n\t *\n\t * @param n - Maximum number of documents to return.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).limit(10).toArray() // at most 10 docs\n\t * ```\n\t */\n\tlimit(n: number): this {\n\t\tthis.cursor.limit(n)\n\t\treturn this\n\t}\n\n\t/**\n\t * Force the query optimizer to use the specified index.\n\t *\n\t * Only accepts index names that were declared via `.name()` in the\n\t * collection definition. If no named indexes exist, any string is accepted.\n\t *\n\t * @param indexName - The name of a declared compound index.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * const Users = collection('users', { email: z.string(), role: z.string() }, {\n\t * indexes: [index({ email: 1, role: -1 }).name('email_role_idx')],\n\t * })\n\t * const admins = await users.find({ role: 'admin' })\n\t * .hint('email_role_idx')\n\t * .toArray()\n\t * ```\n\t */\n\thint(indexName: TIndexNames): this {\n\t\tthis.cursor.hint(indexName)\n\t\treturn this\n\t}\n\n\t/**\n\t * Execute the query with offset-based pagination, returning a page of documents\n\t * with total count and navigation metadata.\n\t *\n\t * Runs `countDocuments` and `find` in parallel for performance. Ignores any\n\t * `.skip()` or `.limit()` already set on the cursor — issues a fresh query.\n\t *\n\t * @param opts - Offset pagination options: `page` (1-indexed) and `perPage`.\n\t * @returns A page with `docs`, `total`, `totalPages`, `hasNext`, `hasPrev`.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const page = await users.find({ role: 'admin' })\n\t * .sort({ createdAt: -1 })\n\t * .paginate({ page: 2, perPage: 10 })\n\t * console.log(page.total, page.totalPages, page.hasNext)\n\t * ```\n\t */\n\tpaginate(opts: OffsetPaginateOptions): Promise<OffsetPage<InferDocument<TDef>>>\n\t/**\n\t * Execute the query with cursor-based pagination, returning a page of documents\n\t * with opaque cursors for forward/backward navigation.\n\t *\n\t * Uses the `limit + 1` trick to determine `hasNext`/`hasPrev` without extra queries.\n\t * Direction is encoded in the cursor — pass `endCursor` to go forward, `startCursor`\n\t * to go backward.\n\t *\n\t * @param opts - Cursor pagination options: `limit` and optional `cursor`.\n\t * @returns A page with `docs`, `hasNext`, `hasPrev`, `startCursor`, `endCursor`.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t * @throws {Error} When the cursor string is malformed.\n\t *\n\t * @example\n\t * ```ts\n\t * const first = await users.find({}).sort({ name: 1 }).paginate({ limit: 10 })\n\t * const next = await users.find({}).sort({ name: 1 })\n\t * .paginate({ cursor: first.endCursor, limit: 10 })\n\t * ```\n\t */\n\tpaginate(opts: CursorPaginateOptions): Promise<CursorPage<InferDocument<TDef>>>\n\tasync paginate(\n\t\topts: OffsetPaginateOptions | CursorPaginateOptions,\n\t): Promise<OffsetPage<InferDocument<TDef>> | CursorPage<InferDocument<TDef>>> {\n\t\tconst sortRecord = this.sortSpec ? (this.sortSpec as Record<string, 1 | -1>) : null\n\t\tconst sortKeys = resolveSortKeys(sortRecord)\n\t\tconst sort = Object.fromEntries(sortKeys) as Sort\n\n\t\tif ('page' in opts) {\n\t\t\treturn await this.offsetPaginate(sortKeys, sort, opts)\n\t\t}\n\t\treturn await this.cursorPaginate(sortKeys, sort, opts)\n\t}\n\n\t/** @internal Offset pagination implementation. */\n\tprivate async offsetPaginate(\n\t\t_sortKeys: SortEntry[],\n\t\tsort: Sort,\n\t\topts: OffsetPaginateOptions,\n\t): Promise<OffsetPage<InferDocument<TDef>>> {\n\t\tlet total: number\n\t\t// biome-ignore lint/suspicious/noExplicitAny: declaring raw before try/catch for driver error wrapping; assigned inside try, guaranteed non-null after catch (wrapMongoError returns never)\n\t\tlet raw: any[]\n\t\ttry {\n\t\t\t;[total, raw] = await Promise.all([\n\t\t\t\tthis.nativeCollection.countDocuments(this.filter),\n\t\t\t\tthis.nativeCollection\n\t\t\t\t\t.find(this.filter)\n\t\t\t\t\t.sort(sort)\n\t\t\t\t\t.skip((opts.page - 1) * opts.perPage)\n\t\t\t\t\t.limit(opts.perPage)\n\t\t\t\t\t.toArray(),\n\t\t\t])\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\n\t\t// Safe cast: our schemas always include _id, so WithId<T> is structurally\n\t\t// identical to InferDocument<TDef>. TypeScript can't prove this under\n\t\t// exactOptionalPropertyTypes.\n\t\tconst docs = (raw as unknown as InferDocument<TDef>[]).map((doc) => this.validateDoc(doc))\n\t\tconst totalPages = Math.ceil(total / opts.perPage)\n\n\t\treturn {\n\t\t\tdocs,\n\t\t\ttotal,\n\t\t\tpage: opts.page,\n\t\t\tperPage: opts.perPage,\n\t\t\ttotalPages,\n\t\t\thasNext: opts.page < totalPages,\n\t\t\thasPrev: opts.page > 1,\n\t\t}\n\t}\n\n\t/** @internal Cursor pagination implementation. */\n\tprivate async cursorPaginate(\n\t\tsortKeys: SortEntry[],\n\t\tsort: Sort,\n\t\topts: CursorPaginateOptions,\n\t): Promise<CursorPage<InferDocument<TDef>>> {\n\t\tlet isBackward = false\n\t\tlet combinedFilter = this.filter\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor)\n\t\t\tisBackward = decoded.direction === 'b'\n\t\t\tconst cursorFilter = buildCursorFilter(sortKeys, decoded.values, isBackward)\n\t\t\tcombinedFilter =\n\t\t\t\tthis.filter && Object.keys(this.filter).length > 0\n\t\t\t\t\t? { $and: [this.filter, cursorFilter] }\n\t\t\t\t\t: cursorFilter\n\t\t}\n\n\t\t// For backward pagination, reverse all sort directions\n\t\tconst effectiveSort = isBackward\n\t\t\t? (Object.fromEntries(sortKeys.map(([f, d]) => [f, d === 1 ? -1 : 1])) as Sort)\n\t\t\t: sort\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: declaring raw before try/catch for driver error wrapping; assigned inside try, guaranteed non-null after catch (wrapMongoError returns never)\n\t\tlet raw: any[]\n\t\ttry {\n\t\t\traw = await this.nativeCollection\n\t\t\t\t.find(combinedFilter)\n\t\t\t\t.sort(effectiveSort)\n\t\t\t\t.limit(opts.limit + 1)\n\t\t\t\t.toArray()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\n\t\tconst hasMore = raw.length > opts.limit\n\t\tif (hasMore) raw.pop()\n\n\t\t// Reverse back to original sort order for backward pagination\n\t\tif (isBackward) raw.reverse()\n\n\t\t// Safe cast: same WithId<T> → InferDocument<TDef> cast as offsetPaginate\n\t\tconst docs = (raw as unknown as InferDocument<TDef>[]).map((doc) => this.validateDoc(doc))\n\n\t\treturn {\n\t\t\tdocs,\n\t\t\thasNext: isBackward ? true : hasMore,\n\t\t\thasPrev: isBackward ? hasMore : opts.cursor != null,\n\t\t\tstartCursor:\n\t\t\t\tdocs.length > 0 ? encodeCursor(docs[0] as Record<string, unknown>, sortKeys, 'b') : null,\n\t\t\tendCursor:\n\t\t\t\tdocs.length > 0\n\t\t\t\t\t? encodeCursor(docs[docs.length - 1] as Record<string, unknown>, sortKeys, 'f')\n\t\t\t\t\t: null,\n\t\t}\n\t}\n\n\t/**\n\t * Execute the query and return all matching documents as an array.\n\t *\n\t * Each document is validated against the collection's Zod schema\n\t * according to the resolved validation mode.\n\t *\n\t * @returns Array of validated documents.\n\t * @throws {ZodmonValidationError} When a document fails schema validation in strict/strip mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const admins = await find(users, { role: 'admin' }).toArray()\n\t * ```\n\t */\n\tasync toArray(): Promise<InferDocument<TDef>[]> {\n\t\tlet raw: InferDocument<TDef>[]\n\t\ttry {\n\t\t\traw = await this.cursor.toArray()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\t\treturn raw.map((doc) => this.validateDoc(doc))\n\t}\n\n\t/**\n\t * Async iterator for streaming documents one at a time.\n\t *\n\t * Each yielded document is validated against the collection's Zod schema.\n\t * Memory-efficient for large result sets.\n\t *\n\t * @yields Validated documents one at a time.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * for await (const user of find(users, {})) {\n\t * console.log(user.name)\n\t * }\n\t * ```\n\t */\n\tasync *[Symbol.asyncIterator](): AsyncGenerator<InferDocument<TDef>> {\n\t\ttry {\n\t\t\tfor await (const doc of this.cursor) {\n\t\t\t\tyield this.validateDoc(doc)\n\t\t\t}\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\t}\n\n\t/** @internal Validate a single raw document against the schema. */\n\tprivate validateDoc(raw: InferDocument<TDef>): InferDocument<TDef> {\n\t\tif (this.mode === false || this.mode === 'passthrough') {\n\t\t\treturn raw\n\t\t}\n\n\t\ttry {\n\t\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\t\treturn this.schema.parse(raw) as InferDocument<TDef>\n\t\t} catch (err) {\n\t\t\tif (err instanceof z.ZodError) {\n\t\t\t\tthrow new ZodmonValidationError(this.collectionName, err, raw)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n}\n","import { ObjectId } from 'mongodb'\n\n// ── Public types ────────────────────────────────────────────────────────\n\n/**\n * Options for offset-based pagination.\n *\n * @example\n * ```ts\n * await users.find({}).sort({ name: 1 }).paginate({ page: 2, perPage: 10 })\n * ```\n */\nexport type OffsetPaginateOptions = {\n\t/** The page number to retrieve (1-indexed). */\n\tpage: number\n\t/** The number of documents per page. */\n\tperPage: number\n}\n\n/**\n * Options for cursor-based pagination.\n *\n * @example\n * ```ts\n * const first = await users.find({}).sort({ name: 1 }).paginate({ limit: 10 })\n * const next = await users.find({}).sort({ name: 1 }).paginate({ cursor: first.endCursor, limit: 10 })\n * ```\n */\nexport type CursorPaginateOptions = {\n\t/** Maximum number of documents to return. */\n\tlimit: number\n\t/** Opaque cursor string from a previous `startCursor` or `endCursor`. */\n\tcursor?: string | null\n}\n\n/**\n * Result of offset-based pagination.\n *\n * @example\n * ```ts\n * const page = await users.find({}).paginate({ page: 1, perPage: 10 })\n * console.log(page.total, page.totalPages, page.hasNext)\n * ```\n */\nexport type OffsetPage<TDoc> = {\n\t/** The documents for this page. */\n\tdocs: TDoc[]\n\t/** Total number of matching documents. */\n\ttotal: number\n\t/** Current page number (1-indexed). */\n\tpage: number\n\t/** Number of documents per page. */\n\tperPage: number\n\t/** Total number of pages (`Math.ceil(total / perPage)`). */\n\ttotalPages: number\n\t/** Whether there is a next page. */\n\thasNext: boolean\n\t/** Whether there is a previous page. */\n\thasPrev: boolean\n}\n\n/**\n * Result of cursor-based pagination.\n *\n * @example\n * ```ts\n * const page = await users.find({}).paginate({ limit: 10 })\n * if (page.hasNext) {\n * const next = await users.find({}).paginate({ cursor: page.endCursor, limit: 10 })\n * }\n * ```\n */\nexport type CursorPage<TDoc> = {\n\t/** The documents for this page. */\n\tdocs: TDoc[]\n\t/** Whether there are more documents after this page. */\n\thasNext: boolean\n\t/** Whether there are documents before this page. */\n\thasPrev: boolean\n\t/** Cursor for the first document (pass to `cursor` to go backward). `null` when empty. */\n\tstartCursor: string | null\n\t/** Cursor for the last document (pass to `cursor` to go forward). `null` when empty. */\n\tendCursor: string | null\n}\n\n// ── Sort key type ───────────────────────────────────────────────────────\n\n/** A [field, direction] tuple used internally for sort resolution. */\nexport type SortEntry = [field: string, direction: 1 | -1]\n\n// ── Cursor value serialization ──────────────────────────────────────────\n\n/**\n * Serialize a value for cursor encoding, preserving ObjectId and Date types.\n *\n * @example\n * ```ts\n * serializeValue(new ObjectId('...')) // { $oid: '...' }\n * serializeValue(new Date('2024-01-01')) // { $date: 1704067200000 }\n * serializeValue('hello') // 'hello'\n * ```\n */\nexport function serializeValue(value: unknown): unknown {\n\tif (value instanceof ObjectId) return { $oid: value.toHexString() }\n\tif (value instanceof Date) return { $date: value.getTime() }\n\treturn value\n}\n\n/**\n * Deserialize a cursor value, restoring ObjectId and Date types.\n *\n * @example\n * ```ts\n * deserializeValue({ $oid: '507f1f...' }) // ObjectId('507f1f...')\n * deserializeValue({ $date: 1704067200000 }) // Date('2024-01-01')\n * deserializeValue('hello') // 'hello'\n * ```\n */\nexport function deserializeValue(value: unknown): unknown {\n\tif (value != null && typeof value === 'object') {\n\t\tif ('$oid' in value) return new ObjectId((value as { $oid: string }).$oid)\n\t\tif ('$date' in value) return new Date((value as { $date: number }).$date)\n\t}\n\treturn value\n}\n\n// ── Cursor encoding/decoding ────────────────────────────────────────────\n\n/**\n * Encode a cursor from a document's sort field values.\n *\n * Format: base64(JSON([ direction, ...serializedValues ]))\n * Direction: 'f' (forward / endCursor) or 'b' (backward / startCursor).\n *\n * @example\n * ```ts\n * encodeCursor({ age: 25, _id: oid }, [['age', 1], ['_id', 1]], 'f')\n * // base64-encoded string\n * ```\n */\nexport function encodeCursor(\n\tdoc: Record<string, unknown>,\n\tsortKeys: SortEntry[],\n\tdirection: 'f' | 'b',\n): string {\n\tconst values = sortKeys.map(([field]) => serializeValue(doc[field]))\n\treturn btoa(JSON.stringify([direction, ...values]))\n}\n\n/**\n * Decode a cursor string into direction and sort field values.\n *\n * @throws {Error} When the cursor is malformed or has invalid format.\n *\n * @example\n * ```ts\n * const { direction, values } = decodeCursor(cursorString)\n * // direction: 'f' | 'b', values: unknown[]\n * ```\n */\nexport function decodeCursor(cursor: string): { direction: 'f' | 'b'; values: unknown[] } {\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(atob(cursor))\n\t} catch {\n\t\tthrow new Error('Invalid cursor: malformed encoding')\n\t}\n\tif (!Array.isArray(parsed) || parsed.length < 1) {\n\t\tthrow new Error('Invalid cursor: expected non-empty array')\n\t}\n\tconst [direction, ...rawValues] = parsed as [unknown, ...unknown[]]\n\tif (direction !== 'f' && direction !== 'b') {\n\t\tthrow new Error('Invalid cursor: unknown direction flag')\n\t}\n\treturn { direction, values: rawValues.map(deserializeValue) }\n}\n\n// ── Cursor filter builder ───────────────────────────────────────────────\n\n/**\n * Build a MongoDB `$or` filter for cursor-based pagination.\n *\n * For sort `{ role: 1, createdAt: -1, _id: 1 }` with values `['admin', date, id]`:\n * ```\n * { $or: [\n * { role: { $gt: 'admin' } },\n * { role: 'admin', createdAt: { $lt: date } },\n * { role: 'admin', createdAt: date, _id: { $gt: id } },\n * ]}\n * ```\n *\n * @example\n * ```ts\n * buildCursorFilter([['age', 1], ['_id', 1]], [25, oid], false)\n * // { $or: [{ age: { $gt: 25 } }, { age: 25, _id: { $gt: oid } }] }\n * ```\n */\nexport function buildCursorFilter(\n\tsortKeys: SortEntry[],\n\tvalues: unknown[],\n\tisBackward: boolean,\n): Record<string, unknown> {\n\tconst clauses: Record<string, unknown>[] = []\n\n\tfor (let i = 0; i < sortKeys.length; i++) {\n\t\tconst clause: Record<string, unknown> = {}\n\n\t\t// Equality prefix for all preceding fields\n\t\tfor (let j = 0; j < i; j++) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: index is bounded by outer loop\n\t\t\tclause[sortKeys[j]![0]] = values[j]\n\t\t}\n\n\t\t// Comparison operator for current field\n\t\t// Forward + asc = $gt, Forward + desc = $lt\n\t\t// Backward reverses: Backward + asc = $lt, Backward + desc = $gt\n\t\t// biome-ignore lint/style/noNonNullAssertion: index is bounded by loop\n\t\tconst [field, direction] = sortKeys[i]!\n\t\tconst isAsc = direction === 1\n\t\tconst op = isAsc !== isBackward ? '$gt' : '$lt'\n\n\t\t// MongoDB's $gt/$lt with null doesn't work for cursor pagination:\n\t\t// $gt: null only matches BSON types above null (regex, etc.), not\n\t\t// strings/numbers. $lt: null matches nothing. In both directions,\n\t\t// \"past null\" means \"not null\", so use $ne: null.\n\t\tif (values[i] === null) {\n\t\t\tclause[field] = { $ne: null }\n\t\t} else {\n\t\t\tclause[field] = { [op]: values[i] }\n\t\t}\n\n\t\tclauses.push(clause)\n\t}\n\n\treturn { $or: clauses }\n}\n\n// ── Sort resolution ─────────────────────────────────────────────────────\n\n/**\n * Resolve sort keys, always appending `_id` as tiebreaker if not present.\n * Defaults to `[['_id', 1]]` when no sort is specified.\n *\n * @example\n * ```ts\n * resolveSortKeys({ age: 1 }) // [['age', 1], ['_id', 1]]\n * resolveSortKeys(null) // [['_id', 1]]\n * resolveSortKeys({ _id: -1 }) // [['_id', -1]]\n * ```\n */\nexport function resolveSortKeys(sortSpec: Record<string, 1 | -1> | null): SortEntry[] {\n\tconst entries: SortEntry[] = sortSpec ? (Object.entries(sortSpec) as SortEntry[]) : []\n\n\tif (!entries.some(([field]) => field === '_id')) {\n\t\tentries.push(['_id', 1])\n\t}\n\n\treturn entries\n}\n","import { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, InferInsert } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\n\n/**\n * Insert a single document into the collection.\n *\n * Validates the input against the collection's Zod schema before writing.\n * Schema defaults (including auto-generated `_id`) are applied during\n * validation. Returns the full document with all defaults filled in.\n *\n * @param handle - The collection handle to insert into.\n * @param doc - The document to insert. Fields with `.default()` are optional.\n * @returns The inserted document with `_id` and all defaults applied.\n * @throws {ZodmonValidationError} When the document fails schema validation.\n *\n * @example\n * ```ts\n * const user = await insertOne(users, { name: 'Ada' })\n * console.log(user._id) // ObjectId (auto-generated)\n * console.log(user.role) // 'user' (schema default)\n * ```\n */\nexport async function insertOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tdoc: InferInsert<TDef>,\n): Promise<InferDocument<TDef>> {\n\tlet parsed: InferDocument<TDef>\n\ttry {\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\tparsed = handle.definition.schema.parse(doc) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, doc)\n\t\t}\n\t\tthrow err\n\t}\n\t// Safe cast: parsed is a full document with _id, matching the collection's\n\t// document type. MongoDB driver's OptionalUnlessRequiredId makes _id optional\n\t// for generic types, but we always have _id after parse.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertOne parameter type uses OptionalUnlessRequiredId which is not directly assignable from our generic InferDocument\n\t\tawait handle.native.insertOne(parsed as any)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\treturn parsed\n}\n\n/**\n * Insert multiple documents into the collection.\n *\n * Validates every document against the collection's Zod schema before\n * writing any to MongoDB. If any document fails validation, none are\n * inserted (fail-fast before the driver call).\n *\n * @param handle - The collection handle to insert into.\n * @param docs - The documents to insert.\n * @returns The inserted documents with `_id` and all defaults applied.\n * @throws {ZodmonValidationError} When any document fails schema validation.\n *\n * @example\n * ```ts\n * const users = await insertMany(handle, [\n * { name: 'Ada' },\n * { name: 'Bob', role: 'admin' },\n * ])\n * ```\n */\nexport async function insertMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tdocs: InferInsert<TDef>[],\n): Promise<InferDocument<TDef>[]> {\n\tif (docs.length === 0) return []\n\tconst parsed: InferDocument<TDef>[] = []\n\tfor (const doc of docs) {\n\t\ttry {\n\t\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\t\tparsed.push(handle.definition.schema.parse(doc) as InferDocument<TDef>)\n\t\t} catch (err) {\n\t\t\tif (err instanceof z.ZodError) {\n\t\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, doc)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertMany parameter type is not directly assignable from our generic InferDocument\n\t\tawait handle.native.insertMany(parsed as any)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\treturn parsed\n}\n","import type { UpdateResult } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { TypedFilter } from '../query/filter'\nimport type { TypedUpdateFilter } from '../query/update'\n\n/**\n * Options for {@link updateOne} and {@link updateMany}.\n */\nexport type UpdateOptions = {\n\t/** When `true`, inserts a new document if no document matches the filter. */\n\tupsert?: boolean\n}\n\n/**\n * Options for {@link findOneAndUpdate}.\n */\nexport type FindOneAndUpdateOptions = {\n\t/** Whether to return the document before or after the update. Defaults to `'after'`. */\n\treturnDocument?: 'before' | 'after'\n\t/** When `true`, inserts a new document if no document matches the filter. */\n\tupsert?: boolean\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Update a single document matching the filter.\n *\n * Applies the update operators to the first document that matches the filter.\n * Does not validate the update against the Zod schema — validation happens\n * at the field-operator level through {@link TypedUpdateFilter}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings such as `upsert`.\n * @returns The MongoDB `UpdateResult` with match/modify counts.\n *\n * @example\n * ```ts\n * const result = await updateOne(users, { name: 'Ada' }, { $set: { role: 'admin' } })\n * console.log(result.modifiedCount) // 1\n * ```\n */\nexport async function updateOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: UpdateOptions,\n): Promise<UpdateResult> {\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter/TypedUpdateFilter intersection types are not directly assignable to MongoDB's Filter/UpdateFilter\n\t\treturn await handle.native.updateOne(filter as any, update as any, options)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Update all documents matching the filter.\n *\n * Applies the update operators to every document that matches the filter.\n * Does not validate the update against the Zod schema — validation happens\n * at the field-operator level through {@link TypedUpdateFilter}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings such as `upsert`.\n * @returns The MongoDB `UpdateResult` with match/modify counts.\n *\n * @example\n * ```ts\n * const result = await updateMany(users, { role: 'guest' }, { $set: { role: 'user' } })\n * console.log(result.modifiedCount) // number of guests promoted\n * ```\n */\nexport async function updateMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: UpdateOptions,\n): Promise<UpdateResult> {\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter/TypedUpdateFilter intersection types are not directly assignable to MongoDB's Filter/UpdateFilter\n\t\treturn await handle.native.updateMany(filter as any, update as any, options)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Find a single document matching the filter, apply an update, and return the document.\n *\n * By default, returns the document **after** the update is applied. Set\n * `returnDocument: 'before'` to get the pre-update snapshot. The returned\n * document is validated against the collection's Zod schema using the same\n * resolution logic as {@link findOne}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings: `returnDocument`, `upsert`, `validate`.\n * @returns The matched document (before or after update), or `null` if no document matches.\n * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneAndUpdate(\n * users,\n * { name: 'Ada' },\n * { $set: { role: 'admin' } },\n * )\n * if (user) console.log(user.role) // 'admin' (returned after update)\n * ```\n *\n * @example\n * ```ts\n * const before = await findOneAndUpdate(\n * users,\n * { name: 'Ada' },\n * { $inc: { loginCount: 1 } },\n * { returnDocument: 'before' },\n * )\n * ```\n */\nexport async function findOneAndUpdate<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: FindOneAndUpdateOptions,\n): Promise<InferDocument<TDef> | null> {\n\tconst driverOptions: Record<string, unknown> = {\n\t\treturnDocument: options?.returnDocument ?? 'after',\n\t\tincludeResultMetadata: false,\n\t}\n\tif (options?.upsert !== undefined) {\n\t\tdriverOptions['upsert'] = options.upsert\n\t}\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\t// The options object is built dynamically to satisfy exactOptionalPropertyTypes.\n\t// biome-ignore lint/suspicious/noExplicitAny: declaring result before try/catch for driver error wrapping; the actual value is assigned inside try and is non-null after the catch (wrapMongoError is never-returning)\n\tlet result: any\n\ttry {\n\t\tresult = await handle.native.findOneAndUpdate(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter\n\t\t\tupdate as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic options object is not assignable to driver's FindOneAndUpdateOptions under exactOptionalPropertyTypes\n\t\t\tdriverOptions as any,\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!result) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\t// Safe cast: raw document from MongoDB matches the collection's document\n\t\t// shape at runtime. Skipping validation per user request.\n\t\treturn result as InferDocument<TDef>\n\t}\n\n\ttry {\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\treturn handle.definition.schema.parse(result) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, result)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { Collection, DeleteResult, UpdateResult } from 'mongodb'\nimport type { AggregatePipeline } from '../aggregate/pipeline'\nimport { aggregate as _aggregate } from '../aggregate/pipeline'\nimport type { AnyCollection, IndexNames, InferDocument, InferInsert } from '../collection/types'\nimport type { FindOneAndDeleteOptions } from '../crud/delete'\nimport {\n\tdeleteMany as _deleteMany,\n\tdeleteOne as _deleteOne,\n\tfindOneAndDelete as _findOneAndDelete,\n} from '../crud/delete'\nimport type { FindOneOptions, FindOptions } from '../crud/find'\nimport { find as _find, findOne as _findOne, findOneOrThrow as _findOneOrThrow } from '../crud/find'\nimport { insertMany as _insertMany, insertOne as _insertOne } from '../crud/insert'\nimport type { FindOneAndUpdateOptions, UpdateOptions } from '../crud/update'\nimport {\n\tfindOneAndUpdate as _findOneAndUpdate,\n\tupdateMany as _updateMany,\n\tupdateOne as _updateOne,\n} from '../crud/update'\nimport { syncIndexes as _syncIndexes } from '../indexes/sync'\nimport type { SyncIndexesOptions, SyncIndexesResult } from '../indexes/types'\nimport type { TypedFindCursor } from '../query/cursor'\nimport type { TypedFilter } from '../query/filter'\nimport type { TypedUpdateFilter } from '../query/update'\n\n/**\n * Typed wrapper around a MongoDB driver `Collection`.\n *\n * Created by {@link Database.use}. Holds the original `CollectionDefinition`\n * (for runtime schema validation and index metadata) alongside the native\n * driver collection parameterized with the inferred document type.\n *\n * @typeParam TDef - The collection definition type. Used to derive both\n * the document type (`InferDocument`) and the insert type (`InferInsert`).\n */\nexport class CollectionHandle<TDef extends AnyCollection = AnyCollection> {\n\t/** The collection definition containing schema, name, and index metadata. */\n\treadonly definition: TDef\n\n\t/** The underlying MongoDB driver collection, typed to the inferred document type. */\n\treadonly native: Collection<InferDocument<TDef>>\n\n\tconstructor(definition: TDef, native: Collection<InferDocument<TDef>>) {\n\t\tthis.definition = definition\n\t\tthis.native = native\n\t}\n\n\t/**\n\t * Insert a single document into the collection.\n\t *\n\t * Validates the input against the collection's Zod schema before writing.\n\t * Schema defaults (including auto-generated `_id`) are applied during\n\t * validation. Returns the full document with all defaults filled in.\n\t *\n\t * @param doc - The document to insert. Fields with `.default()` are optional.\n\t * @returns The inserted document with `_id` and all defaults applied.\n\t * @throws {ZodmonValidationError} When the document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.insertOne({ name: 'Ada' })\n\t * console.log(user._id) // ObjectId (auto-generated)\n\t * console.log(user.role) // 'user' (schema default)\n\t * ```\n\t */\n\tasync insertOne(doc: InferInsert<TDef>): Promise<InferDocument<TDef>> {\n\t\treturn await _insertOne(this, doc)\n\t}\n\n\t/**\n\t * Insert multiple documents into the collection.\n\t *\n\t * Validates every document against the collection's Zod schema before\n\t * writing any to MongoDB. If any document fails validation, none are\n\t * inserted (fail-fast before the driver call).\n\t *\n\t * @param docs - The documents to insert.\n\t * @returns The inserted documents with `_id` and all defaults applied.\n\t * @throws {ZodmonValidationError} When any document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const created = await users.insertMany([\n\t * { name: 'Ada' },\n\t * { name: 'Bob', role: 'admin' },\n\t * ])\n\t * ```\n\t */\n\tasync insertMany(docs: InferInsert<TDef>[]): Promise<InferDocument<TDef>[]> {\n\t\treturn await _insertMany(this, docs)\n\t}\n\n\t/**\n\t * Find a single document matching the filter.\n\t *\n\t * Queries MongoDB, then validates the fetched document against the collection's\n\t * Zod schema. Validation mode is resolved from the per-query option, falling\n\t * back to the collection-level default (which defaults to `'strict'`).\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional projection and validation overrides.\n\t * @returns The matched document, or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOne({ name: 'Ada' })\n\t * if (user) console.log(user.role)\n\t * ```\n\t */\n\tasync findOne(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneOptions,\n\t): Promise<InferDocument<TDef> | null> {\n\t\treturn await _findOne(this, filter, options)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, or throw if none exists.\n\t *\n\t * Behaves identically to {@link findOne} but throws {@link ZodmonNotFoundError}\n\t * instead of returning `null` when no document matches the filter.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional projection and validation overrides.\n\t * @returns The matched document (never null).\n\t * @throws {ZodmonNotFoundError} When no document matches the filter.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneOrThrow({ name: 'Ada' })\n\t * console.log(user.role) // guaranteed non-null\n\t * ```\n\t */\n\tasync findOneOrThrow(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneOptions,\n\t): Promise<InferDocument<TDef>> {\n\t\treturn await _findOneOrThrow(this, filter, options)\n\t}\n\n\t/**\n\t * Find all documents matching the filter, returning a chainable typed cursor.\n\t *\n\t * The cursor is lazy — no query is executed until a terminal method\n\t * (`toArray`, `for await`) is called. Use `sort`, `skip`, and `limit`\n\t * to shape the query before executing.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional validation overrides.\n\t * @returns A typed cursor for chaining query modifiers.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const admins = await users.find({ role: 'admin' })\n\t * .sort({ name: 1 })\n\t * .limit(10)\n\t * .toArray()\n\t * ```\n\t */\n\tfind(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOptions,\n\t): TypedFindCursor<TDef, IndexNames<TDef>> {\n\t\treturn _find(this, filter, options)\n\t}\n\n\t/**\n\t * Update a single document matching the filter.\n\t *\n\t * Applies the update operators to the first document that matches the filter.\n\t * Does not validate the update against the Zod schema — validation happens\n\t * at the field-operator level through {@link TypedUpdateFilter}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings such as `upsert`.\n\t * @returns The MongoDB `UpdateResult` with match/modify counts.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.updateOne({ name: 'Ada' }, { $set: { role: 'admin' } })\n\t * console.log(result.modifiedCount) // 1\n\t * ```\n\t */\n\tasync updateOne(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: UpdateOptions,\n\t): Promise<UpdateResult> {\n\t\treturn await _updateOne(this, filter, update, options)\n\t}\n\n\t/**\n\t * Update all documents matching the filter.\n\t *\n\t * Applies the update operators to every document that matches the filter.\n\t * Does not validate the update against the Zod schema — validation happens\n\t * at the field-operator level through {@link TypedUpdateFilter}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings such as `upsert`.\n\t * @returns The MongoDB `UpdateResult` with match/modify counts.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.updateMany({ role: 'guest' }, { $set: { role: 'user' } })\n\t * console.log(result.modifiedCount) // number of guests promoted\n\t * ```\n\t */\n\tasync updateMany(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: UpdateOptions,\n\t): Promise<UpdateResult> {\n\t\treturn await _updateMany(this, filter, update, options)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, apply an update, and return the document.\n\t *\n\t * By default, returns the document **after** the update is applied. Set\n\t * `returnDocument: 'before'` to get the pre-update snapshot. The returned\n\t * document is validated against the collection's Zod schema using the same\n\t * resolution logic as {@link findOne}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings: `returnDocument`, `upsert`, `validate`.\n\t * @returns The matched document (before or after update), or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneAndUpdate(\n\t * { name: 'Ada' },\n\t * { $set: { role: 'admin' } },\n\t * )\n\t * if (user) console.log(user.role) // 'admin' (returned after update)\n\t * ```\n\t */\n\tasync findOneAndUpdate(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneAndUpdateOptions,\n\t): Promise<InferDocument<TDef> | null> {\n\t\treturn await _findOneAndUpdate(this, filter, update, options)\n\t}\n\n\t/**\n\t * Delete a single document matching the filter.\n\t *\n\t * Removes the first document that matches the filter from the collection.\n\t * No validation is performed — the document is deleted directly through\n\t * the MongoDB driver.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @returns The MongoDB `DeleteResult` with the deleted count.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.deleteOne({ name: 'Ada' })\n\t * console.log(result.deletedCount) // 1\n\t * ```\n\t */\n\tasync deleteOne(filter: TypedFilter<InferDocument<TDef>>): Promise<DeleteResult> {\n\t\treturn await _deleteOne(this, filter)\n\t}\n\n\t/**\n\t * Delete all documents matching the filter.\n\t *\n\t * Removes every document that matches the filter from the collection.\n\t * No validation is performed — documents are deleted directly through\n\t * the MongoDB driver.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @returns The MongoDB `DeleteResult` with the deleted count.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.deleteMany({ role: 'guest' })\n\t * console.log(result.deletedCount) // number of guests removed\n\t * ```\n\t */\n\tasync deleteMany(filter: TypedFilter<InferDocument<TDef>>): Promise<DeleteResult> {\n\t\treturn await _deleteMany(this, filter)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, delete it, and return the document.\n\t *\n\t * Returns the deleted document, or `null` if no document matches the filter.\n\t * The returned document is validated against the collection's Zod schema\n\t * using the same resolution logic as {@link findOne}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional settings: `validate`.\n\t * @returns The deleted document, or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneAndDelete({ name: 'Ada' })\n\t * if (user) console.log(user.name) // 'Ada' (the deleted document)\n\t * ```\n\t */\n\tasync findOneAndDelete(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneAndDeleteOptions,\n\t): Promise<InferDocument<TDef> | null> {\n\t\treturn await _findOneAndDelete(this, filter, options)\n\t}\n\n\t/**\n\t * Synchronize the indexes declared in this collection's schema with MongoDB.\n\t *\n\t * Compares the desired indexes (from field-level `.index()` / `.unique()` /\n\t * `.text()` / `.expireAfter()` and compound `indexes` in collection options)\n\t * with the indexes that currently exist in MongoDB, then creates, drops, or\n\t * reports differences depending on the options.\n\t *\n\t * @param options - Optional sync behavior (dryRun, dropOrphaned).\n\t * @returns A summary of created, dropped, skipped, and stale indexes.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.syncIndexes()\n\t * console.log('Created:', result.created)\n\t * console.log('Stale:', result.stale.map(s => s.name))\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Dry run to preview changes without modifying the database\n\t * const diff = await users.syncIndexes({ dryRun: true })\n\t * console.log('Would create:', diff.created)\n\t * console.log('Would drop:', diff.dropped)\n\t * ```\n\t */\n\tasync syncIndexes(options?: SyncIndexesOptions): Promise<SyncIndexesResult> {\n\t\treturn await _syncIndexes(this, options)\n\t}\n\n\t/**\n\t * Start a type-safe aggregation pipeline on this collection.\n\t *\n\t * Returns a fluent pipeline builder that tracks the output document\n\t * shape through each stage. The pipeline is lazy — no query executes\n\t * until a terminal method (`toArray`, `for await`, `explain`) is called.\n\t *\n\t * @returns A new pipeline builder starting with this collection's document type.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.aggregate()\n\t * .match({ role: 'admin' })\n\t * .groupBy('role', { count: $count() })\n\t * .toArray()\n\t * ```\n\t */\n\taggregate(): AggregatePipeline<TDef, InferDocument<TDef>> {\n\t\treturn _aggregate(this)\n\t}\n}\n","import { ObjectId } from 'mongodb'\nimport { z } from 'zod'\nimport { getIndexMetadata } from '../schema/extensions'\nimport { objectId } from '../schema/object-id'\nimport type {\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tResolvedShape,\n} from './types'\n\n/**\n * Walk a Zod shape and extract field-level index metadata from each field.\n *\n * Returns an array of {@link FieldIndexDefinition} for every field that has\n * been marked with `.index()`, `.unique()`, `.text()`, or `.expireAfter()`.\n * Fields without index metadata are silently skipped.\n *\n * @param shape - A Zod shape object (the value passed to `z.object()`).\n * @returns An array of field index definitions with the field name attached.\n */\nexport function extractFieldIndexes(shape: z.core.$ZodShape): FieldIndexDefinition[] {\n\tconst result: FieldIndexDefinition[] = []\n\tfor (const [field, schema] of Object.entries(shape)) {\n\t\tconst meta = getIndexMetadata(schema)\n\t\tif (meta) {\n\t\t\tresult.push({ field, ...meta })\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Define a MongoDB collection with a Zod schema.\n *\n * Creates a {@link CollectionDefinition} that:\n * - Adds `_id: objectId()` if the shape doesn't already include `_id`\n * - Uses the user-provided `_id` schema if one is present (e.g. nanoid, UUID)\n * - Extracts field-level index metadata from the shape\n * - Separates compound indexes from the rest of the options\n * - Returns an immutable definition object\n *\n * @param name - The MongoDB collection name.\n * @param shape - A Zod shape object defining the document fields. May include a custom `_id`.\n * @param options - Optional collection-level configuration including compound indexes.\n * @returns A {@link CollectionDefinition} ready for use with `createClient()`.\n *\n * @example\n * ```ts\n * const Users = collection('users', {\n * email: z.string().unique(),\n * name: z.string().index(),\n * age: z.number().optional(),\n * })\n * ```\n */\nexport function collection<\n\tTName extends string,\n\tTShape extends z.core.$ZodShape,\n\tconst TIndexes extends readonly CompoundIndexDefinition<\n\t\tExtract<keyof TShape, string>\n\t>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[],\n>(\n\tname: TName,\n\tshape: TShape,\n\toptions?: Omit<CollectionOptions<Extract<keyof TShape, string>>, 'indexes'> & {\n\t\tindexes?: TIndexes\n\t},\n): CollectionDefinition<TName, TShape, [...TIndexes]> {\n\t// TypeScript cannot narrow generic conditional types through control flow,\n\t// so the assertion is needed here. Both branches are provably correct:\n\t// - when _id is in shape: ResolvedShape<TShape> = TShape\n\t// - when _id is absent: ResolvedShape<TShape> = { _id: ZodObjectId } & TShape\n\tconst resolvedShape = (\n\t\t'_id' in shape ? shape : { _id: objectId().default(() => new ObjectId()), ...shape }\n\t) as ResolvedShape<TShape>\n\tconst schema = z.object(resolvedShape)\n\n\tconst fieldIndexes = extractFieldIndexes(shape)\n\n\tconst { indexes: compoundIndexes, validation, ...rest } = options ?? {}\n\n\treturn {\n\t\tname,\n\t\t// Zod v4's z.object() returns ZodObject<{ -readonly [P in keyof T]: T[P] }> which\n\t\t// strips readonly modifiers. With exactOptionalPropertyTypes this mapped type is\n\t\t// not assignable to ZodObject<ResolvedShape<TShape>>. The cast is safe because\n\t\t// the runtime shape is correct — only the readonly modifier differs.\n\t\tschema: schema as CollectionDefinition<TName, TShape, [...TIndexes]>['schema'],\n\t\tshape,\n\t\tfieldIndexes,\n\t\t// Safe cast: compoundIndexes is TIndexes at runtime (or an empty array when\n\t\t// no options provided). The spread into [...TIndexes] preserves the tuple type.\n\t\tcompoundIndexes: (compoundIndexes ?? []) as [...TIndexes],\n\t\toptions: {\n\t\t\tvalidation: validation ?? 'strict',\n\t\t\t...rest,\n\t\t},\n\t}\n}\n","import { z } from 'zod'\nimport { installRefExtension } from './ref'\n\n/**\n * Options controlling how a field-level MongoDB index is created.\n *\n * Passed to the `.index()` Zod extension method. Every property is optional;\n * omitting all of them creates a standard ascending, non-unique index.\n */\nexport type IndexOptions = {\n\t/** When `true`, MongoDB enforces a unique constraint on this field. */\n\tunique?: boolean\n\t/**\n\t * When `true`, the index skips documents where the field is `null` or missing.\n\t * Useful for optional fields that should be indexed only when present.\n\t */\n\tsparse?: boolean\n\t/** When `true`, creates a MongoDB text index for full-text search on this field. */\n\ttext?: boolean\n\t/**\n\t * When `true`, the index is created in descending order (`-1`).\n\t * Defaults to ascending (`1`) when omitted.\n\t */\n\tdescending?: boolean\n\t/**\n\t * TTL in seconds. MongoDB will automatically delete documents once the\n\t * indexed `Date` field is older than this many seconds. Only valid on\n\t * fields whose runtime type is `Date`.\n\t */\n\texpireAfter?: number\n\t/**\n\t * A partial filter expression. Only documents matching this filter are\n\t * included in the index. Maps directly to MongoDB's `partialFilterExpression`.\n\t */\n\tpartial?: Record<string, unknown>\n}\n\n/**\n * Metadata stored in the WeakMap sidecar for every schema that has been\n * marked with `.index()`. Always contains `indexed: true` plus any\n * {@link IndexOptions} the caller provided.\n */\nexport type IndexMetadata = {\n\t/** Always `true` — acts as a discriminator for \"this field is indexed\". */\n\tindexed: true\n} & IndexOptions\n\ndeclare module 'zod' {\n\tinterface ZodType {\n\t\t/**\n\t\t * Mark this field for indexing when `syncIndexes()` is called.\n\t\t *\n\t\t * Stores {@link IndexOptions} in a WeakMap sidecar so the collection\n\t\t * factory can later introspect each field and build the appropriate\n\t\t * MongoDB index specification.\n\t\t *\n\t\t * @param options - Optional index configuration (unique, sparse, etc.).\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const UserSchema = z.object({\n\t\t * email: z.string().index({ unique: true }),\n\t\t * age: z.number().index({ sparse: true }),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tindex(options?: IndexOptions): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ unique: true })`.\n\t\t *\n\t\t * Creates a unique index on this field, causing MongoDB to reject\n\t\t * duplicate values.\n\t\t *\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const UserSchema = z.object({\n\t\t * email: z.string().unique(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tunique(): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ text: true })`.\n\t\t *\n\t\t * Creates a MongoDB text index on this field, enabling `$text` queries\n\t\t * for full-text search.\n\t\t *\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const PostSchema = z.object({\n\t\t * body: z.string().text(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\ttext(): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ expireAfter: seconds })`.\n\t\t *\n\t\t * Creates a TTL (Time-To-Live) index. MongoDB will automatically\n\t\t * remove documents once the indexed `Date` field is older than\n\t\t * the specified number of seconds.\n\t\t *\n\t\t * @param seconds - Number of seconds after which documents expire.\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const SessionSchema = z.object({\n\t\t * createdAt: z.date().expireAfter(3600), // 1 hour TTL\n\t\t * })\n\t\t * ```\n\t\t */\n\t\texpireAfter(seconds: number): this\n\t}\n}\n\n/**\n * WeakMap sidecar that associates a Zod schema instance with its\n * {@link IndexMetadata}.\n *\n * A WeakMap is used so that index metadata does not prevent garbage collection\n * of schema instances. The keys are the Zod schema objects themselves, and\n * the values are the corresponding `IndexMetadata` descriptors.\n */\nconst indexMetadata = new WeakMap<object, IndexMetadata>()\n\n/**\n * Retrieve the index metadata attached to a Zod schema, if any.\n *\n * Returns `undefined` when the schema was never marked with an index\n * extension (`.index()`, `.unique()`, `.text()`, or `.expireAfter()`).\n *\n * @param schema - The Zod schema to inspect. Accepts `unknown` for\n * convenience; non-object values safely return `undefined`.\n * @returns The {@link IndexMetadata} for the schema, or `undefined`.\n *\n * @example\n * ```ts\n * const email = z.string().index({ unique: true })\n * const meta = getIndexMetadata(email)\n * // => { indexed: true, unique: true }\n * ```\n */\nexport function getIndexMetadata(schema: unknown): IndexMetadata | undefined {\n\tif (typeof schema !== 'object' || schema === null) return undefined\n\treturn indexMetadata.get(schema)\n}\n\n/**\n * Symbol used as a guard property on `ZodType.prototype` to prevent\n * double-registration of Zodmon extension methods. The symbol is created\n * with `Symbol.for` so it is shared across realms / duplicate module loads.\n */\nconst GUARD = Symbol.for('zodmon_extensions')\n\n/**\n * Monkey-patch Zod's `ZodType.prototype` with Zodmon extension methods\n * (`.index()`, `.unique()`, `.text()`, `.expireAfter()`).\n *\n * In Zod v4, methods are copied from `ZodType.prototype` to each instance\n * during construction via the internal `init` loop (`Object.keys(proto)` ->\n * copy to instance). Extension methods use `enumerable: true` so they are\n * picked up by this loop for every schema created after installation.\n *\n * The function is idempotent: calling it more than once is a safe no-op,\n * guarded by a non-enumerable `Symbol.for('zodmon_extensions')` property\n * on the prototype.\n *\n * This function is called at module level when `extensions.ts` is first\n * imported, so consumers never need to call it manually. It is exported\n * primarily for use in tests.\n *\n * @example\n * ```ts\n * import { installExtensions } from '@zodmon/core/schema/extensions'\n * installExtensions() // safe to call multiple times\n *\n * const indexed = z.string().index({ unique: true })\n * ```\n */\nexport function installExtensions(): void {\n\tconst proto = z.ZodType.prototype\n\tif (GUARD in proto) return\n\n\tObject.defineProperty(proto, 'index', {\n\t\t/**\n\t\t * Declares a MongoDB index on this field. Accepts optional\n\t\t * {@link IndexOptions} to configure uniqueness, sparseness, text search,\n\t\t * sort direction, TTL, or partial filters.\n\t\t *\n\t\t * @param options - Index configuration. Omit for a standard ascending index.\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const name = z.string().index()\n\t\t * const email = z.string().index({ unique: true, sparse: true })\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto, options?: IndexOptions): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, ...options })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'unique', {\n\t\t/**\n\t\t * Shorthand for `.index({ unique: true })`. Marks this field as requiring\n\t\t * a unique index in MongoDB, preventing duplicate values.\n\t\t *\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const email = z.string().unique()\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, unique: true })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'text', {\n\t\t/**\n\t\t * Shorthand for `.index({ text: true })`. Creates a MongoDB text index on\n\t\t * this field, enabling full-text search queries with `$text`.\n\t\t *\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const bio = z.string().text()\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, text: true })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'expireAfter', {\n\t\t/**\n\t\t * Shorthand for `.index({ expireAfter: seconds })`. Creates a TTL index on\n\t\t * a `Date` field. MongoDB will automatically remove documents once the field\n\t\t * value is older than the specified number of seconds.\n\t\t *\n\t\t * @param seconds - TTL in seconds after which documents expire.\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const expiresAt = z.date().expireAfter(86400) // 24 hours\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto, seconds: number): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, expireAfter: seconds })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tinstallRefExtension()\n\n\tObject.defineProperty(proto, GUARD, {\n\t\tvalue: true,\n\t\tenumerable: false,\n\t\tconfigurable: false,\n\t\twritable: false,\n\t})\n}\n\ninstallExtensions()\n","import { ObjectId } from 'mongodb'\nimport { type ZodCustom, type ZodPipe, type ZodTransform, z } from 'zod'\n\n/** Matches a 24-character hexadecimal string (case-insensitive). */\nconst OBJECT_ID_HEX = /^[a-f\\d]{24}$/i\n\n/**\n * The Zod type produced by {@link objectId}. A pipeline that validates an\n * input as either a `string` (24-char hex) or an `ObjectId` instance, then\n * transforms it into a concrete `ObjectId`.\n *\n * Use `z.infer<ZodObjectId>` to extract the output type (`ObjectId`) and\n * `z.input<ZodObjectId>` for the input type (`string | ObjectId`).\n */\nexport type ZodObjectId = ZodPipe<\n\tZodCustom<string | ObjectId, string | ObjectId>,\n\tZodTransform<ObjectId, string | ObjectId>\n>\n\n/**\n * Create a Zod schema that validates and coerces values into MongoDB\n * `ObjectId` instances.\n *\n * Accepts either:\n * - An existing `ObjectId` instance (passed through unchanged).\n * - A 24-character hexadecimal string (coerced to `ObjectId`).\n *\n * All other inputs are rejected with the message `\"Invalid ObjectId\"`.\n *\n * @returns A {@link ZodObjectId} schema.\n *\n * @example\n * ```ts\n * const schema = objectId()\n *\n * schema.parse(new ObjectId()) // OK — pass-through\n * schema.parse('64f1a2b3c4d5e6f7a8b9c0d1') // OK — coerced to ObjectId\n * schema.parse('not-valid') // throws ZodError\n * ```\n *\n * @example Inside a z.object() shape:\n * ```ts\n * const UserSchema = z.object({\n * _id: objectId(),\n * name: z.string(),\n * })\n * ```\n */\nexport function objectId(): ZodObjectId {\n\treturn z\n\t\t.custom<string | ObjectId>((val): val is string | ObjectId => {\n\t\t\tif (val instanceof ObjectId) return true\n\t\t\treturn typeof val === 'string' && OBJECT_ID_HEX.test(val)\n\t\t}, 'Invalid ObjectId')\n\t\t.transform((val) => (val instanceof ObjectId ? val : ObjectId.createFromHexString(val)))\n}\n","import type { CompoundIndexDefinition } from './types'\n\ntype IndexDirection = 1 | -1\n\ntype CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>\n\n/**\n * A builder for compound index definitions.\n *\n * Provides a fluent API for declaring compound indexes with options like\n * `unique`, `sparse`, and custom `name`. Each method returns a new\n * IndexBuilder instance (immutable pattern — the original is never mutated).\n *\n * IndexBuilder is structurally compatible with {@link CompoundIndexDefinition}\n * so instances can be used directly in `CollectionOptions.indexes`.\n *\n * Dot-notation paths like `'address.city'` are accepted at the value level\n * (any string satisfies `TKeys`), but type-level validation against nested\n * schema paths is deferred to a future release.\n *\n * @example\n * ```ts\n * index({ email: 1, role: -1 }).unique().name('email_role_idx')\n * ```\n */\nexport class IndexBuilder<TKeys extends string> {\n\t// Typed as Partial for structural compatibility with CompoundIndexDefinition.\n\t// The constructor guarantees all keys are present at runtime.\n\treadonly fields: Partial<Record<TKeys, IndexDirection>>\n\treadonly options: CompoundIndexOptions\n\n\tconstructor(fields: Record<TKeys, IndexDirection>) {\n\t\tthis.fields = fields\n\t\tthis.options = {}\n\t}\n\n\tprivate _clone(options: CompoundIndexOptions): IndexBuilder<TKeys> {\n\t\t// Object.create returns `any`; cast is safe because we assign the correct shape\n\t\treturn Object.assign(Object.create(IndexBuilder.prototype) as IndexBuilder<TKeys>, {\n\t\t\tfields: this.fields,\n\t\t\toptions,\n\t\t})\n\t}\n\n\t// Safe cast: _clone returns IndexBuilder<TKeys> but `this` may carry an\n\t// intersection from .name(). The cast is safe because _clone preserves all fields.\n\tunique(): this {\n\t\treturn this._clone({ ...this.options, unique: true }) as this\n\t}\n\n\t// Safe cast: same reasoning as unique().\n\tsparse(): this {\n\t\treturn this._clone({ ...this.options, sparse: true }) as this\n\t}\n\n\t/**\n\t * Set a custom name for this index, preserving the literal type.\n\t *\n\t * The returned builder carries the literal name type via an intersection,\n\t * enabling type-safe `.hint()` on cursors that only accepts declared names.\n\t *\n\t * @param name - The index name.\n\t * @returns A new IndexBuilder with the name recorded at the type level.\n\t *\n\t * @example\n\t * ```ts\n\t * index({ email: 1, role: -1 }).name('email_role_idx')\n\t * ```\n\t */\n\tname<TName extends string>(\n\t\tname: TName,\n\t): IndexBuilder<TKeys> & { readonly options: { readonly name: TName } } {\n\t\t// Safe cast: _clone returns IndexBuilder<TKeys> which is structurally correct;\n\t\t// the intersection adds the literal name type for downstream type extraction.\n\t\treturn this._clone({ ...this.options, name }) as IndexBuilder<TKeys> & {\n\t\t\treadonly options: { readonly name: TName }\n\t\t}\n\t}\n}\n\n/**\n * Create a compound index definition with a fluent builder API.\n *\n * Returns an {@link IndexBuilder} that is structurally compatible with\n * `CompoundIndexDefinition`, so it can be used directly in\n * `CollectionOptions.indexes` alongside plain objects.\n *\n * @param fields - An object mapping field names to sort direction (1 or -1).\n * @returns An {@link IndexBuilder} instance.\n *\n * @example\n * ```ts\n * collection('users', { email: z.string(), role: z.string() }, {\n * indexes: [\n * index({ email: 1, role: -1 }).unique(),\n * { fields: { role: 1 } },\n * ],\n * })\n * ```\n */\nexport function index<TKeys extends string>(\n\tfields: Record<TKeys, IndexDirection>,\n): IndexBuilder<TKeys> {\n\treturn new IndexBuilder(fields)\n}\n","import { ObjectId } from 'mongodb'\n\n/**\n * Create or coerce a MongoDB `ObjectId`.\n *\n * - Called with **no arguments**: generates a brand-new `ObjectId`.\n * - Called with a **hex string**: coerces it to an `ObjectId` via\n * `ObjectId.createFromHexString`.\n * - Called with an **existing `ObjectId`**: returns it unchanged.\n *\n * This is a convenience wrapper that removes the need for `new ObjectId()`\n * boilerplate throughout application code.\n *\n * @param value - Optional hex string or `ObjectId` to coerce. Omit to\n * generate a new `ObjectId`.\n * @returns An `ObjectId` instance.\n *\n * @example\n * ```ts\n * oid() // new random ObjectId\n * oid('64f1a2b3c4d5e6f7a8b9c0d1') // coerce hex string\n * oid(existingId) // pass-through\n * ```\n */\nexport function oid(): ObjectId\nexport function oid(value: string): ObjectId\nexport function oid(value: ObjectId): ObjectId\nexport function oid(value?: string | ObjectId): ObjectId {\n\tif (value === undefined) return new ObjectId()\n\tif (value instanceof ObjectId) return value\n\treturn ObjectId.createFromHexString(value)\n}\n\n/**\n * Type guard that narrows an `unknown` value to `ObjectId`.\n *\n * Uses `instanceof` internally, so it works with any value without risk\n * of throwing.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is an `ObjectId` instance.\n *\n * @example\n * ```ts\n * const raw: unknown = getFromDb()\n * if (isOid(raw)) {\n * console.log(raw.toHexString()) // raw is narrowed to ObjectId\n * }\n * ```\n */\nexport function isOid(value: unknown): value is ObjectId {\n\treturn value instanceof ObjectId\n}\n","import type { TypedFilter } from './filter'\n\n// ── Value operators ──────────────────────────────────────────────────────────\n\n/**\n * Matches values equal to the specified value.\n *\n * @example\n * ```ts\n * // Explicit equality (equivalent to { name: 'Alice' })\n * users.find({ name: $eq('Alice') })\n * ```\n */\nexport const $eq = <V>(value: V): { $eq: V } => ({ $eq: value })\n\n/**\n * Matches values not equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ role: $ne('banned') })\n * ```\n */\nexport const $ne = <V>(value: V): { $ne: V } => ({ $ne: value })\n\n/**\n * Matches values greater than the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $gt(18) })\n * ```\n */\nexport const $gt = <V>(value: V): { $gt: V } => ({ $gt: value })\n\n/**\n * Matches values greater than or equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $gte(18) })\n * ```\n */\nexport const $gte = <V>(value: V): { $gte: V } => ({ $gte: value })\n\n/**\n * Matches values less than the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $lt(65) })\n * ```\n */\nexport const $lt = <V>(value: V): { $lt: V } => ({ $lt: value })\n\n/**\n * Matches values less than or equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $lte(65) })\n * ```\n */\nexport const $lte = <V>(value: V): { $lte: V } => ({ $lte: value })\n\n/**\n * Matches any value in the specified array.\n *\n * @example\n * ```ts\n * users.find({ role: $in(['admin', 'moderator']) })\n * ```\n */\nexport const $in = <V>(values: readonly V[]): { $in: readonly V[] } => ({ $in: values })\n\n/**\n * Matches none of the values in the specified array.\n *\n * @example\n * ```ts\n * users.find({ role: $nin(['banned', 'suspended']) })\n * ```\n */\nexport const $nin = <V>(values: readonly V[]): { $nin: readonly V[] } => ({ $nin: values })\n\n/**\n * Matches documents where the field exists (or does not exist).\n * Defaults to `true` when called with no arguments.\n *\n * @example\n * ```ts\n * // Field must exist\n * users.find({ email: $exists() })\n *\n * // Field must not exist\n * users.find({ deletedAt: $exists(false) })\n * ```\n */\nexport const $exists = (flag = true): { $exists: boolean } => ({ $exists: flag })\n\n/**\n * Matches string values against a regular expression pattern.\n * Only valid on string fields.\n *\n * @example\n * ```ts\n * users.find({ name: $regex(/^A/i) })\n * users.find({ email: $regex('^admin@') })\n * ```\n */\nexport const $regex = (pattern: RegExp | string): { $regex: RegExp | string } => ({\n\t$regex: pattern,\n})\n\n/**\n * Negates a comparison operator. Wraps the given operator object\n * in a `$not` condition.\n *\n * @example\n * ```ts\n * // Age is NOT greater than 65\n * users.find({ age: $not($gt(65)) })\n *\n * // Name does NOT match pattern\n * users.find({ name: $not($regex(/^test/)) })\n * ```\n */\nexport const $not = <O extends Record<string, unknown>>(op: O): { $not: O } => ({\n\t$not: op,\n})\n\n// ── Logical operators ────────────────────────────────────────────────────────\n\n/**\n * Joins filter clauses with a logical OR. Matches documents that satisfy\n * at least one of the provided filters.\n *\n * @example\n * ```ts\n * // T inferred from collection's find() context\n * users.find($or({ role: 'admin' }, { age: $gte(18) }))\n *\n * // Explicit generic for standalone usage\n * const filter = $or<User>({ role: 'admin' }, { age: $gte(18) })\n * ```\n */\nexport const $or = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $or: filters }) as TypedFilter<T>\n\n/**\n * Joins filter clauses with a logical AND. Matches documents that satisfy\n * all of the provided filters. Useful for dynamic filter building where\n * multiple conditions on the same field would conflict in an object literal.\n *\n * @example\n * ```ts\n * // T inferred from collection's find() context\n * users.find($and(\n * $or({ role: 'admin' }, { role: 'moderator' }),\n * { age: $gte(18) },\n * { email: $exists() },\n * ))\n * ```\n */\nexport const $and = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $and: filters }) as TypedFilter<T>\n\n/**\n * Joins filter clauses with a logical NOR. Matches documents that fail\n * all of the provided filters.\n *\n * @example\n * ```ts\n * // Exclude banned and suspended users\n * users.find($nor({ role: 'banned' }, { role: 'suspended' }))\n * ```\n */\nexport const $nor = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $nor: filters }) as TypedFilter<T>\n\n// ── Escape hatch ─────────────────────────────────────────────────────────────\n\n/**\n * Escape hatch for unsupported or raw MongoDB filter operators.\n * Wraps an untyped filter object so it can be passed where `TypedFilter<T>` is expected.\n * Use when you need operators not covered by the type system (e.g., `$text`, `$geoNear`).\n *\n * @example\n * ```ts\n * users.find(raw({ $text: { $search: 'mongodb tutorial' } }))\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional escape hatch for raw MongoDB filters\nexport const raw = <T = any>(filter: Record<string, unknown>): TypedFilter<T> =>\n\tfilter as TypedFilter<T>\n","import {\n\t$and,\n\t$eq,\n\t$exists,\n\t$gt,\n\t$gte,\n\t$in,\n\t$lt,\n\t$lte,\n\t$ne,\n\t$nin,\n\t$nor,\n\t$not,\n\t$or,\n\t$regex,\n\traw,\n} from './operators'\n\n/**\n * Convenience namespace that groups all query operators under a single import.\n *\n * Property names strip the `$` prefix since the namespace itself is `$`.\n * Individual operator exports (`$or`, `$gt`, etc.) remain available for\n * tree-shaking — this namespace is the ergonomic alternative.\n *\n * @example\n * ```ts\n * import { $ } from '@zodmon/core'\n *\n * users.find($.or({ role: 'admin' }, { age: $.gte(25) }))\n * users.find({ name: $.regex(/^A/i), age: $.gt(18) })\n * users.find($.and({ published: true }, { views: $.gte(100) }))\n * ```\n */\nexport const $ = {\n\teq: $eq,\n\tne: $ne,\n\tgt: $gt,\n\tgte: $gte,\n\tlt: $lt,\n\tlte: $lte,\n\tin: $in,\n\tnin: $nin,\n\texists: $exists,\n\tregex: $regex,\n\tnot: $not,\n\tor: $or,\n\tand: $and,\n\tnor: $nor,\n\traw,\n} as const\n"],"mappings":"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","names":["$","collection","collection","collection","collection","collection","index","collection","collection","collection","collection","collection","collection","collection","import_mongodb","import_zod","collection","import_zod","collection","import_zod","import_mongodb","sortKeys","sortKeys","raw","raw","import_zod","import_zod","import_mongodb","import_zod","import_zod","import_mongodb","import_zod","import_mongodb"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/aggregate/expressions.ts","../src/errors/wrap.ts","../src/errors/base.ts","../src/errors/auth.ts","../src/errors/bulk-write.ts","../src/errors/doc-validation.ts","../src/errors/duplicate-key.ts","../src/errors/index-error.ts","../src/errors/network.ts","../src/errors/query.ts","../src/errors/timeout.ts","../src/errors/write-conflict.ts","../src/schema/ref.ts","../src/aggregate/pipeline.ts","../src/client/client.ts","../src/indexes/spec.ts","../src/indexes/sync.ts","../src/transaction/transaction.ts","../src/crud/delete.ts","../src/errors/validation.ts","../src/crud/find.ts","../src/errors/not-found.ts","../src/indexes/warn.ts","../src/query/cursor.ts","../src/crud/paginate.ts","../src/populate/builder.ts","../src/populate/execute.ts","../src/populate/cursor.ts","../src/query/projection.ts","../src/crud/insert.ts","../src/crud/update.ts","../src/populate/query.ts","../src/client/handle.ts","../src/collection/collection.ts","../src/schema/extensions.ts","../src/schema/object-id.ts","../src/collection/index-def.ts","../src/helpers/oid.ts","../src/query/operators.ts","../src/query/namespace.ts"],"sourcesContent":["export type {\n\tAccumulator,\n\tAccumulatorBuilder,\n\tArrayElement,\n\tCollectionName,\n\tExpression,\n\tExpressionBuilder,\n\tFieldOrExpr,\n\tFieldRef,\n\tFieldRefType,\n\tGroupByCompoundResult,\n\tGroupByNullResult,\n\tGroupByResult,\n\tInferAccumulator,\n\tInferAccumulators,\n\tInferAddedFields,\n\tInferExpression,\n\tNarrowFromFilter,\n\tReplaceDots,\n\tUnwindResult,\n} from './aggregate'\nexport {\n\t$addToSet,\n\t$avg,\n\t$count,\n\t$first,\n\t$last,\n\t$max,\n\t$min,\n\t$push,\n\t$sum,\n\tAggregatePipeline,\n\taggregate,\n\tcreateAccumulatorBuilder,\n\tcreateExpressionBuilder,\n} from './aggregate'\nexport { CollectionHandle, createClient, Database, extractDbName } from './client'\nexport type {\n\tAnyCollection,\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tIndexNames,\n\tInferDocument,\n\tInferInsert,\n\tResolvedShape,\n\tValidationMode,\n} from './collection'\nexport { collection, extractFieldIndexes, IndexBuilder, index } from './collection'\nexport type {\n\tCursorPage,\n\tCursorPaginateOptions,\n\tFindOneAndDeleteOptions,\n\tFindOneAndUpdateOptions,\n\tFindOneOptions,\n\tFindOneProjectionOptions,\n\tFindOptions,\n\tFindProjectionOptions,\n\tOffsetPage,\n\tOffsetPaginateOptions,\n\tUpdateOptions,\n} from './crud'\nexport {\n\tdeleteMany,\n\tdeleteOne,\n\tfind,\n\tfindOne,\n\tfindOneAndDelete,\n\tfindOneAndUpdate,\n\tfindOneOrThrow,\n\tinsertMany,\n\tinsertOne,\n\tupdateMany,\n\tupdateOne,\n} from './crud'\nexport {\n\twrapMongoError,\n\tZodmonAuthError,\n\tZodmonBulkWriteError,\n\tZodmonDocValidationError,\n\tZodmonDuplicateKeyError,\n\tZodmonError,\n\tZodmonIndexError,\n\tZodmonNetworkError,\n\tZodmonNotFoundError,\n\tZodmonQueryError,\n\tZodmonTimeoutError,\n\tZodmonValidationError,\n\tZodmonWriteConflictError,\n} from './errors'\nexport { isOid, oid } from './helpers/oid'\nexport type { DotPath, DotPathValue, Prettify } from './helpers/types'\nexport type { IndexSpec, StaleIndex, SyncIndexesOptions, SyncIndexesResult } from './indexes'\nexport {\n\tcheckUnindexedFields,\n\textractComparableOptions,\n\tgenerateIndexName,\n\tserializeIndexKey,\n\tsyncIndexes,\n\ttoCompoundIndexSpec,\n\ttoFieldIndexSpec,\n} from './indexes'\nexport type {\n\tApplyPopulate,\n\tApplyPopulateProjected,\n\tDeepPopulate,\n\tNestedRefPath,\n\tPopulated,\n\tPopulateField,\n\tPopulateFieldProjected,\n\tPopulateProjectionConfig,\n\tPopulateStep,\n} from './populate'\nexport {\n\tcreatePopulateCursor,\n\texecutePopulate,\n\tPopulateCursor,\n\tPopulateOneOrThrowQuery,\n\tPopulateOneQuery,\n\tPopulateRefBuilder,\n\tresolvePopulateStep,\n\tunwrapRefSchema,\n} from './populate'\nexport type {\n\tAddToSetEach,\n\tAddToSetFields,\n\tComparisonOperators,\n\tCurrentDateFields,\n\tDotSubPaths,\n\tExclusionProjection,\n\tIncFields,\n\tInclusionProjection,\n\tPopFields,\n\tProjectionResult,\n\tPullFields,\n\tPushFields,\n\tPushModifiers,\n\tRenameFields,\n\tSetFields,\n\tTypedFilter,\n\tTypedProjection,\n\tTypedSort,\n\tTypedUpdateFilter,\n\tUnsetFields,\n} from './query'\nexport {\n\t$,\n\t$and,\n\t$eq,\n\t$exists,\n\t$gt,\n\t$gte,\n\t$in,\n\t$lt,\n\t$lte,\n\t$ne,\n\t$nin,\n\t$nor,\n\t$not,\n\t$or,\n\t$regex,\n\tderiveProjectedSchema,\n\tisInclusionProjection,\n\traw,\n\tTypedFindCursor,\n} from './query'\nexport {\n\ttype ExtractRefCollection,\n\tgetIndexMetadata,\n\tgetRefMetadata,\n\ttype IndexMetadata,\n\ttype IndexOptions,\n\tobjectId,\n\ttype RefFields,\n\ttype RefMarker,\n\ttype RefMetadata,\n\ttype UnwrapRef,\n\ttype ZodObjectId,\n} from './schema'\nexport type { TransactionFn } from './transaction'\nexport { TransactionContext } from './transaction'\nexport type { FilterOf, HandleOf, SortOf, UpdateFilterOf } from './types'\n","import type {\n\tAccumulator,\n\tAccumulatorBuilder,\n\tExpression,\n\tExpressionBuilder,\n\tFieldRef,\n\tFieldRefType,\n} from './types'\n\n/**\n * Counts the number of documents in each group.\n *\n * Equivalent to `{ $sum: 1 }` in a MongoDB `$group` stage.\n *\n * @returns An `Accumulator<number>` that counts documents.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('status', { count: $count() })\n * ```\n */\nexport const $count = (): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $sum: 1 },\n})\n\n/**\n * Sums numeric values across documents in each group.\n *\n * Accepts either a `$`-prefixed field reference or a literal number.\n *\n * @param field - A `$field` reference to a numeric field, or a literal number.\n * @returns An `Accumulator<number>`.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('status', {\n * \t\ttotal: $sum('$amount'),\n * \t\tfixed: $sum(1),\n * \t})\n * ```\n */\nexport const $sum = (field: `$${string}` | number): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $sum: field },\n})\n\n/**\n * Computes the average of numeric values across documents in each group.\n *\n * @param field - A `$field` reference to a numeric field.\n * @returns An `Accumulator<number>`.\n *\n * @example\n * ```ts\n * const pipeline = orders.aggregate()\n * \t.groupBy('category', { avgPrice: $avg('$price') })\n * ```\n */\nexport const $avg = (field: `$${string}`): Accumulator<number> => ({\n\t__accum: true,\n\texpr: { $avg: field },\n})\n\n/**\n * Returns the minimum value across documents in each group.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$min<Doc>('$address.city')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$min<number>('$price')` — manual result type.\n * - **Tier 3 (untyped):** `$min('$price')` — defaults to `unknown`.\n *\n * For best type safety, prefer the callback builder (`acc.min('price')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $min<Doc>('$address.city') // Accumulator<string>\n *\n * // Tier 2 — explicit result type\n * $min<number>('$price') // Accumulator<number>\n *\n * // Tier 3 — untyped\n * $min('$price') // Accumulator<unknown>\n * ```\n */\nexport function $min<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>>\nexport function $min<R = unknown>(field: `$${string}`): Accumulator<R>\nexport function $min(field: string): Accumulator<unknown> {\n\treturn { __accum: true, expr: { $min: field } }\n}\n\n/**\n * Returns the maximum value across documents in each group.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$max<Doc>('$address.city')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$max<number>('$price')` — manual result type.\n * - **Tier 3 (untyped):** `$max('$price')` — defaults to `unknown`.\n *\n * For best type safety, prefer the callback builder (`acc.max('price')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $max<Doc>('$tags.label') // Accumulator<string>\n *\n * // Tier 2 — explicit result type\n * $max<number>('$price') // Accumulator<number>\n *\n * // Tier 3 — untyped\n * $max('$price') // Accumulator<unknown>\n * ```\n */\nexport function $max<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>>\nexport function $max<R = unknown>(field: `$${string}`): Accumulator<R>\nexport function $max(field: string): Accumulator<unknown> {\n\treturn { __accum: true, expr: { $max: field } }\n}\n\n/**\n * Returns the first value in each group according to the document order.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$first<Doc>('$address.city')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$first<Date>('$createdAt')` — manual result type.\n * - **Tier 3 (untyped):** `$first('$name')` — defaults to `unknown`.\n *\n * For best type safety, prefer the callback builder (`acc.first('name')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $first<Doc>('$address.city') // Accumulator<string>\n *\n * // Tier 2 — explicit result type\n * $first<Date>('$createdAt') // Accumulator<Date>\n *\n * // Tier 3 — untyped\n * $first('$name') // Accumulator<unknown>\n * ```\n */\nexport function $first<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>>\nexport function $first<R = unknown>(field: `$${string}`): Accumulator<R>\nexport function $first(field: string): Accumulator<unknown> {\n\treturn { __accum: true, expr: { $first: field } }\n}\n\n/**\n * Returns the last value in each group according to the document order.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$last<Doc>('$address.city')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$last<Date>('$createdAt')` — manual result type.\n * - **Tier 3 (untyped):** `$last('$name')` — defaults to `unknown`.\n *\n * For best type safety, prefer the callback builder (`acc.last('name')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $last<Doc>('$address.city') // Accumulator<string>\n *\n * // Tier 2 — explicit result type\n * $last<Date>('$createdAt') // Accumulator<Date>\n *\n * // Tier 3 — untyped\n * $last('$name') // Accumulator<unknown>\n * ```\n */\nexport function $last<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>>\nexport function $last<R = unknown>(field: `$${string}`): Accumulator<R>\nexport function $last(field: string): Accumulator<unknown> {\n\treturn { __accum: true, expr: { $last: field } }\n}\n\n/**\n * Pushes values into an array for each group.\n *\n * May contain duplicates. Use `$addToSet` for unique values.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$push<Doc>('$address.city')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$push<string>('$name')` — manual element type.\n * - **Tier 3 (untyped):** `$push('$name')` — defaults to `unknown[]`.\n *\n * For best type safety, prefer the callback builder (`acc.push('name')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved array result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $push<Doc>('$address.city') // Accumulator<string[]>\n *\n * // Tier 2 — explicit element type\n * $push<string>('$name') // Accumulator<string[]>\n *\n * // Tier 3 — untyped\n * $push('$name') // Accumulator<unknown[]>\n * ```\n */\nexport function $push<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>[]>\nexport function $push<R = unknown>(field: `$${string}`): Accumulator<R[]>\nexport function $push(field: string): Accumulator<unknown[]> {\n\treturn { __accum: true, expr: { $push: field } }\n}\n\n/**\n * Collects unique values into an array for each group (set semantics).\n *\n * Like `$push` but deduplicates.\n *\n * Three tiers of type safety:\n * - **Tier 1 (document type):** `$addToSet<Doc>('$address.zip')` — resolves via `FieldRefType`.\n * - **Tier 2 (explicit scalar):** `$addToSet<string>('$tag')` — manual element type.\n * - **Tier 3 (untyped):** `$addToSet('$tag')` — defaults to `unknown[]`.\n *\n * For best type safety, prefer the callback builder (`acc.addToSet('tag')`).\n *\n * @param field - A `$field` reference (supports dot-paths with document type param).\n * @returns An `Accumulator` with the resolved array result type.\n *\n * @example\n * ```ts\n * // Tier 1 — document type with dot-path\n * $addToSet<Doc>('$address.zip') // Accumulator<string[]>\n *\n * // Tier 2 — explicit element type\n * $addToSet<string>('$tag') // Accumulator<string[]>\n *\n * // Tier 3 — untyped\n * $addToSet('$tag') // Accumulator<unknown[]>\n * ```\n */\nexport function $addToSet<T extends Record<string, unknown>>(\n\tfield: FieldRef<T>,\n): Accumulator<FieldRefType<T, FieldRef<T>>[]>\nexport function $addToSet<R = unknown>(field: `$${string}`): Accumulator<R[]>\nexport function $addToSet(field: string): Accumulator<unknown[]> {\n\treturn { __accum: true, expr: { $addToSet: field } }\n}\n\n/**\n * Create a typed accumulator builder for use inside `groupBy` callbacks.\n *\n * The builder adds the `$` prefix to field names automatically and returns\n * properly typed `Accumulator<T[K]>` values. Primarily used internally by\n * `AggregatePipeline.groupBy` — most users interact with the builder via\n * the callback parameter rather than calling this directly.\n *\n * @typeParam T - The current pipeline output document type.\n * @returns An `AccumulatorBuilder<T>` with methods for each MongoDB accumulator.\n *\n * @example\n * ```ts\n * const acc = createAccumulatorBuilder<{ salary: number; name: string }>()\n * acc.min('salary') // { __accum: true, expr: { $min: '$salary' } }\n * acc.push('name') // { __accum: true, expr: { $push: '$name' } }\n * ```\n */\nexport function createAccumulatorBuilder<T>(): AccumulatorBuilder<T> {\n\treturn {\n\t\tcount: () => ({ __accum: true, expr: { $sum: 1 } }),\n\t\tsum: (field: string | number) => ({\n\t\t\t__accum: true,\n\t\t\texpr: { $sum: typeof field === 'number' ? field : `$${field}` },\n\t\t}),\n\t\tavg: (field: string) => ({ __accum: true, expr: { $avg: `$${field}` } }),\n\t\tmin: (field: string) => ({ __accum: true, expr: { $min: `$${field}` } }),\n\t\tmax: (field: string) => ({ __accum: true, expr: { $max: `$${field}` } }),\n\t\tfirst: (field: string) => ({ __accum: true, expr: { $first: `$${field}` } }),\n\t\tlast: (field: string) => ({ __accum: true, expr: { $last: `$${field}` } }),\n\t\tpush: (field: string) => ({ __accum: true, expr: { $push: `$${field}` } }),\n\t\taddToSet: (field: string) => ({ __accum: true, expr: { $addToSet: `$${field}` } }),\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Runtime implementation uses string field names and returns plain objects — TypeScript cannot verify that the runtime Accumulator objects match the generic AccumulatorBuilder<T> return types. Safe because type resolution happens at compile time via AccumulatorBuilder<T>, and runtime values are identical to what the standalone $min/$max/etc. produce.\n\t} as any\n}\n\n/**\n * Type guard for `Expression` objects.\n *\n * Checks the `__expr` brand so callers can safely extract `.value` without\n * an `as` cast. Used internally by `createExpressionBuilder`.\n *\n * @internal\n */\nconst isExpr = (v: unknown): v is Expression<unknown> =>\n\ttypeof v === 'object' && v !== null && (v as Expression<unknown>).__expr === true\n\n/**\n * Create a typed expression builder for use inside `addFields` callbacks.\n *\n * The builder accepts either a field name string (auto-prefixed with `$`) or a\n * pre-built `Expression<R>` from another builder method, enabling composition.\n * Primarily used internally by `AggregatePipeline.addFields` — most users\n * interact with the builder via the callback parameter rather than calling\n * this directly.\n *\n * @typeParam T - The current pipeline output document type.\n * @returns An `ExpressionBuilder<T>` with methods for each MongoDB expression operator.\n *\n * @example\n * ```ts\n * const expr = createExpressionBuilder<{ salary: number; hiredAt: Date }>()\n * expr.year('hiredAt') // { __expr: true, value: { $year: '$hiredAt' } }\n * expr.round(expr.multiply('salary', 0.1), 2) // { __expr: true, value: { $round: [{ $multiply: ['$salary', 0.1] }, 2] } }\n * ```\n */\nexport function createExpressionBuilder<T>(): ExpressionBuilder<T> {\n\t// Resolve a field-or-expression arg to a MongoDB expression operand.\n\t// Strings become $-prefixed field refs; numbers pass through; Expressions use .value.\n\t// Accepts unknown so call sites in the as-any return block need no casts.\n\tconst resolveArg = (arg: unknown): unknown => {\n\t\tif (typeof arg === 'number') return arg\n\t\tif (isExpr(arg)) return arg.value\n\t\treturn `$${arg}`\n\t}\n\n\t// Resolve a then/else value for cond: extract .value if it's an Expression,\n\t// otherwise pass the literal (number, string, null, etc.) through unchanged.\n\tconst resolveExprVal = (v: unknown): unknown => (isExpr(v) ? v.value : v)\n\n\tconst expr = <R>(value: unknown): Expression<R> => ({ __expr: true, value }) as Expression<R>\n\n\treturn {\n\t\t// Arithmetic\n\t\tadd: (a: unknown, b: unknown) => expr({ $add: [resolveArg(a), resolveArg(b)] }),\n\t\tsubtract: (a: unknown, b: unknown) => expr({ $subtract: [resolveArg(a), resolveArg(b)] }),\n\t\tmultiply: (a: unknown, b: unknown) => expr({ $multiply: [resolveArg(a), resolveArg(b)] }),\n\t\tdivide: (a: unknown, b: unknown) => expr({ $divide: [resolveArg(a), resolveArg(b)] }),\n\t\tmod: (a: unknown, b: unknown) => expr({ $mod: [resolveArg(a), resolveArg(b)] }),\n\t\tabs: (field: unknown) => expr({ $abs: resolveArg(field) }),\n\t\tceil: (field: unknown) => expr({ $ceil: resolveArg(field) }),\n\t\tfloor: (field: unknown) => expr({ $floor: resolveArg(field) }),\n\t\tround: (field: unknown, place = 0) => expr({ $round: [resolveArg(field), place] }),\n\n\t\t// String\n\t\tconcat: (...parts: unknown[]) => {\n\t\t\tconst resolved = parts.map((p) => {\n\t\t\t\t// Expression<string> — embed .value directly\n\t\t\t\tif (isExpr(p)) return p.value\n\t\t\t\t// Single-word string (may include dots for nested paths) → field ref\n\t\t\t\tif (/^[a-zA-Z_][a-zA-Z0-9_.]*$/.test(p as string)) return `$${p}`\n\t\t\t\t// Literal string (contains spaces, punctuation, etc.)\n\t\t\t\treturn p\n\t\t\t})\n\t\t\treturn expr({ $concat: resolved })\n\t\t},\n\t\ttoLower: (field: unknown) => expr({ $toLower: resolveArg(field) }),\n\t\ttoUpper: (field: unknown) => expr({ $toUpper: resolveArg(field) }),\n\t\ttrim: (field: unknown) => expr({ $trim: { input: resolveArg(field) } }),\n\t\tsubstr: (field: unknown, start: number, length: number) =>\n\t\t\texpr({ $substrBytes: [resolveArg(field), start, length] }),\n\n\t\t// Comparison — single runtime implementation handles both overloads:\n\t\t// field path → resolveArg('name') → '$name'\n\t\t// expression → resolveArg(expr.sub(...)) → { $subtract: [...] }\n\t\teq: (field: unknown, value: unknown) =>\n\t\t\texpr({ $eq: [resolveArg(field), resolveExprVal(value)] }),\n\t\tgt: (field: unknown, value: unknown) =>\n\t\t\texpr({ $gt: [resolveArg(field), resolveExprVal(value)] }),\n\t\tgte: (field: unknown, value: unknown) =>\n\t\t\texpr({ $gte: [resolveArg(field), resolveExprVal(value)] }),\n\t\tlt: (field: unknown, value: unknown) =>\n\t\t\texpr({ $lt: [resolveArg(field), resolveExprVal(value)] }),\n\t\tlte: (field: unknown, value: unknown) =>\n\t\t\texpr({ $lte: [resolveArg(field), resolveExprVal(value)] }),\n\t\tne: (field: unknown, value: unknown) =>\n\t\t\texpr({ $ne: [resolveArg(field), resolveExprVal(value)] }),\n\n\t\t// Date\n\t\tyear: (field: unknown) => expr({ $year: resolveArg(field) }),\n\t\tmonth: (field: unknown) => expr({ $month: resolveArg(field) }),\n\t\tdayOfMonth: (field: unknown) => expr({ $dayOfMonth: resolveArg(field) }),\n\n\t\t// Array\n\t\tsize: (field: unknown) => expr({ $size: resolveArg(field) }),\n\n\t\t// Conditional\n\t\tcond: (condition: Expression<boolean>, thenValue: unknown, elseValue: unknown) =>\n\t\t\texpr({\n\t\t\t\t$cond: [condition.value, resolveExprVal(thenValue), resolveExprVal(elseValue)],\n\t\t\t}),\n\t\tifNull: (field: unknown, fallback: unknown) => expr({ $ifNull: [resolveArg(field), fallback] }),\n\n\t\t// Date (extended)\n\t\tdayOfWeek: (field: unknown) => expr({ $dayOfWeek: resolveArg(field) }),\n\t\tdateToString: (field: unknown, format: string) =>\n\t\t\texpr({ $dateToString: { format, date: resolveArg(field) } }),\n\t\t// $$NOW is a MongoDB system variable string — not a Document, but valid anywhere\n\t\t// an aggregation expression is expected. Cast is safe; the MongoDB driver accepts it.\n\t\tnow: () => ({ __expr: true, value: '$$NOW' }) as unknown as Expression<Date>,\n\n\t\t// String conversion\n\t\ttoString: (field: unknown) => expr({ $toString: resolveArg(field) }),\n\n\t\t// Array (extended)\n\t\tinArray: (value: unknown, array: unknown) =>\n\t\t\texpr({ $in: [resolveArg(value), Array.isArray(array) ? array : resolveArg(array)] }),\n\t\tarrayElemAt: (field: unknown, index: number) =>\n\t\t\texpr({ $arrayElemAt: [resolveArg(field), index] }),\n\n\t\t// Conditional (extended)\n\t\tswitch: (\n\t\t\tbranches: ReadonlyArray<{ case: Expression<unknown>; then: unknown }>,\n\t\t\tfallback: unknown,\n\t\t) =>\n\t\t\texpr({\n\t\t\t\t$switch: {\n\t\t\t\t\tbranches: branches.map((b) => ({\n\t\t\t\t\t\tcase: b.case.value,\n\t\t\t\t\t\t// biome-ignore lint/suspicious/noThenProperty: MongoDB $switch branch object requires a `then` key\n\t\t\t\t\t\tthen: resolveExprVal(b.then),\n\t\t\t\t\t})),\n\t\t\t\t\tdefault: resolveExprVal(fallback),\n\t\t\t\t},\n\t\t\t}),\n\t\t// Field reference\n\t\tfield: (name: unknown) =>\n\t\t\t({ __expr: true, value: `$${name}` }) as unknown as Expression<unknown>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Runtime implementation uses resolveArg/resolveExprVal — TypeScript cannot verify generic ExpressionBuilder<T> return types match. Safe because type resolution happens at compile time via ExpressionBuilder<T>.\n\t} as any\n}\n","import { MongoBulkWriteError, MongoNetworkError, MongoServerError } from 'mongodb'\nimport { ZodmonAuthError } from './auth'\nimport { ZodmonError } from './base'\nimport { ZodmonBulkWriteError } from './bulk-write'\nimport { ZodmonDocValidationError } from './doc-validation'\nimport { ZodmonDuplicateKeyError } from './duplicate-key'\nimport { ZodmonIndexError } from './index-error'\nimport { ZodmonNetworkError } from './network'\nimport { ZodmonQueryError } from './query'\nimport { ZodmonTimeoutError } from './timeout'\nimport { ZodmonWriteConflictError } from './write-conflict'\n\n/**\n * Maps a caught MongoDB error to the appropriate Zodmon error subclass and throws it.\n *\n * This function always throws — it never returns. Use it in `catch` blocks to convert\n * raw MongoDB driver errors into structured, typed Zodmon errors. If the error is already\n * a `ZodmonError`, it is rethrown as-is to prevent double-wrapping.\n *\n * @example\n * ```ts\n * try {\n * await db.collection('users').insertOne(doc)\n * } catch (err) {\n * wrapMongoError(err, 'users')\n * }\n * ```\n */\nexport function wrapMongoError(err: unknown, collection: string): never {\n\t// 1. Already a ZodmonError — rethrow as-is (no double-wrap)\n\tif (err instanceof ZodmonError) {\n\t\tthrow err\n\t}\n\n\t// 2. MongoBulkWriteError (extends MongoServerError, so check first)\n\tif (err instanceof MongoBulkWriteError) {\n\t\tthrow new ZodmonBulkWriteError(collection, err)\n\t}\n\n\t// 3. MongoNetworkError\n\tif (err instanceof MongoNetworkError) {\n\t\tthrow new ZodmonNetworkError(collection, err)\n\t}\n\n\t// 4. MongoServerError — switch on error code\n\tif (err instanceof MongoServerError) {\n\t\tswitch (err.code) {\n\t\t\tcase 11000:\n\t\t\tcase 11001:\n\t\t\t\tthrow new ZodmonDuplicateKeyError(collection, err)\n\t\t\tcase 112:\n\t\t\t\tthrow new ZodmonWriteConflictError(collection, err)\n\t\t\tcase 50:\n\t\t\tcase 262:\n\t\t\t\tthrow new ZodmonTimeoutError(collection, err.code, err)\n\t\t\tcase 13:\n\t\t\tcase 18:\n\t\t\t\tthrow new ZodmonAuthError(collection, err.code, err)\n\t\t\tcase 67:\n\t\t\tcase 85:\n\t\t\tcase 86:\n\t\t\t\tthrow new ZodmonIndexError(collection, err.code, err.message, err)\n\t\t\tcase 2:\n\t\t\tcase 9:\n\t\t\tcase 292:\n\t\t\t\tthrow new ZodmonQueryError(collection, err.code, err.message, err)\n\t\t\tcase 121:\n\t\t\t\tthrow new ZodmonDocValidationError(\n\t\t\t\t\tcollection,\n\t\t\t\t\t(err as MongoServerError & { errInfo?: unknown }).errInfo,\n\t\t\t\t\terr,\n\t\t\t\t)\n\t\t\tdefault:\n\t\t\t\tthrow new ZodmonError(`MongoDB error on \"${collection}\": ${err.message}`, collection, {\n\t\t\t\t\tcause: err,\n\t\t\t\t})\n\t\t}\n\t}\n\n\t// 5. Any other Error\n\tif (err instanceof Error) {\n\t\tthrow new ZodmonError(`Unexpected error on \"${collection}\": ${err.message}`, collection, {\n\t\t\tcause: err,\n\t\t})\n\t}\n\n\t// 6. Non-Error value\n\tthrow new ZodmonError(`Unexpected error on \"${collection}\": ${String(err)}`, collection)\n}\n","/**\n * Base error class for all Zodmon errors.\n *\n * Every error thrown by Zodmon extends this class, making it easy to catch all\n * Zodmon-related errors in a single `catch` block while still allowing more\n * specific handling via subclass checks.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 123 })\n * } catch (err) {\n * if (err instanceof ZodmonError) {\n * console.log(err.name) // => 'ZodmonError' (or a subclass name)\n * console.log(err.collection) // => 'users'\n * console.log(err.cause) // => original Error, if provided\n * }\n * }\n * ```\n */\nexport class ZodmonError extends Error {\n\toverride readonly name: string = 'ZodmonError'\n\n\t/** The MongoDB collection name associated with this error. */\n\treadonly collection: string\n\n\t/** The underlying error that caused this error, if any. */\n\toverride readonly cause?: Error\n\n\tconstructor(message: string, collection: string, options?: { cause?: Error }) {\n\t\tsuper(message, options?.cause !== undefined ? { cause: options.cause } : undefined)\n\t\tthis.collection = collection\n\t\tif (options?.cause !== undefined) {\n\t\t\tthis.cause = options.cause\n\t\t}\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when MongoDB rejects an operation due to authentication or authorization failure.\n *\n * Corresponds to MongoDB error codes 13 (Unauthorized) and 18 (AuthenticationFailed).\n * Inspect `.code` to distinguish between authorization and authentication failures.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 'Alice' })\n * } catch (err) {\n * if (err instanceof ZodmonAuthError) {\n * console.log(err.message) // => 'Not authorized to perform this operation on \"users\"'\n * console.log(err.code) // => 13 or 18\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonAuthError extends ZodmonError {\n\toverride readonly name = 'ZodmonAuthError'\n\n\t/** The MongoDB error code (13 or 18). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, cause: Error) {\n\t\tconst message =\n\t\t\tcode === 18\n\t\t\t\t? `Authentication failed for \"${collection}\": check connection credentials`\n\t\t\t\t: `Not authorized to perform this operation on \"${collection}\"`\n\t\tsuper(message, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a bulk write operation partially or fully fails.\n *\n * Exposes partial result counts (`.insertedCount`, `.matchedCount`, etc.) alongside\n * an array of `.writeErrors` describing each individual failure. Use this to determine\n * which operations succeeded and which failed.\n *\n * @example\n * ```ts\n * try {\n * await users.insertMany([{ name: 'Alice' }, { name: 'Alice' }]) // duplicate\n * } catch (err) {\n * if (err instanceof ZodmonBulkWriteError) {\n * console.log(err.insertedCount) // => 1\n * console.log(err.writeErrors) // => [{ index: 1, code: 11000, message: '...' }]\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonBulkWriteError extends ZodmonError {\n\toverride readonly name = 'ZodmonBulkWriteError'\n\n\t/** Number of documents successfully inserted. */\n\treadonly insertedCount: number\n\n\t/** Number of documents matched by update filters. */\n\treadonly matchedCount: number\n\n\t/** Number of documents actually modified. */\n\treadonly modifiedCount: number\n\n\t/** Number of documents deleted. */\n\treadonly deletedCount: number\n\n\t/** Individual write errors with their operation index, code, and message. */\n\treadonly writeErrors: Array<{ index: number; code: number; message: string }>\n\n\tconstructor(collection: string, cause: Error, totalOps?: number) {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: accessing MongoBulkWriteError properties not on Error type\n\t\tconst bulkErr = cause as any\n\t\tconst result = (bulkErr['result'] ?? {}) as Record<string, unknown>\n\t\tconst rawErrors = (bulkErr['writeErrors'] ?? []) as Array<Record<string, unknown>>\n\n\t\tconst writeErrors = rawErrors.map((e) => ({\n\t\t\tindex: (e['index'] as number) ?? 0,\n\t\t\tcode: (e['code'] as number) ?? 0,\n\t\t\tmessage: ((e['errmsg'] ?? e['message']) as string) ?? 'unknown error',\n\t\t}))\n\n\t\tconst failedMsg =\n\t\t\ttotalOps !== undefined\n\t\t\t\t? `${writeErrors.length} of ${totalOps} operations failed`\n\t\t\t\t: `${writeErrors.length} operations failed`\n\t\tsuper(`Bulk write failed on \"${collection}\": ${failedMsg}`, collection, { cause })\n\n\t\tthis.insertedCount = (result['insertedCount'] as number) ?? 0\n\t\tthis.matchedCount = (result['matchedCount'] as number) ?? 0\n\t\tthis.modifiedCount = (result['modifiedCount'] as number) ?? 0\n\t\tthis.deletedCount = (result['deletedCount'] as number) ?? 0\n\t\tthis.writeErrors = writeErrors\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a document fails server-side JSON Schema validation (MongoDB error code 121).\n *\n * This is distinct from {@link ZodmonValidationError}, which validates against Zod schemas\n * on the client side. This error surfaces when MongoDB's own document validation rejects\n * a write. Inspect `.errInfo` for the server's detailed validation failure information.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 'Alice', age: -1 })\n * } catch (err) {\n * if (err instanceof ZodmonDocValidationError) {\n * console.log(err.message) // => 'Server-side document validation failed for \"users\": ...'\n * console.log(err.errInfo) // => { failingDocumentId: ..., details: ... }\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonDocValidationError extends ZodmonError {\n\toverride readonly name = 'ZodmonDocValidationError'\n\n\t/** Server-provided validation failure details. */\n\treadonly errInfo: unknown\n\n\tconstructor(collection: string, errInfo: unknown, cause: Error) {\n\t\tsuper(\n\t\t\t`Server-side document validation failed for \"${collection}\": ${cause.message}`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\t\tthis.errInfo = errInfo\n\t}\n}\n","import { ZodmonError } from './base'\n\nconst INDEX_REGEX = /index:\\s+(\\S+)/\nconst DUP_KEY_FIELD_REGEX = /dup key:\\s*\\{\\s*(\\w+):/\n\n/**\n * Thrown when a MongoDB insert or update violates a unique index constraint (E11000).\n *\n * Parses the duplicate key information from the MongoDB driver error to expose\n * structured fields: `.field` (first conflicting key), `.value`, `.index` (index name),\n * `.keyPattern`, and `.keyValue`. Falls back to regex parsing for older drivers.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ email: 'alice@example.com' })\n * } catch (err) {\n * if (err instanceof ZodmonDuplicateKeyError) {\n * console.log(err.field) // => 'email'\n * console.log(err.value) // => 'alice@example.com'\n * console.log(err.index) // => 'email_1'\n * console.log(err.keyPattern) // => { email: 1 }\n * console.log(err.keyValue) // => { email: 'alice@example.com' }\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonDuplicateKeyError extends ZodmonError {\n\toverride readonly name = 'ZodmonDuplicateKeyError'\n\n\t/** The first field that caused the duplicate key violation. */\n\treadonly field: string\n\n\t/** The duplicate value, or `undefined` if it could not be extracted. */\n\treadonly value: unknown\n\n\t/** The name of the index that was violated. */\n\treadonly index: string\n\n\t/** The key pattern of the violated index (e.g. `{ email: 1 }`). */\n\treadonly keyPattern: Record<string, number>\n\n\t/** The key values that caused the violation. */\n\treadonly keyValue: Record<string, unknown>\n\n\tconstructor(collection: string, cause: Error) {\n\t\t// Extract from keyPattern/keyValue properties (MongoDB 4.2+)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: accessing MongoServerError properties not on Error type\n\t\tconst serverErr = cause as any\n\t\tconst kp = serverErr['keyPattern'] as Record<string, number> | undefined\n\t\tconst kv = serverErr['keyValue'] as Record<string, unknown> | undefined\n\n\t\tlet field: string\n\t\tlet value: unknown\n\t\tlet keyPattern: Record<string, number>\n\t\tlet keyValue: Record<string, unknown>\n\n\t\tif (kp && kv) {\n\t\t\tconst firstKey = Object.keys(kp)[0] ?? 'unknown'\n\t\t\tfield = firstKey\n\t\t\tvalue = kv[firstKey]\n\t\t\tkeyPattern = kp\n\t\t\tkeyValue = kv\n\t\t} else {\n\t\t\t// Fallback: regex parse from errmsg\n\t\t\tconst fieldMatch = cause.message.match(DUP_KEY_FIELD_REGEX)\n\t\t\tfield = fieldMatch?.[1] ?? 'unknown'\n\t\t\tvalue = undefined\n\t\t\tkeyPattern = field !== 'unknown' ? { [field]: 1 } : {}\n\t\t\tkeyValue = {}\n\t\t}\n\n\t\tconst indexMatch = cause.message.match(INDEX_REGEX)\n\t\tconst index = indexMatch?.[1] ?? 'unknown'\n\n\t\tconst valueStr = typeof value === 'string' ? `\"${value}\"` : String(value)\n\t\tsuper(\n\t\t\t`Duplicate key in \"${collection}\": ${field} = ${valueStr} (index: ${index})`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\n\t\tthis.field = field\n\t\tthis.value = value\n\t\tthis.index = index\n\t\tthis.keyPattern = keyPattern\n\t\tthis.keyValue = keyValue\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB index operation fails.\n *\n * Corresponds to MongoDB error codes 67 (CannotCreateIndex), 85 (IndexOptionsConflict),\n * and 86 (IndexKeySpecsConflict). Inspect `.code` to determine the specific failure reason.\n *\n * @example\n * ```ts\n * try {\n * await syncIndexes(db, [Users])\n * } catch (err) {\n * if (err instanceof ZodmonIndexError) {\n * console.log(err.message) // => 'Index options conflict on \"users\": ...'\n * console.log(err.code) // => 67, 85, or 86\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonIndexError extends ZodmonError {\n\toverride readonly name = 'ZodmonIndexError'\n\n\t/** The MongoDB error code (67, 85, or 86). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, errmsg: string, cause: Error) {\n\t\tconst prefix =\n\t\t\tcode === 67\n\t\t\t\t? 'Cannot create index'\n\t\t\t\t: code === 85\n\t\t\t\t\t? 'Index options conflict'\n\t\t\t\t\t: 'Index key specs conflict'\n\t\tsuper(`${prefix} on \"${collection}\": ${errmsg}`, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB operation fails due to a network error.\n *\n * Wraps `MongoNetworkError` from the MongoDB driver with the collection name\n * and the original error message for easier debugging.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ status: 'active' })\n * } catch (err) {\n * if (err instanceof ZodmonNetworkError) {\n * console.log(err.message) // => 'Network error on \"users\": connection refused'\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonNetworkError extends ZodmonError {\n\toverride readonly name = 'ZodmonNetworkError'\n\n\tconstructor(collection: string, cause: Error) {\n\t\tsuper(`Network error on \"${collection}\": ${cause.message}`, collection, { cause })\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB query is malformed or exceeds resource limits.\n *\n * Corresponds to MongoDB error codes 2 (BadValue), 9 (FailedToParse), and\n * 292 (QueryExceededMemoryLimit). Inspect `.code` to determine the specific failure.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ $invalid: true })\n * } catch (err) {\n * if (err instanceof ZodmonQueryError) {\n * console.log(err.message) // => 'Bad value in query on \"users\": ...'\n * console.log(err.code) // => 2, 9, or 292\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonQueryError extends ZodmonError {\n\toverride readonly name = 'ZodmonQueryError'\n\n\t/** The MongoDB error code (2, 9, or 292). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, errmsg: string, cause: Error) {\n\t\tconst message =\n\t\t\tcode === 292\n\t\t\t\t? `Query exceeded memory limit on \"${collection}\": enable allowDiskUse for large sorts or aggregations`\n\t\t\t\t: code === 9\n\t\t\t\t\t? `Failed to parse query on \"${collection}\": ${errmsg}`\n\t\t\t\t\t: `Bad value in query on \"${collection}\": ${errmsg}`\n\t\tsuper(message, collection, { cause })\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a MongoDB operation exceeds its server time limit.\n *\n * Corresponds to MongoDB error codes 50 (MaxTimeMSExpired) and\n * 262 (ExceededTimeLimit). Inspect `.code` to distinguish between the two.\n *\n * @example\n * ```ts\n * try {\n * await users.find({ status: 'active' })\n * } catch (err) {\n * if (err instanceof ZodmonTimeoutError) {\n * console.log(err.message) // => 'Operation timed out on \"users\": ...'\n * console.log(err.code) // => 50 or 262\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonTimeoutError extends ZodmonError {\n\toverride readonly name = 'ZodmonTimeoutError'\n\n\t/** The MongoDB error code (50 or 262). */\n\treadonly code: number\n\n\tconstructor(collection: string, code: number, cause: Error) {\n\t\tsuper(`Operation timed out on \"${collection}\": exceeded server time limit`, collection, {\n\t\t\tcause,\n\t\t})\n\t\tthis.code = code\n\t}\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a transaction encounters a write conflict (MongoDB error code 112).\n *\n * This occurs when another operation modifies the same document concurrently during\n * a transaction. The recommended recovery strategy is to retry the transaction.\n *\n * @example\n * ```ts\n * try {\n * await db.transaction(async (tx) => {\n * const users = tx.use(Users)\n * await users.updateOne({ _id: id }, { $inc: { balance: -100 } })\n * })\n * } catch (err) {\n * if (err instanceof ZodmonWriteConflictError) {\n * console.log(err.message) // => 'Write conflict in \"users\": ...'\n * console.log(err.collection) // => 'users'\n * }\n * }\n * ```\n */\nexport class ZodmonWriteConflictError extends ZodmonError {\n\toverride readonly name = 'ZodmonWriteConflictError'\n\n\tconstructor(collection: string, cause: Error) {\n\t\tsuper(\n\t\t\t`Write conflict in \"${collection}\": another operation modified this document concurrently — retry the transaction`,\n\t\t\tcollection,\n\t\t\t{ cause },\n\t\t)\n\t}\n}\n","import { z } from 'zod'\nimport type { AnyCollection, InferDocument } from '../collection/types'\n\n/**\n * Type-level marker that carries the target collection type through the\n * type system. Intersected with the schema return type by `.ref()` so\n * that `RefFields<T>` (future) can extract ref relationships.\n *\n * This is a phantom brand — no runtime value has this property.\n */\nexport type RefMarker<TCollection extends AnyCollection = AnyCollection> = {\n\treadonly _ref: TCollection\n}\n\n/**\n * Metadata stored in the WeakMap sidecar for schemas marked with `.ref()`.\n * Holds a reference to the target collection definition object.\n */\nexport type RefMetadata = {\n\treadonly collection: AnyCollection\n}\n\n/**\n * Module augmentation: adds `.ref()` to all `ZodType` schemas.\n *\n * The intersection constraint `this['_zod']['output'] extends InferDocument<TCollection>['_id']`\n * ensures compile-time type safety: the field's output type must match the\n * target collection's `_id` type. Mismatches produce a type error.\n *\n * Supports both default ObjectId `_id` and custom `_id` types (string, nanoid, etc.):\n * - `objectId().ref(Users)` compiles when Users has ObjectId `_id`\n * - `z.string().ref(Orgs)` compiles when Orgs has string `_id`\n * - `z.string().ref(Users)` is a type error (string ≠ ObjectId)\n * - `objectId().ref(Orgs)` is a type error (ObjectId ≠ string)\n */\ndeclare module 'zod' {\n\tinterface ZodType {\n\t\t/**\n\t\t * Declare a typed foreign key reference to another collection.\n\t\t *\n\t\t * Stores the target collection definition in metadata for runtime\n\t\t * populate resolution, and brands the return type with\n\t\t * `RefMarker<TCollection>` so `RefFields<T>` can extract refs\n\t\t * at the type level.\n\t\t *\n\t\t * The field's output type must match the target collection's `_id` type.\n\t\t * Mismatched types produce a compile error.\n\t\t *\n\t\t * Apply `.ref()` before wrapper methods like `.optional()` or `.nullable()`:\n\t\t * `objectId().ref(Users).optional()` — not `objectId().optional().ref(Users)`.\n\t\t *\n\t\t * @param collection - The target collection definition object.\n\t\t * @returns The same schema instance, branded with the ref marker.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const Posts = collection('posts', {\n\t\t * authorId: objectId().ref(Users),\n\t\t * title: z.string(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tref<TCollection extends AnyCollection>(\n\t\t\tcollection: TCollection &\n\t\t\t\t(this['_zod']['output'] extends InferDocument<TCollection>['_id'] ? unknown : never),\n\t\t): this & RefMarker<TCollection>\n\t}\n}\n\n/**\n * WeakMap sidecar that associates a Zod schema instance with its\n * {@link RefMetadata}. Uses WeakMap so ref metadata does not prevent\n * garbage collection of schema instances.\n */\nconst refMetadata = new WeakMap<object, RefMetadata>()\n\n/**\n * Retrieve the ref metadata attached to a Zod schema, if any.\n *\n * Returns `undefined` when the schema was never marked with `.ref()`.\n *\n * @param schema - The Zod schema to inspect. Accepts `unknown` for\n * convenience; non-object values safely return `undefined`.\n * @returns The {@link RefMetadata} for the schema, or `undefined`.\n *\n * @example\n * ```ts\n * const authorId = objectId().ref(Users)\n * const meta = getRefMetadata(authorId)\n * // => { collection: Users }\n * ```\n */\nexport function getRefMetadata(schema: unknown): RefMetadata | undefined {\n\tif (typeof schema !== 'object' || schema === null) return undefined\n\treturn refMetadata.get(schema)\n}\n\n/**\n * Peel Zod wrappers (ZodOptional, ZodNullable, ZodDefault, ZodArray)\n * to reach the inner schema type. Used to detect RefMarker on wrapped\n * fields like `objectId().ref(X).optional()` or `z.array(objectId().ref(X))`.\n *\n * Bounded by wrapper depth (1-3 layers) — no circular risk.\n *\n * @example\n * ```ts\n * // ZodOptional<ZodObjectId & RefMarker<typeof Users>> → ZodObjectId & RefMarker<typeof Users>\n * type Inner = UnwrapRef<typeof schema>\n * ```\n */\nexport type UnwrapRef<T> =\n\tT extends z.ZodOptional<infer U>\n\t\t? UnwrapRef<U>\n\t\t: T extends z.ZodNullable<infer U>\n\t\t\t? UnwrapRef<U>\n\t\t\t: T extends z.ZodDefault<infer U>\n\t\t\t\t? UnwrapRef<U>\n\t\t\t\t: T extends z.ZodArray<infer E>\n\t\t\t\t\t? UnwrapRef<E>\n\t\t\t\t\t: T\n\n/**\n * Extract field names that carry `.ref()` metadata from a collection definition.\n *\n * Unwraps ZodArray, ZodOptional, ZodNullable, ZodDefault to detect refs on\n * inner schemas. Works for bare refs, array refs, and optional refs.\n *\n * @example\n * ```ts\n * type PostRefs = RefFields<typeof Posts>\n * // ^? 'authorId' | 'categoryIds' | 'reviewerId'\n * ```\n */\nexport type RefFields<TDef extends AnyCollection> = {\n\t[K in keyof TDef['shape'] & string]: UnwrapRef<TDef['shape'][K]> extends RefMarker ? K : never\n}[keyof TDef['shape'] & string]\n\n/**\n * Given a collection definition and a ref-bearing field key, extract\n * the target collection type from the `RefMarker<TCollection>` phantom.\n *\n * Unwraps Zod wrappers to reach the inner RefMarker.\n *\n * @example\n * ```ts\n * type Target = ExtractRefCollection<typeof Posts, 'authorId'>\n * // ^? typeof Users\n * ```\n */\nexport type ExtractRefCollection<TDef extends AnyCollection, K extends RefFields<TDef>> =\n\tUnwrapRef<TDef['shape'][K]> extends RefMarker<infer TCol> ? TCol : never\n\n/**\n * Symbol guard to prevent double-registration of the `.ref()` extension.\n * Uses `Symbol.for` so it is shared across realms / duplicate module loads.\n */\nconst REF_GUARD = Symbol.for('zodmon_ref')\n\n/**\n * Install the `.ref()` extension method on `ZodType.prototype`.\n *\n * Idempotent — safe to call multiple times.\n */\nexport function installRefExtension(): void {\n\tconst proto = z.ZodType.prototype\n\tif (REF_GUARD in proto) return\n\n\tObject.defineProperty(proto, 'ref', {\n\t\tvalue(this: typeof proto, collection: AnyCollection): typeof proto {\n\t\t\trefMetadata.set(this, { collection })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, REF_GUARD, {\n\t\tvalue: true,\n\t\tenumerable: false,\n\t\tconfigurable: false,\n\t\twritable: false,\n\t})\n}\n","import type { ClientSession, Collection, Document } from 'mongodb'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument } from '../collection/types'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { DotPath, Prettify } from '../helpers/types'\nimport type { TypedFilter } from '../query/filter'\nimport type { ExtractRefCollection, RefFields } from '../schema/ref'\nimport { getRefMetadata } from '../schema/ref'\nimport { createAccumulatorBuilder, createExpressionBuilder } from './expressions'\nimport type {\n\tAccumulator,\n\tAccumulatorBuilder,\n\tCollectionName,\n\tExpression,\n\tExpressionBuilder,\n\tGroupByCompoundResult,\n\tGroupByNullResult,\n\tGroupByResult,\n\tInferAddedFields,\n\tNarrowFromFilter,\n\tUnwindResult,\n} from './types'\n\n/**\n * Immutable aggregation pipeline builder for type-safe MongoDB aggregations.\n *\n * Each stage method returns a **new** `AggregatePipeline` instance — the\n * original is never mutated. This makes it safe to branch from a shared base\n * pipeline without cross-contamination.\n *\n * Use {@link aggregate} to create a pipeline from a {@link CollectionHandle},\n * or call `raw()` to append arbitrary stages.\n *\n * @typeParam TDef - The collection definition type, used to derive document types.\n * @typeParam TOutput - The current output document type (changes as stages transform the shape).\n *\n * @example\n * ```ts\n * const results = await aggregate(users)\n * .raw({ $match: { role: 'admin' } })\n * .raw({ $sort: { name: 1 } })\n * .toArray()\n * ```\n */\nexport class AggregatePipeline<TDef extends AnyCollection, TOutput> {\n\tprotected readonly definition: TDef\n\tprivate readonly nativeCollection: Collection<InferDocument<TDef>>\n\tprivate readonly stages: Document[]\n\tprivate readonly session: ClientSession | undefined\n\n\tconstructor(\n\t\tdefinition: TDef,\n\t\tnativeCollection: Collection<InferDocument<TDef>>,\n\t\tstages: Document[],\n\t\tsession?: ClientSession,\n\t) {\n\t\tthis.definition = definition\n\t\tthis.nativeCollection = nativeCollection\n\t\tthis.stages = stages\n\t\tthis.session = session\n\t}\n\n\t/**\n\t * Append an arbitrary aggregation stage to the pipeline (escape hatch).\n\t *\n\t * Returns a new pipeline instance with the stage appended — the\n\t * original pipeline is not modified.\n\t *\n\t * Optionally accepts a type parameter `TNew` to change the output\n\t * type when the stage transforms the document shape.\n\t *\n\t * @typeParam TNew - The output type after this stage. Defaults to the current output type.\n\t * @param stage - A raw MongoDB aggregation stage document (e.g. `{ $match: { ... } }`).\n\t * @returns A new pipeline with the stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const admins = aggregate(users)\n\t * .raw({ $match: { role: 'admin' } })\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Change output type with a $project stage\n\t * const names = aggregate(users)\n\t * .raw<{ name: string }>({ $project: { name: 1, _id: 0 } })\n\t * .toArray()\n\t * ```\n\t */\n\traw<TNew = TOutput>(stage: Document): AggregatePipeline<TDef, TNew> {\n\t\treturn new AggregatePipeline<TDef, TNew>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, stage],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/**\n\t * Execute the pipeline and return all results as an array.\n\t *\n\t * @returns A promise resolving to the array of output documents.\n\t *\n\t * @example\n\t * ```ts\n\t * const results = await aggregate(users)\n\t * .raw({ $match: { age: { $gte: 18 } } })\n\t * .toArray()\n\t * ```\n\t */\n\tasync toArray(): Promise<TOutput[]> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(\n\t\t\t\tthis.stages,\n\t\t\t\tthis.session ? { session: this.session } : {},\n\t\t\t)\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB aggregate() returns AggregationCursor<Document>; casting to TOutput[] is safe because the pipeline stages determine the output shape\n\t\t\treturn (await cursor.toArray()) as any as TOutput[]\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t/**\n\t * Stream pipeline results one document at a time via `for await...of`.\n\t *\n\t * @returns An async generator yielding output documents.\n\t *\n\t * @example\n\t * ```ts\n\t * for await (const user of aggregate(users).raw({ $match: { role: 'admin' } })) {\n\t * console.log(user.name)\n\t * }\n\t * ```\n\t */\n\tasync *[Symbol.asyncIterator](): AsyncGenerator<TOutput> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(\n\t\t\t\tthis.stages,\n\t\t\t\tthis.session ? { session: this.session } : {},\n\t\t\t)\n\t\t\tfor await (const doc of cursor) {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB aggregate() yields Document; casting to TOutput is safe because the pipeline stages determine the output shape\n\t\t\t\tyield doc as any as TOutput\n\t\t\t}\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t/**\n\t * Return the query execution plan without running the pipeline.\n\t *\n\t * Useful for debugging and understanding how MongoDB will process\n\t * the pipeline stages.\n\t *\n\t * @returns A promise resolving to the explain output document.\n\t *\n\t * @example\n\t * ```ts\n\t * const plan = await aggregate(users)\n\t * .raw({ $match: { role: 'admin' } })\n\t * .explain()\n\t * console.log(plan)\n\t * ```\n\t */\n\tasync explain(): Promise<Document> {\n\t\ttry {\n\t\t\tconst cursor = this.nativeCollection.aggregate(\n\t\t\t\tthis.stages,\n\t\t\t\tthis.session ? { session: this.session } : {},\n\t\t\t)\n\t\t\treturn await cursor.explain()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.definition.name)\n\t\t}\n\t}\n\n\t// ── Shape-preserving stages ──────────────────────────────────────\n\n\t/**\n\t * Filter documents using a type-safe match expression.\n\t *\n\t * Appends a `$match` stage to the pipeline. The filter is constrained\n\t * to the current output type, so only valid fields and operators are accepted.\n\t *\n\t * Supports two forms of type narrowing:\n\t *\n\t * **Tier 1 — Explicit type parameter:**\n\t * ```ts\n\t * .match<{ role: 'engineer' | 'designer' }>({ role: { $in: ['engineer', 'designer'] } })\n\t * // role narrows to 'engineer' | 'designer'\n\t * ```\n\t *\n\t * **Tier 2 — Automatic inference from filter literals:**\n\t * ```ts\n\t * .match({ role: 'engineer' }) // role narrows to 'engineer'\n\t * .match({ role: { $ne: 'intern' } }) // role narrows to Exclude<Role, 'intern'>\n\t * .match({ role: { $in: ['engineer', 'designer'] as const } }) // needs as const\n\t * ```\n\t *\n\t * When no type parameter is provided and the filter doesn't contain\n\t * inferrable literals, the output type is unchanged (backward compatible).\n\t *\n\t * @typeParam TNarrow - Optional object mapping field names to narrowed types. Must be a subtype of the corresponding fields in TOutput.\n\t * @typeParam F - Inferred from the filter argument. Do not provide explicitly.\n\t * @param filter - A type-safe filter for the current output type.\n\t * @returns A new pipeline with the `$match` stage appended and output type narrowed.\n\t *\n\t * @example\n\t * ```ts\n\t * // Explicit narrowing\n\t * const filtered = await users.aggregate()\n\t * .match<{ role: 'engineer' }>({ role: 'engineer' })\n\t * .toArray()\n\t * // filtered[0].role → 'engineer'\n\t *\n\t * // Automatic narrowing with $in (requires as const)\n\t * const subset = await users.aggregate()\n\t * .match({ role: { $in: ['engineer', 'designer'] as const } })\n\t * .toArray()\n\t * // subset[0].role → 'engineer' | 'designer'\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Field-vs-field comparison via $expr callback\n\t * const overRefunded = await orders.aggregate()\n\t * .match(\n\t * { status: 'completed' },\n\t * (expr) => expr.gt('totalAmount', expr.field('refundedAmount')),\n\t * )\n\t * .toArray()\n\t * ```\n\t */\n\tmatch<\n\t\tTNarrow extends {\n\t\t\t[K in keyof TNarrow]: K extends keyof TOutput ? TOutput[K] : never\n\t\t\t// biome-ignore lint/complexity/noBannedTypes: {} is the correct default for TNarrow — it means \"no explicit narrowing\", which produces Omit<NarrowFromFilter<TOutput, F>, never> & {} ≡ NarrowFromFilter<TOutput, F>\n\t\t} = {},\n\t\tF extends TypedFilter<TOutput> = TypedFilter<TOutput>,\n\t>(\n\t\tfilter: F,\n\t\texprCb?: (expr: ExpressionBuilder<TOutput>) => Expression<boolean>,\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Omit<NarrowFromFilter<TOutput, F>, keyof TNarrow> & TNarrow>\n\t> {\n\t\tconst stage: Record<string, unknown> = { ...filter }\n\t\tif (exprCb) {\n\t\t\tconst built = exprCb(createExpressionBuilder<TOutput>())\n\t\t\tstage['$expr'] = built.value\n\t\t}\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $match: stage }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The narrowed output type is computed from generic params TNarrow and F — TypeScript cannot prove the structural equivalence after $match. Safe because $match only filters documents; it does not change field shapes.\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sort documents by one or more fields.\n\t *\n\t * Appends a `$sort` stage. Keys are constrained to `keyof TOutput & string`\n\t * and values must be `1` (ascending) or `-1` (descending).\n\t *\n\t * @param spec - A sort specification mapping field names to sort direction.\n\t * @returns A new pipeline with the `$sort` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const sorted = await aggregate(users)\n\t * .sort({ age: -1, name: 1 })\n\t * .toArray()\n\t * ```\n\t */\n\tsort(spec: Partial<Record<keyof TOutput & string, 1 | -1>>): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $sort: spec }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/**\n\t * Skip a number of documents in the pipeline.\n\t *\n\t * Appends a `$skip` stage. Commonly used with {@link limit} for pagination.\n\t *\n\t * @param n - The number of documents to skip.\n\t * @returns A new pipeline with the `$skip` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Page 2 (10 items per page)\n\t * const page2 = await aggregate(users)\n\t * .sort({ name: 1 })\n\t * .skip(10)\n\t * .limit(10)\n\t * .toArray()\n\t * ```\n\t */\n\tskip(n: number): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $skip: n }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/**\n\t * Limit the number of documents passing through the pipeline.\n\t *\n\t * Appends a `$limit` stage. Commonly used with {@link skip} for pagination,\n\t * or after {@link sort} to get top/bottom N results.\n\t *\n\t * @param n - The maximum number of documents to pass through.\n\t * @returns A new pipeline with the `$limit` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const top5 = await aggregate(users)\n\t * .sort({ score: -1 })\n\t * .limit(5)\n\t * .toArray()\n\t * ```\n\t */\n\tlimit(n: number): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $limit: n }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t// ── Shape-transforming projection stages ─────────────────────────\n\n\t/**\n\t * Include only specified fields in the output.\n\t *\n\t * Appends a `$project` stage with inclusion (`1`) for each key.\n\t * The `_id` field is always included. The output type narrows to\n\t * `Pick<TOutput, K | '_id'>`.\n\t *\n\t * @param spec - An object mapping field names to `1` for inclusion.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const namesOnly = await aggregate(users)\n\t * .project({ name: 1 })\n\t * .toArray()\n\t * // [{ _id: ..., name: 'Ada' }, ...]\n\t * ```\n\t */\n\tproject<K extends keyof TOutput & string>(\n\t\tspec: Record<K, 1>,\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>\n\t> {\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $project: spec }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Pick<TOutput, K | '_id'> is assignable to the generic parameter after $project reshapes the output — safe because the MongoDB $project stage produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Variadic shorthand for {@link project} — pick fields to include.\n\t *\n\t * Generates a `$project` stage that includes only the listed fields\n\t * (plus `_id`). Equivalent to `.project({ field1: 1, field2: 1 })`.\n\t *\n\t * @param fields - Field names to include in the output.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const namesAndRoles = await aggregate(users)\n\t * .pick('name', 'role')\n\t * .toArray()\n\t * ```\n\t */\n\tpick<K extends keyof TOutput & string>(\n\t\t...fields: K[]\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<Pick<TOutput, K | ('_id' extends keyof TOutput ? '_id' : never)>>\n\t> {\n\t\tconst spec = Object.fromEntries(fields.map((f) => [f, 1]))\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $project: spec }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Pick<TOutput, K | '_id'> is assignable to the generic parameter after $project reshapes the output — safe because the MongoDB $project stage produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Exclude specified fields from the output.\n\t *\n\t * Appends a `$project` stage with exclusion (`0`) for each key.\n\t * All other fields pass through. The output type becomes `Omit<TOutput, K>`.\n\t *\n\t * @param fields - Field names to exclude from the output.\n\t * @returns A new pipeline with the `$project` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const noAge = await aggregate(users)\n\t * .omit('age')\n\t * .toArray()\n\t * ```\n\t */\n\tomit<K extends keyof TOutput & string>(\n\t\t...fields: K[]\n\t): AggregatePipeline<TDef, Prettify<Omit<TOutput, K>>> {\n\t\tconst spec = Object.fromEntries(fields.map((f) => [f, 0]))\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $project: spec }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that Omit<TOutput, K> is assignable after $project exclusion reshapes the output — safe because MongoDB $project exclusion produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t// ── groupBy stage ────────────────────────────────────────────────\n\n\t/**\n\t * Group documents by one or more fields with accumulator expressions.\n\t *\n\t * Accepts accumulators as either a **callback** (recommended) or a plain object.\n\t *\n\t * The callback receives a typed `AccumulatorBuilder` with full autocomplete\n\t * and compile-time field validation. Builder methods resolve return types\n\t * to the actual field type (`T[K]`), not `unknown`.\n\t *\n\t * @param field - A field name, array of field names, or `null` to aggregate all documents into a single group.\n\t * @param accumulators - A callback `(acc) => ({ ... })` or plain accumulator object.\n\t * @returns A new pipeline with the `$group` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Callback style (recommended — full type safety)\n\t * const byRole = await aggregate(users)\n\t * .groupBy('role', acc => ({\n\t * count: acc.count(),\n\t * minSalary: acc.min('salary'), // → number\n\t * firstName: acc.first('name'), // → string\n\t * }))\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Object style (backward compatible)\n\t * const byRole = await aggregate(users)\n\t * .groupBy('role', { count: $count() })\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Compound groupBy\n\t * const byRoleAndDept = await aggregate(users)\n\t * .groupBy(['role', 'dept'], acc => ({ count: acc.count() }))\n\t * .toArray()\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Null groupBy — aggregate all documents into a single summary\n\t * const totals = await aggregate(orders)\n\t * .groupBy(null, acc => ({\n\t * grandTotal: acc.sum('amount'),\n\t * orderCount: acc.count(),\n\t * }))\n\t * .toArray()\n\t * // → [{ _id: null, grandTotal: 2740, orderCount: 7 }]\n\t * ```\n\t */\n\tgroupBy<TAccum extends Record<string, Accumulator>>(\n\t\tfield: null,\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t): AggregatePipeline<TDef, GroupByNullResult<TAccum>>\n\tgroupBy<K extends DotPath<TOutput>, TAccum extends Record<string, Accumulator>>(\n\t\tfield: K,\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t): AggregatePipeline<TDef, GroupByResult<TOutput, K, TAccum>>\n\tgroupBy<K extends DotPath<TOutput>, TAccum extends Record<string, Accumulator>>(\n\t\tfield: K[],\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t): AggregatePipeline<TDef, GroupByCompoundResult<TOutput, K, TAccum>>\n\tgroupBy<K extends DotPath<TOutput>, TAccum extends Record<string, Accumulator>>(\n\t\tfield: null | K | K[],\n\t\taccumulators: ((acc: AccumulatorBuilder<TOutput>) => TAccum) | TAccum,\n\t):\n\t\t| AggregatePipeline<TDef, GroupByNullResult<TAccum>>\n\t\t| AggregatePipeline<TDef, GroupByResult<TOutput, K, TAccum>>\n\t\t| AggregatePipeline<TDef, GroupByCompoundResult<TOutput, K, TAccum>> {\n\t\tconst resolved =\n\t\t\ttypeof accumulators === 'function'\n\t\t\t\t? accumulators(createAccumulatorBuilder<TOutput>())\n\t\t\t\t: accumulators\n\n\t\tlet _id: null | string | Record<string, string>\n\t\tif (field === null) {\n\t\t\t_id = null\n\t\t} else if (Array.isArray(field)) {\n\t\t\tconst entries = field.map((f) => [f.replaceAll('.', '_'), `$${f}`] as const)\n\t\t\tconst keys = entries.map(([k]) => k)\n\t\t\tconst dupes = keys.filter((k, i) => keys.indexOf(k) !== i)\n\t\t\tif (dupes.length > 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Compound groupBy key collision: ${dupes.join(', ')}. ` +\n\t\t\t\t\t\t'Two or more fields produce the same _id key after dot-to-underscore conversion. ' +\n\t\t\t\t\t\t'Use raw() with explicit aliases instead.',\n\t\t\t\t)\n\t\t\t}\n\t\t\t_id = Object.fromEntries(entries)\n\t\t} else {\n\t\t\t_id = `$${field}`\n\t\t}\n\n\t\tconst accumExprs = Object.fromEntries(\n\t\t\tObject.entries(resolved).map(([key, acc]) => [key, acc.expr]),\n\t\t)\n\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $group: { _id, ...accumExprs } }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The output type depends on whether `field` is null, a string, or an array — TypeScript cannot narrow the overloaded return type from the union, so we cast. Safe because $group produces exactly GroupByNullResult, GroupByResult, or GroupByCompoundResult.\n\t\treturn pipeline as any\n\t}\n\n\t// ── addFields stage ──────────────────────────────────────────────\n\n\t/**\n\t * Add new fields or overwrite existing ones in the output documents.\n\t *\n\t * **Callback style (recommended)** — the `ExpressionBuilder` provides\n\t * autocomplete for field names and infers return types automatically:\n\t *\n\t * ```ts\n\t * employees.aggregate()\n\t * .addFields(expr => ({\n\t * hireYear: expr.year('hiredAt'), // Expression<number>\n\t * isHighPay: expr.gte('salary', 100_000), // Expression<boolean>\n\t * }))\n\t * ```\n\t *\n\t * **Raw style** — pass MongoDB expression objects directly. Use an\n\t * explicit type parameter to preserve type safety:\n\t *\n\t * ```ts\n\t * // Tier 2: explicit type parameter\n\t * .addFields<{ hireYear: number }>({ hireYear: { $year: '$hiredAt' } })\n\t *\n\t * // Tier 3: no type parameter — fields resolve to unknown\n\t * .addFields({ hireYear: { $year: '$hiredAt' } })\n\t * ```\n\t *\n\t * @param fields - A callback `(expr) => ({ ... })` or plain fields object.\n\t * @returns A new pipeline with the `$addFields` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const enriched = await aggregate(employees)\n\t * .addFields(expr => ({\n\t * hireYear: expr.year('hiredAt'),\n\t * monthlySalary: expr.divide('salary', 12),\n\t * }))\n\t * .toArray()\n\t * ```\n\t */\n\t// Overload 1: Callback with ExpressionBuilder\n\taddFields<TFields extends Record<string, Expression>>(\n\t\tfields: (expr: ExpressionBuilder<TOutput>) => TFields,\n\t): AggregatePipeline<TDef, Prettify<TOutput & InferAddedFields<TFields>>>\n\t// Overload 2: Raw object (with optional explicit type parameter)\n\taddFields<TFields extends Record<string, unknown> = Record<string, unknown>>(\n\t\tfields: TFields,\n\t): AggregatePipeline<TDef, Prettify<TOutput & TFields>>\n\t// Implementation\n\taddFields(\n\t\tfields:\n\t\t\t| ((expr: ExpressionBuilder<TOutput>) => Record<string, unknown>)\n\t\t\t| Record<string, unknown>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Implementation must be wide enough for both overloads\n\t): AggregatePipeline<TDef, any> {\n\t\tconst resolved =\n\t\t\ttypeof fields === 'function' ? fields(createExpressionBuilder<TOutput>()) : fields\n\n\t\t// Unwrap Expression wrappers — extract .value for the MongoDB stage\n\t\tconst stage = Object.fromEntries(\n\t\t\tObject.entries(resolved).map(([k, v]) => [\n\t\t\t\tk,\n\t\t\t\tv && typeof v === 'object' && '__expr' in v ? (v as Expression).value : v,\n\t\t\t]),\n\t\t)\n\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $addFields: stage }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that TOutput & InferAddedFields<TFields> is assignable after $addFields merges — safe because $addFields preserves existing fields and adds new ones\n\t\treturn pipeline as any\n\t}\n\n\t// ── unwind stage ─────────────────────────────────────────────────\n\n\t/**\n\t * Deconstruct an array field, outputting one document per array element.\n\t *\n\t * Appends an `$unwind` stage. The unwound field's type changes from\n\t * `T[]` to `T` in the output type. Documents with empty or missing\n\t * arrays are dropped unless `preserveEmpty` is `true`.\n\t *\n\t * @param field - The name of the array field to unwind.\n\t * @param options - Optional settings for the unwind stage.\n\t * @param options.preserveEmpty - If `true`, documents with null, missing, or empty arrays are preserved.\n\t * @returns A new pipeline with the `$unwind` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const flat = await aggregate(orders)\n\t * .unwind('items')\n\t * .toArray()\n\t * // Each result has a single `items` value instead of an array\n\t * ```\n\t */\n\tunwind<K extends keyof TOutput & string>(\n\t\tfield: K,\n\t\toptions?: { preserveEmpty?: boolean },\n\t): AggregatePipeline<TDef, UnwindResult<TOutput, K>> {\n\t\tconst stage: Document = options?.preserveEmpty\n\t\t\t? { $unwind: { path: `$${field}`, preserveNullAndEmptyArrays: true } }\n\t\t\t: { $unwind: `$${field}` }\n\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, stage],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove that UnwindResult<TOutput, K> is assignable after $unwind transforms the array field to its element type — safe because $unwind produces exactly this shape\n\t\treturn pipeline as any\n\t}\n\n\t// ── lookup stage ────────────────────────────────────────────────\n\n\t/**\n\t * Join documents from another collection via a `$lookup` stage.\n\t *\n\t * **Forward lookup** — when the field has `.ref()` metadata pointing to\n\t * another collection, resolves the target collection and output type\n\t * automatically:\n\t *\n\t * ```ts\n\t * books.aggregate().lookup('authorId').toArray()\n\t * // Each book gains an `authors: Author[]` array\n\t * ```\n\t *\n\t * **Reverse lookup** — when the foreign key lives on the *other*\n\t * collection, pass the collection definition and the `on` field:\n\t *\n\t * ```ts\n\t * users.aggregate().lookup(Books, { on: 'authorId' }).toArray()\n\t * // Each user gains a `books: Book[]` array\n\t * ```\n\t *\n\t * Pass `unwind: true` to flatten the joined array into a single object\n\t * (adds a `$unwind` stage with `preserveNullAndEmptyArrays: true`).\n\t *\n\t * @param fieldOrCollection - A ref-bearing field name (forward) or collection definition (reverse).\n\t * @param options - `as` alias, `unwind` flag, and `on` (reverse only).\n\t * @returns A new pipeline with `$lookup` (and optionally `$unwind`) appended.\n\t *\n\t * @example\n\t * ```ts\n\t * // Forward lookup with custom alias and unwind\n\t * const results = await aggregate(books)\n\t * .lookup('authorId', { as: 'author', unwind: true })\n\t * .toArray()\n\t * // Each book has a single `author: Author` object\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Reverse lookup: each author gains their books\n\t * const results = await aggregate(authors)\n\t * .lookup(Books, { on: 'authorId' })\n\t * .toArray()\n\t * // Each author has a `books: Book[]` array\n\t * ```\n\t */\n\tlookup<\n\t\tK extends RefFields<TDef>,\n\t\tTAs extends string = CollectionName<ExtractRefCollection<TDef, K>>,\n\t>(\n\t\tfield: K,\n\t\toptions: { as?: TAs; unwind: true },\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<TOutput & { [P in TAs]: InferDocument<ExtractRefCollection<TDef, K>> }>\n\t>\n\tlookup<\n\t\tK extends RefFields<TDef>,\n\t\tTAs extends string = CollectionName<ExtractRefCollection<TDef, K>>,\n\t>(\n\t\tfield: K,\n\t\toptions?: { as?: TAs; unwind?: false },\n\t): AggregatePipeline<\n\t\tTDef,\n\t\tPrettify<TOutput & { [P in TAs]: InferDocument<ExtractRefCollection<TDef, K>>[] }>\n\t>\n\tlookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(\n\t\tfrom: TForeignDef,\n\t\toptions: { on: keyof InferDocument<TForeignDef> & string; as?: TAs; unwind: true },\n\t): AggregatePipeline<TDef, Prettify<TOutput & { [P in TAs]: InferDocument<TForeignDef> }>>\n\tlookup<TForeignDef extends AnyCollection, TAs extends string = CollectionName<TForeignDef>>(\n\t\tfrom: TForeignDef,\n\t\toptions: { on: keyof InferDocument<TForeignDef> & string; as?: TAs; unwind?: false },\n\t): AggregatePipeline<TDef, Prettify<TOutput & { [P in TAs]: InferDocument<TForeignDef>[] }>>\n\tlookup(\n\t\tfieldOrFrom: string | AnyCollection,\n\t\toptions?: { on?: string; as?: string; unwind?: boolean },\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Implementation signature must be wide enough to cover all four overloads — TypeScript cannot unify the generic return types across overloads, so `any` is the standard escape hatch for overloaded method implementations.\n\t): AggregatePipeline<TDef, any> {\n\t\tconst stages = [...this.stages]\n\n\t\tif (typeof fieldOrFrom === 'object') {\n\t\t\t// Reverse lookup: fieldOrFrom is a collection definition\n\t\t\tconst foreignName = fieldOrFrom.name\n\t\t\tconst foreignField = options?.on\n\t\t\tif (!foreignField) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[zodmon] lookup: reverse lookup on '${foreignName}' requires an 'on' option ` +\n\t\t\t\t\t\t'specifying which field on the foreign collection references this collection.',\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst asField = options?.as ?? foreignName\n\t\t\tstages.push({\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: foreignName,\n\t\t\t\t\tlocalField: '_id',\n\t\t\t\t\tforeignField,\n\t\t\t\t\tas: asField,\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (options?.unwind) {\n\t\t\t\tstages.push({ $unwind: { path: `$${asField}`, preserveNullAndEmptyArrays: true } })\n\t\t\t}\n\t\t} else {\n\t\t\t// Forward lookup: field has .ref() metadata\n\t\t\tconst shape = this.definition.shape\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: shape values are z.core.$ZodType but getRefMetadata accepts unknown — the cast is a no-op at runtime\n\t\t\tconst fieldSchema = (shape as any)[fieldOrFrom]\n\t\t\tconst ref = getRefMetadata(fieldSchema)\n\t\t\tif (!ref) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`[zodmon] lookup: field '${fieldOrFrom}' has no .ref() metadata. ` +\n\t\t\t\t\t\t'Use .lookup(CollectionDef, { on: foreignKey }) for reverse lookups, ' +\n\t\t\t\t\t\t'or add .ref(TargetCollection) to the field schema.',\n\t\t\t\t)\n\t\t\t}\n\t\t\tconst targetName = ref.collection.name\n\t\t\tconst asField = options?.as ?? targetName\n\t\t\tstages.push({\n\t\t\t\t$lookup: {\n\t\t\t\t\tfrom: targetName,\n\t\t\t\t\tlocalField: fieldOrFrom,\n\t\t\t\t\tforeignField: '_id',\n\t\t\t\t\tas: asField,\n\t\t\t\t},\n\t\t\t})\n\t\t\tif (options?.unwind) {\n\t\t\t\tstages.push({ $unwind: { path: `$${asField}`, preserveNullAndEmptyArrays: true } })\n\t\t\t}\n\t\t}\n\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\tstages,\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The lookup output type is TOutput intersected with a dynamic record — TypeScript cannot prove the structural equivalence after $lookup reshapes the document. Safe because $lookup preserves all existing fields and adds the joined field.\n\t\treturn pipeline as any\n\t}\n\n\t// ── facet stage ──────────────────────────────────────────────────\n\n\t/**\n\t * Run multiple sub-pipelines on the same input documents in parallel.\n\t *\n\t * Each key in `spec` maps to a callback that receives a fresh `SubPipeline`\n\t * starting from `TOutput`. The callback chains stages and returns the terminal\n\t * pipeline. Zodmon extracts the accumulated stages at runtime to build the\n\t * `$facet` document. The output type is fully inferred — no annotation needed.\n\t *\n\t * Sub-pipelines support all stage methods including `.raw()` for operators not\n\t * yet first-class. Execution methods (`toArray`, `explain`) are not available\n\t * inside branches.\n\t *\n\t * @param spec - An object mapping branch names to sub-pipeline builder callbacks.\n\t * @returns A new pipeline whose output is one document with each branch name mapped to an array of results.\n\t *\n\t * @example\n\t * ```ts\n\t * const [report] = await aggregate(orders)\n\t * .facet({\n\t * byCategory: (sub) => sub\n\t * .groupBy('category', acc => ({ count: acc.count() }))\n\t * .sort({ count: -1 }),\n\t * totals: (sub) => sub\n\t * .groupBy(null, acc => ({ grandTotal: acc.sum('amount') })),\n\t * })\n\t * .toArray()\n\t * // report.byCategory → { _id: 'electronics' | 'books' | 'clothing'; count: number }[]\n\t * // report.totals → { _id: null; grandTotal: number }[]\n\t * ```\n\t */\n\tfacet<\n\t\tTSpec extends Record<\n\t\t\tstring,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: The return side uses `any` to avoid TypeScript contravariance rejection — the concrete inferred return type is captured by `InferFacetOutput<TSpec>` via the extends constraint\n\t\t\t(sub: SubPipeline<TDef, TOutput>) => AggregatePipeline<TDef, any>\n\t\t>,\n\t>(spec: TSpec): AggregatePipeline<TDef, Prettify<InferFacetOutput<TSpec>>> {\n\t\tconst branches: Record<string, Document[]> = {}\n\t\tfor (const [key, cb] of Object.entries(spec)) {\n\t\t\tconst sub = new AggregatePipeline(\n\t\t\t\tthis.definition,\n\t\t\t\tthis.nativeCollection,\n\t\t\t\t[],\n\t\t\t\tthis.session,\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: sub must be cast to `any` so the concrete `AggregatePipeline<TDef, TOutput>` is accepted where `SubPipeline<TDef, TOutput>` (which lacks execution methods) is expected — safe at runtime because the pipeline instance always has the right shape\n\t\t\t) as any\n\t\t\tbranches[key] = cb(sub).getStages()\n\t\t}\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $facet: branches }],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypeScript cannot prove Prettify<InferFacetOutput<TSpec>> is assignable after $facet reshapes the document — safe because $facet produces exactly one document with each branch key mapped to its result array\n\t\treturn pipeline as any\n\t}\n\n\t// ── Convenience shortcuts ────────────────────────────────────────\n\n\t/**\n\t * Count documents per group, sorted by count descending.\n\t *\n\t * Shorthand for `.groupBy(field, { count: $count() }).sort({ count: -1 })`.\n\t *\n\t * @param field - The field to group and count by.\n\t * @returns A new pipeline producing `{ _id: TOutput[K], count: number }` results.\n\t *\n\t * @example\n\t * ```ts\n\t * const roleCounts = await aggregate(users)\n\t * .countBy('role')\n\t * .toArray()\n\t * // [{ _id: 'user', count: 3 }, { _id: 'admin', count: 2 }]\n\t * ```\n\t */\n\tcountBy<K extends keyof TOutput & string>(\n\t\tfield: K,\n\t): AggregatePipeline<TDef, Prettify<{ _id: TOutput[K]; count: number }>> {\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[\n\t\t\t\t...this.stages,\n\t\t\t\t{ $group: { _id: `$${field}`, count: { $sum: 1 } } },\n\t\t\t\t{ $sort: { count: -1 } },\n\t\t\t],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The shortcut composes $group + $sort stages; TypeScript cannot infer the combined output type — safe because the stages produce exactly { _id, count } sorted by count descending\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sum a numeric field per group, sorted by total descending.\n\t *\n\t * Shorthand for `.groupBy(field, { total: $sum('$sumField') }).sort({ total: -1 })`.\n\t *\n\t * @param field - The field to group by.\n\t * @param sumField - The numeric field to sum.\n\t * @returns A new pipeline producing `{ _id: TOutput[K], total: number }` results.\n\t *\n\t * @example\n\t * ```ts\n\t * const revenueByCategory = await aggregate(orders)\n\t * .sumBy('category', 'amount')\n\t * .toArray()\n\t * // [{ _id: 'electronics', total: 5000 }, ...]\n\t * ```\n\t */\n\tsumBy<K extends keyof TOutput & string, S extends keyof TOutput & string>(\n\t\tfield: K,\n\t\tsumField: S,\n\t): AggregatePipeline<TDef, Prettify<{ _id: TOutput[K]; total: number }>> {\n\t\tconst pipeline = new AggregatePipeline(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[\n\t\t\t\t...this.stages,\n\t\t\t\t{ $group: { _id: `$${field}`, total: { $sum: `$${sumField}` } } },\n\t\t\t\t{ $sort: { total: -1 } },\n\t\t\t],\n\t\t\tthis.session,\n\t\t)\n\t\t// biome-ignore lint/suspicious/noExplicitAny: The shortcut composes $group + $sort stages; TypeScript cannot infer the combined output type — safe because the stages produce exactly { _id, total } sorted by total descending\n\t\treturn pipeline as any\n\t}\n\n\t/**\n\t * Sort by a single field with a friendly direction name.\n\t *\n\t * Shorthand for `.sort({ [field]: direction === 'desc' ? -1 : 1 })`.\n\t *\n\t * @param field - The field to sort by.\n\t * @param direction - Sort direction: `'asc'` (default) or `'desc'`.\n\t * @returns A new pipeline with the `$sort` stage appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const youngest = await aggregate(users)\n\t * .sortBy('age')\n\t * .toArray()\n\t * ```\n\t */\n\tsortBy(\n\t\tfield: keyof TOutput & string,\n\t\tdirection: 'asc' | 'desc' = 'asc',\n\t): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $sort: { [field]: direction === 'desc' ? -1 : 1 } }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/**\n\t * Return the top N documents sorted by a field descending.\n\t *\n\t * Shorthand for `.sort({ [by]: -1 }).limit(n)`.\n\t *\n\t * @param n - The number of documents to return.\n\t * @param options - An object with a `by` field specifying the sort key.\n\t * @returns A new pipeline with `$sort` and `$limit` stages appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const top3 = await aggregate(users)\n\t * .top(3, { by: 'score' })\n\t * .toArray()\n\t * ```\n\t */\n\ttop(n: number, options: { by: keyof TOutput & string }): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $sort: { [options.by]: -1 } }, { $limit: n }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/**\n\t * Return the bottom N documents sorted by a field ascending.\n\t *\n\t * Shorthand for `.sort({ [by]: 1 }).limit(n)`.\n\t *\n\t * @param n - The number of documents to return.\n\t * @param options - An object with a `by` field specifying the sort key.\n\t * @returns A new pipeline with `$sort` and `$limit` stages appended.\n\t *\n\t * @example\n\t * ```ts\n\t * const bottom3 = await aggregate(users)\n\t * .bottom(3, { by: 'score' })\n\t * .toArray()\n\t * ```\n\t */\n\tbottom(n: number, options: { by: keyof TOutput & string }): AggregatePipeline<TDef, TOutput> {\n\t\treturn new AggregatePipeline<TDef, TOutput>(\n\t\t\tthis.definition,\n\t\t\tthis.nativeCollection,\n\t\t\t[...this.stages, { $sort: { [options.by]: 1 } }, { $limit: n }],\n\t\t\tthis.session,\n\t\t)\n\t}\n\n\t/** @internal Used by facet() to extract branch stages. Not part of the public API. */\n\tgetStages(): Document[] {\n\t\treturn this.stages\n\t}\n}\n\n/**\n * Create a new aggregation pipeline for a collection.\n *\n * Returns an empty pipeline that can be extended with stage methods\n * like `raw()`, or future typed stages (`match`, `project`, etc.).\n *\n * @param handle - A typed collection handle obtained from `db.use()`.\n * @returns A new empty `AggregatePipeline` whose output type is the collection's document type.\n *\n * @example\n * ```ts\n * const users = db.use(Users)\n * const admins = await aggregate(users)\n * .raw({ $match: { role: 'admin' } })\n * .toArray()\n * ```\n */\nexport function aggregate<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n): AggregatePipeline<TDef, InferDocument<TDef>> {\n\treturn new AggregatePipeline<TDef, InferDocument<TDef>>(\n\t\thandle.definition,\n\t\thandle.native,\n\t\t[],\n\t\thandle.session,\n\t)\n}\n\n/**\n * A sub-pipeline passed to each `.facet()` branch callback.\n *\n * All stage-building methods are available. Execution methods (`toArray`,\n * `explain`, `[Symbol.asyncIterator]`) are omitted — sub-pipelines are\n * not executed directly; they only accumulate stages for the parent `$facet` stage.\n *\n * @typeParam TDef - The collection definition type.\n * @typeParam TOutput - The current output document type.\n *\n * @example\n * ```ts\n * .facet({\n * summary: (sub: SubPipeline<typeof Orders, Order>) => sub.groupBy(null, acc => ({ total: acc.sum('amount') }))\n * })\n * ```\n */\nexport type SubPipeline<TDef extends AnyCollection, TOutput> = Omit<\n\tAggregatePipeline<TDef, TOutput>,\n\t'toArray' | 'explain' | typeof Symbol.asyncIterator\n>\n\n/**\n * Maps a `.facet()` spec object to its inferred output shape.\n *\n * Each key maps to the array of results produced by that branch's terminal pipeline.\n * Uses `any` for the sub-pipeline parameter to avoid TypeScript contravariance\n * complications — inference of `TOut` from the return type is what matters.\n *\n * @example\n * ```ts\n * type Spec = {\n * byCategory: (sub: SubPipeline<any, any>) => AggregatePipeline<any, { _id: string; count: number }>\n * }\n * type Result = InferFacetOutput<Spec>\n * // ^? { byCategory: { _id: string; count: number }[] }\n * ```\n */\nexport type InferFacetOutput<TSpec> = {\n\t// biome-ignore lint/suspicious/noExplicitAny: `any` is required for the sub-pipeline parameter to avoid TypeScript contravariance complications — inference of TOut from the return type is what matters\n\t[K in keyof TSpec]: TSpec[K] extends (sub: any) => AggregatePipeline<any, infer TOut>\n\t\t? TOut[]\n\t\t: never\n}\n","import type { Db, MongoClientOptions } from 'mongodb'\nimport { MongoClient } from 'mongodb'\nimport type { z } from 'zod'\nimport type {\n\tCollectionDefinition,\n\tCompoundIndexDefinition,\n\tInferDocument,\n} from '../collection/types'\nimport { syncIndexes as _syncCollectionIndexes } from '../indexes/sync'\nimport type { SyncIndexesOptions, SyncIndexesResult } from '../indexes/types'\nimport { TransactionContext, type TransactionFn } from '../transaction'\nimport { CollectionHandle } from './handle'\n\n/**\n * Wraps a MongoDB `MongoClient` and `Db`, providing typed collection access\n * through {@link CollectionHandle}s.\n *\n * Connection is lazy — the driver connects on the first operation, not at\n * construction time. Call {@link close} for graceful shutdown.\n *\n * @example\n * ```ts\n * const db = createClient('mongodb://localhost:27017', 'myapp')\n * const users = db.use(UsersCollection)\n * await users.native.insertOne({ _id: oid(), name: 'Ada' })\n * await db.close()\n * ```\n */\nexport class Database {\n\tprivate readonly _client: MongoClient\n\tprivate readonly _db: Db\n\t/** Registered collection definitions, keyed by name. Used by syncIndexes(). */\n\tprivate readonly _collections = new Map<string, CollectionDefinition>()\n\n\tconstructor(uri: string, dbName: string, options?: MongoClientOptions) {\n\t\tthis._client = new MongoClient(uri, options)\n\t\tthis._db = this._client.db(dbName)\n\t}\n\n\t/**\n\t * Register a collection definition and return a typed {@link CollectionHandle}.\n\t *\n\t * The handle's `native` property is a MongoDB `Collection<TDoc>` where `TDoc`\n\t * is the document type inferred from the definition's Zod schema. Calling\n\t * `use()` multiple times with the same definition is safe — each call returns\n\t * a new lightweight handle backed by the same underlying driver collection.\n\t *\n\t * @param def - A collection definition created by `collection()`.\n\t * @returns A typed collection handle for CRUD operations.\n\t */\n\tuse<\n\t\tTName extends string,\n\t\tTShape extends z.core.$ZodShape,\n\t\tTIndexes extends readonly CompoundIndexDefinition<\n\t\t\tExtract<keyof TShape, string>\n\t\t>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[],\n\t>(\n\t\tdef: CollectionDefinition<TName, TShape, TIndexes>,\n\t): CollectionHandle<CollectionDefinition<TName, TShape, TIndexes>> {\n\t\t// Safe cast: erasing generics for internal collection tracking.\n\t\t// Stored definitions are only iterated in syncIndexes() where\n\t\t// index metadata is accessed structurally.\n\t\tthis._collections.set(def.name, def as unknown as CollectionDefinition)\n\t\tconst native = this._db.collection<\n\t\t\tInferDocument<CollectionDefinition<TName, TShape, TIndexes>>\n\t\t>(def.name)\n\t\t// Safe cast: CollectionDefinition<TName, TShape, TIndexes> → AnyCollection for the\n\t\t// constructor. The generic is preserved through the return type annotation.\n\t\treturn new CollectionHandle(\n\t\t\tdef as unknown as CollectionDefinition<TName, TShape, TIndexes>,\n\t\t\tnative,\n\t\t) as CollectionHandle<CollectionDefinition<TName, TShape, TIndexes>>\n\t}\n\n\t/**\n\t * Synchronize indexes for all registered collections with MongoDB.\n\t *\n\t * Iterates every collection registered via {@link use} and calls\n\t * {@link syncIndexes} on each one. Returns a record keyed by collection\n\t * name with the sync result for each.\n\t *\n\t * @param options - Optional sync behavior (dryRun, dropOrphaned).\n\t * @returns A record mapping collection names to their sync results.\n\t *\n\t * @example\n\t * ```ts\n\t * const db = createClient('mongodb://localhost:27017', 'myapp')\n\t * db.use(Users)\n\t * db.use(Posts)\n\t * const results = await db.syncIndexes()\n\t * console.log(results['users'].created) // ['email_1']\n\t * console.log(results['posts'].created) // ['title_1']\n\t * ```\n\t */\n\tasync syncIndexes(options?: SyncIndexesOptions): Promise<Record<string, SyncIndexesResult>> {\n\t\tconst results: Record<string, SyncIndexesResult> = {}\n\t\tfor (const [name, def] of this._collections) {\n\t\t\tconst native = this._db.collection(name)\n\t\t\tconst handle = new CollectionHandle(def, native)\n\t\t\tresults[name] = await _syncCollectionIndexes(handle, options)\n\t\t}\n\t\treturn results\n\t}\n\n\t/**\n\t * Execute a function within a MongoDB transaction.\n\t *\n\t * Starts a client session and runs the callback inside\n\t * `session.withTransaction()`. The driver handles commit on success,\n\t * abort on error, and automatic retries for transient transaction errors.\n\t *\n\t * The return value of `fn` is forwarded as the return value of this method.\n\t *\n\t * @param fn - Async callback receiving a {@link TransactionContext}.\n\t * @returns The value returned by `fn`.\n\t *\n\t * @example\n\t * ```ts\n\t * const user = await db.transaction(async (tx) => {\n\t * const txUsers = tx.use(users)\n\t * return await txUsers.insertOne({ name: 'Ada' })\n\t * })\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Rollback on error\n\t * try {\n\t * await db.transaction(async (tx) => {\n\t * const txUsers = tx.use(users)\n\t * await txUsers.insertOne({ name: 'Ada' })\n\t * throw new Error('abort!')\n\t * })\n\t * } catch (err) {\n\t * // insert was rolled back, err is the original error\n\t * }\n\t * ```\n\t */\n\tasync transaction<T>(fn: TransactionFn<T>): Promise<T> {\n\t\tconst session = this._client.startSession()\n\t\ttry {\n\t\t\tlet result: T\n\t\t\tawait session.withTransaction(async () => {\n\t\t\t\tconst tx = new TransactionContext(session)\n\t\t\t\tresult = await fn(tx)\n\t\t\t})\n\t\t\t// Safe assertion: withTransaction only resolves after fn completes\n\t\t\t// successfully. The `result` variable is guaranteed to be assigned.\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: result is assigned inside withTransaction callback which completes before this line\n\t\t\treturn result!\n\t\t} finally {\n\t\t\tawait session.endSession()\n\t\t}\n\t}\n\n\t/**\n\t * Close the underlying `MongoClient` connection. Safe to call even if\n\t * no connection was established (the driver handles this gracefully).\n\t */\n\tasync close(): Promise<void> {\n\t\tawait this._client.close()\n\t}\n}\n\n/**\n * Extract the database name from a MongoDB connection URI.\n *\n * Handles standard URIs, multi-host/replica set, SRV (`mongodb+srv://`),\n * auth credentials, query parameters, and percent-encoded database names.\n * Returns `undefined` when no database name is present.\n */\nexport function extractDbName(uri: string): string | undefined {\n\tconst withoutProtocol = uri.replace(/^mongodb(?:\\+srv)?:\\/\\//, '')\n\t// Safe cast: split() always returns at least one element, but noUncheckedIndexedAccess\n\t// types [0] as string | undefined.\n\tconst withoutQuery = withoutProtocol.split('?')[0] as string\n\t// Skip past auth credentials (user:pass@) before searching for the path separator\n\tconst atIndex = withoutQuery.lastIndexOf('@')\n\tconst hostAndPath = atIndex === -1 ? withoutQuery : withoutQuery.slice(atIndex + 1)\n\tconst slashIndex = hostAndPath.indexOf('/')\n\tif (slashIndex === -1) return undefined\n\tconst dbName = decodeURIComponent(hostAndPath.slice(slashIndex + 1))\n\treturn dbName || undefined\n}\n\n/**\n * Create a new {@link Database} instance wrapping a MongoDB connection.\n *\n * The connection is lazy — the driver connects on the first operation.\n * Pass any `MongoClientOptions` to configure connection pooling, timeouts, etc.\n *\n * When `dbName` is omitted, the database name is extracted from the URI path\n * (e.g. `mongodb://localhost:27017/myapp` → `'myapp'`). If no database name\n * is found in either the arguments or the URI, a warning is logged and\n * MongoDB's default `'test'` database is used.\n *\n * @param uri - MongoDB connection string (e.g. `mongodb://localhost:27017`).\n * @param dbName - The database name to use.\n * @param options - Optional MongoDB driver client options.\n * @returns A new `Database` instance.\n */\nexport function createClient(uri: string, dbName: string, options?: MongoClientOptions): Database\nexport function createClient(uri: string, options?: MongoClientOptions): Database\nexport function createClient(\n\turi: string,\n\tdbNameOrOptions?: string | MongoClientOptions,\n\tmaybeOptions?: MongoClientOptions,\n): Database {\n\tif (typeof dbNameOrOptions === 'string') {\n\t\treturn new Database(uri, dbNameOrOptions, maybeOptions)\n\t}\n\tconst parsed = extractDbName(uri)\n\tif (!parsed) {\n\t\tconsole.warn('[zodmon] No database name provided — using MongoDB default \"test\"')\n\t}\n\treturn new Database(uri, parsed ?? 'test', dbNameOrOptions)\n}\n","import type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\n\n/**\n * A normalized index specification ready for comparison and creation.\n *\n * `key` maps field paths to direction (`1`, `-1`, or `'text'`).\n * `options` holds MongoDB index options (`unique`, `sparse`, etc.).\n *\n * @example\n * ```ts\n * const spec: IndexSpec = {\n * key: { email: 1 },\n * options: { unique: true },\n * }\n * ```\n */\nexport type IndexSpec = {\n\tkey: Record<string, 1 | -1 | 'text'>\n\toptions: Record<string, unknown>\n}\n\n/**\n * Convert a field-level index definition to a normalized {@link IndexSpec}.\n *\n * Maps schema metadata (`text`, `descending`, `unique`, `sparse`, `expireAfter`,\n * `partial`) to their MongoDB driver equivalents.\n *\n * @param def - A field index definition extracted from schema metadata.\n * @returns A normalized index spec with key and options.\n *\n * @example\n * ```ts\n * const spec = toFieldIndexSpec({ field: 'email', indexed: true, unique: true })\n * // => { key: { email: 1 }, options: { unique: true } }\n *\n * const ttl = toFieldIndexSpec({ field: 'expiresAt', indexed: true, expireAfter: 3600 })\n * // => { key: { expiresAt: 1 }, options: { expireAfterSeconds: 3600 } }\n * ```\n */\nexport function toFieldIndexSpec(def: FieldIndexDefinition): IndexSpec {\n\tconst direction: 1 | -1 | 'text' = def.text ? 'text' : def.descending ? -1 : 1\n\tconst key: Record<string, 1 | -1 | 'text'> = { [def.field]: direction }\n\n\tconst options: Record<string, unknown> = {}\n\tif (def.unique) options['unique'] = true\n\tif (def.sparse) options['sparse'] = true\n\tif (def.expireAfter !== undefined) options['expireAfterSeconds'] = def.expireAfter\n\tif (def.partial) options['partialFilterExpression'] = def.partial\n\n\treturn { key, options }\n}\n\n/**\n * Convert a compound index definition to a normalized {@link IndexSpec}.\n *\n * Copies the `fields` map directly to `key` and maps builder options\n * (`unique`, `sparse`, `name`, `partial`) to MongoDB driver equivalents.\n *\n * @param def - A compound index definition from the collection options.\n * @returns A normalized index spec with key and options.\n *\n * @example\n * ```ts\n * const spec = toCompoundIndexSpec({\n * fields: { email: 1, role: -1 },\n * options: { unique: true, name: 'email_role_idx' },\n * })\n * // => { key: { email: 1, role: -1 }, options: { unique: true, name: 'email_role_idx' } }\n * ```\n */\nexport function toCompoundIndexSpec(def: CompoundIndexDefinition): IndexSpec {\n\t// Compound fields are Partial<Record<K, 1|-1>> structurally, but all keys\n\t// are present at runtime. Cast to the concrete key type for IndexSpec.\n\tconst key = { ...def.fields } as Record<string, 1 | -1 | 'text'>\n\n\tconst options: Record<string, unknown> = {}\n\tif (def.options?.unique) options['unique'] = true\n\tif (def.options?.sparse) options['sparse'] = true\n\tif (def.options?.name) options['name'] = def.options.name\n\tif (def.options?.partial) options['partialFilterExpression'] = def.options.partial\n\n\treturn { key, options }\n}\n\n/**\n * Produce a stable, deterministic string from an index key for comparison.\n *\n * Entries are sorted alphabetically by field name and formatted as\n * `field:direction` pairs joined by commas. Two index keys that should be\n * considered the same will always produce the same string.\n *\n * @param key - An index key mapping field names to direction.\n * @returns A string like `'email:1,role:-1'`.\n *\n * @example\n * ```ts\n * serializeIndexKey({ email: 1, role: -1 })\n * // => 'email:1,role:-1'\n *\n * serializeIndexKey({ name: 'text' })\n * // => 'name:text'\n * ```\n */\nexport function serializeIndexKey(key: Record<string, 1 | -1 | 'text'>): string {\n\t// Field order is preserved intentionally — in MongoDB, { a: 1, b: 1 } and\n\t// { b: 1, a: 1 } are distinct compound indexes (order determines prefix matching).\n\treturn Object.entries(key)\n\t\t.map(([field, dir]) => `${field}:${dir}`)\n\t\t.join(',')\n}\n","import type { Collection } from 'mongodb'\nimport type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { IndexSpec } from './spec'\nimport { serializeIndexKey, toCompoundIndexSpec, toFieldIndexSpec } from './spec'\nimport type { StaleIndex, SyncIndexesOptions, SyncIndexesResult } from './types'\n\n/**\n * Structural constraint for the handle argument of {@link syncIndexes}.\n *\n * Uses a structural type rather than `CollectionHandle<AnyCollection>` to avoid\n * TypeScript variance issues with `exactOptionalPropertyTypes`. Any collection\n * handle returned by `db.use()` satisfies this constraint.\n */\ntype SyncableHandle = {\n\treadonly definition: {\n\t\treadonly fieldIndexes: FieldIndexDefinition[]\n\t\treadonly compoundIndexes: readonly CompoundIndexDefinition[]\n\t}\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\treadonly native: Collection<any>\n}\n\n/**\n * Relevant option keys extracted from MongoDB index info for comparison.\n *\n * When checking whether an existing index matches a desired spec, only these\n * keys are compared — other MongoDB-internal properties (v, ns, etc.) are\n * ignored.\n */\nconst COMPARABLE_OPTION_KEYS = [\n\t'unique',\n\t'sparse',\n\t'expireAfterSeconds',\n\t'partialFilterExpression',\n] as const\n\n/**\n * Extract the comparable options from a MongoDB index info object.\n *\n * Pulls only the keys listed in {@link COMPARABLE_OPTION_KEYS} from the raw\n * index info returned by `listIndexes()`. Keys whose value is `undefined`\n * are omitted so that JSON comparison works correctly.\n *\n * @param info - A raw MongoDB index info object.\n * @returns A plain object with only the relevant option keys.\n *\n * @example\n * ```ts\n * const opts = extractComparableOptions({ v: 2, unique: true, key: { email: 1 } })\n * // => { unique: true }\n * ```\n */\nexport function extractComparableOptions(info: Record<string, unknown>): Record<string, unknown> {\n\tconst result: Record<string, unknown> = {}\n\tfor (const key of COMPARABLE_OPTION_KEYS) {\n\t\tif (info[key] !== undefined) {\n\t\t\tresult[key] = info[key]\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Generate the default MongoDB index name from a key spec.\n *\n * MongoDB names indexes by joining `field_direction` pairs with underscores.\n * For example, `{ email: 1, role: -1 }` becomes `'email_1_role_-1'`.\n *\n * @param key - An index key mapping field names to direction.\n * @returns The generated index name string.\n *\n * @example\n * ```ts\n * generateIndexName({ email: 1 })\n * // => 'email_1'\n *\n * generateIndexName({ email: 1, role: -1 })\n * // => 'email_1_role_-1'\n * ```\n */\nexport function generateIndexName(key: Record<string, 1 | -1 | 'text'>): string {\n\treturn Object.entries(key)\n\t\t.map(([field, dir]) => `${field}_${dir}`)\n\t\t.join('_')\n}\n\n/**\n * Sort an object's keys alphabetically for deterministic JSON comparison.\n *\n * @param obj - A plain object.\n * @returns A new object with keys sorted alphabetically.\n */\nfunction sortKeys(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst sorted: Record<string, unknown> = {}\n\tfor (const key of Object.keys(obj).sort()) {\n\t\tsorted[key] = obj[key]\n\t}\n\treturn sorted\n}\n\n/** Resolve the name for an index spec, preferring an explicit name. */\nfunction resolveSpecName(spec: IndexSpec): string {\n\tconst specName = spec.options['name']\n\treturn typeof specName === 'string' ? specName : generateIndexName(spec.key)\n}\n\n/** Resolve the name from a raw MongoDB index info object. */\nfunction resolveExistingName(\n\tinfo: Record<string, unknown>,\n\tkey: Record<string, 1 | -1 | 'text'>,\n): string {\n\tconst infoName = info['name']\n\tif (typeof infoName === 'string') return infoName\n\treturn generateIndexName(key)\n}\n\n/**\n * Check whether two option objects are equivalent via sorted JSON.\n * The `name` key is excluded from comparison since it identifies\n * the index rather than defining its behavior.\n */\nfunction optionsMatch(a: Record<string, unknown>, b: Record<string, unknown>): boolean {\n\treturn JSON.stringify(sortKeys(stripName(a))) === JSON.stringify(sortKeys(stripName(b)))\n}\n\n/** Remove the `name` key from an options object for comparison purposes. */\nfunction stripName(obj: Record<string, unknown>): Record<string, unknown> {\n\tconst { name: _, ...rest } = obj\n\treturn rest\n}\n\n/** Mutable accumulator for sync results. */\ntype SyncAccumulator = {\n\tcreated: string[]\n\tdropped: string[]\n\tskipped: string[]\n\tstale: StaleIndex[]\n\tmatchedKeys: Set<string>\n}\n\n/** Process a single desired spec against the existing index map. */\nasync function processDesiredSpec(\n\tspec: IndexSpec,\n\texistingByKey: Map<string, Record<string, unknown>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tdryRun: boolean,\n\tdropOrphaned: boolean,\n\tacc: SyncAccumulator,\n): Promise<void> {\n\tconst serialized = serializeIndexKey(spec.key)\n\tconst existing = existingByKey.get(serialized)\n\n\tif (!existing) {\n\t\tif (!dryRun) await safeCreateIndex(native, spec.key, spec.options)\n\t\tacc.created.push(resolveSpecName(spec))\n\t\treturn\n\t}\n\n\tacc.matchedKeys.add(serialized)\n\tconst existingName = resolveExistingName(existing, spec.key)\n\tconst existingOpts = extractComparableOptions(existing)\n\n\tif (optionsMatch(existingOpts, spec.options)) {\n\t\tacc.skipped.push(existingName)\n\t\treturn\n\t}\n\n\tif (dropOrphaned) {\n\t\tif (!dryRun) {\n\t\t\tawait safeDropIndex(native, existingName)\n\t\t\tawait safeCreateIndex(native, spec.key, spec.options)\n\t\t}\n\t\tacc.dropped.push(existingName)\n\t\tacc.created.push(resolveSpecName(spec))\n\t\treturn\n\t}\n\n\tacc.stale.push({\n\t\tname: existingName,\n\t\tkey: spec.key,\n\t\texisting: existingOpts,\n\t\tdesired: spec.options,\n\t})\n}\n\n/** Create a single index, wrapping driver errors into ZodmonError. */\nasync function safeCreateIndex(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tkey: Record<string, 1 | -1 | 'text'>,\n\toptions: Record<string, unknown>,\n): Promise<void> {\n\ttry {\n\t\tawait native.createIndex(key, options)\n\t} catch (err) {\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/** Drop a single index, wrapping driver errors into ZodmonError. */\nasync function safeDropIndex(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tname: string,\n): Promise<void> {\n\ttry {\n\t\tawait native.dropIndex(name)\n\t} catch (err) {\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/** Collect orphaned indexes that exist in MongoDB but are not in the desired set. */\nasync function processOrphanedIndexes(\n\texistingIndexes: Record<string, unknown>[],\n\tdesiredKeys: Set<string>,\n\tmatchedKeys: Set<string>,\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n\tdryRun: boolean,\n\tdropOrphaned: boolean,\n\tdropped: string[],\n): Promise<void> {\n\tfor (const idx of existingIndexes) {\n\t\tconst rawName = idx['name']\n\t\tconst name = typeof rawName === 'string' ? rawName : ''\n\t\tif (name === '_id_') continue\n\n\t\tconst serialized = serializeIndexKey(idx['key'] as Record<string, 1 | -1 | 'text'>)\n\t\tif (matchedKeys.has(serialized) || desiredKeys.has(serialized)) continue\n\n\t\tif (dropOrphaned) {\n\t\t\tif (!dryRun) await safeDropIndex(native, name)\n\t\t\tdropped.push(name)\n\t\t}\n\t}\n}\n\n/**\n * Fetch existing indexes, returning an empty array when the collection\n * does not exist yet (MongoDB throws \"ns does not exist\" in that case).\n */\nasync function listIndexesSafe(\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB native collection type variance requires escape hatch\n\tnative: Collection<any>,\n): Promise<Record<string, unknown>[]> {\n\ttry {\n\t\treturn (await native.listIndexes().toArray()) as unknown as Record<string, unknown>[]\n\t} catch (err) {\n\t\t// MongoDB 7 throws when the namespace (collection) doesn't exist\n\t\tif (err instanceof Error && err.message.includes('ns does not exist')) {\n\t\t\treturn []\n\t\t}\n\t\twrapMongoError(err, native.collectionName)\n\t}\n}\n\n/**\n * Synchronize the indexes declared in a collection's schema with MongoDB.\n *\n * Compares the desired indexes (from field-level and compound index definitions)\n * with the indexes that currently exist in MongoDB, then creates, drops, or\n * reports differences depending on the options.\n *\n * **Algorithm:**\n * 1. Build desired specs from field indexes and compound indexes.\n * 2. Fetch existing indexes from MongoDB via `listIndexes()`.\n * 3. For each desired spec, compare against existing:\n * - Missing → create (unless `dryRun`).\n * - Present with same options → skip.\n * - Present with different options → stale (or drop+recreate if `dropOrphaned`).\n * 4. For each existing index not in desired set (excluding `_id_`):\n * - If `dropOrphaned` → drop (unless `dryRun`).\n * 5. Return a summary of all actions taken.\n *\n * @param handle - A collection handle created by `db.use()`.\n * @param options - Optional sync behavior (dryRun, dropOrphaned).\n * @returns A summary of created, dropped, skipped, and stale indexes.\n *\n * @example\n * ```ts\n * import { syncIndexes } from '@zodmon/core'\n *\n * const users = db.use(Users)\n * const result = await syncIndexes(users)\n * console.log('Created:', result.created)\n * console.log('Stale:', result.stale.map(s => s.name))\n * ```\n *\n * @example\n * ```ts\n * // Dry run — no changes made\n * const diff = await syncIndexes(users, { dryRun: true })\n * console.log('Would create:', diff.created)\n * console.log('Would drop:', diff.dropped)\n * ```\n */\nexport async function syncIndexes(\n\thandle: SyncableHandle,\n\toptions?: SyncIndexesOptions,\n): Promise<SyncIndexesResult> {\n\tconst { dryRun = false, dropOrphaned = false } = options ?? {}\n\tconst native = handle.native\n\tconst def = handle.definition\n\n\t// 1. Build desired specs\n\tconst desiredSpecs: IndexSpec[] = [\n\t\t...def.fieldIndexes.map(toFieldIndexSpec),\n\t\t...def.compoundIndexes.map(toCompoundIndexSpec),\n\t]\n\n\t// 2. Fetch existing indexes (empty array when collection doesn't exist yet)\n\tconst existingIndexes = await listIndexesSafe(native)\n\n\t// 3. Build map of existing indexes keyed by serialized key\n\tconst existingByKey = new Map<string, Record<string, unknown>>()\n\tfor (const idx of existingIndexes) {\n\t\tconst serialized = serializeIndexKey(idx['key'] as Record<string, 1 | -1 | 'text'>)\n\t\texistingByKey.set(serialized, idx)\n\t}\n\n\tconst acc: SyncAccumulator = {\n\t\tcreated: [],\n\t\tdropped: [],\n\t\tskipped: [],\n\t\tstale: [],\n\t\tmatchedKeys: new Set<string>(),\n\t}\n\n\t// 4. Process desired specs\n\tfor (const spec of desiredSpecs) {\n\t\tawait processDesiredSpec(spec, existingByKey, native, dryRun, dropOrphaned, acc)\n\t}\n\n\t// 5. Handle orphaned indexes\n\tconst desiredKeys = new Set(desiredSpecs.map((s) => serializeIndexKey(s.key)))\n\tawait processOrphanedIndexes(\n\t\texistingIndexes,\n\t\tdesiredKeys,\n\t\tacc.matchedKeys,\n\t\tnative,\n\t\tdryRun,\n\t\tdropOrphaned,\n\t\tacc.dropped,\n\t)\n\n\treturn {\n\t\tcreated: acc.created,\n\t\tdropped: acc.dropped,\n\t\tskipped: acc.skipped,\n\t\tstale: acc.stale,\n\t}\n}\n","import type { ClientSession } from 'mongodb'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection } from '../collection/types'\n\n/**\n * The callback signature for {@link Database.transaction}.\n *\n * @typeParam T - The return type of the transaction callback.\n *\n * @example\n * ```ts\n * const fn: TransactionFn<void> = async (tx) => {\n * const txUsers = tx.use(users)\n * await txUsers.insertOne({ name: 'Ada' })\n * }\n * ```\n */\nexport type TransactionFn<T> = (tx: TransactionContext) => Promise<T>\n\n/**\n * Transaction context passed to the {@link Database.transaction} callback.\n *\n * Use {@link use} to bind existing collection handles to this transaction's\n * session. All operations on the returned handle participate in the\n * transaction -- auto-committed on success, auto-rolled-back on error.\n *\n * @example\n * ```ts\n * await db.transaction(async (tx) => {\n * const txUsers = tx.use(users)\n * const txPosts = tx.use(posts)\n * const user = await txUsers.insertOne({ name: 'Ada' })\n * await txPosts.insertOne({ authorId: user._id, title: 'Hello' })\n * })\n * ```\n */\nexport class TransactionContext {\n\t/** @internal */\n\tprivate readonly session: ClientSession\n\n\t/** @internal */\n\tconstructor(session: ClientSession) {\n\t\tthis.session = session\n\t}\n\n\t/**\n\t * Bind a collection handle to this transaction's session.\n\t *\n\t * Returns a cloned handle whose CRUD operations automatically include\n\t * the transaction session. The original handle is not modified.\n\t *\n\t * @param handle - An existing collection handle from `db.use()`.\n\t * @returns A new handle bound to the transaction session.\n\t *\n\t * @example\n\t * ```ts\n\t * await db.transaction(async (tx) => {\n\t * const txUsers = tx.use(users)\n\t * await txUsers.insertOne({ name: 'Ada' })\n\t * })\n\t * ```\n\t */\n\tuse<TDef extends AnyCollection>(handle: CollectionHandle<TDef>): CollectionHandle<TDef> {\n\t\treturn handle.withSession(this.session)\n\t}\n}\n","import type { DeleteResult } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { TypedFilter } from '../query/filter'\n\n/**\n * Options for {@link findOneAndDelete}.\n */\nexport type FindOneAndDeleteOptions = {\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Delete a single document matching the filter.\n *\n * Removes the first document that matches the filter from the collection.\n * No validation is performed — the document is deleted directly through\n * the MongoDB driver.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @returns The MongoDB `DeleteResult` with the deleted count.\n *\n * @example\n * ```ts\n * const result = await deleteOne(users, { name: 'Ada' })\n * console.log(result.deletedCount) // 1\n * ```\n */\nexport async function deleteOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n): Promise<DeleteResult> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\ttry {\n\t\treturn await handle.native.deleteOne(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\thandle.session ? { session: handle.session } : {},\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Delete all documents matching the filter.\n *\n * Removes every document that matches the filter from the collection.\n * No validation is performed — documents are deleted directly through\n * the MongoDB driver.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @returns The MongoDB `DeleteResult` with the deleted count.\n *\n * @example\n * ```ts\n * const result = await deleteMany(users, { role: 'guest' })\n * console.log(result.deletedCount) // number of guests removed\n * ```\n */\nexport async function deleteMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n): Promise<DeleteResult> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\ttry {\n\t\treturn await handle.native.deleteMany(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\thandle.session ? { session: handle.session } : {},\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Find a single document matching the filter, delete it, and return the document.\n *\n * Returns the deleted document, or `null` if no document matches the filter.\n * The returned document is validated against the collection's Zod schema\n * using the same resolution logic as {@link findOne}.\n *\n * @param handle - The collection handle to delete from.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional settings: `validate`.\n * @returns The deleted document, or `null` if no document matches.\n * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneAndDelete(users, { name: 'Ada' })\n * if (user) console.log(user.name) // 'Ada' (the deleted document)\n * ```\n *\n * @example\n * ```ts\n * const user = await findOneAndDelete(\n * users,\n * { role: 'guest' },\n * { validate: false },\n * )\n * ```\n */\nexport async function findOneAndDelete<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneAndDeleteOptions,\n): Promise<InferDocument<TDef> | null> {\n\t// Safe cast: TypedFilter is a strict subset of MongoDB's Filter<T>,\n\t// but the intersection-based mapped type cannot be structurally\n\t// matched by the driver's looser type.\n\t// The options object uses includeResultMetadata: false to return the\n\t// document directly instead of a ModifyResult wrapper.\n\t// biome-ignore lint/suspicious/noExplicitAny: declaring result before try/catch for driver error wrapping; the actual value is assigned inside try and is non-null after the catch (wrapMongoError is never-returning)\n\tlet result: any\n\ttry {\n\t\tresult = await handle.native.findOneAndDelete(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\thandle.session\n\t\t\t\t? { includeResultMetadata: false, session: handle.session }\n\t\t\t\t: { includeResultMetadata: false },\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!result) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\t// Safe cast: raw document from MongoDB matches the collection's document\n\t\t// shape at runtime. Skipping validation per user request.\n\t\treturn result as InferDocument<TDef>\n\t}\n\n\ttry {\n\t\tconst schema = mode === 'strict' ? handle.definition.strictSchema : handle.definition.schema\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\treturn schema.parse(result) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, result)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { z } from 'zod'\nimport { ZodmonError } from './base'\n\n/**\n * Thrown when a document fails Zod schema validation before a MongoDB write.\n *\n * Wraps the original `ZodError` with the collection name and a human-readable\n * message listing each invalid field and its error. Callers can inspect\n * `.zodError.issues` for programmatic access to individual failures.\n *\n * @example\n * ```ts\n * try {\n * await users.insertOne({ name: 123 })\n * } catch (err) {\n * if (err instanceof ZodmonValidationError) {\n * console.log(err.message)\n * // => 'Validation failed for \"users\": name (Expected string, received number)'\n * console.log(err.collection) // => 'users'\n * console.log(err.zodError) // => ZodError with .issues array\n * console.log(err.document) // => the document that failed validation\n * }\n * }\n * ```\n */\nexport class ZodmonValidationError extends ZodmonError {\n\toverride readonly name = 'ZodmonValidationError'\n\n\t/** The original Zod validation error with detailed issue information. */\n\treadonly zodError: z.ZodError\n\n\t/** The document that failed validation. */\n\treadonly document: unknown\n\n\tconstructor(collection: string, zodError: z.ZodError, document: unknown) {\n\t\tconst fields = zodError.issues\n\t\t\t.map((issue) => {\n\t\t\t\tconst path = issue.path.join('.') || '(root)'\n\t\t\t\treturn `${path} (${issue.message})`\n\t\t\t})\n\t\t\t.join(', ')\n\t\tsuper(`Validation failed for \"${collection}\": ${fields}`, collection, { cause: zodError })\n\t\tthis.zodError = zodError\n\t\tthis.document = document\n\t}\n}\n","import type { FindCursor } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, IndexNames, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonNotFoundError } from '../errors/not-found'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { Prettify } from '../helpers/types'\nimport { checkUnindexedFields } from '../indexes/warn'\nimport { TypedFindCursor } from '../query/cursor'\nimport type { TypedFilter } from '../query/filter'\nimport type { ProjectionResult, TypedProjection } from '../query/projection'\nimport { deriveProjectedSchema } from '../query/projection'\n\n/**\n * Options for {@link findOne} and {@link findOneOrThrow} without projection.\n */\nexport type FindOneOptions = {\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Options for projected {@link findOne} and {@link findOneOrThrow} queries.\n *\n * @typeParam T - The document type.\n * @typeParam P - The projection document type.\n *\n * @example\n * ```ts\n * const user = await findOne(users, { name: 'Ada' }, { project: { name: 1 } })\n * // ^? { _id: ObjectId; name: string } | null\n * ```\n */\nexport type FindOneProjectionOptions<T, P extends TypedProjection<T>> = {\n\t/** Type-safe MongoDB projection — include (`1 | true`) or exclude (`0 | false`) fields. */\n\tproject: P\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Find a single document matching the filter.\n *\n * Queries MongoDB, then validates the fetched document against the collection's\n * Zod schema. Validation mode is resolved from the per-query option, falling\n * back to the collection-level default (which defaults to `'strict'`).\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional validation overrides.\n * @returns The matched document, or `null` if no document matches.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOne(users, { name: 'Ada' })\n * if (user) console.log(user.role) // typed as 'admin' | 'user'\n * ```\n */\nexport async function findOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneOptions,\n): Promise<InferDocument<TDef> | null>\n/**\n * Find a single document matching the filter with a type-safe projection.\n *\n * Returns only the fields specified by the projection. The return type is\n * narrowed to reflect which fields are included or excluded.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Projection and optional validation overrides.\n * @returns The projected document, or `null` if no document matches.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOne(users, { name: 'Ada' }, { project: { name: 1 } })\n * if (user) console.log(user.name) // typed as string\n * // user.role would be a type error — not in the projection\n * ```\n */\nexport async function findOne<\n\tTDef extends AnyCollection,\n\tP extends TypedProjection<InferDocument<TDef>>,\n>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions: FindOneProjectionOptions<InferDocument<TDef>, P>,\n): Promise<Prettify<ProjectionResult<InferDocument<TDef>, P>> | null>\nexport async function findOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?:\n\t\t| FindOneOptions\n\t\t| FindOneProjectionOptions<InferDocument<TDef>, TypedProjection<InferDocument<TDef>>>,\n): Promise<unknown> {\n\t// Safe cast: TypedFilter's top-level keys are string field names and $-operators,\n\t// both of which are captured by Record<string, unknown>.\n\tcheckUnindexedFields(handle.definition, filter as Record<string, unknown>)\n\tconst project = options && 'project' in options ? options.project : undefined\n\tconst findOptions = project ? { projection: project } : undefined\n\t// Safe cast: TypedFilter<InferDocument<TDef>> is a strict subset of\n\t// MongoDB's Filter<T>, but the intersection-based mapped type cannot\n\t// be structurally matched by the driver's looser Filter type.\n\tlet raw: Awaited<ReturnType<typeof handle.native.findOne>>\n\ttry {\n\t\traw = await handle.native.findOne(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\thandle.session ? { ...findOptions, session: handle.session } : findOptions,\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!raw) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\treturn raw\n\t}\n\n\t// Use derived schema when projection is present, full schema otherwise.\n\t// For strict mode without projection, use strictSchema (schema.strict()) so\n\t// unknown fields cause a ZodError rather than being silently stripped.\n\tconst schema = project\n\t\t? deriveProjectedSchema(\n\t\t\t\thandle.definition.schema as z.ZodObject<z.core.$ZodShape>,\n\t\t\t\tproject as Record<string, 0 | 1 | boolean>,\n\t\t\t)\n\t\t: mode === 'strict'\n\t\t\t? handle.definition.strictSchema\n\t\t\t: handle.definition.schema\n\n\ttry {\n\t\treturn schema.parse(raw)\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, raw)\n\t\t}\n\t\tthrow err\n\t}\n}\n\n/**\n * Find a single document matching the filter, or throw if none exists.\n *\n * Behaves identically to {@link findOne} but throws {@link ZodmonNotFoundError}\n * instead of returning `null` when no document matches the filter.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional validation overrides.\n * @returns The matched document (never null).\n * @throws {ZodmonNotFoundError} When no document matches the filter.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneOrThrow(users, { name: 'Ada' })\n * console.log(user.role) // typed as 'admin' | 'user', guaranteed non-null\n * ```\n */\nexport async function findOneOrThrow<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOneOptions,\n): Promise<InferDocument<TDef>>\n/**\n * Find a single document matching the filter with a type-safe projection, or throw if none exists.\n *\n * Returns only the fields specified by the projection. The return type is\n * narrowed to reflect which fields are included or excluded. Throws\n * {@link ZodmonNotFoundError} instead of returning `null`.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Projection and optional validation overrides.\n * @returns The projected document (never null).\n * @throws {ZodmonNotFoundError} When no document matches the filter.\n * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneOrThrow(users, { name: 'Ada' }, { project: { name: 1 } })\n * console.log(user.name) // typed as string\n * // user.role would be a type error — not in the projection\n * ```\n */\nexport async function findOneOrThrow<\n\tTDef extends AnyCollection,\n\tP extends TypedProjection<InferDocument<TDef>>,\n>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions: FindOneProjectionOptions<InferDocument<TDef>, P>,\n): Promise<Prettify<ProjectionResult<InferDocument<TDef>, P>>>\nexport async function findOneOrThrow<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?:\n\t\t| FindOneOptions\n\t\t| FindOneProjectionOptions<InferDocument<TDef>, TypedProjection<InferDocument<TDef>>>,\n): Promise<unknown> {\n\t// Safe cast: options is passed through to findOne which handles both overloads.\n\t// The union type cannot be narrowed to a specific overload by TypeScript, but\n\t// findOne's implementation handles both cases correctly at runtime.\n\tconst doc = await findOne(handle, filter, options as FindOneOptions)\n\tif (!doc) {\n\t\tthrow new ZodmonNotFoundError(handle.definition.name, filter)\n\t}\n\treturn doc\n}\n\n/**\n * Options for {@link find}.\n */\nexport type FindOptions = {\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Options for projected {@link find} queries.\n *\n * @typeParam T - The document type.\n * @typeParam P - The projection document type.\n *\n * @example\n * ```ts\n * const admins = await find(users, { role: 'admin' }, { project: { name: 1 } })\n * .toArray()\n * // ^? Array<{ _id: ObjectId; name: string }>\n * ```\n */\nexport type FindProjectionOptions<T, P extends TypedProjection<T>> = {\n\t/** Type-safe MongoDB projection — include (`1 | true`) or exclude (`0 | false`) fields. */\n\tproject: P\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Find all documents matching the filter, returning a chainable typed cursor.\n *\n * The cursor is lazy — no query is executed until a terminal method\n * (`toArray`, `for await`) is called. Use `sort`, `skip`, and `limit`\n * to shape the query before executing.\n *\n * Each document is validated against the collection's Zod schema when\n * a terminal method consumes it.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Optional validation overrides.\n * @returns A typed cursor for chaining query modifiers.\n *\n * @example\n * ```ts\n * const admins = await find(users, { role: 'admin' })\n * .sort({ name: 1 })\n * .limit(10)\n * .toArray()\n * ```\n *\n * @example\n * ```ts\n * for await (const user of find(users, {})) {\n * console.log(user.name)\n * }\n * ```\n */\nexport function find<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?: FindOptions,\n): TypedFindCursor<TDef, IndexNames<TDef>>\n/**\n * Find all documents matching the filter with a type-safe projection, returning a chainable typed cursor.\n *\n * The cursor is lazy — no query is executed until a terminal method\n * (`toArray`, `for await`) is called. The return type is narrowed to\n * reflect which fields are included or excluded by the projection.\n *\n * @param handle - The collection handle to query.\n * @param filter - Type-safe filter to match documents.\n * @param options - Projection and optional validation overrides.\n * @returns A typed cursor whose output type matches the projection.\n *\n * @example\n * ```ts\n * const names = await find(users, { role: 'admin' }, { project: { name: 1 } })\n * .sort({ name: 1 })\n * .toArray()\n * // names[0].name — string\n * // names[0].role — type error, not in projection\n * ```\n */\nexport function find<TDef extends AnyCollection, P extends TypedProjection<InferDocument<TDef>>>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions: FindProjectionOptions<InferDocument<TDef>, P>,\n): TypedFindCursor<TDef, IndexNames<TDef>, Prettify<ProjectionResult<InferDocument<TDef>, P>>>\nexport function find<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\toptions?:\n\t\t| FindOptions\n\t\t| FindProjectionOptions<InferDocument<TDef>, TypedProjection<InferDocument<TDef>>>,\n\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation return type\n): any {\n\t// Safe cast: TypedFilter's top-level keys are string field names and $-operators,\n\t// both of which are captured by Record<string, unknown>.\n\tcheckUnindexedFields(handle.definition, filter as Record<string, unknown>)\n\t// Safe cast: TypedFilter<InferDocument<TDef>> is a strict subset of\n\t// MongoDB's Filter<T>, but the intersection-based mapped type cannot\n\t// be structurally matched by the driver's looser Filter type.\n\tconst raw = handle.native.find(\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\tfilter as any,\n\t\thandle.session ? { session: handle.session } : undefined,\n\t)\n\t// Safe cast: Collection.find() returns FindCursor<WithId<T>>, but our schemas\n\t// always include _id so WithId<InferDocument<TDef>> is structurally identical\n\t// to InferDocument<TDef>. TypeScript cannot prove this with exactOptionalPropertyTypes.\n\tconst cursor = raw as unknown as FindCursor<InferDocument<TDef>>\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\tconst typedCursor = new TypedFindCursor(\n\t\tcursor,\n\t\thandle.definition,\n\t\tmode,\n\t\thandle.native,\n\t\tfilter,\n\t\thandle.session,\n\t)\n\n\tconst project = options && 'project' in options ? options.project : undefined\n\tif (project) {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedProjection generic boundary\n\t\treturn typedCursor.project(project as any)\n\t}\n\treturn typedCursor\n}\n","import { ZodmonError } from './base'\n\n/**\n * Thrown when a query expected to find a document returns no results.\n *\n * Used by {@link findOneOrThrow} when no document matches the provided filter.\n * Callers can inspect `.collection` to identify which collection the query targeted,\n * and `.filter` to see the query that produced no results.\n *\n * @example\n * ```ts\n * try {\n * await users.findOneOrThrow({ name: 'nonexistent' })\n * } catch (err) {\n * if (err instanceof ZodmonNotFoundError) {\n * console.log(err.message) // => 'Document not found in \"users\"'\n * console.log(err.collection) // => 'users'\n * console.log(err.filter) // => { name: 'nonexistent' }\n * }\n * }\n * ```\n */\nexport class ZodmonNotFoundError extends ZodmonError {\n\toverride readonly name = 'ZodmonNotFoundError'\n\n\t/** The filter that produced no results. */\n\treadonly filter: unknown\n\n\tconstructor(collection: string, filter: unknown) {\n\t\tsuper(`Document not found in \"${collection}\"`, collection)\n\t\tthis.filter = filter\n\t}\n}\n","import type { CompoundIndexDefinition, FieldIndexDefinition } from '../collection/types'\n\n/**\n * Structural constraint for the definition argument of {@link checkUnindexedFields}.\n *\n * Uses a structural type rather than `CollectionDefinition<z.core.$ZodShape>` to avoid\n * TypeScript variance issues with `exactOptionalPropertyTypes`. Any collection\n * definition returned by `collection()` satisfies this constraint.\n */\ntype WarnableDefinition = {\n\treadonly name: string\n\treadonly fieldIndexes: FieldIndexDefinition[]\n\treadonly compoundIndexes: readonly CompoundIndexDefinition[]\n\treadonly options: {\n\t\twarnUnindexedQueries?: boolean\n\t}\n}\n\n/** MongoDB query operators that should be skipped during unindexed field checks. */\nconst SKIP_OPERATORS = new Set(['$or', '$and', '$nor', '$text', '$where', '$expr', '$comment'])\n\n/**\n * Warn about unindexed fields used in a query filter.\n *\n * When `warnUnindexedQueries` is enabled on a collection definition, this\n * function checks each top-level field in the filter against the collection's\n * declared indexes. Fields that are not covered by any index produce a\n * `console.warn` message to help identify queries that may cause full\n * collection scans in development.\n *\n * **Covered fields:**\n * - `_id` (always indexed by MongoDB)\n * - Fields with `.index()`, `.unique()`, `.text()`, or `.expireAfter()` (field-level indexes)\n * - The **first** field of each compound index (prefix matching)\n *\n * **Skipped keys:**\n * - MongoDB operators: `$or`, `$and`, `$nor`, `$text`, `$where`, `$expr`, `$comment`\n *\n * This function is a no-op (zero overhead) when `warnUnindexedQueries` is not\n * explicitly set to `true`.\n *\n * @param definition - The collection definition containing index metadata.\n * @param filter - The query filter to check for unindexed fields.\n *\n * @example\n * ```ts\n * import { collection, checkUnindexedFields } from '@zodmon/core'\n *\n * const Users = collection('users', {\n * email: z.string().unique(),\n * name: z.string(),\n * }, { warnUnindexedQueries: true })\n *\n * // No warning — email is indexed\n * checkUnindexedFields(Users, { email: 'ada@example.com' })\n *\n * // Warns: \"[zodmon] warn: query on 'users' uses unindexed field 'name'\"\n * checkUnindexedFields(Users, { name: 'Ada' })\n * ```\n */\nexport function checkUnindexedFields(\n\tdefinition: WarnableDefinition,\n\tfilter: Record<string, unknown>,\n): void {\n\tif (definition.options.warnUnindexedQueries !== true) return\n\n\tconst covered = new Set<string>()\n\n\tfor (const fi of definition.fieldIndexes) {\n\t\tcovered.add(fi.field)\n\t}\n\n\tfor (const ci of definition.compoundIndexes) {\n\t\tconst firstField = Object.keys(ci.fields)[0]\n\t\tif (firstField !== undefined) {\n\t\t\tcovered.add(firstField)\n\t\t}\n\t}\n\n\tfor (const key of Object.keys(filter)) {\n\t\tif (key === '_id') continue\n\t\tif (SKIP_OPERATORS.has(key)) continue\n\t\tif (!covered.has(key)) {\n\t\t\tconsole.warn(`[zodmon] warn: query on '${definition.name}' uses unindexed field '${key}'`)\n\t\t}\n\t}\n}\n","import type { ClientSession, Collection, FindCursor, Sort } from 'mongodb'\nimport { z } from 'zod'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport {\n\tbuildCursorFilter,\n\ttype CursorPage,\n\ttype CursorPaginateOptions,\n\tdecodeCursor,\n\tencodeCursor,\n\ttype OffsetPage,\n\ttype OffsetPaginateOptions,\n\tresolveSortKeys,\n\ttype SortEntry,\n} from '../crud/paginate'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { Prettify } from '../helpers/types'\nimport type { PopulateProjectionConfig, PopulateRefBuilder } from '../populate/builder'\nimport { createPopulateCursor, type PopulateCursor } from '../populate/cursor'\nimport type { ApplyPopulate, ApplyPopulateProjected } from '../populate/types'\nimport type { ExtractRefCollection, RefFields } from '../schema/ref'\nimport { deriveProjectedSchema, type ProjectionResult, type TypedProjection } from './projection'\n\n/**\n * Type-safe sort specification for a document type.\n *\n * Constrains sort keys to top-level fields of `T` with direction `1` (ascending)\n * or `-1` (descending). Dot-path sorts deferred to v1.0.\n *\n * @example\n * ```ts\n * const sort: TypedSort<User> = { name: 1, createdAt: -1 }\n * ```\n */\nexport type TypedSort<T> = Partial<Record<keyof T & string, 1 | -1>>\n\n/**\n * Type-safe cursor wrapping MongoDB's `FindCursor`.\n *\n * Provides chainable query modifiers (`sort`, `skip`, `limit`, `hint`) that return\n * `this` for fluent chaining, and terminal methods (`toArray`,\n * `[Symbol.asyncIterator]`) that validate each document against the\n * collection's Zod schema before returning.\n *\n * Created by {@link find} — do not construct directly.\n *\n * @typeParam TDef - The collection definition type, used to infer the document type.\n * @typeParam TIndexNames - Union of declared index names accepted by `.hint()`.\n * @typeParam TOutput - The output document type, narrowed by `.project()`.\n *\n * @example\n * ```ts\n * const docs = await find(users, { role: 'admin' })\n * .sort({ name: 1 })\n * .limit(10)\n * .toArray()\n * ```\n */\nexport class TypedFindCursor<\n\tTDef extends AnyCollection,\n\tTIndexNames extends string = string,\n\tTOutput = InferDocument<TDef>,\n> {\n\t/** @internal */\n\tprivate cursor: FindCursor<InferDocument<TDef>>\n\t/** @internal */\n\treadonly definition: TDef\n\t/** @internal */\n\tprivate schema: z.ZodType\n\t/** @internal */\n\tprivate collectionName: string\n\t/** @internal */\n\tprivate mode: ValidationMode | false\n\t/** @internal */\n\treadonly nativeCollection: Collection<InferDocument<TDef>>\n\t/** @internal */\n\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter is not assignable to MongoDB's Filter; stored opaquely for paginate\n\tprivate readonly filter: any\n\t/** @internal */\n\tprivate readonly session: ClientSession | undefined\n\t/** @internal */\n\tprivate sortSpec: TypedSort<InferDocument<TDef>> | null\n\t/** @internal */\n\tprivate projectedSchema: z.ZodType | null\n\n\t/** @internal */\n\tconstructor(\n\t\tcursor: FindCursor<InferDocument<TDef>>,\n\t\tdefinition: TDef,\n\t\tmode: ValidationMode | false,\n\t\tnativeCollection: Collection<InferDocument<TDef>>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter is not assignable to MongoDB's Filter; stored opaquely for paginate\n\t\tfilter: any,\n\t\tsession?: ClientSession,\n\t) {\n\t\tthis.cursor = cursor\n\t\tthis.definition = definition\n\t\tthis.schema = definition.schema\n\t\tthis.collectionName = definition.name\n\t\tthis.mode = mode\n\t\tthis.nativeCollection = nativeCollection\n\t\tthis.filter = filter\n\t\tthis.session = session\n\t\tthis.sortSpec = null\n\t\tthis.projectedSchema = null\n\t}\n\n\t/**\n\t * Set the sort order for the query.\n\t *\n\t * Only top-level document fields are accepted as sort keys.\n\t * Values must be `1` (ascending) or `-1` (descending).\n\t *\n\t * @param spec - Sort specification mapping field names to sort direction.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).sort({ name: 1, age: -1 }).toArray()\n\t * ```\n\t */\n\tsort(spec: TypedSort<InferDocument<TDef>>): this {\n\t\tthis.sortSpec = spec\n\t\t// Safe cast: TypedSort is a strict subset of MongoDB's Sort type,\n\t\t// but Record<keyof T & string, 1 | -1> is not assignable to Sort\n\t\t// due to index signature differences.\n\t\tthis.cursor.sort(spec as Sort)\n\t\treturn this\n\t}\n\n\t/**\n\t * Skip the first `n` documents in the result set.\n\t *\n\t * @param n - Number of documents to skip.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).skip(10).limit(10).toArray() // page 2\n\t * ```\n\t */\n\tskip(n: number): this {\n\t\tthis.cursor.skip(n)\n\t\treturn this\n\t}\n\n\t/**\n\t * Limit the number of documents returned.\n\t *\n\t * @param n - Maximum number of documents to return.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * find(users, {}).limit(10).toArray() // at most 10 docs\n\t * ```\n\t */\n\tlimit(n: number): this {\n\t\tthis.cursor.limit(n)\n\t\treturn this\n\t}\n\n\t/**\n\t * Force the query optimizer to use the specified index.\n\t *\n\t * Only accepts index names that were declared via `.name()` in the\n\t * collection definition. If no named indexes exist, any string is accepted.\n\t *\n\t * @param indexName - The name of a declared compound index.\n\t * @returns `this` for chaining.\n\t *\n\t * @example\n\t * ```ts\n\t * const Users = collection('users', { email: z.string(), role: z.string() }, {\n\t * indexes: [index({ email: 1, role: -1 }).name('email_role_idx')],\n\t * })\n\t * const admins = await users.find({ role: 'admin' })\n\t * .hint('email_role_idx')\n\t * .toArray()\n\t * ```\n\t */\n\thint(indexName: TIndexNames): this {\n\t\tthis.cursor.hint(indexName)\n\t\treturn this\n\t}\n\n\t/**\n\t * Apply a projection to narrow the returned fields.\n\t *\n\t * Inclusion projections (`{ name: 1 }`) return only the specified fields\n\t * plus `_id` (unless `_id: 0`). Exclusion projections (`{ email: 0 }`)\n\t * return all fields except those excluded.\n\t *\n\t * The cursor's output type is narrowed at compile time. A derived Zod\n\t * schema is built for runtime validation of the projected fields.\n\t *\n\t * Projects from the original document type, not from a previous projection.\n\t * Calling `.project()` twice overrides the previous projection.\n\t *\n\t * @param spec - Type-safe projection document.\n\t * @returns A new cursor with the narrowed output type.\n\t *\n\t * @example\n\t * ```ts\n\t * const names = await find(users, {})\n\t * .project({ name: 1 })\n\t * .sort({ name: 1 })\n\t * .toArray()\n\t * // names[0].name ✓\n\t * // names[0].email TS error\n\t * ```\n\t */\n\tproject<P extends TypedProjection<InferDocument<TDef>>>(\n\t\tspec: P,\n\t): TypedFindCursor<TDef, TIndexNames, Prettify<ProjectionResult<InferDocument<TDef>, P>>> {\n\t\t// Apply projection to the underlying MongoDB cursor\n\t\tthis.cursor.project(spec as Record<string, 0 | 1>)\n\t\t// Derive a scoped Zod schema for validation of projected documents\n\t\tthis.projectedSchema = deriveProjectedSchema(\n\t\t\tthis.schema as z.ZodObject<z.core.$ZodShape>,\n\t\t\tspec as Record<string, 0 | 1 | boolean>,\n\t\t)\n\t\t// Safe cast: the TypedProjection constraint guarantees P produces a valid\n\t\t// ProjectionResult, but TypeScript cannot prove this through the class\n\t\t// generic boundary. Runtime correctness is ensured by MongoDB's projection\n\t\t// and the derived schema.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: generic type boundary — see comment above\n\t\treturn this as any\n\t}\n\n\t/**\n\t * Populate a top-level ref field, keeping the original field name.\n\t *\n\t * Transitions to a {@link PopulateCursor} that only exposes `.populate()`\n\t * and terminal methods. Cursor modifiers (`sort`, `skip`, `limit`) must\n\t * be called before `.populate()`.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @returns A populate cursor with the field type replaced by the referenced document.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId')\n\t * .toArray()\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>>(\n\t\tfield: K,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K>,\n\t\t{ [P in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field with a projection, keeping the original field name.\n\t *\n\t * Transitions to a {@link PopulateCursor}. Cursor modifiers (`sort`, `skip`, `limit`)\n\t * must be called before `.populate()`.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param configure - Callback receiving a builder; call `.project()` to set the projection.\n\t * @returns A populate cursor with the field type narrowed to only the projected fields.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n\t * .toArray()\n\t * // posts[0].authorId is { _id: ObjectId; name: string; email: string }\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, P>(\n\t\tfield: K,\n\t\tconfigure: (\n\t\t\tb: PopulateRefBuilder<InferDocument<ExtractRefCollection<TDef, K>>>,\n\t\t) => PopulateProjectionConfig<P>,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulateProjected<TOutput, TDef, K, P>,\n\t\t{ [F in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field and rename it in the output.\n\t *\n\t * Transitions to a {@link PopulateCursor} that only exposes `.populate()`\n\t * and terminal methods. Cursor modifiers (`sort`, `skip`, `limit`) must\n\t * be called before `.populate()`.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param as - The new field name in the output document.\n\t * @returns A populate cursor with the old field removed and the new field added.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .sort({ createdAt: -1 })\n\t * .limit(10)\n\t * .populate('authorId', 'author')\n\t * .toArray()\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, TAs extends string>(\n\t\tfield: K,\n\t\tas: TAs,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K, TAs>,\n\t\t{ [P in TAs]: ExtractRefCollection<TDef, K> }\n\t>\n\t// Implementation — creates a PopulateCursor and delegates the first populate call.\n\t// No circular runtime dependency: populate/cursor.ts imports TypedFindCursor as a\n\t// *type* only (erased at runtime), so the runtime import flows one way:\n\t// query/cursor.ts → populate/cursor.ts.\n\tpopulate(\n\t\tfield: string,\n\t\tasOrConfigure?:\n\t\t\t| string\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TDoc is phantom; widened for overload implementation\n\t\t\t| ((b: PopulateRefBuilder<any>) => PopulateProjectionConfig<unknown>),\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation requires widened return\n\t): any {\n\t\t// Safe cast: createPopulateCursor expects TypedFindCursor<TDef> with default\n\t\t// TOutput = InferDocument<TDef>, but `this` may have a narrower TOutput from\n\t\t// .project(). The populate step doesn't depend on TOutput — it operates on\n\t\t// the raw documents from the underlying cursor. The .populate() call on the\n\t\t// returned PopulateCursor uses widened string params that the overload\n\t\t// signatures on PopulateCursor don't accept — the overloads carry the\n\t\t// correct types for callers. Here we bypass them via cast.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload + generic boundary bypass — see comment above\n\t\tconst popCursor: any = createPopulateCursor(this as any, this.definition, [])\n\t\treturn popCursor.populate(field, asOrConfigure)\n\t}\n\n\t/**\n\t * Execute the query with offset-based pagination, returning a page of documents\n\t * with total count and navigation metadata.\n\t *\n\t * Runs `countDocuments` and `find` in parallel for performance. Ignores any\n\t * `.skip()` or `.limit()` already set on the cursor — issues a fresh query.\n\t *\n\t * @param opts - Offset pagination options: `page` (1-indexed) and `perPage`.\n\t * @returns A page with `docs`, `total`, `totalPages`, `hasNext`, `hasPrev`.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const page = await users.find({ role: 'admin' })\n\t * .sort({ createdAt: -1 })\n\t * .paginate({ page: 2, perPage: 10 })\n\t * console.log(page.total, page.totalPages, page.hasNext)\n\t * ```\n\t */\n\tpaginate(opts: OffsetPaginateOptions): Promise<OffsetPage<TOutput>>\n\t/**\n\t * Execute the query with cursor-based pagination, returning a page of documents\n\t * with opaque cursors for forward/backward navigation.\n\t *\n\t * Uses the `limit + 1` trick to determine `hasNext`/`hasPrev` without extra queries.\n\t * Direction is encoded in the cursor — pass `endCursor` to go forward, `startCursor`\n\t * to go backward.\n\t *\n\t * @param opts - Cursor pagination options: `limit` and optional `cursor`.\n\t * @returns A page with `docs`, `hasNext`, `hasPrev`, `startCursor`, `endCursor`.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t * @throws {Error} When the cursor string is malformed.\n\t *\n\t * @example\n\t * ```ts\n\t * const first = await users.find({}).sort({ name: 1 }).paginate({ limit: 10 })\n\t * const next = await users.find({}).sort({ name: 1 })\n\t * .paginate({ cursor: first.endCursor, limit: 10 })\n\t * ```\n\t */\n\tpaginate(opts: CursorPaginateOptions): Promise<CursorPage<TOutput>>\n\tasync paginate(\n\t\topts: OffsetPaginateOptions | CursorPaginateOptions,\n\t): Promise<OffsetPage<TOutput> | CursorPage<TOutput>> {\n\t\tconst sortRecord = this.sortSpec ? (this.sortSpec as Record<string, 1 | -1>) : null\n\t\tconst sortKeys = resolveSortKeys(sortRecord)\n\t\tconst sort = Object.fromEntries(sortKeys) as Sort\n\n\t\tif ('page' in opts) {\n\t\t\treturn await this.offsetPaginate(sortKeys, sort, opts)\n\t\t}\n\t\treturn await this.cursorPaginate(sortKeys, sort, opts)\n\t}\n\n\t/** @internal Offset pagination implementation. */\n\tprivate async offsetPaginate(\n\t\t_sortKeys: SortEntry[],\n\t\tsort: Sort,\n\t\topts: OffsetPaginateOptions,\n\t): Promise<OffsetPage<TOutput>> {\n\t\tlet total: number\n\t\t// biome-ignore lint/suspicious/noExplicitAny: declaring raw before try/catch for driver error wrapping; assigned inside try, guaranteed non-null after catch (wrapMongoError returns never)\n\t\tlet raw: any[]\n\t\ttry {\n\t\t\t;[total, raw] = await Promise.all([\n\t\t\t\tthis.nativeCollection.countDocuments(\n\t\t\t\t\tthis.filter,\n\t\t\t\t\tthis.session ? { session: this.session } : {},\n\t\t\t\t),\n\t\t\t\tthis.nativeCollection\n\t\t\t\t\t.find(this.filter, this.session ? { session: this.session } : undefined)\n\t\t\t\t\t.sort(sort)\n\t\t\t\t\t.skip((opts.page - 1) * opts.perPage)\n\t\t\t\t\t.limit(opts.perPage)\n\t\t\t\t\t.toArray(),\n\t\t\t])\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\n\t\t// Safe cast: our schemas always include _id, so WithId<T> is structurally\n\t\t// identical to InferDocument<TDef>. TypeScript can't prove this under\n\t\t// exactOptionalPropertyTypes.\n\t\tconst docs = (raw as unknown as InferDocument<TDef>[]).map((doc) => this.validateDoc(doc))\n\t\tconst totalPages = Math.ceil(total / opts.perPage)\n\n\t\treturn {\n\t\t\tdocs,\n\t\t\ttotal,\n\t\t\tpage: opts.page,\n\t\t\tperPage: opts.perPage,\n\t\t\ttotalPages,\n\t\t\thasNext: opts.page < totalPages,\n\t\t\thasPrev: opts.page > 1,\n\t\t}\n\t}\n\n\t/** @internal Cursor pagination implementation. */\n\tprivate async cursorPaginate(\n\t\tsortKeys: SortEntry[],\n\t\tsort: Sort,\n\t\topts: CursorPaginateOptions,\n\t): Promise<CursorPage<TOutput>> {\n\t\tlet isBackward = false\n\t\tlet combinedFilter = this.filter\n\n\t\tif (opts.cursor) {\n\t\t\tconst decoded = decodeCursor(opts.cursor)\n\t\t\tisBackward = decoded.direction === 'b'\n\t\t\tconst cursorFilter = buildCursorFilter(sortKeys, decoded.values, isBackward)\n\t\t\tcombinedFilter =\n\t\t\t\tthis.filter && Object.keys(this.filter).length > 0\n\t\t\t\t\t? { $and: [this.filter, cursorFilter] }\n\t\t\t\t\t: cursorFilter\n\t\t}\n\n\t\t// For backward pagination, reverse all sort directions\n\t\tconst effectiveSort = isBackward\n\t\t\t? (Object.fromEntries(sortKeys.map(([f, d]) => [f, d === 1 ? -1 : 1])) as Sort)\n\t\t\t: sort\n\n\t\t// biome-ignore lint/suspicious/noExplicitAny: declaring raw before try/catch for driver error wrapping; assigned inside try, guaranteed non-null after catch (wrapMongoError returns never)\n\t\tlet raw: any[]\n\t\ttry {\n\t\t\traw = await this.nativeCollection\n\t\t\t\t.find(combinedFilter, this.session ? { session: this.session } : undefined)\n\t\t\t\t.sort(effectiveSort)\n\t\t\t\t.limit(opts.limit + 1)\n\t\t\t\t.toArray()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\n\t\tconst hasMore = raw.length > opts.limit\n\t\tif (hasMore) raw.pop()\n\n\t\t// Reverse back to original sort order for backward pagination\n\t\tif (isBackward) raw.reverse()\n\n\t\t// Safe cast: same WithId<T> → InferDocument<TDef> cast as offsetPaginate\n\t\tconst docs = (raw as unknown as InferDocument<TDef>[]).map((doc) => this.validateDoc(doc))\n\n\t\treturn {\n\t\t\tdocs,\n\t\t\thasNext: isBackward ? true : hasMore,\n\t\t\thasPrev: isBackward ? hasMore : opts.cursor != null,\n\t\t\tstartCursor:\n\t\t\t\tdocs.length > 0 ? encodeCursor(docs[0] as Record<string, unknown>, sortKeys, 'b') : null,\n\t\t\tendCursor:\n\t\t\t\tdocs.length > 0\n\t\t\t\t\t? encodeCursor(docs[docs.length - 1] as Record<string, unknown>, sortKeys, 'f')\n\t\t\t\t\t: null,\n\t\t}\n\t}\n\n\t/**\n\t * Execute the query and return all matching documents as an array.\n\t *\n\t * Each document is validated against the collection's Zod schema\n\t * according to the resolved validation mode.\n\t *\n\t * @returns Array of validated documents.\n\t * @throws {ZodmonValidationError} When a document fails schema validation in strict/strip mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const admins = await find(users, { role: 'admin' }).toArray()\n\t * ```\n\t */\n\tasync toArray(): Promise<TOutput[]> {\n\t\tlet raw: InferDocument<TDef>[]\n\t\ttry {\n\t\t\traw = await this.cursor.toArray()\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\t\treturn raw.map((doc) => this.validateDoc(doc))\n\t}\n\n\t/**\n\t * Async iterator for streaming documents one at a time.\n\t *\n\t * Each yielded document is validated against the collection's Zod schema.\n\t * Memory-efficient for large result sets.\n\t *\n\t * @yields Validated documents one at a time.\n\t * @throws {ZodmonValidationError} When a document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * for await (const user of find(users, {})) {\n\t * console.log(user.name)\n\t * }\n\t * ```\n\t */\n\tasync *[Symbol.asyncIterator](): AsyncGenerator<TOutput> {\n\t\ttry {\n\t\t\tfor await (const doc of this.cursor) {\n\t\t\t\tyield this.validateDoc(doc)\n\t\t\t}\n\t\t} catch (err) {\n\t\t\twrapMongoError(err, this.collectionName)\n\t\t}\n\t}\n\n\t/** @internal Validate a single raw document against the schema. */\n\tprivate validateDoc(raw: InferDocument<TDef>): TOutput {\n\t\tif (this.mode === false || this.mode === 'passthrough') {\n\t\t\t// Safe cast: projected runtime data matches TOutput via the projection constraint.\n\t\t\treturn raw as TOutput\n\t\t}\n\n\t\t// Use projectedSchema when a projection is active (its shape differs from the full doc).\n\t\t// For strict mode without projection, use strictSchema to reject unknown fields.\n\t\tconst schema =\n\t\t\tthis.projectedSchema ?? (this.mode === 'strict' ? this.definition.strictSchema : this.schema)\n\n\t\ttry {\n\t\t\t// Safe cast: schema.parse() returns the validated shape which matches TOutput\n\t\t\t// when projected, or InferDocument<TDef> when not.\n\t\t\treturn schema.parse(raw) as TOutput\n\t\t} catch (err) {\n\t\t\tif (err instanceof z.ZodError) {\n\t\t\t\tthrow new ZodmonValidationError(this.collectionName, err, raw)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n}\n","import { ObjectId } from 'mongodb'\n\n// ── Public types ────────────────────────────────────────────────────────\n\n/**\n * Options for offset-based pagination.\n *\n * @example\n * ```ts\n * await users.find({}).sort({ name: 1 }).paginate({ page: 2, perPage: 10 })\n * ```\n */\nexport type OffsetPaginateOptions = {\n\t/** The page number to retrieve (1-indexed). */\n\tpage: number\n\t/** The number of documents per page. */\n\tperPage: number\n}\n\n/**\n * Options for cursor-based pagination.\n *\n * @example\n * ```ts\n * const first = await users.find({}).sort({ name: 1 }).paginate({ limit: 10 })\n * const next = await users.find({}).sort({ name: 1 }).paginate({ cursor: first.endCursor, limit: 10 })\n * ```\n */\nexport type CursorPaginateOptions = {\n\t/** Maximum number of documents to return. */\n\tlimit: number\n\t/** Opaque cursor string from a previous `startCursor` or `endCursor`. */\n\tcursor?: string | null\n}\n\n/**\n * Result of offset-based pagination.\n *\n * @example\n * ```ts\n * const page = await users.find({}).paginate({ page: 1, perPage: 10 })\n * console.log(page.total, page.totalPages, page.hasNext)\n * ```\n */\nexport type OffsetPage<TDoc> = {\n\t/** The documents for this page. */\n\tdocs: TDoc[]\n\t/** Total number of matching documents. */\n\ttotal: number\n\t/** Current page number (1-indexed). */\n\tpage: number\n\t/** Number of documents per page. */\n\tperPage: number\n\t/** Total number of pages (`Math.ceil(total / perPage)`). */\n\ttotalPages: number\n\t/** Whether there is a next page. */\n\thasNext: boolean\n\t/** Whether there is a previous page. */\n\thasPrev: boolean\n}\n\n/**\n * Result of cursor-based pagination.\n *\n * @example\n * ```ts\n * const page = await users.find({}).paginate({ limit: 10 })\n * if (page.hasNext) {\n * const next = await users.find({}).paginate({ cursor: page.endCursor, limit: 10 })\n * }\n * ```\n */\nexport type CursorPage<TDoc> = {\n\t/** The documents for this page. */\n\tdocs: TDoc[]\n\t/** Whether there are more documents after this page. */\n\thasNext: boolean\n\t/** Whether there are documents before this page. */\n\thasPrev: boolean\n\t/** Cursor for the first document (pass to `cursor` to go backward). `null` when empty. */\n\tstartCursor: string | null\n\t/** Cursor for the last document (pass to `cursor` to go forward). `null` when empty. */\n\tendCursor: string | null\n}\n\n// ── Sort key type ───────────────────────────────────────────────────────\n\n/** A [field, direction] tuple used internally for sort resolution. */\nexport type SortEntry = [field: string, direction: 1 | -1]\n\n// ── Cursor value serialization ──────────────────────────────────────────\n\n/**\n * Serialize a value for cursor encoding, preserving ObjectId and Date types.\n *\n * @example\n * ```ts\n * serializeValue(new ObjectId('...')) // { $oid: '...' }\n * serializeValue(new Date('2024-01-01')) // { $date: 1704067200000 }\n * serializeValue('hello') // 'hello'\n * ```\n */\nexport function serializeValue(value: unknown): unknown {\n\tif (value instanceof ObjectId) return { $oid: value.toHexString() }\n\tif (value instanceof Date) return { $date: value.getTime() }\n\treturn value\n}\n\n/**\n * Deserialize a cursor value, restoring ObjectId and Date types.\n *\n * @example\n * ```ts\n * deserializeValue({ $oid: '507f1f...' }) // ObjectId('507f1f...')\n * deserializeValue({ $date: 1704067200000 }) // Date('2024-01-01')\n * deserializeValue('hello') // 'hello'\n * ```\n */\nexport function deserializeValue(value: unknown): unknown {\n\tif (value != null && typeof value === 'object') {\n\t\tif ('$oid' in value) return new ObjectId((value as { $oid: string }).$oid)\n\t\tif ('$date' in value) return new Date((value as { $date: number }).$date)\n\t}\n\treturn value\n}\n\n// ── Cursor encoding/decoding ────────────────────────────────────────────\n\n/**\n * Encode a cursor from a document's sort field values.\n *\n * Format: base64(JSON([ direction, ...serializedValues ]))\n * Direction: 'f' (forward / endCursor) or 'b' (backward / startCursor).\n *\n * @example\n * ```ts\n * encodeCursor({ age: 25, _id: oid }, [['age', 1], ['_id', 1]], 'f')\n * // base64-encoded string\n * ```\n */\nexport function encodeCursor(\n\tdoc: Record<string, unknown>,\n\tsortKeys: SortEntry[],\n\tdirection: 'f' | 'b',\n): string {\n\tconst values = sortKeys.map(([field]) => serializeValue(doc[field]))\n\treturn btoa(JSON.stringify([direction, ...values]))\n}\n\n/**\n * Decode a cursor string into direction and sort field values.\n *\n * @throws {Error} When the cursor is malformed or has invalid format.\n *\n * @example\n * ```ts\n * const { direction, values } = decodeCursor(cursorString)\n * // direction: 'f' | 'b', values: unknown[]\n * ```\n */\nexport function decodeCursor(cursor: string): { direction: 'f' | 'b'; values: unknown[] } {\n\tlet parsed: unknown\n\ttry {\n\t\tparsed = JSON.parse(atob(cursor))\n\t} catch {\n\t\tthrow new Error('Invalid cursor: malformed encoding')\n\t}\n\tif (!Array.isArray(parsed) || parsed.length < 1) {\n\t\tthrow new Error('Invalid cursor: expected non-empty array')\n\t}\n\tconst [direction, ...rawValues] = parsed as [unknown, ...unknown[]]\n\tif (direction !== 'f' && direction !== 'b') {\n\t\tthrow new Error('Invalid cursor: unknown direction flag')\n\t}\n\treturn { direction, values: rawValues.map(deserializeValue) }\n}\n\n// ── Cursor filter builder ───────────────────────────────────────────────\n\n/**\n * Build a MongoDB `$or` filter for cursor-based pagination.\n *\n * For sort `{ role: 1, createdAt: -1, _id: 1 }` with values `['admin', date, id]`:\n * ```\n * { $or: [\n * { role: { $gt: 'admin' } },\n * { role: 'admin', createdAt: { $lt: date } },\n * { role: 'admin', createdAt: date, _id: { $gt: id } },\n * ]}\n * ```\n *\n * @example\n * ```ts\n * buildCursorFilter([['age', 1], ['_id', 1]], [25, oid], false)\n * // { $or: [{ age: { $gt: 25 } }, { age: 25, _id: { $gt: oid } }] }\n * ```\n */\nexport function buildCursorFilter(\n\tsortKeys: SortEntry[],\n\tvalues: unknown[],\n\tisBackward: boolean,\n): Record<string, unknown> {\n\tconst clauses: Record<string, unknown>[] = []\n\n\tfor (let i = 0; i < sortKeys.length; i++) {\n\t\tconst clause: Record<string, unknown> = {}\n\n\t\t// Equality prefix for all preceding fields\n\t\tfor (let j = 0; j < i; j++) {\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: index is bounded by outer loop\n\t\t\tclause[sortKeys[j]![0]] = values[j]\n\t\t}\n\n\t\t// Comparison operator for current field\n\t\t// Forward + asc = $gt, Forward + desc = $lt\n\t\t// Backward reverses: Backward + asc = $lt, Backward + desc = $gt\n\t\t// biome-ignore lint/style/noNonNullAssertion: index is bounded by loop\n\t\tconst [field, direction] = sortKeys[i]!\n\t\tconst isAsc = direction === 1\n\t\tconst op = isAsc !== isBackward ? '$gt' : '$lt'\n\n\t\t// MongoDB's $gt/$lt with null doesn't work for cursor pagination:\n\t\t// $gt: null only matches BSON types above null (regex, etc.), not\n\t\t// strings/numbers. $lt: null matches nothing. In both directions,\n\t\t// \"past null\" means \"not null\", so use $ne: null.\n\t\tif (values[i] === null) {\n\t\t\tclause[field] = { $ne: null }\n\t\t} else {\n\t\t\tclause[field] = { [op]: values[i] }\n\t\t}\n\n\t\tclauses.push(clause)\n\t}\n\n\treturn { $or: clauses }\n}\n\n// ── Sort resolution ─────────────────────────────────────────────────────\n\n/**\n * Resolve sort keys, always appending `_id` as tiebreaker if not present.\n * Defaults to `[['_id', 1]]` when no sort is specified.\n *\n * @example\n * ```ts\n * resolveSortKeys({ age: 1 }) // [['age', 1], ['_id', 1]]\n * resolveSortKeys(null) // [['_id', 1]]\n * resolveSortKeys({ _id: -1 }) // [['_id', -1]]\n * ```\n */\nexport function resolveSortKeys(sortSpec: Record<string, 1 | -1> | null): SortEntry[] {\n\tconst entries: SortEntry[] = sortSpec ? (Object.entries(sortSpec) as SortEntry[]) : []\n\n\tif (!entries.some(([field]) => field === '_id')) {\n\t\tentries.push(['_id', 1])\n\t}\n\n\treturn entries\n}\n","import type { TypedProjection } from '../query/projection'\n\n/**\n * Typed return value from {@link PopulateRefBuilder.project}.\n *\n * Carries the projection type `P` for compile-time narrowing in populate calls.\n * Callers never construct this directly — it is returned by the builder and\n * consumed by the `.populate()` overload to narrow the result type.\n *\n * @example\n * ```ts\n * // P is inferred as { name: 1; email: 1 } — post.authorId is narrowed accordingly\n * const post = await posts.findOne({}).populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n * ```\n */\nexport type PopulateProjectionConfig<P> = { readonly projection: P }\n\n/**\n * Fluent builder passed to populate projection callbacks.\n *\n * Call `.project()` to specify which fields to fetch from the referenced collection.\n * The projection type `P` flows back to the `.populate()` overload to narrow the\n * result type at compile time.\n *\n * @typeParam TDoc - The referenced document type (e.g. `InferDocument<typeof Users>`).\n *\n * @example\n * ```ts\n * posts.findOne({}).populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n * // post.authorId is narrowed to { _id: ObjectId; name: string; email: string }\n * ```\n */\nexport class PopulateRefBuilder<TDoc> {\n\t/**\n\t * Declare a projection to apply when fetching the referenced documents.\n\t *\n\t * Supported: inclusion (`{ name: 1 }`), exclusion (`{ email: 0 }`), or\n\t * `_id` suppression (`{ name: 1, _id: 0 }`).\n\t *\n\t * @param projection - MongoDB-style inclusion or exclusion projection.\n\t * @returns A config object carrying the projection type for compile-time narrowing.\n\t *\n\t * @example\n\t * ```ts\n\t * (b) => b.project({ name: 1, email: 1 })\n\t * (b) => b.project({ password: 0 })\n\t * ```\n\t */\n\tproject<P extends TypedProjection<TDoc>>(projection: P): PopulateProjectionConfig<P> {\n\t\treturn { projection }\n\t}\n}\n","import type { Collection, Document } from 'mongodb'\nimport { z } from 'zod'\nimport type { AnyCollection } from '../collection/types'\nimport { getRefMetadata } from '../schema/ref'\nimport type { PopulateStep } from './types'\n\n/**\n * Walk through Zod wrappers to find the inner schema with ref metadata.\n *\n * Mirrors the type-level `UnwrapRef<T>` at runtime. Peels ZodOptional,\n * ZodNullable, ZodDefault (via `_zod.def.innerType`), and ZodArray\n * (via `_zod.def.element`).\n *\n * @param schema - The Zod schema to unwrap.\n * @returns The innermost schema after stripping wrappers.\n *\n * @example\n * ```ts\n * const inner = unwrapRefSchema(Posts.shape.categoryIds)\n * const ref = getRefMetadata(inner) // { collection: Categories }\n * ```\n */\nexport function unwrapRefSchema(schema: z.ZodType): z.ZodType {\n\t// Cast through unknown because ZodType's _zod.def is a branded $ZodTypeDef\n\t// that lacks an index signature — not structurally assignable to Record<string, unknown>\n\tconst def = (schema as unknown as { _zod: { def: Record<string, unknown> } })._zod.def\n\t/* v8 ignore start */\n\tif (def && typeof def === 'object') {\n\t\tif ('innerType' in def && def.innerType instanceof z.ZodType) {\n\t\t\treturn unwrapRefSchema(def.innerType)\n\t\t}\n\t\tif ('element' in def && def.element instanceof z.ZodType) {\n\t\t\treturn unwrapRefSchema(def.element)\n\t\t}\n\t}\n\t/* v8 ignore stop */\n\treturn schema\n}\n\n/**\n * Look up a field schema from a collection shape and validate it has ref metadata.\n *\n * @returns An object with the field's `isArray` flag and the resolved `ref` metadata.\n * @throws When the field does not exist or has no `.ref()` metadata.\n */\nfunction resolveRefField(\n\tshape: Record<string, z.ZodType>,\n\tfieldName: string,\n\tcollectionName: string,\n): { isArray: boolean; ref: { collection: AnyCollection } } {\n\tconst fieldSchema = shape[fieldName]\n\tif (!fieldSchema) {\n\t\tthrow new Error(\n\t\t\t`[zodmon] populate: field '${fieldName}' does not exist on collection '${collectionName}'.`,\n\t\t)\n\t}\n\tconst isArray = fieldSchema instanceof z.ZodArray\n\tconst inner = unwrapRefSchema(fieldSchema)\n\tconst ref = getRefMetadata(inner)\n\tif (!ref) {\n\t\tthrow new Error(\n\t\t\t`[zodmon] populate: field '${fieldName}' has no .ref() metadata. ` +\n\t\t\t\t'Only fields declared with .ref(Collection) can be populated.',\n\t\t)\n\t}\n\treturn { isArray, ref }\n}\n\n/**\n * Resolve a `.populate()` call into a `PopulateStep`.\n *\n * For top-level fields, inspects the collection's shape directly.\n * For nested dot-paths, walks previous steps to find the parent\n * collection definition, then resolves the leaf field in that shape.\n *\n * @param definition - The root collection definition.\n * @param previousSteps - Steps from earlier `.populate()` calls.\n * @param path - The field path (e.g. `'authorId'` or `'author.companyId'`).\n * @param as - The output field name (renamed or original).\n * @param projection - Optional projection to pass to the `$in` query.\n * @returns A resolved `PopulateStep`.\n * @throws When the field has no `.ref()` metadata or the parent path is not populated.\n *\n * @example\n * ```ts\n * const step = resolvePopulateStep(Posts, [], 'authorId', 'author')\n * // { leafField: 'authorId', as: 'author', targetCollection: Users, ... }\n * ```\n */\nexport function resolvePopulateStep(\n\tdefinition: AnyCollection,\n\tpreviousSteps: readonly PopulateStep[],\n\tpath: string,\n\tas: string,\n\tprojection?: Record<string, 0 | 1 | boolean>,\n): PopulateStep {\n\tconst dotIndex = path.indexOf('.')\n\n\tif (dotIndex === -1) {\n\t\tconst shape = definition.shape as Record<string, z.ZodType>\n\t\tconst { isArray, ref } = resolveRefField(shape, path, definition.name)\n\t\treturn {\n\t\t\toriginalPath: path,\n\t\t\tleafField: path,\n\t\t\tas,\n\t\t\tparentOutputPath: undefined,\n\t\t\ttargetCollection: ref.collection,\n\t\t\tisArray,\n\t\t\t...(projection !== undefined ? { projection } : {}),\n\t\t}\n\t}\n\n\t// Nested path: split into parent and leaf\n\tconst parentPath = path.slice(0, dotIndex)\n\tconst leafField = path.slice(dotIndex + 1)\n\n\tconst parentStep = previousSteps.find((s) => s.as === parentPath)\n\tif (!parentStep) {\n\t\tthrow new Error(\n\t\t\t`[zodmon] populate: parent '${parentPath}' has not been populated. ` +\n\t\t\t\t`Populate '${parentPath}' before populating '${path}'.`,\n\t\t)\n\t}\n\n\tconst parentShape = parentStep.targetCollection.shape as Record<string, z.ZodType>\n\tconst { isArray, ref } = resolveRefField(parentShape, leafField, parentStep.targetCollection.name)\n\n\treturn {\n\t\toriginalPath: path,\n\t\tleafField,\n\t\tas,\n\t\tparentOutputPath: parentPath,\n\t\ttargetCollection: ref.collection,\n\t\tisArray,\n\t\t...(projection !== undefined ? { projection } : {}),\n\t}\n}\n\n/** Expand a document value into an array of child Document objects. */\nfunction expandValue(value: unknown): Document[] {\n\tif (value == null) return []\n\tif (Array.isArray(value)) {\n\t\tconst result: Document[] = []\n\t\tfor (const item of value) {\n\t\t\tif (item != null && typeof item === 'object') {\n\t\t\t\t// biome-ignore lint/suspicious/noExplicitAny: Document is a runtime MongoDB type; array elements are untyped\n\t\t\t\tresult.push(item as any)\n\t\t\t}\n\t\t}\n\t\treturn result\n\t}\n\tif (typeof value === 'object') {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: Document is a runtime MongoDB type; nested values are untyped\n\t\treturn [value as any]\n\t}\n\treturn []\n}\n\n/**\n * Navigate into a document by a dot-separated output path.\n *\n * Returns all target objects at the given path. Handles arrays by\n * flat-mapping into each element.\n *\n * @param doc - The root document.\n * @param path - A dot-separated path (e.g. `'author'` or `'author.company'`).\n * @returns Array of target objects at the path.\n *\n * @example\n * ```ts\n * const targets = getNestedTargets({ author: { name: 'Jo' } }, 'author')\n * // [{ name: 'Jo' }]\n * ```\n */\nfunction getNestedTargets(doc: Document, path: string): Document[] {\n\tconst parts = path.split('.')\n\tlet targets: Document[] = [doc]\n\n\tfor (const part of parts) {\n\t\ttargets = targets.flatMap((target) => expandValue(target[part]))\n\t}\n\n\treturn targets\n}\n\n/** Add a value to the unique ID set, returning whether it was new. */\nfunction addUniqueId(value: unknown, idSet: Set<string>, idValues: unknown[]): void {\n\tconst key = String(value)\n\tif (!idSet.has(key)) {\n\t\tidSet.add(key)\n\t\tidValues.push(value)\n\t}\n}\n\n/** Collect unique IDs from the leaf field across all target documents. */\nfunction collectIds(targets: Document[], leafField: string): unknown[] {\n\tconst idSet = new Set<string>()\n\tconst idValues: unknown[] = []\n\n\tfor (const target of targets) {\n\t\tconst value: unknown = target[leafField]\n\t\tif (value == null) continue\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const id of value) {\n\t\t\t\taddUniqueId(id, idSet, idValues)\n\t\t\t}\n\t\t} else {\n\t\t\taddUniqueId(value, idSet, idValues)\n\t\t}\n\t}\n\n\treturn idValues\n}\n\n/** Resolve the populated value for a single field, using the ID-to-document map. */\nfunction resolvePopulatedValue(\n\tvalue: unknown,\n\tmap: Map<string, Document>,\n): Document | Document[] | null | undefined {\n\tif (value == null) return value as null | undefined\n\tif (Array.isArray(value)) {\n\t\treturn value.map((id) => map.get(String(id))).filter((d): d is Document => d != null)\n\t}\n\treturn map.get(String(value)) ?? null\n}\n\n/** Apply populated data to the target documents, handling rename. */\nfunction mergePopulated(targets: Document[], step: PopulateStep, map: Map<string, Document>): void {\n\tfor (const target of targets) {\n\t\tconst value: unknown = target[step.leafField]\n\t\tconst populated = resolvePopulatedValue(value, map)\n\n\t\tif (step.as !== step.leafField) {\n\t\t\tdelete target[step.leafField]\n\t\t}\n\t\ttarget[step.as] = populated\n\t}\n}\n\n/**\n * Execute populate steps against a set of documents.\n *\n * Processes steps in order. For each step:\n * 1. Navigate to the parent level for nested paths\n * 2. Collect unique IDs from the leaf field\n * 3. Batch query the target collection with `$in`\n * 4. Merge results back, applying rename if needed\n *\n * Mutates the documents in place and returns them.\n *\n * @param documents - The documents to populate (mutated in place).\n * @param steps - The populate steps to execute in order.\n * @param getCollection - Function to get a native MongoDB Collection by name.\n * @returns The populated documents.\n *\n * @example\n * ```ts\n * const docs = await executePopulate(rawDocs, steps, name => db.collection(name))\n * ```\n */\nexport async function executePopulate(\n\tdocuments: Document[],\n\tsteps: readonly PopulateStep[],\n\tgetCollection: (name: string) => Collection,\n): Promise<Document[]> {\n\tfor (const step of steps) {\n\t\t// parentOutputPath is string | undefined; when defined, navigate to parent level\n\t\tconst targets = step.parentOutputPath\n\t\t\t? documents.flatMap((doc) => getNestedTargets(doc, step.parentOutputPath as string))\n\t\t\t: documents\n\n\t\tconst idValues = collectIds(targets, step.leafField)\n\t\tif (idValues.length === 0) continue\n\n\t\t// Batch $in query — idValues holds ObjectId instances at runtime but is typed\n\t\t// as unknown[] because the generic Document signature erases the concrete type.\n\t\t// MongoDB's Filter<Document> requires ReadonlyArray<any> for $in.\n\t\tconst col = getCollection(step.targetCollection.name)\n\t\tconst findOptions = step.projection !== undefined ? { projection: step.projection } : {}\n\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB $in filter requires any[] for untyped Document collections\n\t\tconst fetched = await col.find({ _id: { $in: idValues as any[] } }, findOptions).toArray()\n\n\t\t// Build ID -> document map\n\t\tconst map = new Map<string, Document>()\n\t\tfor (const doc of fetched) {\n\t\t\tmap.set(String(doc._id), doc)\n\t\t}\n\n\t\tmergePopulated(targets, step, map)\n\t}\n\n\treturn documents\n}\n","import type { Collection, Document } from 'mongodb'\nimport type { AnyCollection, InferDocument } from '../collection/types'\nimport type { TypedFindCursor } from '../query/cursor'\nimport type { ExtractRefCollection, RefFields } from '../schema/ref'\nimport type { PopulateProjectionConfig } from './builder'\nimport { PopulateRefBuilder } from './builder'\nimport { executePopulate, resolvePopulateStep } from './execute'\nimport type {\n\tApplyPopulate,\n\tApplyPopulateProjected,\n\tDeepPopulate,\n\tNestedRefPath,\n\tPopulateField,\n\tPopulateStep,\n} from './types'\n\n/**\n * Extract the parent segment from a dot-separated path.\n *\n * @example\n * ```ts\n * type P = ExtractParent<'author.companyId'> // 'author'\n * ```\n */\ntype ExtractParent<T extends string> = T extends `${infer P}.${string}` ? P : never\n\n/**\n * Extract the leaf segment from a dot-separated path.\n *\n * @example\n * ```ts\n * type L = ExtractLeaf<'author.companyId'> // 'companyId'\n * ```\n */\ntype ExtractLeaf<T extends string> = T extends `${string}.${infer L}` ? L : never\n\n/**\n * Cursor with chained populate steps, wrapping a {@link TypedFindCursor}.\n *\n * Created by calling `.populate()` on a `TypedFindCursor`. Exposes only\n * `.populate()` (for additional fields) and terminal methods (`toArray`,\n * async iteration). Cursor modifiers (`sort`, `skip`, `limit`) are not\n * available -- they must be called before `.populate()`.\n *\n * @typeParam TDef - The root collection definition type.\n * @typeParam TOutput - The current output document type after populate transforms.\n * @typeParam TPopMap - Map of populated alias names to their collection definitions,\n * used to resolve nested populate paths.\n *\n * @example\n * ```ts\n * const posts = await db.use(Posts)\n * .find({ published: true })\n * .sort({ createdAt: -1 })\n * .limit(10)\n * .populate('authorId', 'author')\n * .populate('categoryIds')\n * .toArray()\n * ```\n */\nexport class PopulateCursor<\n\tTDef extends AnyCollection,\n\tTOutput,\n\tTPopMap extends Record<string, AnyCollection> = Record<string, never>,\n> {\n\tprivate readonly cursor: TypedFindCursor<TDef>\n\tprivate readonly definition: TDef\n\tprivate readonly steps: readonly PopulateStep[]\n\tprivate readonly nativeCollection: Collection<InferDocument<TDef>>\n\n\t/** @internal */\n\tconstructor(\n\t\tcursor: TypedFindCursor<TDef>,\n\t\tdefinition: TDef,\n\t\tsteps: readonly PopulateStep[],\n\t\tnativeCollection: Collection<InferDocument<TDef>>,\n\t) {\n\t\tthis.cursor = cursor\n\t\tthis.definition = definition\n\t\tthis.steps = steps\n\t\tthis.nativeCollection = nativeCollection\n\t}\n\n\t/**\n\t * Populate a top-level ref field, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @returns A new cursor with the field type replaced by the referenced document.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId')\n\t * .toArray()\n\t * // posts[0].authorId is now a User document instead of ObjectId\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>>(\n\t\tfield: K,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K>,\n\t\tTPopMap & { [P in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field with a projection, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param configure - Callback receiving a builder; call `.project()` to set the projection.\n\t * @returns A new cursor with the field type narrowed to only the projected fields.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n\t * .toArray()\n\t * // posts[0].authorId is { _id: ObjectId; name: string; email: string }\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, P>(\n\t\tfield: K,\n\t\tconfigure: (\n\t\t\tb: PopulateRefBuilder<InferDocument<ExtractRefCollection<TDef, K>>>,\n\t\t) => PopulateProjectionConfig<P>,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulateProjected<TOutput, TDef, K, P>,\n\t\tTPopMap & { [F in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field and rename it in the output.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param as - The new field name in the output document.\n\t * @returns A new cursor with the old field removed and the new field added.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', 'author')\n\t * .toArray()\n\t * // posts[0].author is a User document; posts[0].authorId no longer exists\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, TAs extends string>(\n\t\tfield: K,\n\t\tas: TAs,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K, TAs>,\n\t\tTPopMap & { [P in TAs]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a nested ref field, keeping the leaf field name.\n\t *\n\t * The parent path must have been populated in a previous `.populate()` call.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @returns A new cursor with the nested field type replaced.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId')\n\t * .toArray()\n\t * // posts[0].author.companyId is now a Company document\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>>(\n\t\tpath: TPath,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t/**\n\t * Populate a nested ref field and rename the leaf in the output.\n\t *\n\t * The parent path must have been populated in a previous `.populate()` call.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @param as - The new name for the leaf field in the output.\n\t * @returns A new cursor with the nested field renamed and typed.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId', 'company')\n\t * .toArray()\n\t * // posts[0].author.company is a Company document\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>, TAs extends string>(\n\t\tpath: TPath,\n\t\tas: TAs,\n\t): PopulateCursor<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${TAs}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tTAs,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${TAs}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t// Implementation -- TypeScript cannot narrow overloaded generics in the\n\t// implementation body, so param types are widened and the return is cast.\n\tpopulate(\n\t\tfield: string,\n\t\tasOrConfigure?:\n\t\t\t| string\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TDoc is phantom; widened for overload implementation\n\t\t\t| ((b: PopulateRefBuilder<any>) => PopulateProjectionConfig<unknown>),\n\t): PopulateCursor<TDef, unknown, Record<string, AnyCollection>> {\n\t\tlet alias: string\n\t\tlet projection: Record<string, 0 | 1 | boolean> | undefined\n\n\t\tif (typeof asOrConfigure === 'function') {\n\t\t\t/* v8 ignore start */\n\t\t\talias = field.includes('.') ? (field.split('.').pop() ?? field) : field\n\t\t\t/* v8 ignore stop */\n\t\t\tconst config = asOrConfigure(new PopulateRefBuilder())\n\t\t\t// Safe: PopulateProjectionConfig<P>.projection is P extends TypedProjection<TDoc>\n\t\t\t// which has values 0|1|true|false — all assignable to 0|1|boolean.\n\t\t\tprojection = config.projection as Record<string, 0 | 1 | boolean>\n\t\t} else {\n\t\t\t/* v8 ignore start */\n\t\t\talias = asOrConfigure ?? (field.includes('.') ? (field.split('.').pop() ?? field) : field)\n\t\t\t/* v8 ignore stop */\n\t\t\tprojection = undefined\n\t\t}\n\n\t\tconst step = resolvePopulateStep(this.definition, this.steps, field, alias, projection)\n\t\tconst newSteps = [...this.steps, step]\n\t\t// Safe cast: the overload signatures carry the correct generic types;\n\t\t// the implementation cannot prove them due to TypeScript's overload limitation.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation requires widened return\n\t\treturn new PopulateCursor(this.cursor, this.definition, newSteps, this.nativeCollection) as any\n\t}\n\n\t/**\n\t * Execute the query and return all matching documents as a populated array.\n\t *\n\t * Fetches all documents from the underlying cursor, then applies populate\n\t * steps in order using batch `$in` queries (no N+1 problem).\n\t *\n\t * @returns Array of populated documents.\n\t *\n\t * @example\n\t * ```ts\n\t * const posts = await db.use(Posts)\n\t * .find({})\n\t * .populate('authorId', 'author')\n\t * .toArray()\n\t * ```\n\t */\n\tasync toArray(): Promise<TOutput[]> {\n\t\tconst docs = await this.cursor.toArray()\n\t\t/* v8 ignore start */\n\t\tif (this.steps.length === 0) return docs as unknown as TOutput[]\n\t\t/* v8 ignore stop */\n\n\t\tconst populated = await executePopulate(\n\t\t\tdocs as unknown as Document[],\n\t\t\tthis.steps,\n\t\t\t(name: string) => this.nativeCollection.db.collection(name),\n\t\t)\n\t\treturn populated as unknown as TOutput[]\n\t}\n\n\t/**\n\t * Async iterator for streaming populated documents.\n\t *\n\t * Fetches all documents first (populate requires the full batch for\n\t * efficient `$in` queries), then yields results one at a time.\n\t *\n\t * @yields Populated documents one at a time.\n\t *\n\t * @example\n\t * ```ts\n\t * for await (const post of db.use(Posts).find({}).populate('authorId', 'author')) {\n\t * console.log(post.author.name)\n\t * }\n\t * ```\n\t */\n\tasync *[Symbol.asyncIterator](): AsyncGenerator<TOutput> {\n\t\tconst results = await this.toArray()\n\t\tfor (const doc of results) {\n\t\t\tyield doc\n\t\t}\n\t}\n}\n\n/**\n * Create a new {@link PopulateCursor} from a {@link TypedFindCursor}.\n *\n * This factory function exists to break the circular import between\n * `query/cursor.ts` and `populate/cursor.ts`. The `TypedFindCursor.populate()`\n * method uses a lazy `require()` to call this function at runtime.\n *\n * @param cursor - The typed find cursor to wrap.\n * @param definition - The collection definition.\n * @param steps - Initial populate steps (typically empty).\n * @returns A new PopulateCursor instance.\n *\n * @example\n * ```ts\n * const popCursor = createPopulateCursor(typedCursor, Posts, [])\n * ```\n */\nexport function createPopulateCursor<TDef extends AnyCollection>(\n\tcursor: TypedFindCursor<TDef>,\n\tdefinition: TDef,\n\tsteps: readonly PopulateStep[],\n): PopulateCursor<TDef, InferDocument<TDef>> {\n\t// Access nativeCollection from the cursor's internal field.\n\t// TypedFindCursor exposes `nativeCollection` as a readonly @internal field.\n\tconst nativeCollection = (\n\t\tcursor as unknown as { nativeCollection: Collection<InferDocument<TDef>> }\n\t).nativeCollection\n\treturn new PopulateCursor(cursor, definition, steps, nativeCollection)\n}\n","import type { z } from 'zod'\nimport type { Prettify } from '../helpers/types'\n\ntype IncludeValue = 1 | true\ntype ExcludeValue = 0 | false\n\n/**\n * Inclusion projection — maps document fields to `1 | true`.\n *\n * Allows `_id: 0 | false` to suppress the `_id` field from the result.\n * All other fields only accept inclusion values (`1` or `true`).\n *\n * @example\n * ```ts\n * type UserInclusion = InclusionProjection<User>\n * const proj: UserInclusion = { name: 1, email: 1 }\n * const withoutId: UserInclusion = { name: 1, _id: 0 }\n * ```\n */\nexport type InclusionProjection<T> = {\n\t[K in keyof T & string]?: K extends '_id' ? IncludeValue | ExcludeValue : IncludeValue\n}\n\n/**\n * Exclusion projection — maps document fields to `0 | false`.\n *\n * Removes the specified fields from the result, keeping all others.\n *\n * @example\n * ```ts\n * type UserExclusion = ExclusionProjection<User>\n * const proj: UserExclusion = { email: 0, age: 0 }\n * ```\n */\nexport type ExclusionProjection<T> = { [K in keyof T & string]?: ExcludeValue }\n\n/**\n * Union of inclusion or exclusion projection for a document type `T`.\n *\n * MongoDB projections must be either all-inclusion or all-exclusion (with the\n * exception of `_id`, which can always be excluded). This type enforces that\n * constraint at the type level.\n *\n * @example\n * ```ts\n * type UserProjection = TypedProjection<User>\n * const include: UserProjection = { name: 1, email: 1 }\n * const exclude: UserProjection = { email: 0, age: 0 }\n * ```\n */\nexport type TypedProjection<T> = InclusionProjection<T> | ExclusionProjection<T>\n\n/** True if any key in `P` (excluding `_id`) has value `1 | true`. */\ntype IsInclusion<P> = true extends {\n\t[K in keyof P]: K extends '_id' ? never : P[K] extends IncludeValue ? true : never\n}[keyof P]\n\t? true\n\t: false\n\n/** Keys of `P` whose value is `1 | true` (excluding `_id`). */\ntype IncludedKeys<P> = {\n\t[K in keyof P]: K extends '_id' ? never : P[K] extends IncludeValue ? K : never\n}[keyof P]\n\n/** Keys of `P` whose value is `0 | false`. */\ntype ExcludedKeys<P> = {\n\t[K in keyof P]: P[K] extends ExcludeValue ? K : never\n}[keyof P]\n\n/** True if `P` has `_id` set to `0 | false`. */\ntype IsIdSuppressed<P> = '_id' extends keyof P\n\t? P['_id'] extends ExcludeValue\n\t\t? true\n\t\t: false\n\t: false\n\n/**\n * Computes the result type after applying a projection `P` to document type `T`.\n *\n * For inclusion projections (`{ name: 1 }`), returns only the included fields\n * plus `_id` (unless `_id: 0` is specified). For exclusion projections\n * (`{ email: 0 }`), returns all fields except the excluded ones.\n *\n * @example\n * ```ts\n * type User = { _id: ObjectId; name: string; email: string; age: number }\n *\n * // Inclusion: picks name + _id\n * type A = ProjectionResult<User, { name: 1 }>\n * // ^? { _id: ObjectId; name: string }\n *\n * // Inclusion with _id suppressed\n * type B = ProjectionResult<User, { name: 1; _id: 0 }>\n * // ^? { name: string }\n *\n * // Exclusion: drops email\n * type C = ProjectionResult<User, { email: 0 }>\n * // ^? { _id: ObjectId; name: string; age: number }\n * ```\n */\nexport type ProjectionResult<T, P> =\n\tIsInclusion<P> extends true\n\t\t? IsIdSuppressed<P> extends true\n\t\t\t? Prettify<Pick<T, IncludedKeys<P> & keyof T>>\n\t\t\t: Prettify<Pick<T, (IncludedKeys<P> | '_id') & keyof T>>\n\t\t: IsIdSuppressed<P> extends true\n\t\t\t? Prettify<Omit<T, ExcludedKeys<P>>>\n\t\t\t: Prettify<Omit<T, Exclude<ExcludedKeys<P>, '_id'>>>\n\n/** Returns `true` if the value represents an inclusion (`1` or `true`). */\nfunction isIncludeValue(value: 0 | 1 | boolean): boolean {\n\treturn value === 1 || value === true\n}\n\n/** Returns `true` if the value represents an exclusion (`0` or `false`). */\nfunction isExcludeValue(value: 0 | 1 | boolean): boolean {\n\treturn value === 0 || value === false\n}\n\n/**\n * Returns `true` if the projection is an inclusion projection.\n *\n * A projection is considered inclusion when any key other than `_id` has\n * a value of `1` or `true`. This mirrors the MongoDB rule: you cannot mix\n * inclusion and exclusion (except for `_id`, which may always be suppressed).\n *\n * @example\n * ```ts\n * isInclusionProjection({ name: 1 }) // true\n * isInclusionProjection({ name: 1, _id: 0 }) // true\n * isInclusionProjection({ email: 0 }) // false\n * ```\n */\nexport function isInclusionProjection(projection: Record<string, 0 | 1 | boolean>): boolean {\n\tfor (const key of Object.keys(projection)) {\n\t\tif (key === '_id') continue\n\t\tconst value = projection[key]\n\t\tif (value !== undefined && isIncludeValue(value)) return true\n\t}\n\treturn false\n}\n\n/** Builds a `pick` mask for an inclusion projection. */\nfunction buildPickMask(\n\tprojection: Record<string, 0 | 1 | boolean>,\n\tschemaKeys: Set<string>,\n): Record<string, true> {\n\tconst mask: Record<string, true> = {}\n\n\t// Always include _id unless explicitly suppressed\n\tconst idValue = projection._id\n\tif (!(idValue !== undefined && isExcludeValue(idValue)) && schemaKeys.has('_id')) {\n\t\tmask._id = true\n\t}\n\n\tfor (const key of Object.keys(projection)) {\n\t\tif (key === '_id') continue\n\t\tconst value = projection[key]\n\t\tif (value !== undefined && isIncludeValue(value) && schemaKeys.has(key)) {\n\t\t\tmask[key] = true\n\t\t}\n\t}\n\n\treturn mask\n}\n\n/** Builds an `omit` mask for an exclusion projection. */\nfunction buildOmitMask(\n\tprojection: Record<string, 0 | 1 | boolean>,\n\tschemaKeys: Set<string>,\n): Record<string, true> {\n\tconst mask: Record<string, true> = {}\n\n\tfor (const key of Object.keys(projection)) {\n\t\tconst value = projection[key]\n\t\tif (value !== undefined && isExcludeValue(value) && schemaKeys.has(key)) {\n\t\t\tmask[key] = true\n\t\t}\n\t}\n\n\treturn mask\n}\n\n/**\n * Derives a scoped Zod schema by applying a MongoDB-style projection.\n *\n * For inclusion projections (`{ name: 1, email: 1 }`), returns a schema with\n * only the specified fields plus `_id` (unless `_id: 0`). For exclusion\n * projections (`{ email: 0 }`), returns a schema with the specified fields\n * removed.\n *\n * Keys not present in the original schema are silently ignored.\n *\n * @example\n * ```ts\n * const userSchema = z.object({\n * _id: z.string(),\n * name: z.string(),\n * email: z.string(),\n * age: z.number(),\n * })\n *\n * // Inclusion: picks name + email + _id\n * const projected = deriveProjectedSchema(userSchema, { name: 1, email: 1 })\n *\n * // Exclusion: drops email\n * const excluded = deriveProjectedSchema(userSchema, { email: 0 })\n * ```\n */\nexport function deriveProjectedSchema(\n\tschema: z.ZodObject<z.core.$ZodShape>,\n\tprojection: Record<string, 0 | 1 | boolean>,\n): z.ZodObject<z.core.$ZodShape> {\n\tconst schemaKeys = new Set(Object.keys(schema.shape))\n\n\tif (isInclusionProjection(projection)) {\n\t\treturn schema.pick(buildPickMask(projection, schemaKeys))\n\t}\n\n\treturn schema.omit(buildOmitMask(projection, schemaKeys))\n}\n","import { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, InferInsert } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\n\n/**\n * Insert a single document into the collection.\n *\n * Validates the input against the collection's Zod schema before writing.\n * Schema defaults (including auto-generated `_id`) are applied during\n * validation. Returns the full document with all defaults filled in.\n *\n * @param handle - The collection handle to insert into.\n * @param doc - The document to insert. Fields with `.default()` are optional.\n * @returns The inserted document with `_id` and all defaults applied.\n * @throws {ZodmonValidationError} When the document fails schema validation.\n *\n * @example\n * ```ts\n * const user = await insertOne(users, { name: 'Ada' })\n * console.log(user._id) // ObjectId (auto-generated)\n * console.log(user.role) // 'user' (schema default)\n * ```\n */\nexport async function insertOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tdoc: InferInsert<TDef>,\n): Promise<InferDocument<TDef>> {\n\tlet parsed: InferDocument<TDef>\n\ttry {\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\tparsed = handle.definition.schema.parse(doc) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, doc)\n\t\t}\n\t\tthrow err\n\t}\n\t// Safe cast: parsed is a full document with _id, matching the collection's\n\t// document type. MongoDB driver's OptionalUnlessRequiredId makes _id optional\n\t// for generic types, but we always have _id after parse.\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertOne parameter type uses OptionalUnlessRequiredId which is not directly assignable from our generic InferDocument\n\t\tawait handle.native.insertOne(parsed as any, handle.session ? { session: handle.session } : {})\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\treturn parsed\n}\n\n/**\n * Insert multiple documents into the collection.\n *\n * Validates every document against the collection's Zod schema before\n * writing any to MongoDB. If any document fails validation, none are\n * inserted (fail-fast before the driver call).\n *\n * @param handle - The collection handle to insert into.\n * @param docs - The documents to insert.\n * @returns The inserted documents with `_id` and all defaults applied.\n * @throws {ZodmonValidationError} When any document fails schema validation.\n *\n * @example\n * ```ts\n * const users = await insertMany(handle, [\n * { name: 'Ada' },\n * { name: 'Bob', role: 'admin' },\n * ])\n * ```\n */\nexport async function insertMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tdocs: InferInsert<TDef>[],\n): Promise<InferDocument<TDef>[]> {\n\tif (docs.length === 0) return []\n\tconst parsed: InferDocument<TDef>[] = []\n\tfor (const doc of docs) {\n\t\ttry {\n\t\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\t\tparsed.push(handle.definition.schema.parse(doc) as InferDocument<TDef>)\n\t\t} catch (err) {\n\t\t\tif (err instanceof z.ZodError) {\n\t\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, doc)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n\ttry {\n\t\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertMany parameter type is not directly assignable from our generic InferDocument\n\t\tawait handle.native.insertMany(parsed as any, handle.session ? { session: handle.session } : {})\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\treturn parsed\n}\n","import type { UpdateResult } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\nimport { wrapMongoError } from '../errors/wrap'\nimport type { TypedFilter } from '../query/filter'\nimport type { TypedUpdateFilter } from '../query/update'\n\n/**\n * Options for {@link updateOne} and {@link updateMany}.\n */\nexport type UpdateOptions = {\n\t/** When `true`, inserts a new document if no document matches the filter. */\n\tupsert?: boolean\n}\n\n/**\n * Options for {@link findOneAndUpdate}.\n */\nexport type FindOneAndUpdateOptions = {\n\t/** Whether to return the document before or after the update. Defaults to `'after'`. */\n\treturnDocument?: 'before' | 'after'\n\t/** When `true`, inserts a new document if no document matches the filter. */\n\tupsert?: boolean\n\t/** Override the collection-level validation mode, or `false` to skip validation entirely. */\n\tvalidate?: ValidationMode | false\n}\n\n/**\n * Update a single document matching the filter.\n *\n * Applies the update operators to the first document that matches the filter.\n * Does not validate the update against the Zod schema — validation happens\n * at the field-operator level through {@link TypedUpdateFilter}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings such as `upsert`.\n * @returns The MongoDB `UpdateResult` with match/modify counts.\n *\n * @example\n * ```ts\n * const result = await updateOne(users, { name: 'Ada' }, { $set: { role: 'admin' } })\n * console.log(result.modifiedCount) // 1\n * ```\n */\nexport async function updateOne<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: UpdateOptions,\n): Promise<UpdateResult> {\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\ttry {\n\t\treturn await handle.native.updateOne(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter\n\t\t\tupdate as any,\n\t\t\thandle.session ? { ...options, session: handle.session } : options,\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Update all documents matching the filter.\n *\n * Applies the update operators to every document that matches the filter.\n * Does not validate the update against the Zod schema — validation happens\n * at the field-operator level through {@link TypedUpdateFilter}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings such as `upsert`.\n * @returns The MongoDB `UpdateResult` with match/modify counts.\n *\n * @example\n * ```ts\n * const result = await updateMany(users, { role: 'guest' }, { $set: { role: 'user' } })\n * console.log(result.modifiedCount) // number of guests promoted\n * ```\n */\nexport async function updateMany<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: UpdateOptions,\n): Promise<UpdateResult> {\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\ttry {\n\t\treturn await handle.native.updateMany(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter\n\t\t\tupdate as any,\n\t\t\thandle.session ? { ...options, session: handle.session } : options,\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n}\n\n/**\n * Find a single document matching the filter, apply an update, and return the document.\n *\n * By default, returns the document **after** the update is applied. Set\n * `returnDocument: 'before'` to get the pre-update snapshot. The returned\n * document is validated against the collection's Zod schema using the same\n * resolution logic as {@link findOne}.\n *\n * @param handle - The collection handle to update in.\n * @param filter - Type-safe filter to match documents.\n * @param update - Type-safe update operators to apply.\n * @param options - Optional settings: `returnDocument`, `upsert`, `validate`.\n * @returns The matched document (before or after update), or `null` if no document matches.\n * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n *\n * @example\n * ```ts\n * const user = await findOneAndUpdate(\n * users,\n * { name: 'Ada' },\n * { $set: { role: 'admin' } },\n * )\n * if (user) console.log(user.role) // 'admin' (returned after update)\n * ```\n *\n * @example\n * ```ts\n * const before = await findOneAndUpdate(\n * users,\n * { name: 'Ada' },\n * { $inc: { loginCount: 1 } },\n * { returnDocument: 'before' },\n * )\n * ```\n */\nexport async function findOneAndUpdate<TDef extends AnyCollection>(\n\thandle: CollectionHandle<TDef>,\n\tfilter: TypedFilter<InferDocument<TDef>>,\n\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\toptions?: FindOneAndUpdateOptions,\n): Promise<InferDocument<TDef> | null> {\n\tconst driverOptions: Record<string, unknown> = {\n\t\treturnDocument: options?.returnDocument ?? 'after',\n\t\tincludeResultMetadata: false,\n\t}\n\tif (options?.upsert !== undefined) {\n\t\tdriverOptions['upsert'] = options.upsert\n\t}\n\tif (handle.session) {\n\t\tdriverOptions['session'] = handle.session\n\t}\n\t// Safe cast: TypedFilter and TypedUpdateFilter are strict subsets of\n\t// MongoDB's Filter<T> and UpdateFilter<T>, but the intersection-based\n\t// mapped types cannot be structurally matched by the driver's looser types.\n\t// The options object is built dynamically to satisfy exactOptionalPropertyTypes.\n\t// biome-ignore lint/suspicious/noExplicitAny: declaring result before try/catch for driver error wrapping; the actual value is assigned inside try and is non-null after the catch (wrapMongoError is never-returning)\n\tlet result: any\n\ttry {\n\t\tresult = await handle.native.findOneAndUpdate(\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\t\t\tfilter as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter\n\t\t\tupdate as any,\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic options object is not assignable to driver's FindOneAndUpdateOptions under exactOptionalPropertyTypes\n\t\t\tdriverOptions as any,\n\t\t)\n\t} catch (err) {\n\t\twrapMongoError(err, handle.definition.name)\n\t}\n\tif (!result) return null\n\n\tconst mode =\n\t\toptions?.validate !== undefined ? options.validate : handle.definition.options.validation\n\n\tif (mode === false || mode === 'passthrough') {\n\t\t// Safe cast: raw document from MongoDB matches the collection's document\n\t\t// shape at runtime. Skipping validation per user request.\n\t\treturn result as InferDocument<TDef>\n\t}\n\n\ttry {\n\t\tconst schema = mode === 'strict' ? handle.definition.strictSchema : handle.definition.schema\n\t\t// Safe cast: schema.parse() returns z.infer<schema> which equals\n\t\t// InferDocument<TDef>, but TypeScript cannot prove this for\n\t\t// generic TDef. The runtime type is guaranteed correct by Zod.\n\t\treturn schema.parse(result) as InferDocument<TDef>\n\t} catch (err) {\n\t\tif (err instanceof z.ZodError) {\n\t\t\tthrow new ZodmonValidationError(handle.definition.name, err, result)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { Document } from 'mongodb'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument } from '../collection/types'\nimport type { FindOneOptions } from '../crud/find'\nimport { findOne as _findOne } from '../crud/find'\nimport { ZodmonNotFoundError } from '../errors/not-found'\nimport type { TypedFilter } from '../query/filter'\nimport type { ExtractRefCollection, RefFields } from '../schema/ref'\nimport type { PopulateProjectionConfig } from './builder'\nimport { PopulateRefBuilder } from './builder'\nimport { executePopulate, resolvePopulateStep } from './execute'\nimport type {\n\tApplyPopulate,\n\tApplyPopulateProjected,\n\tDeepPopulate,\n\tNestedRefPath,\n\tPopulateField,\n\tPopulateStep,\n} from './types'\n\n/**\n * Extract the parent segment from a dot-separated path.\n *\n * @example\n * ```ts\n * type P = ExtractParent<'author.companyId'> // 'author'\n * ```\n */\ntype ExtractParent<T extends string> = T extends `${infer P}.${string}` ? P : never\n\n/**\n * Extract the leaf segment from a dot-separated path.\n *\n * @example\n * ```ts\n * type L = ExtractLeaf<'author.companyId'> // 'companyId'\n * ```\n */\ntype ExtractLeaf<T extends string> = T extends `${string}.${infer L}` ? L : never\n\n/**\n * Fluent populate builder for findOne queries.\n *\n * Implements `PromiseLike` so it can be awaited directly without `.populate()`.\n * Each `.populate()` call returns a new builder with updated generics.\n *\n * @example\n * ```ts\n * // Without populate (backward compatible)\n * const post = await posts.findOne({ title: 'Hello' })\n *\n * // With populate\n * const post = await posts.findOne({ title: 'Hello' })\n * .populate('authorId', 'author')\n * .populate('author.companyId', 'company')\n * ```\n */\nexport class PopulateOneQuery<\n\tTDef extends AnyCollection,\n\tTOutput,\n\tTPopMap extends Record<string, AnyCollection> = Record<string, never>,\n> implements PromiseLike<TOutput | null>\n{\n\tprivate readonly handle: CollectionHandle<TDef>\n\tprivate readonly filter: TypedFilter<InferDocument<TDef>>\n\tprivate readonly options: FindOneOptions | undefined\n\tprivate readonly steps: readonly PopulateStep[]\n\n\tconstructor(\n\t\thandle: CollectionHandle<TDef>,\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions: FindOneOptions | undefined,\n\t\tsteps: readonly PopulateStep[] = [],\n\t) {\n\t\tthis.handle = handle\n\t\tthis.filter = filter\n\t\tthis.options = options\n\t\tthis.steps = steps\n\t}\n\n\t/**\n\t * Populate a top-level ref field, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @returns A new builder with the field type replaced by the referenced document.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId')\n\t * // post.authorId is now a User document instead of ObjectId\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>>(\n\t\tfield: K,\n\t): PopulateOneQuery<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K>,\n\t\tTPopMap & { [P in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field with a projection, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param configure - Callback receiving a builder; call `.project()` to set the projection.\n\t * @returns A new builder with the field type narrowed to only the projected fields.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n\t * // post.authorId is { _id: ObjectId; name: string; email: string }\n\t * // post.authorId.age → TS error\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, P>(\n\t\tfield: K,\n\t\tconfigure: (\n\t\t\tb: PopulateRefBuilder<InferDocument<ExtractRefCollection<TDef, K>>>,\n\t\t) => PopulateProjectionConfig<P>,\n\t): PopulateOneQuery<\n\t\tTDef,\n\t\tApplyPopulateProjected<TOutput, TDef, K, P>,\n\t\tTPopMap & { [F in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field and rename it in the output.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param as - The new field name in the output document.\n\t * @returns A new builder with the old field removed and the new field added.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * // post.author is a User document; post.authorId no longer exists\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, TAs extends string>(\n\t\tfield: K,\n\t\tas: TAs,\n\t): PopulateOneQuery<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K, TAs>,\n\t\tTPopMap & { [P in TAs]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a nested ref field, keeping the leaf field name.\n\t *\n\t * The parent path must have been populated in a previous `.populate()` call.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @returns A new builder with the nested field type replaced.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId')\n\t * // post.author.companyId is now a Company document\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>>(\n\t\tpath: TPath,\n\t): PopulateOneQuery<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t/**\n\t * Populate a nested ref field and rename the leaf in the output.\n\t *\n\t * The parent path must have been populated in a previous `.populate()` call.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @param as - The new name for the leaf field in the output.\n\t * @returns A new builder with the nested field renamed and typed.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId', 'company')\n\t * // post.author.company is a Company document\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>, TAs extends string>(\n\t\tpath: TPath,\n\t\tas: TAs,\n\t): PopulateOneQuery<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${TAs}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tTAs,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${TAs}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t// Implementation — TypeScript cannot narrow overloaded generics in the\n\t// implementation body, so param types are widened and the return is cast.\n\tpopulate(\n\t\tfield: string,\n\t\tasOrConfigure?:\n\t\t\t| string\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TDoc is phantom; widened for overload implementation\n\t\t\t| ((b: PopulateRefBuilder<any>) => PopulateProjectionConfig<unknown>),\n\t): PopulateOneQuery<TDef, unknown, Record<string, AnyCollection>> {\n\t\tlet alias: string\n\t\tlet projection: Record<string, 0 | 1 | boolean> | undefined\n\n\t\tif (typeof asOrConfigure === 'function') {\n\t\t\t/* v8 ignore start */\n\t\t\talias = field.includes('.') ? (field.split('.').pop() ?? field) : field\n\t\t\t/* v8 ignore stop */\n\t\t\tconst config = asOrConfigure(new PopulateRefBuilder())\n\t\t\t// Safe: PopulateProjectionConfig<P>.projection is P extends TypedProjection<TDoc>\n\t\t\t// which has values 0|1|true|false — all assignable to 0|1|boolean.\n\t\t\tprojection = config.projection as Record<string, 0 | 1 | boolean>\n\t\t} else {\n\t\t\t/* v8 ignore start */\n\t\t\talias = asOrConfigure ?? (field.includes('.') ? (field.split('.').pop() ?? field) : field)\n\t\t\t/* v8 ignore stop */\n\t\t\tprojection = undefined\n\t\t}\n\n\t\tconst step = resolvePopulateStep(this.handle.definition, this.steps, field, alias, projection)\n\t\tconst newSteps = [...this.steps, step]\n\t\t// Safe cast: the overload signatures carry the correct generic types;\n\t\t// the implementation cannot prove them due to TypeScript's overload limitation.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation requires widened return\n\t\treturn new PopulateOneQuery(this.handle, this.filter, this.options, newSteps) as any\n\t}\n\n\t/**\n\t * Attach fulfillment and rejection handlers to the query promise.\n\t *\n\t * Executes the base findOne query and applies populate steps if any.\n\t * Returns `null` when no document matches the filter.\n\t */\n\t// biome-ignore lint/suspicious/noThenProperty: PromiseLike requires a then method\n\tthen<TResult1 = TOutput | null, TResult2 = never>(\n\t\tonfulfilled?: ((value: TOutput | null) => TResult1 | PromiseLike<TResult1>) | null,\n\t\tonrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n\t): Promise<TResult1 | TResult2> {\n\t\tconst promise = this.execute()\n\t\treturn promise.then(onfulfilled, onrejected)\n\t}\n\n\tprivate async execute(): Promise<TOutput | null> {\n\t\tconst doc = await _findOne(this.handle, this.filter, this.options)\n\t\tif (!doc) return null\n\t\t/* v8 ignore start */\n\t\tif (this.steps.length === 0) return doc as unknown as TOutput\n\t\t/* v8 ignore stop */\n\n\t\tconst populated = await executePopulate([doc as Document], this.steps, (name) =>\n\t\t\tthis.handle.native.db.collection(name),\n\t\t)\n\t\t/* v8 ignore start */\n\t\treturn (populated[0] ?? null) as unknown as TOutput\n\t\t/* v8 ignore stop */\n\t}\n}\n\n/**\n * Fluent populate builder for findOneOrThrow queries.\n *\n * Identical to {@link PopulateOneQuery} but resolves to `TOutput` (never null).\n * Throws {@link ZodmonNotFoundError} when no document matches the filter.\n *\n * @example\n * ```ts\n * const post = await posts.findOneOrThrow({ title: 'Hello' })\n * .populate('authorId', 'author')\n * // Guaranteed non-null; throws if not found\n * ```\n */\nexport class PopulateOneOrThrowQuery<\n\tTDef extends AnyCollection,\n\tTOutput,\n\tTPopMap extends Record<string, AnyCollection> = Record<string, never>,\n> implements PromiseLike<TOutput>\n{\n\tprivate readonly handle: CollectionHandle<TDef>\n\tprivate readonly filter: TypedFilter<InferDocument<TDef>>\n\tprivate readonly options: FindOneOptions | undefined\n\tprivate readonly steps: readonly PopulateStep[]\n\n\tconstructor(\n\t\thandle: CollectionHandle<TDef>,\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions: FindOneOptions | undefined,\n\t\tsteps: readonly PopulateStep[] = [],\n\t) {\n\t\tthis.handle = handle\n\t\tthis.filter = filter\n\t\tthis.options = options\n\t\tthis.steps = steps\n\t}\n\n\t/**\n\t * Populate a top-level ref field, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @returns A new builder with the field type replaced by the referenced document.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId')\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>>(\n\t\tfield: K,\n\t): PopulateOneOrThrowQuery<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K>,\n\t\tTPopMap & { [P in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field with a projection, keeping the original field name.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param configure - Callback receiving a builder; call `.project()` to set the projection.\n\t * @returns A new builder with the field type narrowed to only the projected fields.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId', (b) => b.project({ name: 1, email: 1 }))\n\t * // post.authorId is { _id: ObjectId; name: string; email: string }\n\t * // post.authorId.age → TS error\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, P>(\n\t\tfield: K,\n\t\tconfigure: (\n\t\t\tb: PopulateRefBuilder<InferDocument<ExtractRefCollection<TDef, K>>>,\n\t\t) => PopulateProjectionConfig<P>,\n\t): PopulateOneOrThrowQuery<\n\t\tTDef,\n\t\tApplyPopulateProjected<TOutput, TDef, K, P>,\n\t\tTPopMap & { [F in K]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a top-level ref field and rename it in the output.\n\t *\n\t * @param field - A ref-bearing field name on the root collection.\n\t * @param as - The new field name in the output document.\n\t * @returns A new builder with the old field removed and the new field added.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * ```\n\t */\n\tpopulate<K extends RefFields<TDef>, TAs extends string>(\n\t\tfield: K,\n\t\tas: TAs,\n\t): PopulateOneOrThrowQuery<\n\t\tTDef,\n\t\tApplyPopulate<TOutput, TDef, K, TAs>,\n\t\tTPopMap & { [P in TAs]: ExtractRefCollection<TDef, K> }\n\t>\n\t/**\n\t * Populate a nested ref field, keeping the leaf field name.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @returns A new builder with the nested field type replaced.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId')\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>>(\n\t\tpath: TPath,\n\t): PopulateOneOrThrowQuery<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${ExtractLeaf<TPath>}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t/**\n\t * Populate a nested ref field and rename the leaf in the output.\n\t *\n\t * @param path - A dot-separated path like `'author.companyId'`.\n\t * @param as - The new name for the leaf field in the output.\n\t * @returns A new builder with the nested field renamed and typed.\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * .populate('author.companyId', 'company')\n\t * ```\n\t */\n\tpopulate<TPath extends NestedRefPath<TPopMap>, TAs extends string>(\n\t\tpath: TPath,\n\t\tas: TAs,\n\t): PopulateOneOrThrowQuery<\n\t\tTDef,\n\t\tDeepPopulate<\n\t\t\tTOutput,\n\t\t\t`${ExtractParent<TPath>}.${TAs}`,\n\t\t\tExtractLeaf<TPath>,\n\t\t\tTAs,\n\t\t\tPopulateField<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t>,\n\t\tTPopMap & {\n\t\t\t[P in `${ExtractParent<TPath>}.${TAs}`]: ExtractRefCollection<\n\t\t\t\tTPopMap[ExtractParent<TPath>],\n\t\t\t\tExtractLeaf<TPath> & RefFields<TPopMap[ExtractParent<TPath>]>\n\t\t\t>\n\t\t}\n\t>\n\t// Implementation — see PopulateOneQuery for reasoning on casts.\n\tpopulate(\n\t\tfield: string,\n\t\tasOrConfigure?:\n\t\t\t| string\n\t\t\t// biome-ignore lint/suspicious/noExplicitAny: TDoc is phantom; widened for overload implementation\n\t\t\t| ((b: PopulateRefBuilder<any>) => PopulateProjectionConfig<unknown>),\n\t): PopulateOneOrThrowQuery<TDef, unknown, Record<string, AnyCollection>> {\n\t\tlet alias: string\n\t\tlet projection: Record<string, 0 | 1 | boolean> | undefined\n\n\t\tif (typeof asOrConfigure === 'function') {\n\t\t\t/* v8 ignore start */\n\t\t\talias = field.includes('.') ? (field.split('.').pop() ?? field) : field\n\t\t\t/* v8 ignore stop */\n\t\t\tconst config = asOrConfigure(new PopulateRefBuilder())\n\t\t\t// Safe: PopulateProjectionConfig<P>.projection is P extends TypedProjection<TDoc>\n\t\t\t// which has values 0|1|true|false — all assignable to 0|1|boolean.\n\t\t\tprojection = config.projection as Record<string, 0 | 1 | boolean>\n\t\t} else {\n\t\t\t/* v8 ignore start */\n\t\t\talias = asOrConfigure ?? (field.includes('.') ? (field.split('.').pop() ?? field) : field)\n\t\t\t/* v8 ignore stop */\n\t\t\tprojection = undefined\n\t\t}\n\n\t\tconst step = resolvePopulateStep(this.handle.definition, this.steps, field, alias, projection)\n\t\tconst newSteps = [...this.steps, step]\n\t\t// Safe cast: overload signatures carry correct generics; implementation is widened.\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation requires widened return\n\t\treturn new PopulateOneOrThrowQuery(this.handle, this.filter, this.options, newSteps) as any\n\t}\n\n\t/**\n\t * Attach fulfillment and rejection handlers to the query promise.\n\t *\n\t * Executes the base findOneOrThrow query and applies populate steps if any.\n\t * Throws {@link ZodmonNotFoundError} when no document matches.\n\t */\n\t// biome-ignore lint/suspicious/noThenProperty: PromiseLike requires a then method\n\tthen<TResult1 = TOutput, TResult2 = never>(\n\t\tonfulfilled?: ((value: TOutput) => TResult1 | PromiseLike<TResult1>) | null,\n\t\tonrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null,\n\t): Promise<TResult1 | TResult2> {\n\t\tconst promise = this.execute()\n\t\treturn promise.then(onfulfilled, onrejected)\n\t}\n\n\tprivate async execute(): Promise<TOutput> {\n\t\tconst doc = await _findOne(this.handle, this.filter, this.options)\n\t\tif (!doc) {\n\t\t\tthrow new ZodmonNotFoundError(this.handle.definition.name, this.filter)\n\t\t}\n\t\t/* v8 ignore start */\n\t\tif (this.steps.length === 0) return doc as unknown as TOutput\n\t\t/* v8 ignore stop */\n\n\t\tconst populated = await executePopulate([doc as Document], this.steps, (name) =>\n\t\t\tthis.handle.native.db.collection(name),\n\t\t)\n\t\tconst result = populated[0]\n\t\t/* v8 ignore start */\n\t\tif (!result) {\n\t\t\tthrow new ZodmonNotFoundError(this.handle.definition.name, this.filter)\n\t\t}\n\t\t/* v8 ignore stop */\n\t\treturn result as unknown as TOutput\n\t}\n}\n","import type { ClientSession, Collection, DeleteResult, UpdateResult } from 'mongodb'\nimport type { AggregatePipeline } from '../aggregate/pipeline'\nimport { aggregate as _aggregate } from '../aggregate/pipeline'\nimport type { AnyCollection, IndexNames, InferDocument, InferInsert } from '../collection/types'\nimport type { FindOneAndDeleteOptions } from '../crud/delete'\nimport {\n\tdeleteMany as _deleteMany,\n\tdeleteOne as _deleteOne,\n\tfindOneAndDelete as _findOneAndDelete,\n} from '../crud/delete'\nimport type {\n\tFindOneOptions,\n\tFindOneProjectionOptions,\n\tFindOptions,\n\tFindProjectionOptions,\n} from '../crud/find'\nimport { find as _find, findOne as _findOne, findOneOrThrow as _findOneOrThrow } from '../crud/find'\nimport { insertMany as _insertMany, insertOne as _insertOne } from '../crud/insert'\nimport type { FindOneAndUpdateOptions, UpdateOptions } from '../crud/update'\nimport {\n\tfindOneAndUpdate as _findOneAndUpdate,\n\tupdateMany as _updateMany,\n\tupdateOne as _updateOne,\n} from '../crud/update'\nimport type { Prettify } from '../helpers/types'\nimport { syncIndexes as _syncIndexes } from '../indexes/sync'\nimport type { SyncIndexesOptions, SyncIndexesResult } from '../indexes/types'\nimport { PopulateOneOrThrowQuery, PopulateOneQuery } from '../populate/query'\nimport type { TypedFindCursor } from '../query/cursor'\nimport type { TypedFilter } from '../query/filter'\nimport type { ProjectionResult, TypedProjection } from '../query/projection'\nimport type { TypedUpdateFilter } from '../query/update'\n\n/**\n * Typed wrapper around a MongoDB driver `Collection`.\n *\n * Created by {@link Database.use}. Holds the original `CollectionDefinition`\n * (for runtime schema validation and index metadata) alongside the native\n * driver collection parameterized with the inferred document type.\n *\n * @typeParam TDef - The collection definition type. Used to derive both\n * the document type (`InferDocument`) and the insert type (`InferInsert`).\n */\nexport class CollectionHandle<TDef extends AnyCollection = AnyCollection> {\n\t/** The collection definition containing schema, name, and index metadata. */\n\treadonly definition: TDef\n\n\t/** The underlying MongoDB driver collection, typed to the inferred document type. */\n\treadonly native: Collection<InferDocument<TDef>>\n\n\t/**\n\t * The MongoDB client session bound to this handle, if any.\n\t *\n\t * When set, all CRUD and aggregation operations performed through this\n\t * handle will include the session in their options, enabling transactional\n\t * reads and writes. Undefined when no session is bound.\n\t */\n\treadonly session: ClientSession | undefined\n\n\tconstructor(definition: TDef, native: Collection<InferDocument<TDef>>, session?: ClientSession) {\n\t\tthis.definition = definition\n\t\tthis.native = native\n\t\tthis.session = session\n\t}\n\n\t/**\n\t * Create a new handle bound to the given MongoDB client session.\n\t *\n\t * Returns a new {@link CollectionHandle} that shares the same collection\n\t * definition and native driver collection, but passes `session` to every\n\t * CRUD and aggregation operation. The original handle is not modified.\n\t *\n\t * @param session - The MongoDB `ClientSession` to bind.\n\t * @returns A new handle with the session attached.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * await db.client.withSession(async (session) => {\n\t * const bound = users.withSession(session)\n\t * await bound.insertOne({ name: 'Ada' }) // uses session\n\t * })\n\t * ```\n\t */\n\twithSession(session: ClientSession): CollectionHandle<TDef> {\n\t\treturn new CollectionHandle(this.definition, this.native, session)\n\t}\n\n\t/**\n\t * Insert a single document into the collection.\n\t *\n\t * Validates the input against the collection's Zod schema before writing.\n\t * Schema defaults (including auto-generated `_id`) are applied during\n\t * validation. Returns the full document with all defaults filled in.\n\t *\n\t * @param doc - The document to insert. Fields with `.default()` are optional.\n\t * @returns The inserted document with `_id` and all defaults applied.\n\t * @throws {ZodmonValidationError} When the document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.insertOne({ name: 'Ada' })\n\t * console.log(user._id) // ObjectId (auto-generated)\n\t * console.log(user.role) // 'user' (schema default)\n\t * ```\n\t */\n\tasync insertOne(doc: InferInsert<TDef>): Promise<InferDocument<TDef>> {\n\t\treturn await _insertOne(this, doc)\n\t}\n\n\t/**\n\t * Insert multiple documents into the collection.\n\t *\n\t * Validates every document against the collection's Zod schema before\n\t * writing any to MongoDB. If any document fails validation, none are\n\t * inserted (fail-fast before the driver call).\n\t *\n\t * @param docs - The documents to insert.\n\t * @returns The inserted documents with `_id` and all defaults applied.\n\t * @throws {ZodmonValidationError} When any document fails schema validation.\n\t *\n\t * @example\n\t * ```ts\n\t * const created = await users.insertMany([\n\t * { name: 'Ada' },\n\t * { name: 'Bob', role: 'admin' },\n\t * ])\n\t * ```\n\t */\n\tasync insertMany(docs: InferInsert<TDef>[]): Promise<InferDocument<TDef>[]> {\n\t\treturn await _insertMany(this, docs)\n\t}\n\n\t/**\n\t * Find a single document matching the filter.\n\t *\n\t * Returns a {@link PopulateOneQuery} that can be awaited directly or chained\n\t * with `.populate()` calls to resolve foreign key references.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional validation overrides.\n\t * @returns A populate builder that resolves to the matched document, or `null`.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOne({ name: 'Ada' })\n\t * if (user) console.log(user.role)\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOne({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * ```\n\t */\n\tfindOne(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneOptions,\n\t): PopulateOneQuery<TDef, InferDocument<TDef>>\n\t/**\n\t * Find a single document matching the filter with a type-safe projection.\n\t *\n\t * Returns only the fields specified by the projection. The return type is\n\t * narrowed to reflect which fields are included or excluded.\n\t * Projected queries do not support `.populate()`.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Projection and optional validation overrides.\n\t * @returns The projected document, or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOne({ name: 'Ada' }, { project: { name: 1 } })\n\t * if (user) console.log(user.name) // typed as string\n\t * ```\n\t */\n\tfindOne<P extends TypedProjection<InferDocument<TDef>>>(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions: FindOneProjectionOptions<InferDocument<TDef>, P>,\n\t): Promise<Prettify<ProjectionResult<InferDocument<TDef>, P>> | null>\n\tfindOne(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?:\n\t\t\t| FindOneOptions\n\t\t\t| FindOneProjectionOptions<InferDocument<TDef>, TypedProjection<InferDocument<TDef>>>,\n\t): PopulateOneQuery<TDef, InferDocument<TDef>> | Promise<unknown> {\n\t\tif (options && 'project' in options) {\n\t\t\treturn _findOne(this, filter, options as FindOneOptions)\n\t\t}\n\t\treturn new PopulateOneQuery(this, filter, options as FindOneOptions | undefined)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, or throw if none exists.\n\t *\n\t * Returns a {@link PopulateOneOrThrowQuery} that can be awaited directly or\n\t * chained with `.populate()` calls. Throws {@link ZodmonNotFoundError}\n\t * instead of returning `null` when no document matches.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional validation overrides.\n\t * @returns A populate builder that resolves to the matched document (never null).\n\t * @throws {ZodmonNotFoundError} When no document matches the filter.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneOrThrow({ name: 'Ada' })\n\t * console.log(user.role) // guaranteed non-null\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * const post = await posts.findOneOrThrow({ title: 'Hello' })\n\t * .populate('authorId', 'author')\n\t * ```\n\t */\n\tfindOneOrThrow(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneOptions,\n\t): PopulateOneOrThrowQuery<TDef, InferDocument<TDef>>\n\t/**\n\t * Find a single document matching the filter with a type-safe projection, or throw if none exists.\n\t *\n\t * Returns only the fields specified by the projection. The return type is\n\t * narrowed to reflect which fields are included or excluded. Throws\n\t * {@link ZodmonNotFoundError} instead of returning `null`.\n\t * Projected queries do not support `.populate()`.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Projection and optional validation overrides.\n\t * @returns The projected document (never null).\n\t * @throws {ZodmonNotFoundError} When no document matches the filter.\n\t * @throws {ZodmonValidationError} When the fetched document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneOrThrow({ name: 'Ada' }, { project: { name: 1 } })\n\t * console.log(user.name) // typed as string\n\t * ```\n\t */\n\tfindOneOrThrow<P extends TypedProjection<InferDocument<TDef>>>(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions: FindOneProjectionOptions<InferDocument<TDef>, P>,\n\t): Promise<Prettify<ProjectionResult<InferDocument<TDef>, P>>>\n\tfindOneOrThrow(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?:\n\t\t\t| FindOneOptions\n\t\t\t| FindOneProjectionOptions<InferDocument<TDef>, TypedProjection<InferDocument<TDef>>>,\n\t): PopulateOneOrThrowQuery<TDef, InferDocument<TDef>> | Promise<unknown> {\n\t\tif (options && 'project' in options) {\n\t\t\treturn _findOneOrThrow(this, filter, options as FindOneOptions)\n\t\t}\n\t\treturn new PopulateOneOrThrowQuery(this, filter, options as FindOneOptions | undefined)\n\t}\n\n\t/**\n\t * Find all documents matching the filter, returning a chainable typed cursor.\n\t *\n\t * The cursor is lazy — no query is executed until a terminal method\n\t * (`toArray`, `for await`) is called. Use `sort`, `skip`, and `limit`\n\t * to shape the query before executing.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional validation overrides.\n\t * @returns A typed cursor for chaining query modifiers.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const admins = await users.find({ role: 'admin' })\n\t * .sort({ name: 1 })\n\t * .limit(10)\n\t * .toArray()\n\t * ```\n\t */\n\tfind(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOptions,\n\t): TypedFindCursor<TDef, IndexNames<TDef>>\n\t/**\n\t * Find all documents matching the filter with a type-safe projection, returning a chainable typed cursor.\n\t *\n\t * The return type is narrowed to reflect which fields are included or excluded.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Projection and optional validation overrides.\n\t * @returns A typed cursor whose output type matches the projection.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const names = await users.find({ role: 'admin' }, { project: { name: 1 } })\n\t * .toArray()\n\t * // names[0].name — string\n\t * ```\n\t */\n\tfind<P extends TypedProjection<InferDocument<TDef>>>(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions: FindProjectionOptions<InferDocument<TDef>, P>,\n\t): TypedFindCursor<TDef, IndexNames<TDef>, Prettify<ProjectionResult<InferDocument<TDef>, P>>>\n\tfind(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: overload implementation\n\t\toptions?: any,\n\t): TypedFindCursor<TDef, IndexNames<TDef>> {\n\t\treturn _find(this, filter, options)\n\t}\n\n\t/**\n\t * Update a single document matching the filter.\n\t *\n\t * Applies the update operators to the first document that matches the filter.\n\t * Does not validate the update against the Zod schema — validation happens\n\t * at the field-operator level through {@link TypedUpdateFilter}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings such as `upsert`.\n\t * @returns The MongoDB `UpdateResult` with match/modify counts.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.updateOne({ name: 'Ada' }, { $set: { role: 'admin' } })\n\t * console.log(result.modifiedCount) // 1\n\t * ```\n\t */\n\tasync updateOne(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: UpdateOptions,\n\t): Promise<UpdateResult> {\n\t\treturn await _updateOne(this, filter, update, options)\n\t}\n\n\t/**\n\t * Update all documents matching the filter.\n\t *\n\t * Applies the update operators to every document that matches the filter.\n\t * Does not validate the update against the Zod schema — validation happens\n\t * at the field-operator level through {@link TypedUpdateFilter}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings such as `upsert`.\n\t * @returns The MongoDB `UpdateResult` with match/modify counts.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.updateMany({ role: 'guest' }, { $set: { role: 'user' } })\n\t * console.log(result.modifiedCount) // number of guests promoted\n\t * ```\n\t */\n\tasync updateMany(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: UpdateOptions,\n\t): Promise<UpdateResult> {\n\t\treturn await _updateMany(this, filter, update, options)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, apply an update, and return the document.\n\t *\n\t * By default, returns the document **after** the update is applied. Set\n\t * `returnDocument: 'before'` to get the pre-update snapshot. The returned\n\t * document is validated against the collection's Zod schema using the same\n\t * resolution logic as {@link findOne}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param update - Type-safe update operators to apply.\n\t * @param options - Optional settings: `returnDocument`, `upsert`, `validate`.\n\t * @returns The matched document (before or after update), or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneAndUpdate(\n\t * { name: 'Ada' },\n\t * { $set: { role: 'admin' } },\n\t * )\n\t * if (user) console.log(user.role) // 'admin' (returned after update)\n\t * ```\n\t */\n\tasync findOneAndUpdate(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\tupdate: TypedUpdateFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneAndUpdateOptions,\n\t): Promise<InferDocument<TDef> | null> {\n\t\treturn await _findOneAndUpdate(this, filter, update, options)\n\t}\n\n\t/**\n\t * Delete a single document matching the filter.\n\t *\n\t * Removes the first document that matches the filter from the collection.\n\t * No validation is performed — the document is deleted directly through\n\t * the MongoDB driver.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @returns The MongoDB `DeleteResult` with the deleted count.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.deleteOne({ name: 'Ada' })\n\t * console.log(result.deletedCount) // 1\n\t * ```\n\t */\n\tasync deleteOne(filter: TypedFilter<InferDocument<TDef>>): Promise<DeleteResult> {\n\t\treturn await _deleteOne(this, filter)\n\t}\n\n\t/**\n\t * Delete all documents matching the filter.\n\t *\n\t * Removes every document that matches the filter from the collection.\n\t * No validation is performed — documents are deleted directly through\n\t * the MongoDB driver.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @returns The MongoDB `DeleteResult` with the deleted count.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.deleteMany({ role: 'guest' })\n\t * console.log(result.deletedCount) // number of guests removed\n\t * ```\n\t */\n\tasync deleteMany(filter: TypedFilter<InferDocument<TDef>>): Promise<DeleteResult> {\n\t\treturn await _deleteMany(this, filter)\n\t}\n\n\t/**\n\t * Find a single document matching the filter, delete it, and return the document.\n\t *\n\t * Returns the deleted document, or `null` if no document matches the filter.\n\t * The returned document is validated against the collection's Zod schema\n\t * using the same resolution logic as {@link findOne}.\n\t *\n\t * @param filter - Type-safe filter to match documents.\n\t * @param options - Optional settings: `validate`.\n\t * @returns The deleted document, or `null` if no document matches.\n\t * @throws {ZodmonValidationError} When the returned document fails schema validation in strict mode.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const user = await users.findOneAndDelete({ name: 'Ada' })\n\t * if (user) console.log(user.name) // 'Ada' (the deleted document)\n\t * ```\n\t */\n\tasync findOneAndDelete(\n\t\tfilter: TypedFilter<InferDocument<TDef>>,\n\t\toptions?: FindOneAndDeleteOptions,\n\t): Promise<InferDocument<TDef> | null> {\n\t\treturn await _findOneAndDelete(this, filter, options)\n\t}\n\n\t/**\n\t * Synchronize the indexes declared in this collection's schema with MongoDB.\n\t *\n\t * Compares the desired indexes (from field-level `.index()` / `.unique()` /\n\t * `.text()` / `.expireAfter()` and compound `indexes` in collection options)\n\t * with the indexes that currently exist in MongoDB, then creates, drops, or\n\t * reports differences depending on the options.\n\t *\n\t * @param options - Optional sync behavior (dryRun, dropOrphaned).\n\t * @returns A summary of created, dropped, skipped, and stale indexes.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.syncIndexes()\n\t * console.log('Created:', result.created)\n\t * console.log('Stale:', result.stale.map(s => s.name))\n\t * ```\n\t *\n\t * @example\n\t * ```ts\n\t * // Dry run to preview changes without modifying the database\n\t * const diff = await users.syncIndexes({ dryRun: true })\n\t * console.log('Would create:', diff.created)\n\t * console.log('Would drop:', diff.dropped)\n\t * ```\n\t */\n\tasync syncIndexes(options?: SyncIndexesOptions): Promise<SyncIndexesResult> {\n\t\treturn await _syncIndexes(this, options)\n\t}\n\n\t/**\n\t * Start a type-safe aggregation pipeline on this collection.\n\t *\n\t * Returns a fluent pipeline builder that tracks the output document\n\t * shape through each stage. The pipeline is lazy — no query executes\n\t * until a terminal method (`toArray`, `for await`, `explain`) is called.\n\t *\n\t * @returns A new pipeline builder starting with this collection's document type.\n\t *\n\t * @example\n\t * ```ts\n\t * const users = db.use(Users)\n\t * const result = await users.aggregate()\n\t * .match({ role: 'admin' })\n\t * .groupBy('role', { count: $count() })\n\t * .toArray()\n\t * ```\n\t */\n\taggregate(): AggregatePipeline<TDef, InferDocument<TDef>> {\n\t\treturn _aggregate(this)\n\t}\n}\n","import { ObjectId } from 'mongodb'\nimport { z } from 'zod'\nimport { getIndexMetadata } from '../schema/extensions'\nimport { objectId } from '../schema/object-id'\nimport type {\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tResolvedShape,\n} from './types'\n\n/**\n * Walk a Zod shape and extract field-level index metadata from each field.\n *\n * Returns an array of {@link FieldIndexDefinition} for every field that has\n * been marked with `.index()`, `.unique()`, `.text()`, or `.expireAfter()`.\n * Fields without index metadata are silently skipped.\n *\n * @param shape - A Zod shape object (the value passed to `z.object()`).\n * @returns An array of field index definitions with the field name attached.\n */\nexport function extractFieldIndexes(shape: z.core.$ZodShape): FieldIndexDefinition[] {\n\tconst result: FieldIndexDefinition[] = []\n\tfor (const [field, schema] of Object.entries(shape)) {\n\t\tconst meta = getIndexMetadata(schema)\n\t\tif (meta) {\n\t\t\tresult.push({ field, ...meta })\n\t\t}\n\t}\n\treturn result\n}\n\n/**\n * Define a MongoDB collection with a Zod schema.\n *\n * Creates a {@link CollectionDefinition} that:\n * - Adds `_id: objectId()` if the shape doesn't already include `_id`\n * - Uses the user-provided `_id` schema if one is present (e.g. nanoid, UUID)\n * - Extracts field-level index metadata from the shape\n * - Separates compound indexes from the rest of the options\n * - Returns an immutable definition object\n *\n * @param name - The MongoDB collection name.\n * @param shape - A Zod shape object defining the document fields. May include a custom `_id`.\n * @param options - Optional collection-level configuration including compound indexes.\n * @returns A {@link CollectionDefinition} ready for use with `createClient()`.\n *\n * @example\n * ```ts\n * const Users = collection('users', {\n * email: z.string().unique(),\n * name: z.string().index(),\n * age: z.number().optional(),\n * })\n * ```\n */\nexport function collection<\n\tTName extends string,\n\tTShape extends z.core.$ZodShape,\n\tconst TIndexes extends readonly CompoundIndexDefinition<\n\t\tExtract<keyof TShape, string>\n\t>[] = readonly CompoundIndexDefinition<Extract<keyof TShape, string>>[],\n>(\n\tname: TName,\n\tshape: TShape,\n\toptions?: Omit<CollectionOptions<Extract<keyof TShape, string>>, 'indexes'> & {\n\t\tindexes?: TIndexes\n\t},\n): CollectionDefinition<TName, TShape, [...TIndexes]> {\n\t// TypeScript cannot narrow generic conditional types through control flow,\n\t// so the assertion is needed here. Both branches are provably correct:\n\t// - when _id is in shape: ResolvedShape<TShape> = TShape\n\t// - when _id is absent: ResolvedShape<TShape> = { _id: ZodObjectId } & TShape\n\tconst resolvedShape = (\n\t\t'_id' in shape ? shape : { _id: objectId().default(() => new ObjectId()), ...shape }\n\t) as ResolvedShape<TShape>\n\tconst schema = z.object(resolvedShape)\n\tconst strictSchema = schema.strict()\n\n\tconst fieldIndexes = extractFieldIndexes(shape)\n\n\tconst { indexes: compoundIndexes, validation, ...rest } = options ?? {}\n\n\treturn {\n\t\tname,\n\t\t// Zod v4's z.object() returns ZodObject<{ -readonly [P in keyof T]: T[P] }> which\n\t\t// strips readonly modifiers. With exactOptionalPropertyTypes this mapped type is\n\t\t// not assignable to ZodObject<ResolvedShape<TShape>>. The cast is safe because\n\t\t// the runtime shape is correct — only the readonly modifier differs.\n\t\tschema: schema as CollectionDefinition<TName, TShape, [...TIndexes]>['schema'],\n\t\tstrictSchema: strictSchema as CollectionDefinition<\n\t\t\tTName,\n\t\t\tTShape,\n\t\t\t[...TIndexes]\n\t\t>['strictSchema'],\n\t\tshape,\n\t\tfieldIndexes,\n\t\t// Safe cast: compoundIndexes is TIndexes at runtime (or an empty array when\n\t\t// no options provided). The spread into [...TIndexes] preserves the tuple type.\n\t\tcompoundIndexes: (compoundIndexes ?? []) as [...TIndexes],\n\t\toptions: {\n\t\t\tvalidation: validation ?? 'strict',\n\t\t\t...rest,\n\t\t},\n\t}\n}\n","import { z } from 'zod'\nimport { installRefExtension } from './ref'\n\n/**\n * Options controlling how a field-level MongoDB index is created.\n *\n * Passed to the `.index()` Zod extension method. Every property is optional;\n * omitting all of them creates a standard ascending, non-unique index.\n */\nexport type IndexOptions = {\n\t/** When `true`, MongoDB enforces a unique constraint on this field. */\n\tunique?: boolean\n\t/**\n\t * When `true`, the index skips documents where the field is `null` or missing.\n\t * Useful for optional fields that should be indexed only when present.\n\t */\n\tsparse?: boolean\n\t/** When `true`, creates a MongoDB text index for full-text search on this field. */\n\ttext?: boolean\n\t/**\n\t * When `true`, the index is created in descending order (`-1`).\n\t * Defaults to ascending (`1`) when omitted.\n\t */\n\tdescending?: boolean\n\t/**\n\t * TTL in seconds. MongoDB will automatically delete documents once the\n\t * indexed `Date` field is older than this many seconds. Only valid on\n\t * fields whose runtime type is `Date`.\n\t */\n\texpireAfter?: number\n\t/**\n\t * A partial filter expression. Only documents matching this filter are\n\t * included in the index. Maps directly to MongoDB's `partialFilterExpression`.\n\t */\n\tpartial?: Record<string, unknown>\n}\n\n/**\n * Metadata stored in the WeakMap sidecar for every schema that has been\n * marked with `.index()`. Always contains `indexed: true` plus any\n * {@link IndexOptions} the caller provided.\n */\nexport type IndexMetadata = {\n\t/** Always `true` — acts as a discriminator for \"this field is indexed\". */\n\tindexed: true\n} & IndexOptions\n\ndeclare module 'zod' {\n\tinterface ZodType {\n\t\t/**\n\t\t * Mark this field for indexing when `syncIndexes()` is called.\n\t\t *\n\t\t * Stores {@link IndexOptions} in a WeakMap sidecar so the collection\n\t\t * factory can later introspect each field and build the appropriate\n\t\t * MongoDB index specification.\n\t\t *\n\t\t * @param options - Optional index configuration (unique, sparse, etc.).\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const UserSchema = z.object({\n\t\t * email: z.string().index({ unique: true }),\n\t\t * age: z.number().index({ sparse: true }),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tindex(options?: IndexOptions): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ unique: true })`.\n\t\t *\n\t\t * Creates a unique index on this field, causing MongoDB to reject\n\t\t * duplicate values.\n\t\t *\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const UserSchema = z.object({\n\t\t * email: z.string().unique(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\tunique(): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ text: true })`.\n\t\t *\n\t\t * Creates a MongoDB text index on this field, enabling `$text` queries\n\t\t * for full-text search.\n\t\t *\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const PostSchema = z.object({\n\t\t * body: z.string().text(),\n\t\t * })\n\t\t * ```\n\t\t */\n\t\ttext(): this\n\n\t\t/**\n\t\t * Shorthand for `.index({ expireAfter: seconds })`.\n\t\t *\n\t\t * Creates a TTL (Time-To-Live) index. MongoDB will automatically\n\t\t * remove documents once the indexed `Date` field is older than\n\t\t * the specified number of seconds.\n\t\t *\n\t\t * @param seconds - Number of seconds after which documents expire.\n\t\t * @returns The same schema instance for chaining.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const SessionSchema = z.object({\n\t\t * createdAt: z.date().expireAfter(3600), // 1 hour TTL\n\t\t * })\n\t\t * ```\n\t\t */\n\t\texpireAfter(seconds: number): this\n\t}\n}\n\n/**\n * WeakMap sidecar that associates a Zod schema instance with its\n * {@link IndexMetadata}.\n *\n * A WeakMap is used so that index metadata does not prevent garbage collection\n * of schema instances. The keys are the Zod schema objects themselves, and\n * the values are the corresponding `IndexMetadata` descriptors.\n */\nconst indexMetadata = new WeakMap<object, IndexMetadata>()\n\n/**\n * Retrieve the index metadata attached to a Zod schema, if any.\n *\n * Returns `undefined` when the schema was never marked with an index\n * extension (`.index()`, `.unique()`, `.text()`, or `.expireAfter()`).\n *\n * @param schema - The Zod schema to inspect. Accepts `unknown` for\n * convenience; non-object values safely return `undefined`.\n * @returns The {@link IndexMetadata} for the schema, or `undefined`.\n *\n * @example\n * ```ts\n * const email = z.string().index({ unique: true })\n * const meta = getIndexMetadata(email)\n * // => { indexed: true, unique: true }\n * ```\n */\nexport function getIndexMetadata(schema: unknown): IndexMetadata | undefined {\n\tif (typeof schema !== 'object' || schema === null) return undefined\n\treturn indexMetadata.get(schema)\n}\n\n/**\n * Symbol used as a guard property on `ZodType.prototype` to prevent\n * double-registration of Zodmon extension methods. The symbol is created\n * with `Symbol.for` so it is shared across realms / duplicate module loads.\n */\nconst GUARD = Symbol.for('zodmon_extensions')\n\n/**\n * Monkey-patch Zod's `ZodType.prototype` with Zodmon extension methods\n * (`.index()`, `.unique()`, `.text()`, `.expireAfter()`).\n *\n * In Zod v4, methods are copied from `ZodType.prototype` to each instance\n * during construction via the internal `init` loop (`Object.keys(proto)` ->\n * copy to instance). Extension methods use `enumerable: true` so they are\n * picked up by this loop for every schema created after installation.\n *\n * The function is idempotent: calling it more than once is a safe no-op,\n * guarded by a non-enumerable `Symbol.for('zodmon_extensions')` property\n * on the prototype.\n *\n * This function is called at module level when `extensions.ts` is first\n * imported, so consumers never need to call it manually. It is exported\n * primarily for use in tests.\n *\n * @example\n * ```ts\n * import { installExtensions } from '@zodmon/core/schema/extensions'\n * installExtensions() // safe to call multiple times\n *\n * const indexed = z.string().index({ unique: true })\n * ```\n */\nexport function installExtensions(): void {\n\tconst proto = z.ZodType.prototype\n\tif (GUARD in proto) return\n\n\tObject.defineProperty(proto, 'index', {\n\t\t/**\n\t\t * Declares a MongoDB index on this field. Accepts optional\n\t\t * {@link IndexOptions} to configure uniqueness, sparseness, text search,\n\t\t * sort direction, TTL, or partial filters.\n\t\t *\n\t\t * @param options - Index configuration. Omit for a standard ascending index.\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const name = z.string().index()\n\t\t * const email = z.string().index({ unique: true, sparse: true })\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto, options?: IndexOptions): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, ...options })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'unique', {\n\t\t/**\n\t\t * Shorthand for `.index({ unique: true })`. Marks this field as requiring\n\t\t * a unique index in MongoDB, preventing duplicate values.\n\t\t *\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const email = z.string().unique()\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, unique: true })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'text', {\n\t\t/**\n\t\t * Shorthand for `.index({ text: true })`. Creates a MongoDB text index on\n\t\t * this field, enabling full-text search queries with `$text`.\n\t\t *\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const bio = z.string().text()\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, text: true })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tObject.defineProperty(proto, 'expireAfter', {\n\t\t/**\n\t\t * Shorthand for `.index({ expireAfter: seconds })`. Creates a TTL index on\n\t\t * a `Date` field. MongoDB will automatically remove documents once the field\n\t\t * value is older than the specified number of seconds.\n\t\t *\n\t\t * @param seconds - TTL in seconds after which documents expire.\n\t\t * @returns The same schema instance for chainability.\n\t\t *\n\t\t * @example\n\t\t * ```ts\n\t\t * const expiresAt = z.date().expireAfter(86400) // 24 hours\n\t\t * ```\n\t\t */\n\t\tvalue(this: typeof proto, seconds: number): typeof proto {\n\t\t\tindexMetadata.set(this, { indexed: true, expireAfter: seconds })\n\t\t\treturn this\n\t\t},\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t\twritable: true,\n\t})\n\n\tinstallRefExtension()\n\n\tObject.defineProperty(proto, GUARD, {\n\t\tvalue: true,\n\t\tenumerable: false,\n\t\tconfigurable: false,\n\t\twritable: false,\n\t})\n}\n\ninstallExtensions()\n","import { ObjectId } from 'mongodb'\nimport { type ZodCustom, type ZodPipe, type ZodTransform, z } from 'zod'\n\n/** Matches a 24-character hexadecimal string (case-insensitive). */\nconst OBJECT_ID_HEX = /^[a-f\\d]{24}$/i\n\n/**\n * The Zod type produced by {@link objectId}. A pipeline that validates an\n * input as either a `string` (24-char hex) or an `ObjectId` instance, then\n * transforms it into a concrete `ObjectId`.\n *\n * Use `z.infer<ZodObjectId>` to extract the output type (`ObjectId`) and\n * `z.input<ZodObjectId>` for the input type (`string | ObjectId`).\n */\nexport type ZodObjectId = ZodPipe<\n\tZodCustom<string | ObjectId, string | ObjectId>,\n\tZodTransform<ObjectId, string | ObjectId>\n>\n\n/**\n * Create a Zod schema that validates and coerces values into MongoDB\n * `ObjectId` instances.\n *\n * Accepts either:\n * - An existing `ObjectId` instance (passed through unchanged).\n * - A 24-character hexadecimal string (coerced to `ObjectId`).\n *\n * All other inputs are rejected with the message `\"Invalid ObjectId\"`.\n *\n * @returns A {@link ZodObjectId} schema.\n *\n * @example\n * ```ts\n * const schema = objectId()\n *\n * schema.parse(new ObjectId()) // OK — pass-through\n * schema.parse('64f1a2b3c4d5e6f7a8b9c0d1') // OK — coerced to ObjectId\n * schema.parse('not-valid') // throws ZodError\n * ```\n *\n * @example Inside a z.object() shape:\n * ```ts\n * const UserSchema = z.object({\n * _id: objectId(),\n * name: z.string(),\n * })\n * ```\n */\nexport function objectId(): ZodObjectId {\n\treturn z\n\t\t.custom<string | ObjectId>((val): val is string | ObjectId => {\n\t\t\tif (val instanceof ObjectId) return true\n\t\t\treturn typeof val === 'string' && OBJECT_ID_HEX.test(val)\n\t\t}, 'Invalid ObjectId')\n\t\t.transform((val) => (val instanceof ObjectId ? val : ObjectId.createFromHexString(val)))\n}\n","import type { CompoundIndexDefinition } from './types'\n\ntype IndexDirection = 1 | -1\n\ntype CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>\n\n/**\n * A builder for compound index definitions.\n *\n * Provides a fluent API for declaring compound indexes with options like\n * `unique`, `sparse`, and custom `name`. Each method returns a new\n * IndexBuilder instance (immutable pattern — the original is never mutated).\n *\n * IndexBuilder is structurally compatible with {@link CompoundIndexDefinition}\n * so instances can be used directly in `CollectionOptions.indexes`.\n *\n * Dot-notation paths like `'address.city'` are accepted at the value level\n * (any string satisfies `TKeys`), but type-level validation against nested\n * schema paths is deferred to a future release.\n *\n * @example\n * ```ts\n * index({ email: 1, role: -1 }).unique().name('email_role_idx')\n * ```\n */\nexport class IndexBuilder<TKeys extends string> {\n\t// Typed as Partial for structural compatibility with CompoundIndexDefinition.\n\t// The constructor guarantees all keys are present at runtime.\n\treadonly fields: Partial<Record<TKeys, IndexDirection>>\n\treadonly options: CompoundIndexOptions\n\n\tconstructor(fields: Record<TKeys, IndexDirection>) {\n\t\tthis.fields = fields\n\t\tthis.options = {}\n\t}\n\n\tprivate _clone(options: CompoundIndexOptions): IndexBuilder<TKeys> {\n\t\t// Object.create returns `any`; cast is safe because we assign the correct shape\n\t\treturn Object.assign(Object.create(IndexBuilder.prototype) as IndexBuilder<TKeys>, {\n\t\t\tfields: this.fields,\n\t\t\toptions,\n\t\t})\n\t}\n\n\t// Safe cast: _clone returns IndexBuilder<TKeys> but `this` may carry an\n\t// intersection from .name(). The cast is safe because _clone preserves all fields.\n\tunique(): this {\n\t\treturn this._clone({ ...this.options, unique: true }) as this\n\t}\n\n\t// Safe cast: same reasoning as unique().\n\tsparse(): this {\n\t\treturn this._clone({ ...this.options, sparse: true }) as this\n\t}\n\n\t/**\n\t * Set a custom name for this index, preserving the literal type.\n\t *\n\t * The returned builder carries the literal name type via an intersection,\n\t * enabling type-safe `.hint()` on cursors that only accepts declared names.\n\t *\n\t * @param name - The index name.\n\t * @returns A new IndexBuilder with the name recorded at the type level.\n\t *\n\t * @example\n\t * ```ts\n\t * index({ email: 1, role: -1 }).name('email_role_idx')\n\t * ```\n\t */\n\tname<TName extends string>(\n\t\tname: TName,\n\t): IndexBuilder<TKeys> & { readonly options: { readonly name: TName } } {\n\t\t// Safe cast: _clone returns IndexBuilder<TKeys> which is structurally correct;\n\t\t// the intersection adds the literal name type for downstream type extraction.\n\t\treturn this._clone({ ...this.options, name }) as IndexBuilder<TKeys> & {\n\t\t\treadonly options: { readonly name: TName }\n\t\t}\n\t}\n}\n\n/**\n * Create a compound index definition with a fluent builder API.\n *\n * Returns an {@link IndexBuilder} that is structurally compatible with\n * `CompoundIndexDefinition`, so it can be used directly in\n * `CollectionOptions.indexes` alongside plain objects.\n *\n * @param fields - An object mapping field names to sort direction (1 or -1).\n * @returns An {@link IndexBuilder} instance.\n *\n * @example\n * ```ts\n * collection('users', { email: z.string(), role: z.string() }, {\n * indexes: [\n * index({ email: 1, role: -1 }).unique(),\n * { fields: { role: 1 } },\n * ],\n * })\n * ```\n */\nexport function index<TKeys extends string>(\n\tfields: Record<TKeys, IndexDirection>,\n): IndexBuilder<TKeys> {\n\treturn new IndexBuilder(fields)\n}\n","import { ObjectId } from 'mongodb'\n\n/**\n * Create or coerce a MongoDB `ObjectId`.\n *\n * - Called with **no arguments**: generates a brand-new `ObjectId`.\n * - Called with a **hex string**: coerces it to an `ObjectId` via\n * `ObjectId.createFromHexString`.\n * - Called with an **existing `ObjectId`**: returns it unchanged.\n *\n * This is a convenience wrapper that removes the need for `new ObjectId()`\n * boilerplate throughout application code.\n *\n * @param value - Optional hex string or `ObjectId` to coerce. Omit to\n * generate a new `ObjectId`.\n * @returns An `ObjectId` instance.\n *\n * @example\n * ```ts\n * oid() // new random ObjectId\n * oid('64f1a2b3c4d5e6f7a8b9c0d1') // coerce hex string\n * oid(existingId) // pass-through\n * ```\n */\nexport function oid(): ObjectId\nexport function oid(value: string): ObjectId\nexport function oid(value: ObjectId): ObjectId\nexport function oid(value?: string | ObjectId): ObjectId {\n\tif (value === undefined) return new ObjectId()\n\tif (value instanceof ObjectId) return value\n\treturn ObjectId.createFromHexString(value)\n}\n\n/**\n * Type guard that narrows an `unknown` value to `ObjectId`.\n *\n * Uses `instanceof` internally, so it works with any value without risk\n * of throwing.\n *\n * @param value - The value to check.\n * @returns `true` if `value` is an `ObjectId` instance.\n *\n * @example\n * ```ts\n * const raw: unknown = getFromDb()\n * if (isOid(raw)) {\n * console.log(raw.toHexString()) // raw is narrowed to ObjectId\n * }\n * ```\n */\nexport function isOid(value: unknown): value is ObjectId {\n\treturn value instanceof ObjectId\n}\n","import type { TypedFilter } from './filter'\n\n// ── Value operators ──────────────────────────────────────────────────────────\n\n/**\n * Matches values equal to the specified value.\n *\n * @example\n * ```ts\n * // Explicit equality (equivalent to { name: 'Alice' })\n * users.find({ name: $eq('Alice') })\n * ```\n */\nexport const $eq = <V>(value: V): { $eq: V } => ({ $eq: value })\n\n/**\n * Matches values not equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ role: $ne('banned') })\n * ```\n */\nexport const $ne = <V>(value: V): { $ne: V } => ({ $ne: value })\n\n/**\n * Matches values greater than the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $gt(18) })\n * ```\n */\nexport const $gt = <V>(value: V): { $gt: V } => ({ $gt: value })\n\n/**\n * Matches values greater than or equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $gte(18) })\n * ```\n */\nexport const $gte = <V>(value: V): { $gte: V } => ({ $gte: value })\n\n/**\n * Matches values less than the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $lt(65) })\n * ```\n */\nexport const $lt = <V>(value: V): { $lt: V } => ({ $lt: value })\n\n/**\n * Matches values less than or equal to the specified value.\n *\n * @example\n * ```ts\n * users.find({ age: $lte(65) })\n * ```\n */\nexport const $lte = <V>(value: V): { $lte: V } => ({ $lte: value })\n\n/**\n * Matches any value in the specified array.\n *\n * @example\n * ```ts\n * users.find({ role: $in(['admin', 'moderator']) })\n * ```\n */\nexport const $in = <V>(values: readonly V[]): { $in: readonly V[] } => ({ $in: values })\n\n/**\n * Matches none of the values in the specified array.\n *\n * @example\n * ```ts\n * users.find({ role: $nin(['banned', 'suspended']) })\n * ```\n */\nexport const $nin = <V>(values: readonly V[]): { $nin: readonly V[] } => ({ $nin: values })\n\n/**\n * Matches documents where the field exists (or does not exist).\n * Defaults to `true` when called with no arguments.\n *\n * @example\n * ```ts\n * // Field must exist\n * users.find({ email: $exists() })\n *\n * // Field must not exist\n * users.find({ deletedAt: $exists(false) })\n * ```\n */\nexport const $exists = (flag = true): { $exists: boolean } => ({ $exists: flag })\n\n/**\n * Matches string values against a regular expression pattern.\n * Only valid on string fields.\n *\n * @example\n * ```ts\n * users.find({ name: $regex(/^A/i) })\n * users.find({ email: $regex('^admin@') })\n * ```\n */\nexport const $regex = (pattern: RegExp | string): { $regex: RegExp | string } => ({\n\t$regex: pattern,\n})\n\n/**\n * Negates a comparison operator. Wraps the given operator object\n * in a `$not` condition.\n *\n * @example\n * ```ts\n * // Age is NOT greater than 65\n * users.find({ age: $not($gt(65)) })\n *\n * // Name does NOT match pattern\n * users.find({ name: $not($regex(/^test/)) })\n * ```\n */\nexport const $not = <O extends Record<string, unknown>>(op: O): { $not: O } => ({\n\t$not: op,\n})\n\n// ── Logical operators ────────────────────────────────────────────────────────\n\n/**\n * Joins filter clauses with a logical OR. Matches documents that satisfy\n * at least one of the provided filters.\n *\n * @example\n * ```ts\n * // T inferred from collection's find() context\n * users.find($or({ role: 'admin' }, { age: $gte(18) }))\n *\n * // Explicit generic for standalone usage\n * const filter = $or<User>({ role: 'admin' }, { age: $gte(18) })\n * ```\n */\nexport const $or = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $or: filters }) as TypedFilter<T>\n\n/**\n * Joins filter clauses with a logical AND. Matches documents that satisfy\n * all of the provided filters. Useful for dynamic filter building where\n * multiple conditions on the same field would conflict in an object literal.\n *\n * @example\n * ```ts\n * // T inferred from collection's find() context\n * users.find($and(\n * $or({ role: 'admin' }, { role: 'moderator' }),\n * { age: $gte(18) },\n * { email: $exists() },\n * ))\n * ```\n */\nexport const $and = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $and: filters }) as TypedFilter<T>\n\n/**\n * Joins filter clauses with a logical NOR. Matches documents that fail\n * all of the provided filters.\n *\n * @example\n * ```ts\n * // Exclude banned and suspended users\n * users.find($nor({ role: 'banned' }, { role: 'suspended' }))\n * ```\n */\nexport const $nor = <T>(...filters: NoInfer<TypedFilter<T>>[]): TypedFilter<T> =>\n\t({ $nor: filters }) as TypedFilter<T>\n\n// ── Escape hatch ─────────────────────────────────────────────────────────────\n\n/**\n * Escape hatch for unsupported or raw MongoDB filter operators.\n * Wraps an untyped filter object so it can be passed where `TypedFilter<T>` is expected.\n * Use when you need operators not covered by the type system (e.g., `$text`, `$geoNear`).\n *\n * @example\n * ```ts\n * users.find(raw({ $text: { $search: 'mongodb tutorial' } }))\n * ```\n */\n// biome-ignore lint/suspicious/noExplicitAny: intentional escape hatch for raw MongoDB filters\nexport const raw = <T = any>(filter: Record<string, unknown>): TypedFilter<T> =>\n\tfilter as TypedFilter<T>\n","import {\n\t$and,\n\t$eq,\n\t$exists,\n\t$gt,\n\t$gte,\n\t$in,\n\t$lt,\n\t$lte,\n\t$ne,\n\t$nin,\n\t$nor,\n\t$not,\n\t$or,\n\t$regex,\n\traw,\n} from './operators'\n\n/**\n * Convenience namespace that groups all query operators under a single import.\n *\n * Property names strip the `$` prefix since the namespace itself is `$`.\n * Individual operator exports (`$or`, `$gt`, etc.) remain available for\n * tree-shaking — this namespace is the ergonomic alternative.\n *\n * @example\n * ```ts\n * import { $ } from '@zodmon/core'\n *\n * users.find($.or({ role: 'admin' }, { age: $.gte(25) }))\n * users.find({ name: $.regex(/^A/i), age: $.gt(18) })\n * users.find($.and({ published: true }, { views: $.gte(100) }))\n * ```\n */\nexport const $ = {\n\teq: $eq,\n\tne: $ne,\n\tgt: $gt,\n\tgte: $gte,\n\tlt: $lt,\n\tlte: $lte,\n\tin: $in,\n\tnin: $nin,\n\texists: $exists,\n\tregex: $regex,\n\tnot: $not,\n\tor: $or,\n\tand: $and,\n\tnor: $nor,\n\traw,\n} as const\n"],"mappings":"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","names":["index","collection","collection","collection","collection","collection","index","collection","collection","collection","collection","collection","collection","collection","import_mongodb","import_zod","collection","import_zod","collection","import_zod","import_mongodb","sortKeys","import_zod","isArray","ref","sortKeys","raw","raw","import_zod","import_zod","import_mongodb","import_zod","import_zod","import_mongodb","import_zod","import_mongodb"]}
|