@zodmon/core 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +155 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +414 -2
- package/dist/index.d.ts +414 -2
- package/dist/index.js +127 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -20,8 +20,26 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
$and: () => $and,
|
|
24
|
+
$eq: () => $eq,
|
|
25
|
+
$exists: () => $exists,
|
|
26
|
+
$gt: () => $gt,
|
|
27
|
+
$gte: () => $gte,
|
|
28
|
+
$in: () => $in,
|
|
29
|
+
$lt: () => $lt,
|
|
30
|
+
$lte: () => $lte,
|
|
31
|
+
$ne: () => $ne,
|
|
32
|
+
$nin: () => $nin,
|
|
33
|
+
$nor: () => $nor,
|
|
34
|
+
$not: () => $not,
|
|
35
|
+
$or: () => $or,
|
|
36
|
+
$regex: () => $regex,
|
|
37
|
+
CollectionHandle: () => CollectionHandle,
|
|
38
|
+
Database: () => Database,
|
|
23
39
|
IndexBuilder: () => IndexBuilder,
|
|
24
40
|
collection: () => collection,
|
|
41
|
+
createClient: () => createClient,
|
|
42
|
+
extractDbName: () => extractDbName,
|
|
25
43
|
extractFieldIndexes: () => extractFieldIndexes,
|
|
26
44
|
getIndexMetadata: () => getIndexMetadata,
|
|
27
45
|
getRefMetadata: () => getRefMetadata,
|
|
@@ -30,10 +48,97 @@ __export(index_exports, {
|
|
|
30
48
|
installRefExtension: () => installRefExtension,
|
|
31
49
|
isOid: () => isOid,
|
|
32
50
|
objectId: () => objectId,
|
|
33
|
-
oid: () => oid
|
|
51
|
+
oid: () => oid,
|
|
52
|
+
raw: () => raw
|
|
34
53
|
});
|
|
35
54
|
module.exports = __toCommonJS(index_exports);
|
|
36
55
|
|
|
56
|
+
// src/client/client.ts
|
|
57
|
+
var import_mongodb = require("mongodb");
|
|
58
|
+
|
|
59
|
+
// src/client/handle.ts
|
|
60
|
+
var CollectionHandle = class {
|
|
61
|
+
/** The collection definition containing schema, name, and index metadata. */
|
|
62
|
+
definition;
|
|
63
|
+
/** The underlying MongoDB driver collection, typed to `TDoc`. */
|
|
64
|
+
native;
|
|
65
|
+
constructor(definition, native) {
|
|
66
|
+
this.definition = definition;
|
|
67
|
+
this.native = native;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
// src/client/client.ts
|
|
72
|
+
var Database = class {
|
|
73
|
+
_client;
|
|
74
|
+
_db;
|
|
75
|
+
/** Registered collection definitions, keyed by name. Used by syncIndexes(). */
|
|
76
|
+
_collections = /* @__PURE__ */ new Map();
|
|
77
|
+
constructor(uri, dbName, options) {
|
|
78
|
+
this._client = new import_mongodb.MongoClient(uri, options);
|
|
79
|
+
this._db = this._client.db(dbName);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Register a collection definition and return a typed {@link CollectionHandle}.
|
|
83
|
+
*
|
|
84
|
+
* The handle's `native` property is a MongoDB `Collection<TDoc>` where `TDoc`
|
|
85
|
+
* is the document type inferred from the definition's Zod schema. Calling
|
|
86
|
+
* `use()` multiple times with the same definition is safe — each call returns
|
|
87
|
+
* a new lightweight handle backed by the same underlying driver collection.
|
|
88
|
+
*
|
|
89
|
+
* @param def - A collection definition created by `collection()`.
|
|
90
|
+
* @returns A typed collection handle for CRUD operations.
|
|
91
|
+
*/
|
|
92
|
+
use(def) {
|
|
93
|
+
this._collections.set(def.name, def);
|
|
94
|
+
const native = this._db.collection(def.name);
|
|
95
|
+
return new CollectionHandle(def, native);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Synchronize indexes defined in registered collections with MongoDB.
|
|
99
|
+
*
|
|
100
|
+
* Stub — full implementation in TASK-92.
|
|
101
|
+
*/
|
|
102
|
+
syncIndexes() {
|
|
103
|
+
return Promise.resolve();
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Execute a function within a MongoDB transaction with auto-commit/rollback.
|
|
107
|
+
*
|
|
108
|
+
* Stub — full implementation in TASK-106.
|
|
109
|
+
*/
|
|
110
|
+
transaction(_fn) {
|
|
111
|
+
throw new Error("Not implemented");
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Close the underlying `MongoClient` connection. Safe to call even if
|
|
115
|
+
* no connection was established (the driver handles this gracefully).
|
|
116
|
+
*/
|
|
117
|
+
async close() {
|
|
118
|
+
await this._client.close();
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
function extractDbName(uri) {
|
|
122
|
+
const withoutProtocol = uri.replace(/^mongodb(?:\+srv)?:\/\//, "");
|
|
123
|
+
const withoutQuery = withoutProtocol.split("?")[0];
|
|
124
|
+
const atIndex = withoutQuery.lastIndexOf("@");
|
|
125
|
+
const hostAndPath = atIndex === -1 ? withoutQuery : withoutQuery.slice(atIndex + 1);
|
|
126
|
+
const slashIndex = hostAndPath.indexOf("/");
|
|
127
|
+
if (slashIndex === -1) return void 0;
|
|
128
|
+
const dbName = decodeURIComponent(hostAndPath.slice(slashIndex + 1));
|
|
129
|
+
return dbName || void 0;
|
|
130
|
+
}
|
|
131
|
+
function createClient(uri, dbNameOrOptions, maybeOptions) {
|
|
132
|
+
if (typeof dbNameOrOptions === "string") {
|
|
133
|
+
return new Database(uri, dbNameOrOptions, maybeOptions);
|
|
134
|
+
}
|
|
135
|
+
const parsed = extractDbName(uri);
|
|
136
|
+
if (!parsed) {
|
|
137
|
+
console.warn('[zodmon] No database name provided \u2014 using MongoDB default "test"');
|
|
138
|
+
}
|
|
139
|
+
return new Database(uri, parsed ?? "test", dbNameOrOptions);
|
|
140
|
+
}
|
|
141
|
+
|
|
37
142
|
// src/collection/collection.ts
|
|
38
143
|
var import_zod4 = require("zod");
|
|
39
144
|
|
|
@@ -174,14 +279,14 @@ function installExtensions() {
|
|
|
174
279
|
installExtensions();
|
|
175
280
|
|
|
176
281
|
// src/schema/object-id.ts
|
|
177
|
-
var
|
|
282
|
+
var import_mongodb2 = require("mongodb");
|
|
178
283
|
var import_zod3 = require("zod");
|
|
179
284
|
var OBJECT_ID_HEX = /^[a-f\d]{24}$/i;
|
|
180
285
|
function objectId() {
|
|
181
286
|
return import_zod3.z.custom((val) => {
|
|
182
|
-
if (val instanceof
|
|
287
|
+
if (val instanceof import_mongodb2.ObjectId) return true;
|
|
183
288
|
return typeof val === "string" && OBJECT_ID_HEX.test(val);
|
|
184
|
-
}, "Invalid ObjectId").transform((val) => val instanceof
|
|
289
|
+
}, "Invalid ObjectId").transform((val) => val instanceof import_mongodb2.ObjectId ? val : import_mongodb2.ObjectId.createFromHexString(val));
|
|
185
290
|
}
|
|
186
291
|
|
|
187
292
|
// src/collection/collection.ts
|
|
@@ -248,19 +353,58 @@ function index(fields) {
|
|
|
248
353
|
}
|
|
249
354
|
|
|
250
355
|
// src/helpers/oid.ts
|
|
251
|
-
var
|
|
356
|
+
var import_mongodb3 = require("mongodb");
|
|
252
357
|
function oid(value) {
|
|
253
|
-
if (value === void 0) return new
|
|
254
|
-
if (value instanceof
|
|
255
|
-
return
|
|
358
|
+
if (value === void 0) return new import_mongodb3.ObjectId();
|
|
359
|
+
if (value instanceof import_mongodb3.ObjectId) return value;
|
|
360
|
+
return import_mongodb3.ObjectId.createFromHexString(value);
|
|
256
361
|
}
|
|
257
362
|
function isOid(value) {
|
|
258
|
-
return value instanceof
|
|
363
|
+
return value instanceof import_mongodb3.ObjectId;
|
|
259
364
|
}
|
|
365
|
+
|
|
366
|
+
// src/query/operators.ts
|
|
367
|
+
var $eq = (value) => ({ $eq: value });
|
|
368
|
+
var $ne = (value) => ({ $ne: value });
|
|
369
|
+
var $gt = (value) => ({ $gt: value });
|
|
370
|
+
var $gte = (value) => ({ $gte: value });
|
|
371
|
+
var $lt = (value) => ({ $lt: value });
|
|
372
|
+
var $lte = (value) => ({ $lte: value });
|
|
373
|
+
var $in = (values) => ({ $in: values });
|
|
374
|
+
var $nin = (values) => ({ $nin: values });
|
|
375
|
+
var $exists = (flag = true) => ({ $exists: flag });
|
|
376
|
+
var $regex = (pattern) => ({
|
|
377
|
+
$regex: pattern
|
|
378
|
+
});
|
|
379
|
+
var $not = (op) => ({
|
|
380
|
+
$not: op
|
|
381
|
+
});
|
|
382
|
+
var $or = (...filters) => ({ $or: filters });
|
|
383
|
+
var $and = (...filters) => ({ $and: filters });
|
|
384
|
+
var $nor = (...filters) => ({ $nor: filters });
|
|
385
|
+
var raw = (filter) => filter;
|
|
260
386
|
// Annotate the CommonJS export names for ESM import in node:
|
|
261
387
|
0 && (module.exports = {
|
|
388
|
+
$and,
|
|
389
|
+
$eq,
|
|
390
|
+
$exists,
|
|
391
|
+
$gt,
|
|
392
|
+
$gte,
|
|
393
|
+
$in,
|
|
394
|
+
$lt,
|
|
395
|
+
$lte,
|
|
396
|
+
$ne,
|
|
397
|
+
$nin,
|
|
398
|
+
$nor,
|
|
399
|
+
$not,
|
|
400
|
+
$or,
|
|
401
|
+
$regex,
|
|
402
|
+
CollectionHandle,
|
|
403
|
+
Database,
|
|
262
404
|
IndexBuilder,
|
|
263
405
|
collection,
|
|
406
|
+
createClient,
|
|
407
|
+
extractDbName,
|
|
264
408
|
extractFieldIndexes,
|
|
265
409
|
getIndexMetadata,
|
|
266
410
|
getRefMetadata,
|
|
@@ -269,6 +413,7 @@ function isOid(value) {
|
|
|
269
413
|
installRefExtension,
|
|
270
414
|
isOid,
|
|
271
415
|
objectId,
|
|
272
|
-
oid
|
|
416
|
+
oid,
|
|
417
|
+
raw
|
|
273
418
|
});
|
|
274
419
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.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"],"sourcesContent":["export type {\n\tAnyCollection,\n\tCollectionDefinition,\n\tCollectionOptions,\n\tCompoundIndexDefinition,\n\tFieldIndexDefinition,\n\tInferDocument,\n\tResolvedShape,\n} from './collection'\nexport { collection, extractFieldIndexes, IndexBuilder, index } from './collection'\nexport { isOid, oid } from './helpers/oid'\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 { 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(), ...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"],"mappings":"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","names":["import_zod","import_zod","collection","import_zod","import_mongodb"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client/client.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\tResolvedShape,\n} from './collection'\nexport { collection, extractFieldIndexes, IndexBuilder, index } from './collection'\nexport { isOid, oid } from './helpers/oid'\nexport type { ComparisonOperators, DotPaths, DotPathType, TypedFilter } 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} 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<InferDocument<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: definition erased to AnyCollection for storage,\n\t\t// TDoc is preserved through the native Collection generic.\n\t\treturn new CollectionHandle(def as unknown as CollectionDefinition, native)\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 { Collection, Document } from 'mongodb'\nimport type { AnyCollection } from '../collection/types'\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 * CRUD methods (insertOne, find, etc.) are added to this class by\n * subsequent modules — the handle itself is intentionally behavior-free.\n *\n * @typeParam TDoc - The document type inferred from the Zod schema\n * (e.g. `{ _id: ObjectId; name: string }`). Defaults to `Document`.\n */\nexport class CollectionHandle<TDoc extends Document = Document> {\n\t/** The collection definition containing schema, name, and index metadata. */\n\treadonly definition: AnyCollection\n\n\t/** The underlying MongoDB driver collection, typed to `TDoc`. */\n\treadonly native: Collection<TDoc>\n\n\tconstructor(definition: AnyCollection, native: Collection<TDoc>) {\n\t\tthis.definition = definition\n\t\tthis.native = native\n\t}\n}\n","import { 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(), ...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","import_zod","collection","import_mongodb","import_zod","import_mongodb"]}
|