@zodmon/core 0.5.0 → 0.7.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/client/client.ts","../src/crud/find.ts","../src/errors/not-found.ts","../src/errors/validation.ts","../src/query/cursor.ts","../src/crud/insert.ts","../src/client/handle.ts","../src/collection/collection.ts","../src/schema/extensions.ts","../src/schema/ref.ts","../src/schema/object-id.ts","../src/collection/index-def.ts","../src/helpers/oid.ts","../src/query/operators.ts"],"sourcesContent":["export { CollectionHandle, createClient, Database, extractDbName } from './client'\nexport type {\n\tAnyCollection,\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tInferDocument,\n\tInferInsert,\n\tResolvedShape,\n\tValidationMode,\n} from './collection'\nexport { collection, extractFieldIndexes, IndexBuilder, index } from './collection'\nexport type { FindOneOptions, FindOptions } from './crud'\nexport { find, findOne, findOneOrThrow, insertMany, insertOne } from './crud'\nexport { ZodmonNotFoundError, ZodmonValidationError } from './errors'\nexport { isOid, oid } from './helpers/oid'\nexport type { ComparisonOperators, DotPaths, DotPathType, TypedFilter, TypedSort } from './query'\nexport {\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\tinstallExtensions,\n\tinstallRefExtension,\n\tobjectId,\n\ttype RefMarker,\n\ttype RefMetadata,\n\ttype ZodObjectId,\n} from './schema'\n","import type { Db, MongoClientOptions } from 'mongodb'\nimport { MongoClient } from 'mongodb'\nimport type { z } from 'zod'\nimport type { CollectionDefinition, InferDocument } from '../collection/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<TShape extends z.core.$ZodShape>(\n\t\tdef: CollectionDefinition<TShape>,\n\t): CollectionHandle<CollectionDefinition<TShape>> {\n\t\t// Safe cast: erasing TShape 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<InferDocument<CollectionDefinition<TShape>>>(def.name)\n\t\t// Safe cast: CollectionDefinition<TShape> → AnyCollection for the constructor.\n\t\t// The generic is preserved through the return type annotation.\n\t\treturn new CollectionHandle(\n\t\t\tdef as unknown as CollectionDefinition<TShape>,\n\t\t\tnative,\n\t\t) as CollectionHandle<CollectionDefinition<TShape>>\n\t}\n\n\t/**\n\t * Synchronize indexes defined in registered collections with MongoDB.\n\t *\n\t * Stub — full implementation in TASK-92.\n\t */\n\tsyncIndexes(): Promise<void> {\n\t\treturn Promise.resolve()\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 { FindCursor } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonNotFoundError } from '../errors/not-found'\nimport { ZodmonValidationError } from '../errors/validation'\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\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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\tconst raw = await handle.native.findOne(filter as any, findOptions)\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)\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)\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> {\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)\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 *\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 * }\n * }\n * ```\n */\nexport class ZodmonNotFoundError extends Error {\n\toverride readonly name = 'ZodmonNotFoundError'\n\n\t/** The MongoDB collection name where the query found no results. */\n\treadonly collection: string\n\n\tconstructor(collection: string) {\n\t\tsuper(`Document not found in \"${collection}\"`)\n\t\tthis.collection = collection\n\t}\n}\n","import type { z } from 'zod'\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 * }\n * }\n * ```\n */\nexport class ZodmonValidationError extends Error {\n\toverride readonly name = 'ZodmonValidationError'\n\n\t/** The MongoDB collection name where the validation failed. */\n\treadonly collection: string\n\n\t/** The original Zod validation error with detailed issue information. */\n\treadonly zodError: z.ZodError\n\n\tconstructor(collection: string, zodError: z.ZodError) {\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}`)\n\t\tthis.collection = collection\n\t\tthis.zodError = zodError\n\t}\n}\n","import type { FindCursor, Sort } from 'mongodb'\nimport { z } from 'zod'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonValidationError } from '../errors/validation'\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`) 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 *\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> {\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\n\t/** @internal */\n\tconstructor(\n\t\tcursor: FindCursor<InferDocument<TDef>>,\n\t\tdefinition: TDef,\n\t\tmode: ValidationMode | false,\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}\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\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 * 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\tconst raw = await this.cursor.toArray()\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\tfor await (const doc of this.cursor) {\n\t\t\tyield this.validateDoc(doc)\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)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\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'\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)\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\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertOne parameter type uses OptionalUnlessRequiredId which is not directly assignable from our generic InferDocument\n\tawait handle.native.insertOne(parsed as any)\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)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertMany parameter type is not directly assignable from our generic InferDocument\n\tawait handle.native.insertMany(parsed as any)\n\treturn parsed\n}\n","import type { Collection } from 'mongodb'\nimport type { AnyCollection, InferDocument, InferInsert } from '../collection/types'\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 { TypedFindCursor } from '../query/cursor'\nimport type { TypedFilter } from '../query/filter'\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(filter: TypedFilter<InferDocument<TDef>>, options?: FindOptions): TypedFindCursor<TDef> {\n\t\treturn _find(this, filter, options)\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\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<TShape extends z.core.$ZodShape>(\n\tname: string,\n\tshape: TShape,\n\toptions?: CollectionOptions<Extract<keyof TShape, string>>,\n): CollectionDefinition<TShape> {\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<TShape>['schema'],\n\t\tshape,\n\t\tfieldIndexes,\n\t\tcompoundIndexes: compoundIndexes ?? [],\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 { 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 { 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","/**\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 */\n\nimport type { CompoundIndexDefinition } from './types'\n\ntype IndexDirection = 1 | -1\n\ntype CompoundIndexOptions = NonNullable<CompoundIndexDefinition['options']>\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\tunique(): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, unique: true })\n\t}\n\n\tsparse(): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, sparse: true })\n\t}\n\n\tname(name: string): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, name })\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: V[]): { $in: 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: V[]): { $nin: 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 * users.find($or({ role: 'admin' }, { age: $gte(18) }))\n *\n * // Dynamic composition\n * const conditions: TypedFilter<User>[] = []\n * if (name) conditions.push({ name })\n * if (role) conditions.push({ role })\n * users.find($or(...conditions))\n * ```\n */\nexport const $or = <T>(...filters: 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 * users.find($and(\n * $or({ role: 'admin' }, { role: 'moderator' }),\n * { age: $gte(18) },\n * { email: $exists() },\n * ))\n * ```\n */\nexport const $and = <T>(...filters: 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: 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"],"mappings":"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","names":["import_zod","collection","collection","raw","raw","import_zod","import_mongodb","import_zod","import_zod","import_zod","collection","import_mongodb","import_zod","import_mongodb"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/client/client.ts","../src/crud/delete.ts","../src/errors/validation.ts","../src/crud/find.ts","../src/errors/not-found.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/ref.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 { CollectionHandle, createClient, Database, extractDbName } from './client'\nexport type {\n\tAnyCollection,\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\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 { ZodmonNotFoundError, ZodmonValidationError } from './errors'\nexport { isOid, oid } from './helpers/oid'\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 { Db, MongoClientOptions } from 'mongodb'\nimport { MongoClient } from 'mongodb'\nimport type { z } from 'zod'\nimport type { CollectionDefinition, InferDocument } from '../collection/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<TShape extends z.core.$ZodShape>(\n\t\tdef: CollectionDefinition<TShape>,\n\t): CollectionHandle<CollectionDefinition<TShape>> {\n\t\t// Safe cast: erasing TShape 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<InferDocument<CollectionDefinition<TShape>>>(def.name)\n\t\t// Safe cast: CollectionDefinition<TShape> → AnyCollection for the constructor.\n\t\t// The generic is preserved through the return type annotation.\n\t\treturn new CollectionHandle(\n\t\t\tdef as unknown as CollectionDefinition<TShape>,\n\t\t\tnative,\n\t\t) as CollectionHandle<CollectionDefinition<TShape>>\n\t}\n\n\t/**\n\t * Synchronize indexes defined in registered collections with MongoDB.\n\t *\n\t * Stub — full implementation in TASK-92.\n\t */\n\tsyncIndexes(): Promise<void> {\n\t\treturn Promise.resolve()\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 { 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 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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\treturn await handle.native.deleteOne(filter as any)\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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\treturn await handle.native.deleteMany(filter as any)\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\tconst result = await handle.native.findOneAndDelete(\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\t{ includeResultMetadata: false },\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)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { z } from 'zod'\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 * }\n * }\n * ```\n */\nexport class ZodmonValidationError extends Error {\n\toverride readonly name = 'ZodmonValidationError'\n\n\t/** The MongoDB collection name where the validation failed. */\n\treadonly collection: string\n\n\t/** The original Zod validation error with detailed issue information. */\n\treadonly zodError: z.ZodError\n\n\tconstructor(collection: string, zodError: z.ZodError) {\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}`)\n\t\tthis.collection = collection\n\t\tthis.zodError = zodError\n\t}\n}\n","import type { FindCursor } from 'mongodb'\nimport { z } from 'zod'\nimport type { CollectionHandle } from '../client/handle'\nimport type { AnyCollection, InferDocument, ValidationMode } from '../collection/types'\nimport { ZodmonNotFoundError } from '../errors/not-found'\nimport { ZodmonValidationError } from '../errors/validation'\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\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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter intersection type is not directly assignable to MongoDB's Filter\n\tconst raw = await handle.native.findOne(filter as any, findOptions)\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)\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)\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> {\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","/**\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 *\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 * }\n * }\n * ```\n */\nexport class ZodmonNotFoundError extends Error {\n\toverride readonly name = 'ZodmonNotFoundError'\n\n\t/** The MongoDB collection name where the query found no results. */\n\treadonly collection: string\n\n\tconstructor(collection: string) {\n\t\tsuper(`Document not found in \"${collection}\"`)\n\t\tthis.collection = collection\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'\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`) 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 *\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> {\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 * 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\tconst [total, raw] = await Promise.all([\n\t\t\tthis.nativeCollection.countDocuments(this.filter),\n\t\t\tthis.nativeCollection\n\t\t\t\t.find(this.filter)\n\t\t\t\t.sort(sort)\n\t\t\t\t.skip((opts.page - 1) * opts.perPage)\n\t\t\t\t.limit(opts.perPage)\n\t\t\t\t.toArray(),\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\tconst raw = await this.nativeCollection\n\t\t\t.find(combinedFilter)\n\t\t\t.sort(effectiveSort)\n\t\t\t.limit(opts.limit + 1)\n\t\t\t.toArray()\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\tconst raw = await this.cursor.toArray()\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\tfor await (const doc of this.cursor) {\n\t\t\tyield this.validateDoc(doc)\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)\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'\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)\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\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertOne parameter type uses OptionalUnlessRequiredId which is not directly assignable from our generic InferDocument\n\tawait handle.native.insertOne(parsed as any)\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)\n\t\t\t}\n\t\t\tthrow err\n\t\t}\n\t}\n\t// biome-ignore lint/suspicious/noExplicitAny: MongoDB driver's insertMany parameter type is not directly assignable from our generic InferDocument\n\tawait handle.native.insertMany(parsed as any)\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 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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter/TypedUpdateFilter intersection types are not directly assignable to MongoDB's Filter/UpdateFilter\n\treturn await handle.native.updateOne(filter as any, update as any, options)\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\t// biome-ignore lint/suspicious/noExplicitAny: TypedFilter/TypedUpdateFilter intersection types are not directly assignable to MongoDB's Filter/UpdateFilter\n\treturn await handle.native.updateMany(filter as any, update as any, options)\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\t// biome-ignore lint/complexity/useLiteralKeys: bracket notation required — noUncheckedIndexedAccess forbids dot access on Record<string, unknown>\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\tconst result = await handle.native.findOneAndUpdate(\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\t// biome-ignore lint/suspicious/noExplicitAny: TypedUpdateFilter intersection type is not directly assignable to MongoDB's UpdateFilter\n\t\tupdate as any,\n\t\t// biome-ignore lint/suspicious/noExplicitAny: dynamic options object is not assignable to driver's FindOneAndUpdateOptions under exactOptionalPropertyTypes\n\t\tdriverOptions as any,\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)\n\t\t}\n\t\tthrow err\n\t}\n}\n","import type { Collection, DeleteResult, UpdateResult } from 'mongodb'\nimport type { AnyCollection, 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 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(filter: TypedFilter<InferDocument<TDef>>, options?: FindOptions): TypedFindCursor<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","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\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<TShape extends z.core.$ZodShape>(\n\tname: string,\n\tshape: TShape,\n\toptions?: CollectionOptions<Extract<keyof TShape, string>>,\n): CollectionDefinition<TShape> {\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<TShape>['schema'],\n\t\tshape,\n\t\tfieldIndexes,\n\t\tcompoundIndexes: compoundIndexes ?? [],\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 { 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 { 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\tunique(): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, unique: true })\n\t}\n\n\tsparse(): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, sparse: true })\n\t}\n\n\tname(name: string): IndexBuilder<TKeys> {\n\t\treturn this._clone({ ...this.options, name })\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: V[]): { $in: 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: V[]): { $nin: 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":["import_mongodb","collection","import_zod","collection","import_zod","raw","raw","import_zod","import_zod","import_mongodb","import_zod","import_zod","import_zod","collection","import_mongodb","import_zod","import_mongodb"]}