@querykitjs/mongodb 0.0.0-stage → 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Suhrobbek Soatov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.en.md ADDED
@@ -0,0 +1,144 @@
1
+ <div align="right">
2
+
3
+ **English** · [O'zbekcha](./README.md)
4
+
5
+ </div>
6
+
7
+ # @querykitjs/mongodb
8
+
9
+ [![npm](https://img.shields.io/npm/v/@querykitjs/mongodb.svg)](https://www.npmjs.com/package/@querykitjs/mongodb) [![license](https://img.shields.io/npm/l/@querykitjs/mongodb.svg)](./LICENSE)
10
+
11
+ > Advanced filtering + flexible pagination repository layer for the official MongoDB driver.
12
+
13
+ For projects on the plain `mongodb` driver (no Mongoose): one typed repository per collection with complex filters, three pagination styles, transactions, RBAC scoping, soft-delete, bulk writes and aggregation. Field types come from your **zod** schema. The public surface is the same as [`@querykitjs/mongoose`](https://www.npmjs.com/package/@querykitjs/mongoose), [`@querykitjs/drizzle-pg`](https://www.npmjs.com/package/@querykitjs/drizzle-pg) and [`@querykitjs/prisma-pg`](https://www.npmjs.com/package/@querykitjs/prisma-pg), so the **same frontend contract** ([`@querykitjs/web`](https://www.npmjs.com/package/@querykitjs/web)) drives every backend.
14
+
15
+ ## Quick start
16
+
17
+ ```ts
18
+ import { MongoClient, type ObjectId } from "mongodb";
19
+ import { z } from "zod";
20
+ import { createRegistry } from "@querykitjs/mongodb";
21
+
22
+ const WalletSchema = z.object({
23
+ _id: z.string(),
24
+ shop_id: z.string(),
25
+ owner: z.string(),
26
+ status: z.enum(["active", "blocked"]),
27
+ balance: z.number(),
28
+ created_at: z.date(),
29
+ });
30
+ type Wallet = { _id: ObjectId; shop_id: ObjectId; owner: string; status: "active" | "blocked"; balance: number; created_at: Date };
31
+
32
+ const client = await MongoClient.connect(process.env.MONGO_URL!);
33
+ const qk = createRegistry(client, { timestamps: { createdAt: "created_at" }, cursorSecret: process.env.CURSOR_SECRET });
34
+
35
+ export const wallets = qk.repository(client.db("app").collection<Wallet>("wallets"), {
36
+ schema: WalletSchema,
37
+ objectId: ["_id", "shop_id"], // 24-hex strings from the wire → ObjectId
38
+ forcedColumns: { _id: true, owner: true, status: true, balance: true, created_at: true },
39
+ filterable: { status: ["=", "in"], owner: ["=", "startsWith"], created_at: ["between", ">=", "<="] },
40
+ sortable: ["_id", "created_at", "balance"],
41
+ });
42
+
43
+ // one tenant's wallets, newest first, 20 per page
44
+ const shopWallets = wallets.scoped({ shop_id: { in: ["65a1b2c3d4e5f60718293a4b"] } });
45
+ const { data, meta } = await shopWallets.findList({ page: 1, perPage: 20, filter: [{ key: "status", value: "active" }] });
46
+ ```
47
+
48
+ ## Install
49
+
50
+ ```bash
51
+ bun add @querykitjs/mongodb mongodb zod
52
+ # or: npm i @querykitjs/mongodb mongodb zod
53
+ ```
54
+
55
+ ### Requirements
56
+
57
+ - Node.js `>= 22.12` (or Bun).
58
+ - Peers: `mongodb` `^6.21 || ^7.7`, `zod` `^4`.
59
+ - Transactions need a replica set or a sharded cluster (a single-node replica set is enough locally, or `mongodb-memory-server` in tests).
60
+
61
+ ## Setup
62
+
63
+ - `createRegistry(client, options)` — defaults once: `defaultPerPage`, `defaultLimit`, `maxPerPage`, `maxLimit`, `strict`, `onSkippedCondition`, `limits`, `maxTimeMS` (default 2 000), `cursorSecret`, `timestamps`. The same names as every querykit adapter.
64
+ - `qk.repository(collection, options)` — one per collection. `schema` is **required**: the driver has no schema of its own, so the zod object is the one source of field types, unknown keys and the default `filterable`.
65
+ - `objectId` — the fields stored as `ObjectId` (default `["_id"]`). They arrive from JSON as 24-hex strings and are cast here; a malformed id is `invalid-value`.
66
+ - `forcedColumns` / `allowedColumns` — projection guards (the client's `columns` is ignored / intersected).
67
+ - A third argument extends the repository: `qk.repository(collection, options, base => ({ findActive: () => base.findAll({ filter: [{ key: "status", value: "active" }] }) }))`.
68
+
69
+ ## Safe by default — `filterable`, `sortable`, `limits`
70
+
71
+ A client filters and sorts only by the fields the server allows, with the operators it allows. A refused request stops with a `QueryKitError` before it reaches MongoDB, whatever `strict` says.
72
+
73
+ | Option | When not given (default) | When refused |
74
+ | ------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
75
+ | `filterable` | `allowedColumns` (else the `forcedColumns` keys, else only `_id`), with `"="` and `"in"` only | `reason: "forbidden-key"` / `"forbidden-operator"`, `site: "filter"` |
76
+ | `sortable` | `_id` and the createdAt field | `reason: "forbidden-key"`, `site: "sort"` / `"cursorKey"` |
77
+ | `limits` | core `DEFAULT_QUERY_LIMITS` (depth 5, conditions 30, array 200, string 256, offset 10 000, sort 3) | `reason: "limit-exceeded"`, `site: "filter"` / `"sort"` / `"page"` |
78
+
79
+ - **Values are cast by the schema** — `z.number()` takes `30` or `"30"`, `z.date()` an ISO string, an `objectId` field a 24-hex string, a `z.enum` only its values. An object value (`{ "$where": "…" }`, `{ "$gt": "" }`) is never an operator: `invalid-value`, and nothing reaches the driver.
80
+ - An unbranded raw Mongo filter from a JSON body is `forbidden-key`. Server code brands one with `raw({ ... })` from `@querykitjs/core`; ⚠️ `raw()` is not checked by `filterable`.
81
+ - LIKE patterns: more than `maxLikeWildcards` (2) `%`/`_` → `limit-exceeded`.
82
+ - Every read (`find`, `countDocuments`, `aggregate`) carries `maxTimeMS` (default 2 000); past it ⇒ `QueryKitTimeoutError` (`code: "QUERYKIT_TIMEOUT"`) — map it to 503/504, not 400.
83
+ - **Indexes.** `startsWith` is an anchored, case-insensitive regex — MongoDB uses an index poorly for it; on a large collection keep a lowercase shadow field. `contains`, `endsWith`, `!=` and `notIn` cannot use an index — open them only for small collections.
84
+
85
+ ## Pagination — three strategies
86
+
87
+ - `findList({ page, perPage, withTotal })` — offset pages; `withTotal: false` skips the count (`total_items` / `total_pages` are `null`).
88
+ - `findInfinite({ limit, offset })` — infinite scroll (`has_more`, `next_offset`).
89
+ - `findCursor({ cursorKey, limit, cursor, order, direction })` — keyset; ties on `cursorKey` are broken by `_id`, so no row is skipped or repeated; with `cursorSecret` the tokens are signed and an unsigned one is refused.
90
+
91
+ ## Relations (`with`)
92
+
93
+ Not in this version: `$lookup` is not built, so any `with` is `forbidden-key` (`site: "with"`). Load related documents with a second repository call.
94
+
95
+ ## Bulk update and delete
96
+
97
+ `updateWhere(filter, patch)` is one `updateMany` and `deleteWhere(filter)` one `deleteMany` — no read before the write; they return `{ count }` (`{ count, rows }` with `returning: { limit }`). An empty filter is refused (`empty-filter`, `site: "mutation"`) unless you pass `{ all: true }`. Writes store values as given — validate the request with your zod schema first; the driver casts nothing.
98
+
99
+ ## Transactions
100
+
101
+ ```ts
102
+ await qk.transaction(async () => {
103
+ await wallets.updateById(fromId, { balance: 90 });
104
+ await wallets.updateById(toId, { balance: 110 });
105
+ });
106
+ ```
107
+
108
+ `client.withSession` + `withTransaction`; repositories called inside join the transaction, nested calls join the outer one. ⚠️ MongoDB retries a transaction body on a transient error — keep side effects (HTTP calls, emails) outside it.
109
+
110
+ ## Scoped repository, soft delete, upsert, aggregation
111
+
112
+ - `scope` (option) / `repo.scoped(scope)` — added to every read and write; a value may be `{ in: [...] }`; equality values are forced on insert.
113
+ - Soft delete: a schema with `deletedAt` (or `timestamps.deletedAt`) hides deleted documents; `softDelete`, `restore`, `withDeleted: true`.
114
+ - `upsert` / `upsertMany` (`target`, `set`), `aggregate({ count, sum, avg, min, max, groupBy, filter })` — one `$match` + `$group`.
115
+
116
+ ## Testing helper
117
+
118
+ ```ts
119
+ import { explainFind } from "@querykitjs/mongodb/testing";
120
+
121
+ const plan = await explainFind(wallets, { filter: [{ key: "owner", operation: "startsWith", value: "ali" }] });
122
+ ```
123
+
124
+ The query plan of `findAll(params)` with the same checks — assert that a request uses an index. Only in the `/testing` subpath, never in the main bundle.
125
+
126
+ ## API reference
127
+
128
+ | Export | What |
129
+ | ------------------------------------------- | ------------------------------------------ |
130
+ | `createRegistry(client, options)` | registry: `repository(...)`, `transaction` |
131
+ | `buildRepository(runtime, collection, opt)` | a repository without a registry |
132
+ | `createFilters<T>()` / `f` | typed / untyped filter builders |
133
+ | `explainFind(repo, params)` (`/testing`) | the query plan of a `findAll` |
134
+
135
+ ## Development
136
+
137
+ ```bash
138
+ bun run --filter @querykitjs/mongodb test:unit # offline: filter compile + attack tests
139
+ bun run --filter @querykitjs/mongodb test:smoke # real mongod (mongodb-memory-server)
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT
package/README.md CHANGED
@@ -1,3 +1,144 @@
1
- # Temporary Holding Version
1
+ <div align="right">
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [English](./README.en.md) · **O'zbekcha**
4
+
5
+ </div>
6
+
7
+ # @querykitjs/mongodb
8
+
9
+ [![npm](https://img.shields.io/npm/v/@querykitjs/mongodb.svg)](https://www.npmjs.com/package/@querykitjs/mongodb) [![license](https://img.shields.io/npm/l/@querykitjs/mongodb.svg)](./LICENSE)
10
+
11
+ > Rasmiy MongoDB drayveri uchun murakkab filtr + moslashuvchan paginatsiya repository qatlami.
12
+
13
+ Oddiy `mongodb` drayveridagi (Mongoose'siz) loyihalar uchun: har kolleksiyaga bitta tipli repository — murakkab filtrlar, uch xil paginatsiya, tranzaksiyalar, RBAC scope, soft-delete, ommaviy yozish va agregatsiya. Maydon tiplari sizning **zod** sxemangizdan olinadi. Publik shakl [`@querykitjs/mongoose`](https://www.npmjs.com/package/@querykitjs/mongoose), [`@querykitjs/drizzle-pg`](https://www.npmjs.com/package/@querykitjs/drizzle-pg) va [`@querykitjs/prisma-pg`](https://www.npmjs.com/package/@querykitjs/prisma-pg) bilan bir xil, shuning uchun **bitta frontend kontrakti** ([`@querykitjs/web`](https://www.npmjs.com/package/@querykitjs/web)) har backend bilan ishlaydi.
14
+
15
+ ## Tez boshlash
16
+
17
+ ```ts
18
+ import { MongoClient, type ObjectId } from "mongodb";
19
+ import { z } from "zod";
20
+ import { createRegistry } from "@querykitjs/mongodb";
21
+
22
+ const WalletSchema = z.object({
23
+ _id: z.string(),
24
+ shop_id: z.string(),
25
+ owner: z.string(),
26
+ status: z.enum(["active", "blocked"]),
27
+ balance: z.number(),
28
+ created_at: z.date(),
29
+ });
30
+ type Wallet = { _id: ObjectId; shop_id: ObjectId; owner: string; status: "active" | "blocked"; balance: number; created_at: Date };
31
+
32
+ const client = await MongoClient.connect(process.env.MONGO_URL!);
33
+ const qk = createRegistry(client, { timestamps: { createdAt: "created_at" }, cursorSecret: process.env.CURSOR_SECRET });
34
+
35
+ export const wallets = qk.repository(client.db("app").collection<Wallet>("wallets"), {
36
+ schema: WalletSchema,
37
+ objectId: ["_id", "shop_id"], // wire'dagi 24-hex satrlar → ObjectId
38
+ forcedColumns: { _id: true, owner: true, status: true, balance: true, created_at: true },
39
+ filterable: { status: ["=", "in"], owner: ["=", "startsWith"], created_at: ["between", ">=", "<="] },
40
+ sortable: ["_id", "created_at", "balance"],
41
+ });
42
+
43
+ // bitta tenant hamyonlari, eng yangisi birinchi, sahifada 20 ta
44
+ const shopWallets = wallets.scoped({ shop_id: { in: ["65a1b2c3d4e5f60718293a4b"] } });
45
+ const { data, meta } = await shopWallets.findList({ page: 1, perPage: 20, filter: [{ key: "status", value: "active" }] });
46
+ ```
47
+
48
+ ## O'rnatish
49
+
50
+ ```bash
51
+ bun add @querykitjs/mongodb mongodb zod
52
+ # yoki: npm i @querykitjs/mongodb mongodb zod
53
+ ```
54
+
55
+ ### Talablar
56
+
57
+ - Node.js `>= 22.12` (yoki Bun).
58
+ - Peer'lar: `mongodb` `^6.21 || ^7.7`, `zod` `^4`.
59
+ - Tranzaksiyalar replica set yoki sharded klaster talab qiladi (lokalda bitta tugunli replica set yetadi, testlarda `mongodb-memory-server`).
60
+
61
+ ## Sozlash
62
+
63
+ - `createRegistry(client, options)` — default'lar bir marta: `defaultPerPage`, `defaultLimit`, `maxPerPage`, `maxLimit`, `strict`, `onSkippedCondition`, `limits`, `maxTimeMS` (default 2 000), `cursorSecret`, `timestamps`. Har querykit adapteridagi nomlar bilan bir xil.
64
+ - `qk.repository(collection, options)` — har kolleksiyaga bitta. `schema` **majburiy**: drayverning o'z sxemasi yo'q, shuning uchun zod obyekti maydon tiplari, noma'lum kalitlar va default `filterable` uchun yagona manba.
65
+ - `objectId` — `ObjectId` sifatida saqlanadigan maydonlar (default `["_id"]`). JSON'da ular 24-hex satr bo'lib keladi va shu yerda cast qilinadi; buzuq id — `invalid-value`.
66
+ - `forcedColumns` / `allowedColumns` — projection himoyasi (mijozning `columns` i e'tiborsiz / kesishma).
67
+ - Uchinchi argument repository'ni kengaytiradi: `qk.repository(collection, options, base => ({ findActive: () => base.findAll({ filter: [{ key: "status", value: "active" }] }) }))`.
68
+
69
+ ## Standartda xavfsiz — `filterable`, `sortable`, `limits`
70
+
71
+ Mijoz faqat server ruxsat bergan maydonlar bo'yicha, ruxsat berilgan operatorlar bilan filtrlaydi va saralaydi. Rad etilgan so'rov MongoDB'ga yetmasdan `QueryKitError` bilan to'xtaydi — `strict` qanday bo'lmasin.
72
+
73
+ | Opsiya | Berilmasa (default) | Rad etilsa |
74
+ | ------------ | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
75
+ | `filterable` | `allowedColumns` (bo'lmasa `forcedColumns` kalitlari, bo'lmasa faqat `_id`), faqat `"="` va `"in"` | `reason: "forbidden-key"` / `"forbidden-operator"`, `site: "filter"` |
76
+ | `sortable` | `_id` va createdAt maydoni | `reason: "forbidden-key"`, `site: "sort"` / `"cursorKey"` |
77
+ | `limits` | core `DEFAULT_QUERY_LIMITS` (chuqurlik 5, shartlar 30, massiv 200, satr 256, offset 10 000, sort 3) | `reason: "limit-exceeded"`, `site: "filter"` / `"sort"` / `"page"` |
78
+
79
+ - **Qiymatlar sxema bo'yicha cast qilinadi** — `z.number()` `30` yoki `"30"` ni, `z.date()` ISO satrni, `objectId` maydoni 24-hex satrni, `z.enum` faqat o'z qiymatlarini oladi. Obyekt qiymat (`{ "$where": "…" }`, `{ "$gt": "" }`) hech qachon operator emas: `invalid-value`, drayverga hech narsa yetmaydi.
80
+ - JSON body'dan kelgan brendsiz raw Mongo filtri — `forbidden-key`. Server kodi uni `@querykitjs/core` dagi `raw({ ... })` bilan belgilaydi; ⚠️ `raw()` `filterable` tekshiruvidan o'tmaydi.
81
+ - LIKE andozalari: `maxLikeWildcards` (2) dan ko'p `%`/`_` → `limit-exceeded`.
82
+ - Har o'qish (`find`, `countDocuments`, `aggregate`) `maxTimeMS` bilan (default 2 000); oshsa ⇒ `QueryKitTimeoutError` (`code: "QUERYKIT_TIMEOUT"`) — 400 emas, 503/504 ga map qiling.
83
+ - **Indekslar.** `startsWith` — boshi bog'langan, registrga sezgir bo'lmagan regex; MongoDB unga indeksni yomon ishlatadi — katta kolleksiyada kichik harfli soya maydonini saqlang. `contains`, `endsWith`, `!=` va `notIn` indeks ishlata olmaydi — faqat kichik kolleksiyalar uchun oching.
84
+
85
+ ## Paginatsiya — uch strategiya
86
+
87
+ - `findList({ page, perPage, withTotal })` — offset sahifalar; `withTotal: false` count'ni o'tkazib yuboradi (`total_items` / `total_pages` — `null`).
88
+ - `findInfinite({ limit, offset })` — infinite scroll (`has_more`, `next_offset`).
89
+ - `findCursor({ cursorKey, limit, cursor, order, direction })` — keyset; `cursorKey` dagi tengliklar `_id` bilan ajratiladi, shuning uchun hech bir qator tushib qolmaydi yoki takrorlanmaydi; `cursorSecret` bilan tokenlar imzolanadi, imzosizi rad etiladi.
90
+
91
+ ## Relation'lar (`with`)
92
+
93
+ Bu versiyada yo'q: `$lookup` qurilmagan, shuning uchun har qanday `with` — `forbidden-key` (`site: "with"`). Bog'liq hujjatlarni ikkinchi repository chaqiruvi bilan yuklang.
94
+
95
+ ## Ommaviy yangilash va o'chirish
96
+
97
+ `updateWhere(filter, patch)` — bitta `updateMany`, `deleteWhere(filter)` — bitta `deleteMany`: yozishdan oldin o'qish yo'q; `{ count }` qaytaradi (`returning: { limit }` bilan `{ count, rows }`). Bo'sh filtr rad etiladi (`empty-filter`, `site: "mutation"`), agar `{ all: true }` berilmasa. Yozish qiymatlarni berilganicha saqlaydi — so'rovni avval zod sxemangiz bilan tekshiring; drayver hech narsani cast qilmaydi.
98
+
99
+ ## Tranzaksiyalar
100
+
101
+ ```ts
102
+ await qk.transaction(async () => {
103
+ await wallets.updateById(fromId, { balance: 90 });
104
+ await wallets.updateById(toId, { balance: 110 });
105
+ });
106
+ ```
107
+
108
+ `client.withSession` + `withTransaction`; ichida chaqirilgan repository'lar tranzaksiyaga qo'shiladi, ichma-ich chaqiruv tashqisiga qo'shiladi. ⚠️ MongoDB vaqtinchalik xatoda tranzaksiya tanasini qayta ishga tushiradi — yon ta'sirlarni (HTTP chaqiruvlar, xatlar) undan tashqarida qoldiring.
109
+
110
+ ## Scope, soft delete, upsert, agregatsiya
111
+
112
+ - `scope` (opsiya) / `repo.scoped(scope)` — har o'qish va yozishga qo'shiladi; qiymat `{ in: [...] }` bo'lishi mumkin; tenglik qiymatlari insert'da majburan qo'yiladi.
113
+ - Soft delete: `deletedAt` (yoki `timestamps.deletedAt`) maydoni bor sxemada o'chirilgan hujjatlar yashiriladi; `softDelete`, `restore`, `withDeleted: true`.
114
+ - `upsert` / `upsertMany` (`target`, `set`), `aggregate({ count, sum, avg, min, max, groupBy, filter })` — bitta `$match` + `$group`.
115
+
116
+ ## Test yordamchisi
117
+
118
+ ```ts
119
+ import { explainFind } from "@querykitjs/mongodb/testing";
120
+
121
+ const plan = await explainFind(wallets, { filter: [{ key: "owner", operation: "startsWith", value: "ali" }] });
122
+ ```
123
+
124
+ `findAll(params)` ning query plan'i, xuddi shu tekshiruvlar bilan — so'rov indeks ishlatishini tekshirish uchun. Faqat `/testing` subpath'da, asosiy bundle'da hech qachon.
125
+
126
+ ## API ma'lumotnoma
127
+
128
+ | Eksport | Nima |
129
+ | ------------------------------------------- | ------------------------------------------ |
130
+ | `createRegistry(client, options)` | registry: `repository(...)`, `transaction` |
131
+ | `buildRepository(runtime, collection, opt)` | registry'siz repository |
132
+ | `createFilters<T>()` / `f` | tipli / tipsiz filtr quruvchilar |
133
+ | `explainFind(repo, params)` (`/testing`) | `findAll` ning query plan'i |
134
+
135
+ ## Ishlab chiqish
136
+
137
+ ```bash
138
+ bun run --filter @querykitjs/mongodb test:unit # oflayn: filtr kompilyatsiyasi + hujum testlari
139
+ bun run --filter @querykitjs/mongodb test:smoke # haqiqiy mongod (mongodb-memory-server)
140
+ ```
141
+
142
+ ## Litsenziya
143
+
144
+ MIT
package/dist/index.cjs ADDED
@@ -0,0 +1,2 @@
1
+ 'use strict';var core=require('@querykitjs/core'),internal=require('@querykitjs/core/internal'),mongodb=require('mongodb');var he=new Set(["optional","nullable","default","prefault","readonly","catch","nonoptional"]),Te={string:"string",number:"number",boolean:"boolean",date:"date"};function ke(t){let e=t.def;for(;he.has(e.type)&&e.innerType;)e=e.innerType.def;return e.type==="enum"&&e.entries?{kind:"string",values:Object.values(e.entries)}:e.type==="literal"&&e.values?{kind:typeof e.values[0]=="number"?"number":"string",values:e.values}:{kind:Te[e.type]??"other"}}function z(t,e,o=["_id"]){let n=new Map;for(let[s,l]of Object.entries(e.shape))n.set(s,ke(l));for(let s of o)n.set(s,{kind:"objectId"});return n.has("_id")||n.set("_id",{kind:"objectId"}),{source:t,fields:n}}function b(t,e){let o=e==="id"?"_id":e;return t.fields.has(o)?o:void 0}var X=(t,e)=>t.fields.get(e)?.kind;function G(t,e,o,n=b(t,"createdAt")?"createdAt":void 0){let s={};for(let l of internal.normalizeSort(e,o)){let f=b(t,l.key);f?s[f]=l.direction==="desc"?-1:1:internal.reportSkip(o,{site:"sort",key:l.key,reason:"unknown-key"});}return Object.keys(s).length===0&&(n?s[n]=-1:s._id=-1),s}var H=new Set(core.TEXT_FILTER_OPERATORS),x=Symbol("querykit.invalid-value"),Y=t=>H.has(t),xe=/^-?(\d+\.?\d*|\.\d+)(e[+-]?\d+)?$/i;function Se(t,e){switch(t.kind){case "string":return typeof e=="string"||typeof e=="number"||typeof e=="boolean"?String(e):x;case "number":return typeof e=="number"?Number.isFinite(e)?e:x:typeof e=="string"&&xe.test(e.trim())?Number(e):x;case "boolean":return typeof e=="boolean"?e:e==="true"?true:e==="false"?false:x;case "date":{if(!(e instanceof Date)&&typeof e!="string"&&typeof e!="number")return x;let o=new Date(e);return Number.isNaN(o.getTime())?x:o}case "objectId":return e instanceof mongodb.ObjectId?e:typeof e=="string"&&mongodb.ObjectId.isValid(e)&&e.length===24?new mongodb.ObjectId(e):x;case "other":return typeof e=="string"||typeof e=="number"||typeof e=="boolean"?e:x}}function _(t,e,o){let n=t.fields.get(e);if(!n||o===null||o===void 0)return o;let s=Se(n,o);return s===x||n.values&&!n.values.includes(s)?x:s}function Z(t,e,o,n){if(n===void 0)return n;if(H.has(o))return typeof n=="string"?n:x;if(Array.isArray(n)){let l=[];for(let f of n){let p=_(t,e,f);if(p===x)return x;l.push(p);}return l}let s=_(t,e,n);return s===x?x:s}var E=t=>String(t??"").replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),V=t=>{let e="";for(let o of String(t??""))o==="%"?e.endsWith(".*")||(e+=".*"):o==="_"?e+=".":e+=o.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return `^${e}$`},J=t=>Array.isArray(t)&&t.length===2?[t[0],t[1]]:void 0,ee={"=":t=>({$eq:t}),eq:t=>({$eq:t}),"!=":t=>({$nin:[t,null]}),ne:t=>({$nin:[t,null]}),">":t=>({$gt:t}),gt:t=>({$gt:t}),">=":t=>({$gte:t}),gte:t=>({$gte:t}),"<":t=>({$lt:t}),lt:t=>({$lt:t}),"<=":t=>({$lte:t}),lte:t=>({$lte:t}),contains:t=>({$regex:E(t),$options:"i"}),"%_%":t=>({$regex:E(t),$options:"i"}),startsWith:t=>({$regex:`^${E(t)}`,$options:"i"}),"%_":t=>({$regex:`^${E(t)}`,$options:"i"}),endsWith:t=>({$regex:`${E(t)}$`,$options:"i"}),"_%":t=>({$regex:`${E(t)}$`,$options:"i"}),like:t=>({$regex:V(t)}),ilike:t=>({$regex:V(t),$options:"i"}),notLike:t=>({$not:{$regex:V(t)},$ne:null}),in:t=>Array.isArray(t)?{$in:t}:void 0,notIn:t=>Array.isArray(t)?{$nin:[...t,null]}:void 0,between:t=>{let e=J(t);return e?{$gte:e[0],$lte:e[1]}:void 0},notBetween:t=>{let e=J(t);return e?{$not:{$gte:e[0],$lte:e[1]},$ne:null}:void 0},isNull:()=>({$eq:null}),isNotNull:()=>({$ne:null})};var q=t=>typeof t=="object"&&t!==null,te=t=>q(t)&&"key"in t&&!("and"in t)&&!("or"in t)&&!("not"in t);function K(t,e){let o=e.filter(n=>n!==void 0);if(o.length!==0)return o.length===1?o[0]:{[t]:o}}function ne(t,e,o){let n=e.operation??"=",s=ee[n];if(!s)throw new Error(`Unsupported filter operator: "${n}"`);let l=b(t,e.key);if(!l){internal.reportSkip(o,{site:"filter",key:e.key,operation:n,reason:"unknown-key"});return}if(Y(n)&&X(t,l)==="date"){internal.reportSkip(o,{site:"filter",key:e.key,operation:n,reason:"invalid-value"});return}let f=Z(t,l,n,e.value);if(f===x){internal.reportSkip(o,{site:"filter",key:e.key,operation:n,reason:"invalid-value"});return}let p=s(f);if(p===void 0){internal.reportSkip(o,{site:"filter",key:e.key,operation:n,reason:"invalid-value"});return}return {[l]:p}}function M(t,e,o){if(te(e))return ne(t,e,o);if(q(e)){if("and"in e)return K("$and",e.and.map(n=>M(t,n,o)));if("or"in e)return K("$or",e.or.map(n=>M(t,n,o)));if("not"in e)return B(t,e.not,o);if(internal.isRaw(e))return e;throw new core.QueryKitError({source:t.source,site:"filter",key:Object.keys(e)[0]??"",reason:"forbidden-key"})}}function B(t,e,o){if(te(e)){let s=ne(t,e,o);if(!s)return;let l=e.operation??"=",f=l==="isNull"||l==="isNotNull"?void 0:b(t,e.key);return f?{$and:[{[f]:{$ne:null}},{$nor:[s]}]}:{$nor:[s]}}if(q(e)){if("and"in e)return K("$or",e.and.map(s=>B(t,s,o)));if("or"in e)return K("$and",e.or.map(s=>B(t,s,o)));if("not"in e)return M(t,e.not,o)}let n=M(t,e,o);return n?{$nor:[n]}:void 0}function L(t,e,o){if(e!==void 0)return Array.isArray(e)?K("$and",e.map(n=>M(t,n,o))):M(t,e,o)}var oe=t=>Object.entries(t).filter(([,e])=>e).map(([e])=>e);function re(t,e){let o=e.forcedColumns?oe(e.forcedColumns):void 0;if(e.forcedColumns&&o.length===0)throw new Error("buildRepository: forcedColumns must select at least one field (an empty selection would return the full document).");let n=e.allowedColumns?new Set(e.allowedColumns):void 0;if(e.allowedColumns&&n.size===0)throw new Error("buildRepository: allowedColumns must list at least one field (an empty allowlist would return the full document).");let s=p=>o?o.includes(p):n?n.has(p):true,l=p=>{let D=p.filter(u=>n.has(u));return D.length>0?D:[...n]};return {guarded:!!(o??n),permits:s,projection:p=>{let D=p?oe(p):[],u=o??(n?l(D):D);if(u.length===0)return;let h={},F=false;for(let k of u){let r=b(t,k);r&&(h[r]=1,r==="_id"&&(F=true));}if(Object.keys(h).length!==0)return F||(h._id=0),h}}}var Qe={columns:"projection",nested:"with",filters:["match"],logical:["$and","$or","$nor"],paging:["limit","skip"],options:"options"},_e=t=>typeof t=="object"&&t!==null&&(t.codeName==="MaxTimeMSExpired"||t.code===50);function se(t,e,o){let n=z(e.collectionName,o.schema,o.objectId),s=b(n,t.timestamps?.deletedAt??"deletedAt")??"deletedAt",l=n.fields.has(s),f=t.timestamps?.createdAt!==void 0,p=b(n,t.timestamps?.createdAt??"createdAt"),D=n.fields.has("updatedAt"),u=d=>D?{...d,updatedAt:new Date}:d,h={source:n.source,strict:t.strict,onSkipped:t.onSkippedCondition},F=k(n);function k(d){let y=internal.scopeConditions(o.scope);for(let P of y)if(!b(d,P.key))throw new core.QueryKitError({source:d.source,site:"filter",key:P.key,reason:"unknown-key"});return y.length?L(d,y):void 0}let r=d=>G(n,d,h,p),w=d=>{internal.checkWith(d,void 0,Qe,h.source);},T=(d,y)=>{let P=[d,F,l&&!y?{[s]:{$eq:null}}:void 0].filter(A=>A!==void 0);return P.length===0?{}:P.length===1?P[0]:{$and:P}},m=(d,y)=>T(L(n,d,h),y),i=(d,y,P)=>{let A={key:y,operation:"=",value:P};return d?Array.isArray(d)?[...d,A]:{and:[d,A]}:[A]},c=re(n,o),a=o.maxTimeMS??t.maxTimeMS,R=()=>{let d=t.getSession();return d?{session:d}:{}},S=async d=>{try{return await d({maxTimeMS:a,...R()})}catch(y){throw _e(y)?new core.QueryKitTimeoutError(n.source,a,{cause:y}):y}},O=(d,y)=>S(P=>{let A={...P},Q=c.projection(y.columns);return Q&&(A.projection=Q),y.sort&&(A.sort=y.sort),typeof y.skip=="number"&&(A.skip=y.skip),typeof y.limit=="number"&&(A.limit=y.limit),e.find(d,A).toArray()}),I=d=>S(y=>e.countDocuments(d,y)),g=internal.resolvePolicy({source:n.source,fieldOf:d=>b(n,d),primaryKey:"_id",createdAt:f?p:p??b(n,"created_at"),filterable:o.filterable,sortable:o.sortable,allowedColumns:o.allowedColumns,forcedColumns:o.forcedColumns,limits:{...t.limits,...o.limits}});return {...c,runtime:t,collection:e,shape:n,diag:h,hasDeletedAt:l,deletedAtPath:s,forUpdate:u,sortSpec:r,withOf:w,policy:g,maxTimeMS:a,composeWhere:m,mutationWhere:(d,y)=>{if(internal.isAllRows(d))return T(void 0);internal.isEmptyFilter(d)&&internal.refuseEmptyFilter(h.source,y),g.checkFilter(d);let P=L(n,d,h);return P===void 0?internal.refuseEmptyFilter(h.source,y):T(P)},withId:i,session:R,timed:S,runFind:O,countWhere:I}}var j=t=>t===void 0?[]:Array.isArray(t)?t:[t];function ce(t){let{collection:e,shape:o,diag:n,permits:s,policy:l,composeWhere:f,timed:p}=t,D=u=>{let h=s(u)?b(o,u):void 0;return h||internal.reportSkip(n,{site:"aggregate",key:u,reason:"unknown-key"}),h};return {async aggregate(u){l.checkFilter(u.filter);for(let m of [u.groupBy,u.sum,u.avg,u.min,u.max].flatMap(i=>j(i)))l.checkAggregateKey(m);let h=j(u.groupBy).filter(m=>!!D(m)),k={_id:h.length?Object.fromEntries(h.map(m=>[m,`$${D(m)??m}`])):null};u.count&&(k.count={$sum:1});let r=(m,i,c)=>{for(let a of i){let R=D(a);R&&(k[`${c}_${a}`]={[m]:`$${R}`});}};r("$sum",j(u.sum),"sum"),r("$avg",j(u.avg),"avg"),r("$min",j(u.min),"min"),r("$max",j(u.max),"max");let w=[{$match:f(u.filter,u.withDeleted)},{$group:k}];return (await p(m=>e.aggregate(w,m).toArray())).map(({_id:m,...i})=>({...typeof m=="object"&&m?m:{},...i}))}}}function ue(t){let{runtime:e,collection:o,shape:n,diag:s,guarded:l,permits:f,projection:p,policy:D,withOf:u,composeWhere:h,timed:F}=t;return {async findCursor(k={}){let r=internal.clampPageSize(k.limit,e.defaultLimit,e.maxLimit),w=k.cursorKey??"id";D.checkFilter(k.filter),k.cursorKey!==void 0&&D.checkCursorKey(w);let T=k.order??"asc",m=k.direction??"forward",i=b(n,w);if(!i)throw new core.QueryKitError({source:s.source,site:"cursorKey",key:w,reason:"unknown-key"});let c=await internal.decodeCursorToken(k.cursor,{source:s.source,secret:e.cursorSecret,key:w}),a=c===void 0?void 0:_(n,i,c.k),R=c===void 0?void 0:_(n,"_id",c.id);if(a===x||R===x)throw new core.QueryKitError({source:s.source,site:"cursorKey",key:w,reason:"invalid-value"});let S=h(k.filter,k.withDeleted),O=m==="forward"?T==="asc":T==="desc",I=O?"$gt":"$lt",g=i!=="_id",$=c===void 0?void 0:g?{$or:[{[i]:{[I]:a}},{[i]:a,_id:{[I]:R}}]}:{[i]:{[I]:a}},d=$?Object.keys(S).length?{$and:[S,$]}:$:S,y=p(k.columns),P=y?{...y,[i]:1,_id:1}:void 0,A=C=>y!==void 0&&!!y[C],Q=y===void 0?[]:[i,"_id"].filter(C=>l&&(!f(C)||!A(C))||C==="_id"&&C!==i&&!A(C));u(k.with);let ge=g?{[i]:O?1:-1,_id:O?1:-1}:{[i]:O?1:-1},De=await F(C=>o.find(d,{...C,...P?{projection:P}:{},sort:ge,limit:r+1}).toArray()),U=await internal.cursorPage(De,{limit:r,direction:m,hasCursor:c!==void 0,cursorField:i,idField:"_id",secret:e.cursorSecret});return Q.length>0&&(U.data=U.data.map(C=>Object.fromEntries(Object.entries(C).filter(([we])=>!Q.includes(we))))),U}}}var le=1e3,ve="\0";function fe(t,e){let{runtime:o,collection:n,shape:s,hasDeletedAt:l,deletedAtPath:f,forUpdate:p,composeWhere:D,mutationWhere:u,withId:h,session:F,runFind:k}=t,r=i=>internal.clampPageSize(i.limit,o.defaultLimit,o.maxLimit),w=i=>({...internal.scopeDefaults(e.scope),...i,...internal.scopeDefaults(e.scope)}),T=(i,c)=>{let a=j(c.target),R=w(i),S={};for(let $ of a){let d=b(s,$);if(!d)throw new Error(`upsert: unknown target field "${$}".`);S[d]=R[$];}let O=c.set?{...c.set}:Object.fromEntries(Object.entries(R).filter(([$])=>!a.includes($))),I=Object.fromEntries(Object.entries(R).filter(([$])=>!a.includes($)&&!($ in O))),g={};return Object.keys(O).length&&(g.$set=O),Object.keys(I).length&&(g.$setOnInsert=I),{filter:S,update:g}},m=async(i,c)=>await n.findOneAndUpdate(i,{$set:c},{returnDocument:"after",...F()})??void 0;return {async create(i){let c=w(i),{insertedId:a}=await n.insertOne(c,F());return {...c,_id:a}},async createMany(i){if(i.length===0)return [];let c=i.map(w),{insertedIds:a}=await n.insertMany(c,F());return c.map((R,S)=>({...R,_id:a[S]}))},async upsert(i,c){let{filter:a,update:R}=T(i,c);return await n.findOneAndUpdate(a,R,{returnDocument:"after",upsert:true,...F()})},async upsertMany(i,c){if(i.length===0)return [];let a=i.map(g=>T(g,c));for(let g=0;g<a.length;g+=le){let $=a.slice(g,g+le).map(d=>({updateOne:{filter:d.filter,update:d.update,upsert:true}}));await n.bulkWrite($,F());}let R=await k({$or:a.map(g=>g.filter)},{}),S=j(c.target).map(g=>b(s,g)).filter(g=>!!g),O=g=>S.map($=>String(g[$])).join(ve),I=new Map(R.map(g=>[O(g),g]));return a.map(g=>I.get(O(g.filter))).filter(g=>!!g)},updateById(i,c,a="id"){return m(D(h(void 0,a,i)),p(c))},async updateWhere(i,c,a={}){let R=u(i,"updateWhere"),{matchedCount:S}=await n.updateMany(R,{$set:p(c)},F());if(!a.returning)return {count:S};let O=await k(R,{limit:r(a.returning)});return {count:S,rows:O}},async deleteById(i,c="id"){return await n.findOneAndDelete(D(h(void 0,c,i)),F())??void 0},async deleteWhere(i,c={}){let a=u(i,"deleteWhere"),R=c.returning?await k(a,{limit:r(c.returning)}):void 0,{deletedCount:S}=await n.deleteMany(a,F());return R?{count:S,rows:R}:{count:S}},async softDelete(i,c="id"){if(!l)throw new Error("softDelete: schema has no deletedAt field.");return m(D(h(void 0,c,i),false),p({[f]:new Date}))},async restore(i,c="id"){if(!l)throw new Error("restore: schema has no deletedAt field.");return m(D(h(void 0,c,i),true),p({[f]:null}))}}}var pe=Symbol.for("querykit.mongodb.explain");function ye(t){let{runtime:e,collection:o,policy:n,sortSpec:s,withOf:l,composeWhere:f,withId:p,runFind:D,countWhere:u,timed:h}=t,F=r=>{n.checkFilter(r.filter),n.checkSort(r.sort),l(r.with);},k=async(r,w)=>{let[T]=await D(f(w,r.withDeleted),{sort:s(r.sort),columns:r.columns,limit:1});return T};return {async findAll(r={}){return F(r),await D(f(r.filter,r.withDeleted),{sort:s(r.sort),columns:r.columns})},async findOne(r={}){return F(r),await k(r,r.filter)},async findById(r,w={}){let{idKey:T="id",filter:m}=w;return n.checkFilter(m),l(w.with),await k({...w,sort:void 0},p(m,T,r))},async findList(r={}){F(r);let w=internal.clampPage(r.page),T=internal.clampPageSize(r.perPage,e.defaultPerPage,e.maxPerPage);n.checkPage({page:w,perPage:T});let m=f(r.filter,r.withDeleted),i=R=>D(m,{sort:s(r.sort),columns:r.columns,limit:R,skip:(w-1)*T});if(r.withTotal===false)return internal.offsetPageWithoutTotal(await i(T+1),w,T);let[c,a]=await Promise.all([i(T),u(m)]);return {data:c,meta:internal.offsetMeta(w,T,a)}},async findInfinite(r={}){let w=internal.clampPageSize(r.limit,e.defaultLimit,e.maxLimit),T=internal.clampOffset(r.offset);F(r),n.checkPage({offset:T});let m=await D(f(r.filter,r.withDeleted),{sort:s(r.sort),columns:r.columns,limit:w+1,skip:T});return internal.infinitePage(m,w,T)},async count(r){return n.checkFilter(r),u(f(r))},async exists(r){return n.checkFilter(r),await u(f(r))>0},async[pe](r={}){F(r);let w=f(r.filter,r.withDeleted);return h(T=>o.find(w,{...T,sort:s(r.sort)}).explain("queryPlanner"))}}}function N(t,e,o){let n=se(t,e,o);return {collection:e,...ye(n),...ue(n),...fe(n,o),...ce(n),scoped(l){return N(t,e,{...o,scope:{...o.scope,...l}})}}}var et=2e3;function tt(t,e={}){let o=internal.createContextStore(),n={getSession:()=>o.get()?.session,defaultPerPage:e.defaultPerPage??core.DEFAULT_PER_PAGE,defaultLimit:e.defaultLimit??core.DEFAULT_LIMIT,maxPerPage:e.maxPerPage??core.DEFAULT_MAX_PER_PAGE,maxLimit:e.maxLimit??core.DEFAULT_MAX_LIMIT,strict:e.strict??false,onSkippedCondition:e.onSkippedCondition,limits:e.limits,cursorSecret:e.cursorSecret,timestamps:e.timestamps,maxTimeMS:e.maxTimeMS??et};function s(f,p,D){let u=N(n,f,p);return D?{...u,...D(u)}:u}return {repository:s,transaction:async f=>o.get()?.session?f():t.withSession(async p=>{let D;return await p.withTransaction(async()=>{D=await o.run({session:p},f);}),D})}}function rt(){return core.createFilters()}Object.defineProperty(exports,"f",{enumerable:true,get:function(){return core.f}});exports.buildRepository=N;exports.createFilters=rt;exports.createRegistry=tt;//# sourceMappingURL=index.cjs.map
2
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/internal/fields.ts","../src/internal/order-by.ts","../src/internal/coerce.ts","../src/internal/operators.ts","../src/internal/where.ts","../src/repository/projection.ts","../src/repository/context.ts","../src/repository/aggregate.ts","../src/repository/cursor.ts","../src/repository/mutate.ts","../src/internal/explain-key.ts","../src/repository/read.ts","../src/repository/index.ts","../src/registry.ts","../src/filters.ts"],"names":["WRAPPERS","KINDS","fieldOf","schema","def","shapeFromSchema","source","objectId","fields","name","field","resolveField","shape","key","fieldKind","buildSort","sort","diag","createdAt","spec","item","normalizeSort","reportSkip","TEXT_OPERATORS","TEXT_FILTER_OPERATORS","INVALID_VALUE","isTextOperator","operator","NUMERIC","castScalar","value","date","ObjectId","castForField","fieldName","cast","coerceCondition","items","esc","s","sqlLikeToRegex","pattern","out","ch","asTuple","v","operators","t","isObject","n","isFieldCondition","combine","kind","parts","valid","p","buildCondition","cond","build","fragment","buildNode","node","buildFalse","isRaw","QueryKitError","inner","op","buildWhere","filter","c","truthyKeys","selection","on","buildProjection","config","forcedKeys","allowed","permits","intersectAllowed","requested","hit","columns","keys","proj","includesId","WITH_DIALECT","isTimeLimitError","error","buildRepoContext","runtime","collection","deletedAtPath","hasDeletedAt","createdAtConfigured","createdAtPath","stampUpdatedAt","forUpdate","patch","scopeWhere","buildScopeWhere","docShape","conditions","scopeConditions","condition","sortSpec","withOf","checkWith","combineWhere","userWhere","withDeleted","composeWhere","userFilter","withId","idKey","id","idCondition","guards","maxTimeMS","session","current","timed","read","QueryKitTimeoutError","runFind","where","opts","options","findOptions","projection","countWhere","policy","resolvePolicy","method","isAllRows","isEmptyFilter","refuseEmptyFilter","toArr","aggregateMethods","ctx","aggregable","groupKeys","group","k","addAgg","prefix","pipeline","_id","rest","cursorMethods","guarded","params","limit","clampPageSize","cursorKey","order","direction","token","decodeCursorToken","cursorValue","idValue","baseWhere","ascInQuery","past","tieBreak","seek","selected","picked","hidden","rows","page","cursorPage","row","CHUNK","KEY_SEPARATOR","mutateMethods","mutationWhere","returningLimit","returning","forInsert","values","scopeDefaults","buildUpsert","targetKeys","inserted","set","setOnInsert","update","updateOne","doc","insertedId","docs","insertedIds","index","entries","i","ops","e","targetFields","f","keyOf","o","byKey","r","count","EXPLAIN","readMethods","checked","first","clampPage","perPage","offsetPageWithoutTotal","data","totalItems","offsetMeta","offset","clampOffset","infinitePage","buildRepository","scope","DEFAULT_MAX_TIME_MS","createRegistry","client","createContextStore","DEFAULT_PER_PAGE","DEFAULT_LIMIT","DEFAULT_MAX_PER_PAGE","DEFAULT_MAX_LIMIT","repository","repoOptions","extend","base","fn","result","createFilters","coreCreateFilters"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Document fields from the repository's zod schema (task 017 Locked 2): the field kinds the\n * filter casts to, the enum values a string field allows, and which fields hold an ObjectId.\n * The driver has no schema of its own, so the zod object is the one source of field types.\n */\nimport type { z } from \"zod\";\n\n/** How a wire (JSON) value is cast for a field. `other` — arrays, objects, unions: primitives only. */\nexport type FieldKind = \"string\" | \"number\" | \"boolean\" | \"date\" | \"objectId\" | \"other\";\n\nexport interface Field {\n kind: FieldKind;\n /** Allowed values of a `z.enum` / `z.literal` field; a value outside them can never match. */\n values?: readonly unknown[];\n}\n\nexport interface DocShape {\n /** Collection name — the `source` of a `QueryKitError` / skipped condition. */\n source: string;\n fields: ReadonlyMap<string, Field>;\n}\n\n/** Wrappers that do not change what a stored value looks like. */\nconst WRAPPERS = new Set([\"optional\", \"nullable\", \"default\", \"prefault\", \"readonly\", \"catch\", \"nonoptional\"]);\nconst KINDS: Readonly<Record<string, FieldKind>> = { string: \"string\", number: \"number\", boolean: \"boolean\", date: \"date\" };\n\ninterface SchemaDef {\n type: string;\n innerType?: { def: SchemaDef };\n entries?: Record<string, unknown>;\n values?: readonly unknown[];\n}\n\nfunction fieldOf(schema: { def: SchemaDef }): Field {\n let def = schema.def;\n while (WRAPPERS.has(def.type) && def.innerType) def = def.innerType.def;\n if (def.type === \"enum\" && def.entries) return { kind: \"string\", values: Object.values(def.entries) };\n if (def.type === \"literal\" && def.values) return { kind: typeof def.values[0] === \"number\" ? \"number\" : \"string\", values: def.values };\n return { kind: KINDS[def.type] ?? \"other\" };\n}\n\n/**\n * Fields of a zod object schema. `objectId` names the fields stored as `ObjectId` (default\n * `[\"_id\"]`): a JSON body carries them as 24-hex strings, so they are cast here. `_id` is\n * always a field, an ObjectId unless the schema or `objectId` says otherwise.\n */\nexport function shapeFromSchema(source: string, schema: z.ZodObject, objectId: readonly string[] = [\"_id\"]): DocShape {\n const fields = new Map<string, Field>();\n for (const [name, field] of Object.entries(schema.shape)) fields.set(name, fieldOf(field as unknown as { def: SchemaDef }));\n for (const name of objectId) fields.set(name, { kind: \"objectId\" });\n if (!fields.has(\"_id\")) fields.set(\"_id\", { kind: \"objectId\" });\n return { source, fields };\n}\n\n/** A wire key → the stored field name (`id` means `_id`), or `undefined` when the schema has no such field. */\nexport function resolveField(shape: DocShape, key: string): string | undefined {\n const name = key === \"id\" ? \"_id\" : key;\n return shape.fields.has(name) ? name : undefined;\n}\n\nexport const fieldKind = (shape: DocShape, field: string): FieldKind | undefined => shape.fields.get(field)?.kind;\n","import { normalizeSort, reportSkip, type Diagnostics } from \"@querykitjs/core/internal\";\n\nimport type { Sort } from \"../types\";\nimport { resolveField, type DocShape } from \"./fields\";\n\n/** A Mongo sort spec, e.g. `{ name: 1, createdAt: -1 }`. */\nexport type SortSpec = Record<string, 1 | -1>;\n\n/**\n * Build a Mongo sort spec from the sort input. Unknown fields are skipped; when\n * nothing valid remains, defaults to newest-first (`createdAt` desc, else `_id`).\n */\nexport function buildSort(\n shape: DocShape,\n sort?: Sort,\n diag?: Diagnostics,\n createdAt: string | undefined = resolveField(shape, \"createdAt\") ? \"createdAt\" : undefined,\n): SortSpec {\n const spec: SortSpec = {};\n for (const item of normalizeSort(sort, diag)) {\n const field = resolveField(shape, item.key);\n if (field) spec[field] = item.direction === \"desc\" ? -1 : 1;\n // An unknown sort key falls back to the default order, so the list looks\n // \"unsorted\" to the caller with nothing in the log to explain it.\n else reportSkip(diag, { site: \"sort\", key: item.key, reason: \"unknown-key\" });\n }\n if (Object.keys(spec).length === 0) {\n if (createdAt) spec[createdAt] = -1;\n else spec._id = -1;\n }\n return spec;\n}\n","/**\n * Wire value → stored value, by the field kind from the zod schema. A value the field cannot\n * hold is INVALID_VALUE and the condition is dropped as `invalid-value` — the same contract as\n * the mongoose adapter (`path.cast`) and drizzle-pg. A plain object is never a value: that is\n * how `{ \"$where\": … }` or `{ \"$gt\": \"\" }` would reach the driver as an operator (task 017 T-2).\n */\nimport { ObjectId } from \"mongodb\";\nimport { TEXT_FILTER_OPERATORS, type FilterOperator, type FilterValue } from \"@querykitjs/core\";\n\nimport type { DocShape, Field } from \"./fields\";\n\n/** Operators whose value is a text pattern — never cast. */\nconst TEXT_OPERATORS: ReadonlySet<FilterOperator> = new Set(TEXT_FILTER_OPERATORS);\n\n/** Returned when a value cannot be stored in the field; callers drop the condition. */\nexport const INVALID_VALUE = Symbol(\"querykit.invalid-value\");\n\nexport const isTextOperator = (operator: FilterOperator): boolean => TEXT_OPERATORS.has(operator);\n\nconst NUMERIC = /^-?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?$/i;\n\nfunction castScalar(field: Field, value: unknown): unknown {\n switch (field.kind) {\n case \"string\":\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? String(value) : INVALID_VALUE;\n case \"number\": {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : INVALID_VALUE;\n return typeof value === \"string\" && NUMERIC.test(value.trim()) ? Number(value) : INVALID_VALUE;\n }\n case \"boolean\":\n if (typeof value === \"boolean\") return value;\n return value === \"true\" ? true : value === \"false\" ? false : INVALID_VALUE;\n case \"date\": {\n if (!(value instanceof Date) && typeof value !== \"string\" && typeof value !== \"number\") return INVALID_VALUE;\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? INVALID_VALUE : date;\n }\n case \"objectId\":\n if (value instanceof ObjectId) return value;\n return typeof value === \"string\" && ObjectId.isValid(value) && value.length === 24 ? new ObjectId(value) : INVALID_VALUE;\n case \"other\":\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" ? value : INVALID_VALUE;\n }\n}\n\n/** One value for a field: `null` passes (isNull / `=` null), enums are checked, objects refused. */\nexport function castForField(shape: DocShape, fieldName: string, value: unknown): unknown {\n const field = shape.fields.get(fieldName);\n if (!field || value === null || value === undefined) return value;\n const cast = castScalar(field, value);\n if (cast === INVALID_VALUE) return INVALID_VALUE;\n return field.values && !field.values.includes(cast) ? INVALID_VALUE : cast;\n}\n\n/**\n * A condition's value in the field's type before it reaches an operator builder. Text\n * operators keep the caller's string (it must be one); arrays and tuples are all-or-nothing.\n */\nexport function coerceCondition(\n shape: DocShape,\n field: string,\n operator: FilterOperator,\n value: FilterValue | undefined,\n): FilterValue | undefined | typeof INVALID_VALUE {\n if (value === undefined) return value;\n if (TEXT_OPERATORS.has(operator)) return typeof value === \"string\" ? value : INVALID_VALUE;\n if (Array.isArray(value)) {\n const items: unknown[] = [];\n for (const item of value) {\n const cast = castForField(shape, field, item);\n if (cast === INVALID_VALUE) return INVALID_VALUE;\n items.push(cast);\n }\n return items as FilterValue;\n }\n const cast = castForField(shape, field, value);\n return cast === INVALID_VALUE ? INVALID_VALUE : (cast as FilterValue);\n}\n","import type { FilterOperator, FilterValue } from \"@querykitjs/core\";\n\n/** A field-level Mongo fragment, e.g. `{ $gte: 1, $lte: 9 }`. `undefined` = drop. */\ntype Fragment = Record<string, unknown> | undefined;\ntype Builder = (value: FilterValue | undefined) => Fragment;\n\n/** Escape a literal string for use inside a regex (contains/startsWith/endsWith). */\nconst esc = (s: unknown): string => String(s ?? \"\").replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\n/** Translate a SQL LIKE pattern (`%` → any, `_` → one char) to an anchored regex. A run of `%` is one `.*`. */\nconst sqlLikeToRegex = (pattern: unknown): string => {\n let out = \"\";\n for (const ch of String(pattern ?? \"\")) {\n if (ch === \"%\") {\n if (!out.endsWith(\".*\")) out += \".*\";\n } else if (ch === \"_\") out += \".\";\n else out += ch.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n }\n return `^${out}$`;\n};\n\nconst asTuple = (v: FilterValue | undefined): [unknown, unknown] | undefined => (Array.isArray(v) && v.length === 2 ? [v[0], v[1]] : undefined);\n\n/**\n * Operator → Mongo fragment map. Mirrors the Drizzle adapter's semantics: both\n * token (`\"%_%\"`) and name-alias (`\"contains\"`) forms are handled;\n * `contains/startsWith/endsWith` are case-insensitive; invalid values (non-array\n * `in`, non-2-tuple `between`) drop the condition (`undefined`).\n */\nexport const operators: Record<FilterOperator, Builder> = {\n \"=\": v => ({ $eq: v }),\n eq: v => ({ $eq: v }),\n // SQL three-valued logic: inequality/negation excludes NULL (and missing) rows,\n // matching drizzle-pg. `$nin: [v, null]` = \"not v AND not null\".\n \"!=\": v => ({ $nin: [v, null] }),\n ne: v => ({ $nin: [v, null] }),\n \">\": v => ({ $gt: v }),\n gt: v => ({ $gt: v }),\n \">=\": v => ({ $gte: v }),\n gte: v => ({ $gte: v }),\n \"<\": v => ({ $lt: v }),\n lt: v => ({ $lt: v }),\n \"<=\": v => ({ $lte: v }),\n lte: v => ({ $lte: v }),\n\n contains: v => ({ $regex: esc(v), $options: \"i\" }),\n \"%_%\": v => ({ $regex: esc(v), $options: \"i\" }),\n startsWith: v => ({ $regex: `^${esc(v)}`, $options: \"i\" }),\n \"%_\": v => ({ $regex: `^${esc(v)}`, $options: \"i\" }),\n endsWith: v => ({ $regex: `${esc(v)}$`, $options: \"i\" }),\n \"_%\": v => ({ $regex: `${esc(v)}$`, $options: \"i\" }),\n\n like: v => ({ $regex: sqlLikeToRegex(v) }),\n ilike: v => ({ $regex: sqlLikeToRegex(v), $options: \"i\" }),\n // negation also excludes NULL/missing (SQL `NOT LIKE` semantics).\n notLike: v => ({ $not: { $regex: sqlLikeToRegex(v) }, $ne: null }),\n\n in: v => (Array.isArray(v) ? { $in: v } : undefined),\n notIn: v => (Array.isArray(v) ? { $nin: [...v, null] } : undefined),\n\n between: v => {\n const t = asTuple(v);\n return t ? { $gte: t[0], $lte: t[1] } : undefined;\n },\n notBetween: v => {\n const t = asTuple(v);\n return t ? { $not: { $gte: t[0], $lte: t[1] }, $ne: null } : undefined;\n },\n\n isNull: () => ({ $eq: null }),\n isNotNull: () => ({ $ne: null }),\n};\n","import type { FieldCondition, Filter, FilterNode } from \"../types\";\nimport { coerceCondition, INVALID_VALUE, isTextOperator } from \"./coerce\";\nimport { QueryKitError } from \"@querykitjs/core\";\nimport { isRaw, reportSkip, type Diagnostics } from \"@querykitjs/core/internal\";\nimport { operators } from \"./operators\";\nimport { fieldKind, resolveField, type DocShape } from \"./fields\";\n\n/** A Mongo filter query object. */\nexport type Query = Record<string, unknown>;\n\nconst isObject = (n: unknown): n is Record<string, unknown> => typeof n === \"object\" && n !== null;\n\nconst isFieldCondition = (n: unknown): n is FieldCondition => isObject(n) && \"key\" in n && !(\"and\" in n) && !(\"or\" in n) && !(\"not\" in n);\n\n/** Combine parts (dropping `undefined`): 0 → undefined, 1 → the part, else `$and`/`$or`. */\nfunction combine(kind: \"$and\" | \"$or\", parts: (Query | undefined)[]): Query | undefined {\n const valid = parts.filter((p): p is Query => p !== undefined);\n if (valid.length === 0) return undefined;\n if (valid.length === 1) return valid[0];\n return { [kind]: valid };\n}\n\nfunction buildCondition(shape: DocShape, cond: FieldCondition, diag?: Diagnostics): Query | undefined {\n const operator = cond.operation ?? \"=\";\n const build = operators[operator];\n if (!build) throw new Error(`Unsupported filter operator: \"${operator}\"`);\n\n const field = resolveField(shape, cond.key);\n if (!field) {\n // Unknown field → skip. Usually a typo, and a dropped filter widens the\n // result set rather than narrowing it, so it is worth reporting.\n reportSkip(diag, { site: \"filter\", key: cond.key, operation: operator, reason: \"unknown-key\" });\n return undefined;\n }\n\n // A text pattern cannot be matched against a Date path: Mongo rejects\n // `$regex`/`$options` on a Date (\"Can't use $options with Date\"), which used to\n // surface as a 500. The SQL adapters skip a text pattern on a non-text field too\n // (R11, task 024), reported via `onSkippedCondition` instead of a stack trace.\n if (isTextOperator(operator) && fieldKind(shape, field) === \"date\") {\n reportSkip(diag, { site: \"filter\", key: cond.key, operation: operator, reason: \"invalid-value\" });\n return undefined;\n }\n\n // Cast wire (JSON) values to the path's type first, matching the drizzle\n // adapter — text-pattern operators keep their raw string.\n const value = coerceCondition(shape, field, operator, cond.value);\n if (value === INVALID_VALUE) {\n reportSkip(diag, { site: \"filter\", key: cond.key, operation: operator, reason: \"invalid-value\" });\n return undefined;\n }\n\n const fragment = build(value);\n if (fragment === undefined) {\n // The operator rejected the value shape (a non-array `in`, a non-2-tuple\n // `between`) — same class of problem as an uncastable value.\n reportSkip(diag, { site: \"filter\", key: cond.key, operation: operator, reason: \"invalid-value\" });\n return undefined;\n }\n return { [field]: fragment };\n}\n\nfunction buildNode(shape: DocShape, node: FilterNode, diag?: Diagnostics): Query | undefined {\n if (isFieldCondition(node)) return buildCondition(shape, node, diag);\n if (isObject(node)) {\n if (\"and\" in node)\n return combine(\n \"$and\",\n (node.and as FilterNode[]).map(n => buildNode(shape, n, diag)),\n );\n if (\"or\" in node)\n return combine(\n \"$or\",\n (node.or as FilterNode[]).map(n => buildNode(shape, n, diag)),\n );\n if (\"not\" in node) return buildFalse(shape, node.not as FilterNode, diag);\n // Raw escape hatch — a Mongo filter object, used as-is only when server code\n // branded it with core `raw()` (R19). A plain object can come from a JSON body\n // (`{ $where: … }`), so it is refused whatever `strict` says — mutations included.\n if (isRaw(node)) return node as Query;\n throw new QueryKitError({ source: shape.source, site: \"filter\", key: Object.keys(node as object)[0] ?? \"\", reason: \"forbidden-key\" });\n }\n return undefined;\n}\n\n/**\n * The rows where `node` is FALSE — SQL three-valued logic, so drizzle-pg and\n * prisma-pg agree (task 021 B10). MongoDB's `$nor` is two-valued: it also keeps\n * rows where the predicate is UNKNOWN (a null / missing field). So:\n * `isFalse(and(…))` = `or(isFalse(…))`, `isFalse(or(…))` = `and(isFalse(…))`,\n * `isFalse(not(q))` = `isTrue(q)`, and a comparison is FALSE only on a non-null\n * field. `isNull` / `isNotNull` are two-valued (never UNKNOWN) and need no guard.\n */\nfunction buildFalse(shape: DocShape, node: FilterNode, diag?: Diagnostics): Query | undefined {\n if (isFieldCondition(node)) {\n const inner = buildCondition(shape, node, diag);\n if (!inner) return undefined;\n const op = node.operation ?? \"=\";\n const field = op === \"isNull\" || op === \"isNotNull\" ? undefined : resolveField(shape, node.key);\n return field ? { $and: [{ [field]: { $ne: null } }, { $nor: [inner] }] } : { $nor: [inner] };\n }\n if (isObject(node)) {\n if (\"and\" in node)\n return combine(\n \"$or\",\n (node.and as FilterNode[]).map(n => buildFalse(shape, n, diag)),\n );\n if (\"or\" in node)\n return combine(\n \"$and\",\n (node.or as FilterNode[]).map(n => buildFalse(shape, n, diag)),\n );\n if (\"not\" in node) return buildNode(shape, node.not as FilterNode, diag);\n }\n // A branded raw node (or a refusal for an unbranded one) — its own truth value.\n const inner = buildNode(shape, node, diag);\n return inner ? { $nor: [inner] } : undefined;\n}\n\n/**\n * Translate a filter (tree / node / flat array / raw) into a single Mongo query.\n *\n * `diag` is optional: without it, unresolvable conditions are dropped silently\n * exactly as before; with it they are reported (or, in strict mode, throw).\n */\nexport function buildWhere(shape: DocShape, filter?: Filter, diag?: Diagnostics): Query | undefined {\n if (filter === undefined) return undefined;\n // Array elements go through buildNode (not buildCondition) so a flat array may\n // also hold logical groups / raw nodes (implicit AND), matching drizzle-pg.\n if (Array.isArray(filter))\n return combine(\n \"$and\",\n filter.map(c => buildNode(shape, c, diag)),\n );\n return buildNode(shape, filter, diag);\n}\n","/**\n * Projection guards. `columns` may arrive straight from the wire, so the safe\n * selection belongs here rather than in every route — the same reasoning as\n * `scope`. Both options are validated once, at build time, so a\n * misconfiguration surfaces in development instead of quietly returning full\n * documents in production. Identical semantics to the drizzle-pg adapter.\n */\n\nimport type { ColumnSelection, QueryParams, RepositoryOptions } from \"../types\";\nimport { resolveField, type DocShape } from \"../internal/fields\";\n\nexport type MongoProjection = Record<string, 0 | 1>;\n\nexport interface Projection<TDoc> {\n /** `forcedColumns` or `allowedColumns` is configured. */\n guarded: boolean;\n /** Whether a field may appear in a result at all. */\n permits: (key: string) => boolean;\n /**\n * Column selection → Mongo projection, or undefined when empty. Adds `_id: 0`\n * unless the caller selected `id`/`_id`, so the runtime shape matches the\n * inferred `Pick<...>` type (Mongo otherwise always returns `_id`). Returns\n * undefined (full doc) when no requested column resolves.\n *\n * With `forcedColumns` the caller's selection is ignored outright; with\n * `allowedColumns` it is intersected, and an empty intersection falls back to\n * the allowlist — **never** to the full document.\n */\n projection: (columns?: QueryParams<TDoc>[\"columns\"]) => MongoProjection | undefined;\n}\n\nconst truthyKeys = (selection: object): string[] =>\n Object.entries(selection)\n .filter(([, on]) => on)\n .map(([key]) => key);\n\nexport function buildProjection<TDoc>(shape: DocShape, config: RepositoryOptions<TDoc>): Projection<TDoc> {\n const forcedKeys = config.forcedColumns ? truthyKeys(config.forcedColumns) : undefined;\n if (config.forcedColumns && forcedKeys!.length === 0) {\n throw new Error(\"buildRepository: forcedColumns must select at least one field (an empty selection would return the full document).\");\n }\n\n const allowed = config.allowedColumns ? new Set<string>(config.allowedColumns as readonly string[]) : undefined;\n if (config.allowedColumns && allowed!.size === 0) {\n throw new Error(\"buildRepository: allowedColumns must list at least one field (an empty allowlist would return the full document).\");\n }\n\n const permits = (key: string): boolean => (forcedKeys ? forcedKeys.includes(key) : allowed ? allowed.has(key) : true);\n\n /** Client selection ∩ allowlist; empty intersection → the allowlist itself. */\n const intersectAllowed = (requested: string[]): string[] => {\n const hit = requested.filter(key => allowed!.has(key));\n return hit.length > 0 ? hit : [...allowed!];\n };\n\n const projection = (columns?: QueryParams<TDoc>[\"columns\"]): MongoProjection | undefined => {\n const requested = columns ? truthyKeys(columns as ColumnSelection<TDoc>) : [];\n const keys = forcedKeys ?? (allowed ? intersectAllowed(requested) : requested);\n if (keys.length === 0) return undefined;\n const proj: MongoProjection = {};\n let includesId = false;\n for (const k of keys) {\n const field = resolveField(shape, k);\n if (!field) continue;\n proj[field] = 1;\n if (field === \"_id\") includesId = true;\n }\n if (Object.keys(proj).length === 0) return undefined; // all unknown → full doc\n if (!includesId) proj._id = 0; // exclude _id unless explicitly selected (exact columns, like drizzle)\n return proj;\n };\n\n return { guarded: Boolean(forcedKeys ?? allowed), permits, projection };\n}\n","/**\n * Per-repository context shared by the method groups: filter / scope / soft-delete composition,\n * the core request policy, projection guards, and the driver calls with the session and\n * `maxTimeMS` attached. The mongoose adapter's `repository/context.ts` over a driver `Collection`.\n */\nimport type { ClientSession, Collection, Document, FindOptions } from \"mongodb\";\nimport { QueryKitError, QueryKitTimeoutError, type QueryLimits, type SkippedCondition } from \"@querykitjs/core\";\nimport {\n checkWith,\n type Diagnostics,\n isAllRows,\n isEmptyFilter,\n type Policy,\n refuseEmptyFilter,\n resolvePolicy,\n scopeConditions,\n type WithDialect,\n} from \"@querykitjs/core/internal\";\n\nimport type { FieldCondition, FieldKey, Filter, Id, QueryParams, RepositoryOptions, Sort } from \"../types\";\nimport { resolveField, shapeFromSchema, type DocShape } from \"../internal/fields\";\nimport { buildSort } from \"../internal/order-by\";\nimport { buildWhere, type Query } from \"../internal/where\";\nimport { buildProjection, type Projection } from \"./projection\";\n\nexport interface RepoRuntime {\n getSession: () => ClientSession | undefined;\n defaultPerPage: number;\n defaultLimit: number;\n maxPerPage: number;\n maxLimit: number;\n strict: boolean;\n onSkippedCondition?: (info: SkippedCondition) => void;\n limits?: Partial<QueryLimits>;\n maxTimeMS: number;\n cursorSecret?: string;\n timestamps?: { createdAt?: string; deletedAt?: string };\n}\n\nexport interface FindOpts<TDoc> {\n sort?: Record<string, 1 | -1>;\n columns?: QueryParams<TDoc>[\"columns\"];\n limit?: number;\n skip?: number;\n}\n\nexport interface RepoContext<TDoc extends Document> extends Projection<TDoc> {\n runtime: RepoRuntime;\n collection: Collection<TDoc>;\n shape: DocShape;\n diag: Diagnostics;\n hasDeletedAt: boolean;\n deletedAtPath: string;\n forUpdate: <T extends object>(patch: T) => T;\n sortSpec: (sort?: Sort<TDoc>) => Record<string, 1 | -1>;\n /** `with` is refused in this version (no `$lookup`, task 017 L3): `forbidden-key`, site `with`. */\n withOf: (value: unknown) => void;\n policy: Policy;\n maxTimeMS: number;\n composeWhere: (userFilter?: Filter<TDoc>, withDeleted?: boolean) => Query;\n mutationWhere: (filter: unknown, method: \"updateWhere\" | \"deleteWhere\") => Query;\n withId: (filter: Filter<TDoc> | undefined, idKey: string, id: Id) => Filter<TDoc>;\n /** The session (inside `registry.transaction`) for a write. */\n session: () => { session?: ClientSession };\n /** Runs a read with the time limit; a `MaxTimeMSExpired` error becomes `QueryKitTimeoutError`. */\n timed: <T>(read: (options: { maxTimeMS: number; session?: ClientSession }) => Promise<T>) => Promise<T>;\n runFind: (where: Query, opts: FindOpts<TDoc>) => Promise<TDoc[]>;\n countWhere: (where: Query) => Promise<number>;\n}\n\n/** No relation can be opened yet: an empty allow-list makes every `with` key `forbidden-key`. */\nconst WITH_DIALECT: WithDialect = {\n columns: \"projection\",\n nested: \"with\",\n filters: [\"match\"],\n logical: [\"$and\", \"$or\", \"$nor\"],\n paging: [\"limit\", \"skip\"],\n options: \"options\",\n};\n\nexport const isTimeLimitError = (error: unknown): boolean =>\n typeof error === \"object\" &&\n error !== null &&\n ((error as { codeName?: unknown }).codeName === \"MaxTimeMSExpired\" || (error as { code?: unknown }).code === 50);\n\nexport function buildRepoContext<TDoc extends Document>(\n runtime: RepoRuntime,\n collection: Collection<TDoc>,\n config: RepositoryOptions<TDoc>,\n): RepoContext<TDoc> {\n const shape = shapeFromSchema(collection.collectionName, config.schema, config.objectId as readonly string[] | undefined);\n const deletedAtPath = resolveField(shape, runtime.timestamps?.deletedAt ?? \"deletedAt\") ?? \"deletedAt\";\n const hasDeletedAt = shape.fields.has(deletedAtPath);\n const createdAtConfigured = runtime.timestamps?.createdAt !== undefined;\n const createdAtPath = resolveField(shape, runtime.timestamps?.createdAt ?? \"createdAt\");\n // The driver has no `timestamps` option: a schema with `updatedAt` gets it stamped on every update.\n const stampUpdatedAt = shape.fields.has(\"updatedAt\");\n const forUpdate = <T extends object>(patch: T): T => (stampUpdatedAt ? { ...patch, updatedAt: new Date() } : patch);\n\n const diag: Diagnostics = { source: shape.source, strict: runtime.strict, onSkipped: runtime.onSkippedCondition };\n const scopeWhere = buildScopeWhere(shape);\n\n function buildScopeWhere(docShape: DocShape): Query | undefined {\n const conditions = scopeConditions(config.scope as Record<string, unknown> | undefined) as unknown as FieldCondition[];\n for (const condition of conditions) {\n if (!resolveField(docShape, condition.key))\n throw new QueryKitError({ source: docShape.source, site: \"filter\", key: condition.key, reason: \"unknown-key\" });\n }\n return conditions.length ? buildWhere(docShape, conditions) : undefined;\n }\n\n const sortSpec = (sort?: Sort<TDoc>): Record<string, 1 | -1> => buildSort(shape, sort as Sort | undefined, diag, createdAtPath);\n const withOf = (value: unknown): void => {\n checkWith(value, undefined, WITH_DIALECT, diag.source);\n };\n\n const combineWhere = (userWhere: Query | undefined, withDeleted?: boolean): Query => {\n const parts = [userWhere, scopeWhere, hasDeletedAt && !withDeleted ? { [deletedAtPath]: { $eq: null } } : undefined].filter(\n (p): p is Query => p !== undefined,\n );\n if (parts.length === 0) return {};\n if (parts.length === 1) return parts[0]!;\n return { $and: parts };\n };\n const composeWhere = (userFilter?: Filter<TDoc>, withDeleted?: boolean): Query =>\n combineWhere(buildWhere(shape, userFilter as Filter | undefined, diag), withDeleted);\n\n const withId = (filter: Filter<TDoc> | undefined, idKey: string, id: Id): Filter<TDoc> => {\n const idCondition: FieldCondition<TDoc> = { key: idKey as FieldKey<TDoc>, operation: \"=\", value: id as never };\n if (!filter) return [idCondition];\n if (Array.isArray(filter)) return [...filter, idCondition];\n return { and: [filter, idCondition] };\n };\n\n const guards = buildProjection(shape, config);\n const maxTimeMS = config.maxTimeMS ?? runtime.maxTimeMS;\n\n const session = (): { session?: ClientSession } => {\n const current = runtime.getSession();\n return current ? { session: current } : {};\n };\n\n const timed = async <T>(read: (options: { maxTimeMS: number; session?: ClientSession }) => Promise<T>): Promise<T> => {\n try {\n return await read({ maxTimeMS, ...session() });\n } catch (error) {\n throw isTimeLimitError(error) ? new QueryKitTimeoutError(shape.source, maxTimeMS, { cause: error }) : error;\n }\n };\n\n const runFind = (where: Query, opts: FindOpts<TDoc>): Promise<TDoc[]> =>\n timed(options => {\n const findOptions: FindOptions = { ...options };\n const projection = guards.projection(opts.columns);\n if (projection) findOptions.projection = projection;\n if (opts.sort) findOptions.sort = opts.sort;\n if (typeof opts.skip === \"number\") findOptions.skip = opts.skip;\n if (typeof opts.limit === \"number\") findOptions.limit = opts.limit;\n return collection.find(where as never, findOptions).toArray() as Promise<TDoc[]>;\n });\n\n const countWhere = (where: Query): Promise<number> => timed(options => collection.countDocuments(where as never, options));\n\n const policy = resolvePolicy({\n source: shape.source,\n fieldOf: key => resolveField(shape, key),\n primaryKey: \"_id\",\n createdAt: createdAtConfigured ? createdAtPath : (createdAtPath ?? resolveField(shape, \"created_at\")),\n filterable: config.filterable as never,\n sortable: config.sortable as readonly string[] | undefined,\n allowedColumns: config.allowedColumns as readonly string[] | undefined,\n forcedColumns: config.forcedColumns as Record<string, unknown> | undefined,\n limits: { ...runtime.limits, ...config.limits },\n });\n\n const mutationWhere = (filter: unknown, method: \"updateWhere\" | \"deleteWhere\"): Query => {\n if (isAllRows(filter)) return combineWhere(undefined);\n if (isEmptyFilter(filter)) refuseEmptyFilter(diag.source, method);\n policy.checkFilter(filter as Filter<TDoc>);\n const userWhere = buildWhere(shape, filter as Filter, diag);\n return userWhere === undefined ? refuseEmptyFilter(diag.source, method) : combineWhere(userWhere);\n };\n\n return {\n ...guards,\n runtime,\n collection,\n shape,\n diag,\n hasDeletedAt,\n deletedAtPath,\n forUpdate,\n sortSpec,\n withOf,\n policy,\n maxTimeMS,\n composeWhere,\n mutationWhere,\n withId,\n session,\n timed,\n runFind,\n countWhere,\n };\n}\n\nexport const toArr = <T>(v?: T | T[]): T[] => (v === undefined ? [] : Array.isArray(v) ? v : [v]);\n","import type { Document } from \"mongodb\";\nimport { reportSkip } from \"@querykitjs/core/internal\";\n\nimport type { AggregateRow, AggregateSpec } from \"../types\";\nimport { resolveField } from \"../internal/fields\";\nimport { toArr, type RepoContext } from \"./context\";\n\n/** `aggregate` as one `$match` + `$group` pipeline; values in `$match` are already cast by the filter compiler. */\nexport function aggregateMethods<TDoc extends Document>(ctx: RepoContext<TDoc>) {\n const { collection, shape, diag, permits, policy, composeWhere, timed } = ctx;\n\n const aggregable = (key: string) => {\n const field = permits(key) ? resolveField(shape, key) : undefined;\n if (!field) reportSkip(diag, { site: \"aggregate\", key, reason: \"unknown-key\" });\n return field;\n };\n\n return {\n async aggregate(spec: AggregateSpec<TDoc>) {\n policy.checkFilter(spec.filter);\n for (const key of [spec.groupBy, spec.sum, spec.avg, spec.min, spec.max].flatMap(value => toArr(value as string | string[] | undefined)))\n policy.checkAggregateKey(key);\n const groupKeys = (toArr(spec.groupBy) as string[]).filter(key => Boolean(aggregable(key)));\n const groupId = groupKeys.length ? Object.fromEntries(groupKeys.map(k => [k, `$${aggregable(k) ?? k}`])) : null;\n const group: Record<string, unknown> = { _id: groupId };\n if (spec.count) group.count = { $sum: 1 };\n const addAgg = (op: \"$sum\" | \"$avg\" | \"$min\" | \"$max\", keys: string[], prefix: string) => {\n for (const k of keys) {\n const field = aggregable(k);\n if (field) group[`${prefix}_${k}`] = { [op]: `$${field}` };\n }\n };\n addAgg(\"$sum\", toArr(spec.sum) as string[], \"sum\");\n addAgg(\"$avg\", toArr(spec.avg) as string[], \"avg\");\n addAgg(\"$min\", toArr(spec.min) as string[], \"min\");\n addAgg(\"$max\", toArr(spec.max) as string[], \"max\");\n\n const pipeline = [{ $match: composeWhere(spec.filter, spec.withDeleted) }, { $group: group }];\n const rows = await timed(options => collection.aggregate<Record<string, unknown>>(pipeline, options).toArray());\n return rows.map(({ _id, ...rest }) => ({ ...(typeof _id === \"object\" && _id ? _id : {}), ...rest })) as AggregateRow[];\n },\n };\n}\n","import type { Document } from \"mongodb\";\nimport { QueryKitError } from \"@querykitjs/core\";\nimport { clampPageSize, cursorPage, decodeCursorToken } from \"@querykitjs/core/internal\";\n\nimport type { CursorParams, CursorResult, SortDirection } from \"../types\";\nimport { resolveField } from \"../internal/fields\";\nimport { castForField, INVALID_VALUE } from \"../internal/coerce\";\nimport type { Query } from \"../internal/where\";\nimport type { RepoContext } from \"./context\";\n\n/** `findCursor` — keyset pagination on one field. */\nexport function cursorMethods<TDoc extends Document>(ctx: RepoContext<TDoc>) {\n const { runtime, collection, shape, diag, guarded, permits, projection, policy, withOf, composeWhere, timed } = ctx;\n\n return {\n async findCursor(params: CursorParams<TDoc> = {}) {\n const limit = clampPageSize(params.limit, runtime.defaultLimit, runtime.maxLimit);\n const cursorKey = (params.cursorKey ?? \"id\") as string;\n policy.checkFilter(params.filter);\n // The default `id` is the server's choice; a client-sent key must be sortable.\n if (params.cursorKey !== undefined) policy.checkCursorKey(cursorKey);\n const order: SortDirection = params.order ?? \"asc\";\n const direction = params.direction ?? \"forward\";\n\n const field = resolveField(shape, cursorKey);\n // Always fatal: without a usable cursor field there is no pagination to\n // fall back to. Reported as a `QueryKitError` so the backend maps it to a\n // 400 the same way as any other bad condition (both adapters agree).\n if (!field) throw new QueryKitError({ source: diag.source, site: \"cursorKey\", key: cursorKey, reason: \"unknown-key\" });\n\n // Task 012: the token carries the cursor value and _id (tie-break), both cast\n // to their path's type; a token that does not fit is invalid-value.\n const token = await decodeCursorToken(params.cursor, { source: diag.source, secret: runtime.cursorSecret, key: cursorKey });\n const cursorValue = token === undefined ? undefined : castForField(shape, field, token.k);\n const idValue = token === undefined ? undefined : castForField(shape, \"_id\", token.id);\n if (cursorValue === INVALID_VALUE || idValue === INVALID_VALUE) {\n throw new QueryKitError({ source: diag.source, site: \"cursorKey\", key: cursorKey, reason: \"invalid-value\" });\n }\n const baseWhere = composeWhere(params.filter, params.withDeleted);\n\n const ascInQuery = direction === \"forward\" ? order === \"asc\" : order === \"desc\";\n const past = ascInQuery ? \"$gt\" : \"$lt\";\n // (k > v) OR (k = v AND _id > i); an _id cursor needs no tie-break.\n const tieBreak = field !== \"_id\";\n const seek: Query | undefined =\n token === undefined\n ? undefined\n : tieBreak\n ? { $or: [{ [field]: { [past]: cursorValue } }, { [field]: cursorValue, _id: { [past]: idValue } }] }\n : { [field]: { [past]: cursorValue } };\n const where: Query = seek ? (Object.keys(baseWhere).length ? { $and: [baseWhere, seek] } : seek) : baseWhere;\n\n // Force-include the cursor field in the projection so next/prev tokens work.\n // `cursorKey` is client-supplied, so under a projection guard this would be\n // a way to read a forbidden field: keep it in the query (pagination needs\n // it) but strip it from the documents we hand back.\n const selected = projection(params.columns);\n // `_id` too: an exact selection carries `_id: 0`, and the token needs it for the tie-break.\n const proj = selected ? { ...selected, [field]: 1, _id: 1 } : undefined;\n // Stripped from the rows afterwards: under a projection guard the cursor / tie-break\n // keys the caller may not see; always the tie-break key added only for the token.\n const picked = (key: string) => selected !== undefined && Boolean((selected as Record<string, unknown>)[key]);\n const hidden =\n selected === undefined\n ? []\n : [field, \"_id\"].filter(key => (guarded && (!permits(key) || !picked(key))) || (key === \"_id\" && key !== field && !picked(key)));\n\n withOf(params.with);\n const sort = tieBreak ? { [field]: ascInQuery ? 1 : -1, _id: ascInQuery ? 1 : -1 } : { [field]: ascInQuery ? 1 : -1 };\n const rows = (await timed(options =>\n collection\n .find(where as never, { ...options, ...(proj ? { projection: proj } : {}), sort: sort as Record<string, 1 | -1>, limit: limit + 1 })\n .toArray(),\n )) as Record<string, unknown>[];\n\n const page = await cursorPage(rows, {\n limit,\n direction,\n hasCursor: token !== undefined,\n cursorField: field,\n idField: \"_id\",\n secret: runtime.cursorSecret,\n });\n\n // Token values are read above, so the hidden fields can go now.\n if (hidden.length > 0) {\n page.data = page.data.map(row => Object.fromEntries(Object.entries(row).filter(([key]) => !hidden.includes(key))));\n }\n\n return page as CursorResult<never>;\n },\n };\n}\n","import type { AnyBulkWriteOperation, Document, OptionalUnlessRequiredId } from \"mongodb\";\nimport type { AllRows, MutationOptions } from \"@querykitjs/core\";\nimport { clampPageSize, scopeDefaults } from \"@querykitjs/core/internal\";\n\nimport type { FieldKey, Filter, Id, Insert, RepositoryOptions, Row, UpsertOptions } from \"../types\";\nimport { resolveField } from \"../internal/fields\";\nimport type { Query } from \"../internal/where\";\nimport { toArr, type RepoContext } from \"./context\";\n\n/** `bulkWrite` batch size for `upsertMany`. */\nconst CHUNK = 1000;\n/** Joins the upsert target values into one map key (a byte no field value holds). */\nconst KEY_SEPARATOR = String.fromCharCode(0);\n\n/**\n * Writes. Values are stored as given — the zod schema is the API layer's validator; the driver\n * casts nothing. Scope equality values are forced on insert, so a scoped repository cannot\n * write outside its scope.\n */\nexport function mutateMethods<TDoc extends Document>(ctx: RepoContext<TDoc>, config: RepositoryOptions<TDoc>) {\n const { runtime, collection, shape, hasDeletedAt, deletedAtPath, forUpdate, composeWhere, mutationWhere, withId, session, runFind } = ctx;\n\n const returningLimit = (returning: { limit: number }): number => clampPageSize(returning.limit, runtime.defaultLimit, runtime.maxLimit);\n\n const forInsert = (values: object): Record<string, unknown> => ({\n ...scopeDefaults(config.scope as Record<string, unknown> | undefined),\n ...values,\n ...scopeDefaults(config.scope as Record<string, unknown> | undefined),\n });\n\n const buildUpsert = (values: Insert<TDoc>, options: UpsertOptions<TDoc>) => {\n const targetKeys = toArr(options.target) as string[];\n const inserted = forInsert(values);\n const filter: Record<string, unknown> = {};\n for (const key of targetKeys) {\n const field = resolveField(shape, key);\n if (!field) throw new Error(`upsert: unknown target field \"${key}\".`);\n filter[field] = inserted[key];\n }\n const set: Record<string, unknown> = options.set\n ? { ...(options.set as Record<string, unknown>) }\n : Object.fromEntries(Object.entries(inserted).filter(([k]) => !targetKeys.includes(k)));\n const setOnInsert = Object.fromEntries(Object.entries(inserted).filter(([k]) => !targetKeys.includes(k) && !(k in set)));\n const update: Record<string, unknown> = {};\n if (Object.keys(set).length) update.$set = set;\n if (Object.keys(setOnInsert).length) update.$setOnInsert = setOnInsert;\n return { filter, update };\n };\n\n const updateOne = async (where: Query, patch: object) => {\n const row = await collection.findOneAndUpdate(where as never, { $set: patch } as never, { returnDocument: \"after\", ...session() });\n return (row ?? undefined) as Row<TDoc> | undefined;\n };\n\n return {\n async create(values: Insert<TDoc>) {\n const doc = forInsert(values);\n const { insertedId } = await collection.insertOne(doc as OptionalUnlessRequiredId<TDoc>, session());\n return { ...doc, _id: insertedId } as unknown as Row<TDoc>;\n },\n\n async createMany(values: Insert<TDoc>[]) {\n if (values.length === 0) return [];\n const docs = values.map(forInsert);\n const { insertedIds } = await collection.insertMany(docs as OptionalUnlessRequiredId<TDoc>[], session());\n return docs.map((doc, index) => ({ ...doc, _id: insertedIds[index] })) as unknown as Row<TDoc>[];\n },\n\n async upsert(values: Insert<TDoc>, options: UpsertOptions<TDoc>) {\n const { filter, update } = buildUpsert(values, options);\n return (await collection.findOneAndUpdate(filter as never, update as never, { returnDocument: \"after\", upsert: true, ...session() })) as Row<TDoc>;\n },\n\n async upsertMany(values: Insert<TDoc>[], options: UpsertOptions<TDoc>) {\n if (values.length === 0) return [];\n const entries = values.map(v => buildUpsert(v, options)); // input order preserved\n for (let i = 0; i < entries.length; i += CHUNK) {\n const ops = entries.slice(i, i + CHUNK).map(e => ({ updateOne: { filter: e.filter, update: e.update, upsert: true } }));\n await collection.bulkWrite(ops as AnyBulkWriteOperation<TDoc>[], session());\n }\n const rows = (await runFind({ $or: entries.map(e => e.filter) }, {})) as Record<string, unknown>[];\n const targetFields = (toArr(options.target) as string[]).map(k => resolveField(shape, k)).filter((f): f is string => Boolean(f));\n const keyOf = (o: Record<string, unknown>): string => targetFields.map(f => String(o[f])).join(KEY_SEPARATOR);\n const byKey = new Map(rows.map(r => [keyOf(r), r]));\n return entries.map(e => byKey.get(keyOf(e.filter))).filter((r): r is Record<string, unknown> => Boolean(r)) as Row<TDoc>[];\n },\n\n updateById(id: Id, patch: Partial<Insert<TDoc>>, idKey: FieldKey<TDoc> = \"id\" as FieldKey<TDoc>) {\n return updateOne(composeWhere(withId(undefined, idKey as string, id)), forUpdate(patch));\n },\n\n /** One `updateMany` (task 013): no read before the write; `returning` reads after it. */\n async updateWhere(filter: Filter<TDoc> | AllRows, patch: Partial<Insert<TDoc>>, options: MutationOptions = {}) {\n const where = mutationWhere(filter, \"updateWhere\");\n const { matchedCount: count } = await collection.updateMany(where as never, { $set: forUpdate(patch) } as never, session());\n if (!options.returning) return { count };\n const rows = (await runFind(where, { limit: returningLimit(options.returning) })) as Row<TDoc>[];\n return { count, rows };\n },\n\n async deleteById(id: Id, idKey: FieldKey<TDoc> = \"id\" as FieldKey<TDoc>) {\n const row = await collection.findOneAndDelete(composeWhere(withId(undefined, idKey as string, id)) as never, session());\n return (row ?? undefined) as Row<TDoc> | undefined;\n },\n\n async deleteWhere(filter: Filter<TDoc> | AllRows, options: MutationOptions = {}) {\n const where = mutationWhere(filter, \"deleteWhere\");\n const rows = options.returning ? ((await runFind(where, { limit: returningLimit(options.returning) })) as Row<TDoc>[]) : undefined;\n const { deletedCount: count } = await collection.deleteMany(where as never, session());\n return rows ? { count, rows } : { count };\n },\n\n async softDelete(id: Id, idKey: FieldKey<TDoc> = \"id\" as FieldKey<TDoc>) {\n if (!hasDeletedAt) throw new Error(\"softDelete: schema has no deletedAt field.\");\n return updateOne(composeWhere(withId(undefined, idKey as string, id), false), forUpdate({ [deletedAtPath]: new Date() }));\n },\n\n async restore(id: Id, idKey: FieldKey<TDoc> = \"id\" as FieldKey<TDoc>) {\n if (!hasDeletedAt) throw new Error(\"restore: schema has no deletedAt field.\");\n return updateOne(composeWhere(withId(undefined, idKey as string, id), true), forUpdate({ [deletedAtPath]: null }));\n },\n };\n}\n","/**\n * The key of a repository's hidden `explain` method — shared by the repository (main entry)\n * and `@querykitjs/mongodb/testing`, which imports only this key, not the repository code.\n * `Symbol.for`, so the two entries' bundles agree on it.\n */\nexport const EXPLAIN = Symbol.for(\"querykit.mongodb.explain\");\n","import type { Document } from \"mongodb\";\nimport { clampOffset, clampPage, clampPageSize, infinitePage, offsetMeta, offsetPageWithoutTotal } from \"@querykitjs/core/internal\";\n\nimport type { ByIdParams, Filter, Id, InfiniteParams, InfiniteResult, OffsetParams, OffsetResult, QueryParams } from \"../types\";\nimport { EXPLAIN } from \"../internal/explain-key\";\nimport type { RepoContext } from \"./context\";\n\n/** Reads: every one checks the policy first, so a refused request never reaches the driver. */\nexport function readMethods<TDoc extends Document>(ctx: RepoContext<TDoc>) {\n const { runtime, collection, policy, sortSpec, withOf, composeWhere, withId, runFind, countWhere, timed } = ctx;\n\n const checked = (params: QueryParams<TDoc>) => {\n policy.checkFilter(params.filter);\n policy.checkSort(params.sort as never);\n withOf(params.with);\n };\n\n const first = async (params: QueryParams<TDoc>, filter: Filter<TDoc> | undefined) => {\n const [row] = await runFind(composeWhere(filter, params.withDeleted), { sort: sortSpec(params.sort), columns: params.columns, limit: 1 });\n return row;\n };\n\n return {\n async findAll(params: QueryParams<TDoc> = {}) {\n checked(params);\n return (await runFind(composeWhere(params.filter, params.withDeleted), { sort: sortSpec(params.sort), columns: params.columns })) as never;\n },\n\n async findOne(params: QueryParams<TDoc> = {}) {\n checked(params);\n return (await first(params, params.filter)) as never;\n },\n\n async findById(id: Id, params: ByIdParams<TDoc> = {}) {\n const { idKey = \"id\", filter } = params;\n policy.checkFilter(filter);\n withOf(params.with);\n return (await first({ ...params, sort: undefined }, withId(filter, idKey as string, id))) as never;\n },\n\n async findList(params: OffsetParams<TDoc> = {}) {\n checked(params);\n const page = clampPage(params.page);\n const perPage = clampPageSize(params.perPage, runtime.defaultPerPage, runtime.maxPerPage);\n policy.checkPage({ page, perPage });\n const where = composeWhere(params.filter, params.withDeleted);\n const rows = (limit: number) => runFind(where, { sort: sortSpec(params.sort), columns: params.columns, limit, skip: (page - 1) * perPage });\n\n // `withTotal: false` (task 013): one read of perPage + 1 rows, no count.\n if (params.withTotal === false) return offsetPageWithoutTotal(await rows(perPage + 1), page, perPage) as OffsetResult<never>;\n const [data, totalItems] = await Promise.all([rows(perPage), countWhere(where)]);\n return { data, meta: offsetMeta(page, perPage, totalItems) } as OffsetResult<never>;\n },\n\n async findInfinite(params: InfiniteParams<TDoc> = {}) {\n const limit = clampPageSize(params.limit, runtime.defaultLimit, runtime.maxLimit);\n const offset = clampOffset(params.offset);\n checked(params);\n policy.checkPage({ offset });\n const rows = await runFind(composeWhere(params.filter, params.withDeleted), {\n sort: sortSpec(params.sort),\n columns: params.columns,\n limit: limit + 1,\n skip: offset,\n });\n return infinitePage(rows, limit, offset) as InfiniteResult<never>;\n },\n\n async count(filter?: Filter<TDoc>) {\n policy.checkFilter(filter);\n return countWhere(composeWhere(filter));\n },\n\n async exists(filter?: Filter<TDoc>) {\n policy.checkFilter(filter);\n return (await countWhere(composeWhere(filter))) > 0;\n },\n\n /** The query plan of `findAll(params)` — the same checks and filter, `explain()` instead of rows. */\n async [EXPLAIN](params: QueryParams<TDoc> = {}) {\n checked(params);\n const where = composeWhere(params.filter, params.withDeleted);\n return timed(options => collection.find(where as never, { ...options, sort: sortSpec(params.sort) }).explain(\"queryPlanner\"));\n },\n };\n}\n","import type { Collection, Document } from \"mongodb\";\n\nimport type { Repository, RepositoryOptions, Scope } from \"../types\";\nimport { aggregateMethods } from \"./aggregate\";\nimport { buildRepoContext, type RepoRuntime } from \"./context\";\nimport { cursorMethods } from \"./cursor\";\nimport { mutateMethods } from \"./mutate\";\nimport { readMethods } from \"./read\";\n\nexport type { RepoRuntime } from \"./context\";\n\n/** A repository over one collection; `registry.repository(...)` is the usual way to get one. */\nexport function buildRepository<TDoc extends Document>(runtime: RepoRuntime, collection: Collection<TDoc>, config: RepositoryOptions<TDoc>): Repository<TDoc> {\n const ctx = buildRepoContext(runtime, collection, config);\n\n const repository = {\n collection,\n ...readMethods(ctx),\n ...cursorMethods(ctx),\n ...mutateMethods(ctx, config),\n ...aggregateMethods(ctx),\n\n scoped(scope: Scope<TDoc>) {\n return buildRepository(runtime, collection, { ...config, scope: { ...config.scope, ...scope } });\n },\n };\n\n return repository as unknown as Repository<TDoc>;\n}\n","import type { ClientSession, Collection, Document, MongoClient } from \"mongodb\";\nimport { DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_MAX_PER_PAGE, DEFAULT_PER_PAGE } from \"@querykitjs/core\";\nimport { createContextStore } from \"@querykitjs/core/internal\";\n\nimport type { Registry, RegistryOptions, Repository, RepositoryExtender, RepositoryOptions } from \"./types\";\nimport { buildRepository, type RepoRuntime } from \"./repository\";\n\n/** Server time limit per read (ms) when the registry does not set one — the mongoose adapter's default. */\nconst DEFAULT_MAX_TIME_MS = 2000;\n\n/**\n * Create a registry over a connected `MongoClient`: defaults once, then\n * `registry.repository(db.collection(\"users\"), { schema })` per collection.\n *\n * @example\n * ```ts\n * const qk = createRegistry(client, { maxPerPage: 100 });\n * const users = qk.repository(client.db(\"app\").collection<User>(\"users\"), {\n * schema: UserSchema,\n * filterable: { name: [\"=\", \"%_\"], status: [\"=\", \"in\"] },\n * });\n * const { data, meta } = await users.findList({ page: 1, perPage: 20 });\n * ```\n */\nexport function createRegistry(client: MongoClient, options: RegistryOptions = {}): Registry {\n const ctx = createContextStore<{ session?: ClientSession }>();\n const runtime: RepoRuntime = {\n getSession: () => ctx.get()?.session,\n defaultPerPage: options.defaultPerPage ?? DEFAULT_PER_PAGE,\n defaultLimit: options.defaultLimit ?? DEFAULT_LIMIT,\n maxPerPage: options.maxPerPage ?? DEFAULT_MAX_PER_PAGE,\n maxLimit: options.maxLimit ?? DEFAULT_MAX_LIMIT,\n strict: options.strict ?? false,\n onSkippedCondition: options.onSkippedCondition,\n limits: options.limits,\n cursorSecret: options.cursorSecret,\n timestamps: options.timestamps,\n maxTimeMS: options.maxTimeMS ?? DEFAULT_MAX_TIME_MS,\n };\n\n function repository<TDoc extends Document>(collection: Collection<TDoc>, repoOptions: RepositoryOptions<TDoc>): Repository<TDoc>;\n function repository<TDoc extends Document, TExt extends Record<string, unknown>>(\n collection: Collection<TDoc>,\n repoOptions: RepositoryOptions<TDoc>,\n extend: RepositoryExtender<TDoc, TExt>,\n ): Repository<TDoc> & TExt;\n function repository<TDoc extends Document, TExt extends Record<string, unknown>>(\n collection: Collection<TDoc>,\n repoOptions: RepositoryOptions<TDoc>,\n extend?: RepositoryExtender<TDoc, TExt>,\n ) {\n const base = buildRepository(runtime, collection, repoOptions);\n return extend ? { ...base, ...extend(base) } : base;\n }\n\n /** Nested calls join the outer transaction; MongoDB transactions need a replica set or sharded cluster. */\n const transaction = async <T>(fn: () => Promise<T>): Promise<T> => {\n if (ctx.get()?.session) return fn();\n return client.withSession(async session => {\n let result!: T;\n await session.withTransaction(async () => {\n result = await ctx.run({ session }, fn);\n });\n return result;\n });\n };\n\n return { repository, transaction };\n}\n","import { createFilters as coreCreateFilters, f } from \"@querykitjs/core\";\n\nimport type { FieldKey, RawFilter } from \"./types/common\";\n\n/**\n * Typed filter builders for a document type (field-name autocomplete). A thin wrapper over\n * `@querykitjs/core`'s builder — the key type is the document's field key, the raw escape\n * hatch is a native Mongo filter (brand it with core `raw()`).\n *\n * @example\n * ```ts\n * const uf = createFilters<User>();\n * await users.findAll({ filter: uf.and(uf.eq(\"status\", \"active\"), uf.gte(\"age\", 18)) });\n * ```\n */\n// The explicit return type keeps `dist/index.d.ts` free of an inferred expansion.\nexport function createFilters<TDoc>(): ReturnType<typeof coreCreateFilters<FieldKey<TDoc>, RawFilter<TDoc>>> {\n return coreCreateFilters<FieldKey<TDoc>, RawFilter<TDoc>>();\n}\n\n/** Untyped filter helpers for quick use. */\nexport { f };\n"]}