query-builder-prisma 0.1.0 → 0.2.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/README.md CHANGED
@@ -1,59 +1,131 @@
1
1
  # query-builder-prisma
2
2
 
3
- > Zero-coupling, fluent, fully type-safe query builder for any Prisma model delegate.
4
- > **Status: v0.1.0 — core API working.** Architecture: [ARCHITECTURE.md](./ARCHITECTURE.md)
5
- > · Contributing: [CONTRIBUTING.md](./CONTRIBUTING.md)
3
+ [![npm version](https://img.shields.io/npm/v/query-builder-prisma.svg)](https://www.npmjs.com/package/query-builder-prisma)
4
+ [![CI](https://github.com/almamun2b/query-builder-prisma/actions/workflows/ci.yml/badge.svg)](https://github.com/almamun2b/query-builder-prisma/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/query-builder-prisma.svg)](./LICENSE)
6
+ [![node](https://img.shields.io/node/v/query-builder-prisma.svg)](https://www.npmjs.com/package/query-builder-prisma)
6
7
 
7
- Works with **every Prisma version — 5, 6, 7, 8 and future majors by design** — and every
8
- database Prisma supports (PostgreSQL, MySQL, MariaDB, SQLite, SQL Server, CockroachDB,
9
- MongoDB), because it imports **nothing** from Prisma: all types are derived structurally
10
- from the delegate you pass in.
11
-
12
- ## The idea
13
-
14
- An npm package that imports Prisma types will break on Prisma's next major (import paths
15
- changed in v7, the type utilities move in v8, the engine was rewritten...). This package
16
- speaks only Prisma's stable public contract — the model-delegate call shape — so a Prisma
17
- upgrade can never break it.
8
+ > Zero-coupling, fluent, fully type-safe query builder for any Prisma model
9
+ > delegate. Works with **every Prisma version — 5, 6, 7, 8 and future majors by
10
+ > design** — and every database Prisma supports.
18
11
 
19
12
  ```ts
20
13
  const { meta, data } = await new QueryBuilder(prisma.user)
21
- .search({ searchText: q, fields: ['email', 'username'] }) // dialect-aware: no `mode` on MySQL/SQLite/SQLServer
22
- .filter({ role, status }) // undefined values stripped
14
+ .search({ searchText: q, fields: ['email', 'username'] }) // dialect-aware
15
+ .filter({ role, status }) // undefined values stripped
23
16
  .range({ createdAt: { from, to }, 'avatar.size': { from: min } })
24
17
  .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })
25
- .paginate({ page: 1, limit: 20 }) // or .cursorPaginate({...})
26
- .select({ id: true, email: true }) // output type narrows structurally
18
+ .paginate({ page: 1, limit: 20 }) // or .cursorPaginate({...})
19
+ .select({ id: true, email: true }) // output type narrows structurally
27
20
  .executeWithMeta();
28
21
  // meta: { page: 1, limit: 20, total: 142, totalPage: 8 }
29
22
  ```
30
23
 
31
- ## Design rules (enforced in review — [ARCHITECTURE.md](./ARCHITECTURE.md) invariants)
24
+ ## Why
25
+
26
+ An npm package that imports Prisma types breaks on Prisma's next major — import
27
+ paths changed in v7, the type utilities move in v8, the engine was rewritten.
28
+ This package speaks only Prisma's stable public contract, the **model-delegate
29
+ call shape**:
30
+
31
+ ```
32
+ model.findMany({ where, orderBy, skip, take, select, include, cursor, distinct })
33
+ model.count({ where })
34
+ ```
35
+
36
+ It imports **nothing** from Prisma — no runtime imports, no type imports, no
37
+ peer dependencies. All types are derived structurally from the delegate you
38
+ pass in, so a Prisma upgrade can never break it. The test suite runs with zero
39
+ Prisma installed; that is the standing proof.
40
+
41
+ ## Install
42
+
43
+ ```bash
44
+ npm install query-builder-prisma
45
+ ```
46
+
47
+ Published on npm as [`query-builder-prisma`](https://www.npmjs.com/package/query-builder-prisma).
48
+
49
+ Node ≥ 18; TypeScript ≥ 5 for inference (plain JS works). Dual ESM + CJS; zero
50
+ runtime dependencies.
51
+
52
+ ## Documentation
53
+
54
+ | | |
55
+ | -------------------------------------------------------------------- | -------------------------------------------------- |
56
+ | [Getting started](./docs/getting-started.md) | install, first query, imports |
57
+ | [Guides](./docs/index.md#guides) | filtering, sorting, both pagination modes, projections, dialects, advanced patterns |
58
+ | [API reference](./docs/api/query-builder.md) | every method, type and function |
59
+ | [Use cases](./docs/examples/use-cases.md) | end-to-end scenarios |
60
+ | [Framework recipes](./docs/framework-recipes.md) | Next.js, NestJS, Express, edge runtimes |
61
+
62
+ ## Features
63
+
64
+ - **Fluent chain** — `search`, `filter`, `range`, `where`, `sortBy`/`orderBy`,
65
+ `paginate`/`cursorPaginate`, `select`/`include`, `custom`, folded into one
66
+ `findMany` call.
67
+ - **Offset pagination with metadata** — `executeWithMeta()` returns
68
+ `page`/`limit`/`total`/`totalPage`, with `COUNT` + `findMany` in parallel and
69
+ an opt-in fast path (`includeTotal: false`) that skips the `COUNT`.
70
+ - **Cursor (seek) pagination** — stable deep pages for feeds and infinite
71
+ scroll, forward/backward walking, ISO-8601-safe `Date` cursors, exact flags
72
+ via `strict: true`.
73
+ - **Structural type projection** — `.select()`/`.include()` narrow result types
74
+ like Prisma's own overloads, nested includes included, without Prisma types.
75
+ - **Dialect capability registry** — `mode: 'insensitive'` only where Prisma
76
+ accepts it; new databases are one `registerDialect()` call.
77
+ - **Hardened by default** — `undefined` stripping at any depth, prototype-key
78
+ refusal, clamped (or thrown) pagination numbers, a seed `where` that cannot
79
+ be replaced.
80
+
81
+ ### Offsetting and counting
82
+
83
+ ```ts
84
+ const { meta, data } = await new QueryBuilder(prisma.user)
85
+ .filter({ status: 'ACTIVE' })
86
+ .paginate({ page: 2, limit: 20 })
87
+ .executeWithMeta(); // meta: { page: 2, limit: 20, total, totalPage }
88
+
89
+ // Skip the COUNT query on large tables:
90
+ await qb.executeWithMeta({ includeTotal: false }); // total: null, totalPage: null
91
+ ```
92
+
93
+ ### Cursor pagination
94
+
95
+ ```ts
96
+ const page = await new QueryBuilder(prisma.post)
97
+ .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })
98
+ .cursorPaginate({ cursor: prev?.nextCursor, cursorField: 'createdAt', limit: 10 })
99
+ .executeWithCursor();
100
+ // meta: { limit, nextCursor, prevCursor, hasNextPage, hasPrevPage }
101
+ // rows always in configured sort order, whatever the walking direction
102
+ ```
103
+
104
+ ### Type-safe projections
105
+
106
+ ```ts
107
+ const users = await new QueryBuilder(prisma.user)
108
+ .select({ id: true, posts: { select: { title: true } } })
109
+ .execute();
110
+ // users: { id: string; posts: { title: string }[] }[] — no Prisma types involved
32
111
 
33
- 1. **Zero Prisma coupling** — no runtime or type imports from Prisma; no peerDependencies.
34
- 2. **Everything is structural** — only requires that a "model" has `findMany` + `count`
35
- with the standard call shape.
36
- 3. **Types degrade gracefully, never lie** — `select`/`include` narrowing is implemented
37
- by our own structural projection engine; for 100% Prisma-native inference use the
38
- passthrough `prisma.user.findMany(qb.buildArgs())`.
39
- 4. **Dialects are a capability registry** — `mode: 'insensitive'` is only emitted for
40
- PostgreSQL/CockroachDB/MongoDB (it throws on MySQL/SQLite/SQL Server). New/future
41
- databases need one `registerDialect()` call, no core changes.
112
+ // 100% Prisma-native inference whenever you want it:
113
+ await prisma.user.findMany(qb.buildArgs());
114
+ ```
42
115
 
43
- ## Dialect configuration
116
+ ### Dialects
44
117
 
45
118
  ```ts
46
- import { configureQueryBuilder } from 'query-builder-prisma';
119
+ import { configQueryBuilder } from 'query-builder-prisma';
47
120
 
48
- configureQueryBuilder({ dialect: 'postgres' }); // global default
49
- new QueryBuilder(prisma.user, { dialect: 'mysql' }); // per-builder override (recommended)
121
+ configQueryBuilder({ dialect: 'postgresql' }); // global default
122
+ new QueryBuilder(prisma.user, { dialect: 'mysql' }); // per-builder override (recommended)
50
123
  ```
51
124
 
52
- The global config state is shared through `globalThis` under a registered symbol, so
53
- bundler graphs that load this package as both ESM and CJS still see ONE config.
54
- The per-builder option stays the recommended path; unknown dialect names resolve
55
- to `'universal'` (reported name included — the name never lies about the applied
56
- capabilities).
125
+ `search()` emits `mode: 'insensitive'` only on PostgreSQL / CockroachDB /
126
+ MongoDB (it throws on MySQL, SQLite, SQL Server); elsewhere the database's
127
+ collation or Prisma's limits apply. Unknown dialect names resolve to
128
+ `'universal'` — arguments valid on every database.
57
129
 
58
130
  ## Behavior contracts
59
131
 
@@ -131,11 +203,38 @@ Open and documented rather than hidden — none produces a silently wrong result
131
203
  sort-ordered pages (kept as raw-passthrough semantics by design; the
132
204
  `buildArgs()` passthrough is always available).
133
205
 
206
+ ## FAQ
207
+
208
+ **Does this need Prisma installed?**
209
+ The package never imports Prisma, but of course you query *through* your
210
+ Prisma delegates — you pass them in. Any object with the `findMany` + `count`
211
+ call shape works, which is also how the test suite proves the decoupling.
212
+
213
+ **Which Prisma versions are supported?**
214
+ Every version whose model delegates keep the standard call shape — 5, 6, 7, 8
215
+ today, future majors by design. There is nothing to update on a Prisma
216
+ upgrade.
217
+
218
+ **Can I share one builder across requests?**
219
+ No — one builder per query. Instances are cheap; a shared instance mixes
220
+ conditions between concurrent requests. See
221
+ [Advanced patterns](./docs/guides/advanced.md#one-builder-per-query) and the
222
+ [framework recipes](./docs/framework-recipes.md).
223
+
224
+ **What if a type isn't narrow enough?**
225
+ The engine degrades wider, never wrong (today only `_count`). For exact
226
+ Prisma-native inference on any query, use the passthrough:
227
+ `prisma.user.findMany(qb.buildArgs())`.
228
+
229
+ **How do I add a database Prisma adds later?**
230
+ One `registerDialect(name, capabilities)` call — no core changes. See
231
+ [Dialects](./docs/guides/dialects.md).
232
+
134
233
  ## Development
135
234
 
136
235
  ```bash
137
- npm run verify # lint + typecheck + test + build
138
- npm test # unit tests (fake delegates, zero Prisma required)
236
+ npm run verify # lint + typecheck + test + build (the bar for every change)
237
+ npm test # unit tests — fake delegates, zero Prisma required
139
238
  ```
140
239
 
141
240
  - `src/core` — builder, condition assembly, pagination math
@@ -144,12 +243,13 @@ npm test # unit tests (fake delegates, zero Prisma required)
144
243
  - `test/types` — compile-time projection tests (run by `npm run typecheck`)
145
244
  - `builder-old/` — the original prototype this package was extracted from (reference only)
146
245
 
147
- Agent tooling (review agents, official Prisma skills, MCP servers) is documented
148
- in [CONTRIBUTING.md](./CONTRIBUTING.md) and [AGENTS.md](./AGENTS.md).
246
+ ### Links
149
247
 
150
- Docs: [ARCHITECTURE.md](./ARCHITECTURE.md) (design + boundaries),
151
- [AGENTS.md](./AGENTS.md) (agent/contributor rules),
152
- [CONTRIBUTING.md](./CONTRIBUTING.md) (how to contribute),
153
- [framework-recipes](./docs/framework-recipes.md) (Next.js / NestJS wiring).
248
+ - [ARCHITECTURE.md](./ARCHITECTURE.md) — design, boundaries, invariants
249
+ - [docs/index.md](./docs/index.md) — full documentation hub
250
+ - [CONTRIBUTING.md](./CONTRIBUTING.md) — how to contribute
251
+ - [SECURITY.md](./SECURITY.md) — vulnerability reporting
252
+ - [CHANGELOG.md](./CHANGELOG.md) — release history
154
253
 
155
- > **Note:** published on npm as `query-builder-prisma`.
254
+ > Published on npm as [`query-builder-prisma`](https://www.npmjs.com/package/query-builder-prisma).
255
+ > MIT licensed.
package/dist/index.cjs CHANGED
@@ -23,7 +23,7 @@ __export(index_exports, {
23
23
  DIALECT_CAPABILITIES: () => DIALECT_CAPABILITIES,
24
24
  NoResultError: () => NoResultError,
25
25
  QueryBuilder: () => QueryBuilder,
26
- configureQueryBuilder: () => configureQueryBuilder,
26
+ configQueryBuilder: () => configQueryBuilder,
27
27
  detectDialect: () => detectDialect,
28
28
  registerDialect: () => registerDialect,
29
29
  resetDialectConfig: () => resetDialectConfig,
@@ -196,7 +196,7 @@ function state() {
196
196
  function registerDialect(name, capabilities) {
197
197
  state().registry.set(name, capabilities);
198
198
  }
199
- function configureQueryBuilder(options) {
199
+ function configQueryBuilder(options) {
200
200
  state().globalDialect = options.dialect;
201
201
  }
202
202
  function setDialectDetector(detector) {
@@ -626,7 +626,7 @@ var QueryBuilder = class {
626
626
  DIALECT_CAPABILITIES,
627
627
  NoResultError,
628
628
  QueryBuilder,
629
- configureQueryBuilder,
629
+ configQueryBuilder,
630
630
  detectDialect,
631
631
  registerDialect,
632
632
  resetDialectConfig,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/core/conditions.ts","../src/core/pagination.ts","../src/dialects/capabilities.ts","../src/dialects/detect.ts","../src/dialects/registry.ts","../src/core/query-builder.ts"],"sourcesContent":["/**\n * query-builder-prisma\n *\n * Zero-coupling, fluent, fully type-safe query builder for any Prisma model\n * delegate. Works with every Prisma version (5/6/7/8 tested; future versions by\n * design) and every database Prisma supports. See ARCHITECTURE.md for the\n * architecture and AGENTS.md for the working rules.\n */\n\n// Core\nexport { QueryBuilder, NoResultError } from './core/query-builder';\nexport type { QueryBuilderOptions } from './core/query-builder';\n\n// Dialects\nexport {\n configureQueryBuilder,\n registerDialect,\n resolveDialect,\n resetDialectConfig,\n setDialectDetector,\n} from './dialects/registry';\nexport { DIALECT_CAPABILITIES } from './dialects/capabilities';\nexport { detectDialect } from './dialects/detect';\nexport type { Dialect, DialectCapabilities } from './dialects/capabilities';\nexport type { ResolvedDialect } from './dialects/registry';\n\n// Structural types (for advanced wiring by consumers)\nexport type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n RowsOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from './types/delegate';\nexport type {\n ApplyInclude,\n ApplyProjection,\n ApplySelect,\n FindResultOf,\n} from './types/projection';\n\n// Public option/meta types\nexport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from './types/public';\n","/** Build-time condition assembly helpers used by the QueryBuilder core. */\n\n/**\n * Keys we refuse to write into objects we build: computed-key assignment on\n * `'__proto__'` would set a local prototype instead of an own property\n * (audit F16 — reachable via JSON-parsed request bodies).\n */\nconst DANGEROUS_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isSafeKey(key: string): boolean {\n return !DANGEROUS_KEYS.has(key);\n}\n\n/** Strip `undefined` values so optional query params can be passed directly. */\nexport function stripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && isSafeKey(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Recursive {@link stripUndefined}: rebuilds plain objects and arrays of plain\n * objects without `undefined` values at any depth. Values that are not plain\n * objects (Date, BigInt, class instances like Decimal) pass through untouched\n * and the input is never mutated. Used by `.custom()` so a later\n * `custom({ key: undefined })` cannot overwrite an earlier value (audit F15).\n */\nexport function deepStripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || !isSafeKey(key)) {\n continue;\n }\n result[key] = isDeepStrippable(value)\n ? deepStripUndefined(value)\n : Array.isArray(value)\n ? value.map((item) => (isDeepStrippable(item) ? deepStripUndefined(item) : item))\n : value;\n }\n return result;\n}\n\n/** True for objects we may rebuild when deep-stripping (prototype-owned only). */\nfunction isDeepStrippable(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** True for plain objects (not arrays, not null). */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Expand `'avatar.size'` + a leaf value into `{ avatar: { size: leaf } }`.\n * Empty segments are skipped; a path containing a `__proto__`/`constructor`/\n * `prototype` segment expands to `{}` — refused, never written (audit F16).\n */\nexport function expandDotPath(path: string, leaf: unknown): Record<string, unknown> {\n const keys = path.split('.').filter((key) => key.length > 0);\n if (keys.length === 0 || keys.some((key) => !isSafeKey(key))) {\n return {};\n }\n let current: unknown = leaf;\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n if (key === undefined) {\n continue;\n }\n current = { [key]: current };\n }\n return current as Record<string, unknown>;\n}\n\n/**\n * AND-combine accumulated conditions with an optional seeded `where`.\n * A single condition is returned unwrapped (semantically identical to an\n * `AND` of one); zero conditions yields `undefined` (no `where` at all).\n */\nexport function combineAnd(\n conditions: readonly object[],\n customWhere?: unknown,\n): object | undefined {\n const all: object[] = isPlainObject(customWhere) ? [customWhere, ...conditions] : [...conditions];\n if (all.length === 0) {\n return undefined;\n }\n if (all.length === 1) {\n return all[0];\n }\n return { AND: all };\n}\n","/**\n * Offset (\"skip/take\") and cursor (\"seek\") pagination math — pure functions,\n * fully unit-testable without any database.\n */\nimport type { CursorDirection, CursorMeta, PaginationMeta } from '../types/public';\n\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const MAX_PAGE_SIZE = 1000;\n/** Upper bound for offset `skip` so deep pages cannot hit the DB unbounded (audit F18). */\nexport const MAX_SKIP = 100_000;\n\n/** Clamp a page size to `[1, MAX_PAGE_SIZE]`; non-finite input gets the default. */\nexport function clampLimit(limit: number): number {\n if (!Number.isFinite(limit)) {\n return DEFAULT_PAGE_SIZE;\n }\n return Math.min(Math.max(1, Math.floor(limit)), MAX_PAGE_SIZE);\n}\n\n/** Clamp a 1-based page number; `0`, negatives and NaN all become page 1. */\nexport function clampPage(page: number): number {\n if (!Number.isFinite(page)) {\n return 1;\n }\n return Math.max(1, Math.floor(page));\n}\n\n/** `skip`/`take` for a 1-based page + page size (both clamped, `skip` capped). */\nexport function toOffsetArgs(\n page: number,\n limit: number,\n): { take: number; skip: number; page: number; limit: number } {\n const safePage = clampPage(page);\n const safeLimit = clampLimit(limit);\n const skip = Math.min((safePage - 1) * safeLimit, MAX_SKIP);\n return { take: safeLimit, skip, page: safePage, limit: safeLimit };\n}\n\n/** Offset pagination metadata for a known `total`. */\nexport function buildPaginationMeta(total: number, page: number, limit: number): PaginationMeta {\n const safeLimit = clampLimit(limit);\n const safePage = clampPage(page);\n return {\n page: safePage,\n limit: safeLimit,\n total,\n totalPage: Math.ceil(total / safeLimit),\n };\n}\n\n/**\n * Serialize one cursor value. Dates become ISO-8601 strings so cursors are\n * round-trippable and locale/TZ-independent (audit F4); everything else uses\n * plain string coercion.\n */\nexport function serializeCursorValue(value: unknown): string {\n return value instanceof Date ? value.toISOString() : String(value);\n}\n\n/** Everything needed to turn cursor options into `findMany` args. */\nexport interface CursorPlan {\n cursor?: string | number | Date | undefined;\n limit?: number | undefined;\n direction?: CursorDirection;\n cursorField: string;\n}\n\n/**\n * `take`/`cursor`/`skip` for seek pagination:\n * - over-fetches one row (`±(limit + 1)`) to detect the next/previous page,\n * - negative `take` walks backwards,\n * - `skip: 1` excludes the cursor row itself.\n * The cursor value is passed through raw — Prisma accepts strings, numbers\n * and Dates for the cursor field.\n */\nexport function toCursorArgs(plan: CursorPlan): {\n take: number;\n cursor?: Record<string, unknown>;\n skip?: number;\n} {\n const sign = plan.direction === 'backward' ? -1 : 1;\n const take = sign * (clampLimit(plan.limit ?? DEFAULT_PAGE_SIZE) + 1);\n if (plan.cursor === undefined) {\n return { take };\n }\n return {\n take,\n cursor: { [plan.cursorField]: plan.cursor },\n skip: 1,\n };\n}\n\n/** Exact edge flags from a strict-mode probe query (audit F10). */\nexport interface ExactCursorFlags {\n hasNextPage?: boolean | undefined;\n hasPrevPage?: boolean | undefined;\n}\n\n/** Inputs for interpreting an over-fetched cursor page. */\nexport interface CursorPageInfo {\n limit: number;\n direction: CursorDirection;\n cursorField: string;\n /** Whether a cursor was supplied (i.e. this is not the first page). */\n hadCursor: boolean;\n /**\n * Probe-derived flags (strict mode); each entry replaces the optimistic\n * approximation for that edge (audit F10 / G9).\n */\n exactFlags?: ExactCursorFlags | undefined;\n}\n\n/**\n * Slice an over-fetched result set into the page + cursor metadata. Rows are\n * always returned in the configured sort order regardless of `direction`.\n */\nexport function buildCursorPage<T extends Record<string, unknown>>(\n rows: T[],\n info: CursorPageInfo,\n): { data: T[]; meta: CursorMeta } {\n const { limit, direction, cursorField, hadCursor, exactFlags } = info;\n const safeLimit = clampLimit(limit);\n\n const hasExtra = rows.length > safeLimit;\n const pageRows = hasExtra ? rows.slice(0, safeLimit) : rows;\n const ordered = direction === 'backward' ? [...pageRows].reverse() : pageRows;\n\n const hasRows = rows.length > 0;\n const hasNextPage =\n exactFlags?.hasNextPage ?? (direction === 'forward' ? hasExtra : hadCursor && hasRows);\n const hasPrevPage =\n exactFlags?.hasPrevPage ?? (direction === 'backward' ? hasExtra : hadCursor && hasRows);\n\n const first = ordered[0];\n const last = ordered[ordered.length - 1];\n\n return {\n data: ordered,\n meta: {\n limit: safeLimit,\n nextCursor:\n hasNextPage && last !== undefined ? serializeCursorValue(last[cursorField]) : null,\n prevCursor:\n hasPrevPage && first !== undefined ? serializeCursorValue(first[cursorField]) : null,\n hasNextPage,\n hasPrevPage,\n },\n };\n}\n","/**\n * Per-database capability sets (ARCHITECTURE.md, invariant 4).\n *\n * Prisma-supported databases disagree on filter operators — most importantly,\n * `mode: 'insensitive'` is only accepted on PostgreSQL, CockroachDB and MongoDB,\n * and *throws* on MySQL, MariaDB, SQLite and SQL Server. Capability records let\n * every builder method ask \"what is allowed here?\" instead of hardcoding\n * database names.\n */\nexport interface DialectCapabilities {\n /**\n * Prisma accepts `mode: 'insensitive'` on string filters for this dialect\n * (postgresql, cockroachdb, mongodb).\n */\n caseInsensitiveMode: boolean;\n /**\n * The database's default collation makes `contains` case-insensitive without\n * any extra argument (mysql, mariadb, sqlserver). For sqlite this is `false`:\n * ASCII `LIKE` is case-sensitive there, and Prisma offers no `mode`.\n */\n caseInsensitiveCollation: boolean;\n}\n\n/** Built-in capability sets, one per database Prisma supports (plus universal). */\nexport const DIALECT_CAPABILITIES = {\n postgresql: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n cockroachdb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n mysql: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mariadb: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n sqlite: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n sqlserver: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mongodb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n /**\n * Fallback used when no dialect is configured/detected. Only emits arguments\n * that are valid on EVERY Prisma-supported database.\n */\n universal: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n} satisfies Record<string, DialectCapabilities>;\n\n/** Names of the built-in dialects. */\nexport type Dialect = keyof typeof DIALECT_CAPABILITIES;\n","import type { Dialect } from './capabilities';\n\n/**\n * Best-effort dialect auto-detection (M2 scope).\n *\n * v0 intentionally detects nothing and returns `undefined` → callers fall\n * through to `'universal'`, which never emits an invalid argument on any\n * database. Future heuristics (guarded property sniffing of the Prisma client)\n * must keep the same contract: NEVER throw, NEVER guess wrong loudly — an\n * unknown dialect must degrade to `'universal'`, not to a wrong guess.\n *\n * Users who know their database should prefer explicit configuration:\n * configureQueryBuilder({ dialect: 'postgres' })\n * or per builder:\n * new QueryBuilder(prisma.user, { dialect: 'mongodb' })\n */\nexport function detectDialect(): Dialect | undefined {\n return undefined;\n}\n","import { DIALECT_CAPABILITIES } from './capabilities';\nimport type { DialectCapabilities } from './capabilities';\nimport { detectDialect } from './detect';\n\n/*\n * Dialect registry (ARCHITECTURE.md, invariant 4).\n *\n * Resolution order (fails soft to 'universal', which is always valid):\n * 1. explicit per-builder override new QueryBuilder(prisma.user, { dialect: 'mysql' })\n * 2. global config configureQueryBuilder({ dialect: 'postgres' })\n * 3. registered auto-detector setDialectDetector(fn)\n * 4. built-in detector detectDialect() (no-op in v0 — audit G2)\n * 5. 'universal'\n */\n\n/** Mutable dialect state, shared via `globalThis` (audit F7). */\ninterface DialectState {\n registry: Map<string, DialectCapabilities>;\n globalDialect: string | undefined;\n detector: (() => string | undefined) | undefined;\n}\n\n/**\n * The state lives on `globalThis` under a registered symbol so ESM and CJS\n * copies of this package converge on ONE config — a bundler loading both\n * variants can no longer split the global dialect config (dual-package hazard,\n * audit F7). This is the only mutable module-adjacent state in the package;\n * prefer the per-builder `dialect` option anyway.\n */\nconst STATE_KEY = Symbol.for('query-builder-prisma.dialect-state');\n\nfunction state(): DialectState {\n const host = globalThis as typeof globalThis & { [STATE_KEY]?: DialectState };\n return (host[STATE_KEY] ??= {\n registry: new Map(Object.entries(DIALECT_CAPABILITIES) as [string, DialectCapabilities][]),\n globalDialect: undefined,\n detector: undefined,\n });\n}\n\n/**\n * Register capabilities for a database - including ones Prisma adds in the\n * future. No core code changes are ever required to support a new dialect.\n */\nexport function registerDialect(name: string, capabilities: DialectCapabilities): void {\n state().registry.set(name, capabilities);\n}\n\n/** Set the global default dialect for all builders that do not override it. */\nexport function configureQueryBuilder(options: { dialect?: string | undefined }): void {\n state().globalDialect = options.dialect;\n}\n\n/**\n * Plug in an auto-detector (best-effort). It must never throw; an undefined\n * result simply falls through to the built-in detector and then 'universal'.\n */\nexport function setDialectDetector(detector: () => string | undefined): void {\n state().detector = detector;\n}\n\n/** A dialect name plus the capabilities resolved for it. */\nexport interface ResolvedDialect {\n name: string;\n capabilities: DialectCapabilities;\n}\n\n/**\n * Resolve the active dialect per the documented precedence. An unregistered\n * name resolves to `'universal'` — the reported name never lies about the\n * capabilities actually applied (audit G8).\n */\nexport function resolveDialect(explicit?: string | undefined): ResolvedDialect {\n const s = state();\n const requested = explicit ?? s.globalDialect ?? s.detector?.() ?? detectDialect() ?? 'universal';\n const capabilities = s.registry.get(requested);\n return capabilities\n ? { name: requested, capabilities }\n : { name: 'universal', capabilities: DIALECT_CAPABILITIES.universal };\n}\n\n/** Test helper: reset global configuration (registry entries are kept). */\nexport function resetDialectConfig(): void {\n const s = state();\n s.globalDialect = undefined;\n s.detector = undefined;\n}\n","import type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from '../types/delegate';\nimport type { ApplyProjection, FindResultOf } from '../types/projection';\nimport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from '../types/public';\nimport {\n combineAnd,\n deepStripUndefined,\n expandDotPath,\n isPlainObject,\n stripUndefined,\n} from './conditions';\nimport {\n buildCursorPage,\n buildPaginationMeta,\n clampLimit,\n clampPage,\n toCursorArgs,\n toOffsetArgs,\n DEFAULT_PAGE_SIZE,\n MAX_PAGE_SIZE,\n MAX_SKIP,\n} from './pagination';\nimport type { ExactCursorFlags } from './pagination';\nimport { resolveDialect } from '../dialects/registry';\nimport type { Dialect } from '../dialects/capabilities';\n\n/** Options accepted by the {@link QueryBuilder} constructor. */\nexport interface QueryBuilderOptions<D extends PrismaModelDelegate> {\n /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */\n initialArgs?: FindManyArgsOf<D> | undefined;\n /**\n * Per-builder dialect override. When omitted: global `configureQueryBuilder()`\n * config → registered auto-detector → `'universal'` (always-valid args).\n */\n dialect?: Dialect | undefined;\n /**\n * Throw on out-of-range pagination input instead of clamping silently:\n * limits outside `[1, 1000]`, pages below 1, or a computed `skip` beyond\n * `MAX_SKIP` (audits F12 / F18). Defaults to clamping.\n */\n strictNumbers?: boolean | undefined;\n}\n\n/** Meta type of {@link QueryBuilder.executeWithMeta} for the given options. */\ntype MetaOf<O extends { includeTotal?: boolean }> = O['includeTotal'] extends false\n ? PaginationMetaNoTotal\n : PaginationMeta;\n\n/** Thrown by {@link QueryBuilder.firstOrThrow} when no row matched. */\nexport class NoResultError extends Error {\n constructor() {\n super('Query returned no rows');\n this.name = 'NoResultError';\n }\n}\n\n/**\n * Generic, reusable and fully type-safe query builder for any Prisma model\n * delegate, on every Prisma version (see ARCHITECTURE.md).\n *\n * All option types (`where`, `select`, `include`, `orderBy`, ...) are inferred\n * structurally from the delegate passed to the constructor — nothing is imported\n * from Prisma, so no Prisma upgrade can ever break this class.\n *\n * The result type of `execute()` is narrowed by `.select()` / `.include()` via a\n * structural projection engine, mirroring Prisma's own behaviour.\n *\n * @typeParam D - The Prisma model delegate, e.g. `typeof prisma.user`.\n * @typeParam TArgs - Accumulated `findMany` args. Defaults to no projection.\n *\n * @example\n * const result = await new QueryBuilder(prisma.user)\n * .search({ searchText, fields: ['email', 'username'] })\n * .filter({ role, status })\n * .range({ createdAt: { from, to }, 'avatar.size': { from: min, to: max } })\n * .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })\n * .paginate({ page: 1, limit: 10 })\n * .select({ id: true, email: true })\n * .execute();\n */\nexport class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {\n private readonly delegate: D;\n private readonly dialect: Dialect | undefined;\n private readonly strictNumbers: boolean;\n private readonly andConditions: object[] = [];\n private customArgs: Record<string, unknown> = {};\n /**\n * The `initialArgs` seed `where` plus every `.custom({ where })`, AND-merged.\n * Kept out of `customArgs` so a later `.custom({ where })` merges with the\n * seed instead of replacing it (audit F2 — the seed carries safety filters).\n */\n private customWhere: unknown;\n private orderByArg: object | undefined;\n private selectArg: object | undefined;\n private includeArg: object | undefined;\n private page: number | undefined;\n private limit: number | undefined;\n private cursorActive = false;\n private cursor: string | number | Date | undefined;\n private cursorLimit: number | undefined;\n private cursorDirection: CursorDirection = 'forward';\n private cursorField: string = 'id';\n private cursorStrict = false;\n\n /**\n * @param delegate - The Prisma delegate to query (e.g. `prisma.user`).\n * @param options - Optional seed args, a dialect override, or `strictNumbers`.\n */\n constructor(delegate: D, options?: QueryBuilderOptions<D>) {\n this.delegate = delegate;\n this.dialect = options?.dialect;\n this.strictNumbers = options?.strictNumbers ?? false;\n if (options?.initialArgs) {\n const { where, ...rest } = options.initialArgs as Record<string, unknown>;\n this.customArgs = { ...rest };\n this.customWhere = where;\n }\n }\n\n /**\n * Case-insensitive `contains` across the provided string fields. No condition\n * is added when `searchText` is empty or whitespace-only (audit G7).\n *\n * Dialect-aware: adds `mode: 'insensitive'` only where Prisma accepts it (see\n * `caseInsensitiveMode` in `src/dialects/capabilities.ts`); everywhere else\n * the bare `contains` relies on the database's collation, and where that is\n * ASCII-only matching stays case-sensitive — Prisma offers no alternative\n * there.\n */\n search(params: { searchText?: string | undefined; fields: WhereKeyOf<D>[] }): this {\n const text = params.searchText?.trim();\n const fields = params.fields;\n if (text && fields.length > 0) {\n const { capabilities } = resolveDialect(this.dialect);\n this.andConditions.push({\n OR: fields.map((field) => {\n // One match object per arm — never a shared reference (audit F13).\n const match: Record<string, unknown> = { contains: text };\n if (capabilities.caseInsensitiveMode) {\n match.mode = 'insensitive';\n }\n return { [field]: match };\n }),\n });\n }\n return this;\n }\n\n /**\n * Adds an equality/operator filter. Accepts a partial Prisma `where` object;\n * `undefined` values are ignored so optional query params are safe to pass.\n */\n filter(filters: FilterInput<D>): this {\n const cleaned = stripUndefined(filters);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Adds `gte`/`lte` range conditions. Keys may be dot-paths to reach relations\n * or nested objects (e.g. `'avatar.size'`). Bounds left `undefined` are\n * skipped; a field is only added when at least one bound is present.\n */\n range(ranges: Record<string, RangeInput>): this {\n for (const [path, bound] of Object.entries(ranges)) {\n const condition: Record<string, RangeBound> = {};\n if (bound.from !== undefined) {\n condition.gte = bound.from;\n }\n if (bound.to !== undefined) {\n condition.lte = bound.to;\n }\n if (Object.keys(condition).length > 0) {\n const expanded = expandDotPath(path, condition);\n if (Object.keys(expanded).length > 0) {\n this.andConditions.push(expanded);\n }\n }\n }\n return this;\n }\n\n /** Adds an arbitrary, fully-typed Prisma `where` condition. */\n where(condition: WhereOf<D>): this {\n const cleaned = stripUndefined(condition as Record<string, unknown>);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Sets `orderBy` from a single key. No-op when `sortBy` is not provided.\n * Dot paths expand like `.range()` (`'avatar.size'` → `{ avatar: { size } }`,\n * audit F6). For multi-key or nested relation sorts use {@link orderBy}.\n */\n sortBy(params: { sortBy?: OrderKeyOf<D> | (string & {}); sortOrder?: SortOrder }): this {\n const { sortBy, sortOrder = 'desc' } = params;\n if (sortBy) {\n const expanded = expandDotPath(sortBy, sortOrder);\n if (Object.keys(expanded).length > 0) {\n this.orderByArg = expanded;\n }\n }\n return this;\n }\n\n /**\n * Sets `orderBy` verbatim from the full Prisma shape: arrays for multi-key\n * sorts, nested relation order objects. `.sortBy()` remains the single-key\n * convenience — the latest of the two calls wins (audit G1).\n */\n orderBy(order: OrderByOf<D>): this {\n this.orderByArg = order as object;\n return this;\n }\n\n /** Configures `skip`/`take` from a 1-based page number and page size. */\n paginate(params: { page?: number; limit?: number }): this {\n this.assertPage(params.page);\n this.assertLimit(params.limit);\n this.page = params.page ?? 1;\n this.limit = params.limit ?? DEFAULT_PAGE_SIZE;\n return this;\n }\n\n /**\n * Configures cursor-based (\"seek\") pagination. Use {@link executeWithCursor}\n * to run the query and obtain `next`/`prev` cursors.\n *\n * - `cursor` is the value of `cursorField` from the edge row of the previous\n * page (omit it for the first page). Strings, numbers and Dates are\n * accepted; Dates serialize to ISO-8601 in the returned cursors (audit F4).\n * - `direction` walks `'forward'` (next) or `'backward'` (previous).\n * - `cursorField` is the unique, sequential column to seek on (default `id`).\n * Pair it with a matching {@link sortBy} for stable ordering.\n * - `strict` spends one extra 1-row probe query to make `hasNextPage` /\n * `hasPrevPage` exact instead of optimistic (audit F10).\n *\n * Takes precedence over {@link paginate} when both are set.\n */\n cursorPaginate(params: {\n cursor?: string | number | Date | undefined;\n limit?: number;\n direction?: CursorDirection;\n cursorField?: OrderKeyOf<D> | (string & {});\n strict?: boolean;\n }): this {\n this.assertLimit(params.limit);\n this.cursorActive = true;\n this.cursor = params.cursor;\n this.cursorLimit = params.limit;\n this.cursorDirection = params.direction ?? 'forward';\n this.cursorField = params.cursorField ?? 'id';\n this.cursorStrict = params.strict ?? false;\n return this;\n }\n\n /**\n * Projects fields with Prisma `select`. The result type of `execute()` is\n * narrowed to exactly the selected shape. Clears any active `.include()`.\n */\n select<TSelect extends SelectOf<D>>(\n select: TSelect,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { select: TSelect }> {\n this.selectArg = select;\n this.includeArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { select: TSelect }\n >;\n }\n\n /**\n * Eager-loads relations with Prisma `include`. The result type of `execute()`\n * is widened with the included relations. Clears any active `.select()`.\n */\n include<TInclude extends IncludeOf<D>>(\n include: TInclude,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { include: TInclude }> {\n this.includeArg = include;\n this.selectArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { include: TInclude }\n >;\n }\n\n /**\n * Merges raw `findMany` args, e.g. `cursor`, `distinct` or a custom `where`.\n * Values that are `undefined` are stripped at any depth, so\n * `custom({ distinct: undefined })` cannot overwrite an earlier value\n * (audit F15). A custom `where` is AND-ed with the `initialArgs` seed and any\n * previous custom `where` — it never replaces them (audit F2). Successive\n * custom `where`s may nest `{ AND: [...] }` groups; Prisma treats that\n * identically.\n */\n custom(args: FindManyArgsOf<D>): this {\n const { where, ...rest } = args as Record<string, unknown>;\n this.customArgs = { ...this.customArgs, ...deepStripUndefined(rest) };\n if (where !== undefined) {\n const cleaned = isPlainObject(where) ? deepStripUndefined(where) : where;\n const hasKeys = !isPlainObject(cleaned) || Object.keys(cleaned).length > 0;\n if (hasKeys) {\n this.customWhere = combineAnd([cleaned as object], this.customWhere);\n }\n }\n return this;\n }\n\n /** The fully assembled `findMany` args. Useful for debugging or reuse. */\n buildArgs(): FindManyArgsOf<D> {\n const args: Record<string, unknown> = { ...this.customArgs };\n\n const where = this.buildWhere();\n if (where) {\n args.where = where;\n }\n if (this.orderByArg) {\n args.orderBy = this.orderByArg;\n }\n if (this.selectArg) {\n args.select = this.selectArg;\n }\n if (this.includeArg) {\n args.include = this.includeArg;\n }\n\n if (this.cursorActive) {\n const cursorArgs = toCursorArgs({\n cursor: this.cursor,\n limit: this.cursorLimit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n });\n args.take = cursorArgs.take;\n if (cursorArgs.cursor) {\n args.cursor = cursorArgs.cursor;\n }\n if (cursorArgs.skip !== undefined) {\n args.skip = cursorArgs.skip;\n }\n } else if (this.limit !== undefined) {\n const page = this.page ?? 1;\n this.assertSkipCap(page, this.limit);\n const offset = toOffsetArgs(page, this.limit);\n args.take = offset.take;\n args.skip = offset.skip;\n }\n\n return args as FindManyArgsOf<D>;\n }\n\n /**\n * Executes the query and returns the rows, typed from `.select()`/`.include()`.\n *\n * Tip: for 100% Prisma-native inference you can always run the passthrough\n * `prisma.user.findMany(qb.buildArgs())` — same args, Prisma's own overloads.\n */\n async execute(): Promise<FindResultOf<D, TArgs>> {\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const data = await findMany(this.buildArgs());\n return data as FindResultOf<D, TArgs>;\n }\n\n /** Executes the query and returns the first row, or `null` when none matched. */\n async first(): Promise<ApplyProjection<RowElementOf<D>, TArgs> | null> {\n const args = { ...(this.buildArgs() as object) } as Record<string, unknown>;\n args.take = 1;\n delete args.skip;\n delete args.cursor;\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const rows = (await findMany(args)) as unknown[];\n const row = rows[0];\n return (row ?? null) as ApplyProjection<RowElementOf<D>, TArgs> | null;\n }\n\n /** Like {@link first}, but throws {@link NoResultError} when nothing matched. */\n async firstOrThrow(): Promise<ApplyProjection<RowElementOf<D>, TArgs>> {\n const row = await this.first();\n if (row === null) {\n throw new NoResultError();\n }\n return row;\n }\n\n /** Counts rows matching the current filters (ignores pagination/projection). */\n async count(): Promise<number> {\n const where = this.buildWhere();\n const countFn = this.delegate.count.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<number>;\n return countFn(where ? { where } : {});\n }\n\n /**\n * Executes the query and returns the rows plus offset pagination metadata.\n * When no pagination was configured, defaults to page 1, limit 10 so `meta`\n * always describes the data actually returned. `count` and `findMany` run in\n * parallel.\n *\n * Pass `{ includeTotal: false }` to skip the `COUNT` query entirely — `meta`\n * then carries `total: null` / `totalPage: null` (audit G3).\n *\n * Throws when cursor pagination is configured — offset meta cannot describe a\n * seek query, and the cursor over-fetch row would leak into `data` (audit F1).\n * Use {@link executeWithCursor} instead.\n */\n async executeWithMeta<O extends { includeTotal?: boolean } = { includeTotal?: boolean }>(\n opts?: O,\n ): Promise<{ meta: MetaOf<O>; data: FindResultOf<D, TArgs> }> {\n if (this.cursorActive) {\n throw new Error(\n 'executeWithMeta() is offset-mode only: this builder has cursor pagination ' +\n 'configured via cursorPaginate(). Use executeWithCursor() instead.',\n );\n }\n if (this.limit === undefined) {\n this.paginate({ page: 1, limit: DEFAULT_PAGE_SIZE });\n }\n // Fail before the COUNT goes out (strictNumbers + skip cap, audit F18).\n this.assertSkipCap(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n const offset = toOffsetArgs(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n\n if (opts?.includeTotal === false) {\n const data = await this.execute();\n return {\n meta: { page: offset.page, limit: offset.limit, total: null, totalPage: null },\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n const [total, data] = await Promise.all([this.count(), this.execute()]);\n\n return {\n meta: buildPaginationMeta(total, offset.page, offset.limit),\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n /**\n * Executes a cursor-paginated query (see {@link cursorPaginate}) and returns\n * the page rows plus `next`/`prev` cursors. Rows are always returned in the\n * configured sort order, regardless of pagination `direction`.\n *\n * Throws when a `.select()` projection drops `cursorField` — the page cursors\n * are derived from that field and would come out as `undefined` (audit F5).\n */\n async executeWithCursor(): Promise<{ meta: CursorMeta; data: FindResultOf<D, TArgs> }> {\n if (!this.cursorActive) {\n this.cursorPaginate({});\n }\n this.assertCursorFieldProjected();\n const limit = this.cursorLimit ?? DEFAULT_PAGE_SIZE;\n const hadCursor = this.cursor !== undefined;\n\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<Record<string, unknown>[]>;\n const rows = await findMany(this.buildArgs());\n\n // Strict mode spends one extra 1-row probe query to make the optimistic\n // opposite edge exact (audit F10 / G9): forward pages probe the row before\n // the cursor, backward pages the row after it. The probe mirrors the main\n // query's `where`/`orderBy` — Prisma positions the cursor within the\n // query's own sort order and filters.\n let exactFlags: ExactCursorFlags | undefined;\n if (this.cursorStrict && hadCursor) {\n const probeArgs: Record<string, unknown> = {\n take: this.cursorDirection === 'forward' ? -1 : 1,\n cursor: { [this.cursorField]: this.cursor },\n skip: 1,\n };\n const where = this.buildWhere();\n if (where) {\n probeArgs.where = where;\n }\n if (this.orderByArg) {\n probeArgs.orderBy = this.orderByArg;\n }\n const probe = await findMany(probeArgs);\n const hasEdgeRow = probe.length > 0;\n exactFlags =\n this.cursorDirection === 'forward'\n ? { hasPrevPage: hasEdgeRow }\n : { hasNextPage: hasEdgeRow };\n }\n\n const { data, meta } = buildCursorPage(rows, {\n limit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n hadCursor,\n exactFlags,\n });\n\n return { meta, data: data as unknown as FindResultOf<D, TArgs> };\n }\n\n /** strictNumbers: out-of-range limits throw instead of clamping (audit F12). */\n private assertLimit(limit: number | undefined): void {\n if (!this.strictNumbers || limit === undefined) {\n return;\n }\n if (!Number.isFinite(limit) || limit < 1 || limit > MAX_PAGE_SIZE) {\n throw new Error(`strictNumbers: limit ${String(limit)} is outside [1, ${MAX_PAGE_SIZE}].`);\n }\n }\n\n private assertPage(page: number | undefined): void {\n if (!this.strictNumbers || page === undefined) {\n return;\n }\n if (!Number.isFinite(page) || page < 1) {\n throw new Error(`strictNumbers: page ${String(page)} must be a finite number >= 1.`);\n }\n }\n\n /** strictNumbers: a computed skip beyond MAX_SKIP throws (audit F18). */\n private assertSkipCap(page: number, limit: number): void {\n if (!this.strictNumbers) {\n return;\n }\n const skip = (clampPage(page) - 1) * clampLimit(limit);\n if (skip > MAX_SKIP) {\n throw new Error(\n `strictNumbers: computed skip ${String(skip)} exceeds the ${String(MAX_SKIP)} cap — ` +\n 'use cursor pagination for deep pages.',\n );\n }\n }\n\n /** A projection without the cursor field would derive cursors from `undefined` (audit F5). */\n private assertCursorFieldProjected(): void {\n // `.custom({ select })` also feeds args.select when no `.select()` ran.\n const select = (this.selectArg ?? this.customArgs.select) as\n Record<string, unknown> | undefined;\n if (select && !select[this.cursorField]) {\n throw new Error(\n `executeWithCursor(): the projection drops cursorField \"${this.cursorField}\", so page ` +\n 'cursors would be built from undefined. Keep the field in .select() or remove the projection.',\n );\n }\n }\n\n private buildWhere(): object | undefined {\n return combineAnd(this.andConditions, this.customWhere);\n }\n}\n"],"mappings":"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","names":["data"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/core/conditions.ts","../src/core/pagination.ts","../src/dialects/capabilities.ts","../src/dialects/detect.ts","../src/dialects/registry.ts","../src/core/query-builder.ts"],"sourcesContent":["/**\n * query-builder-prisma\n *\n * Zero-coupling, fluent, fully type-safe query builder for any Prisma model\n * delegate. Works with every Prisma version (5/6/7/8 tested; future versions by\n * design) and every database Prisma supports. See ARCHITECTURE.md for the\n * architecture and AGENTS.md for the working rules.\n */\n\n// Core\nexport { QueryBuilder, NoResultError } from './core/query-builder';\nexport type { QueryBuilderOptions } from './core/query-builder';\n\n// Dialects\nexport {\n configQueryBuilder,\n registerDialect,\n resolveDialect,\n resetDialectConfig,\n setDialectDetector,\n} from './dialects/registry';\nexport { DIALECT_CAPABILITIES } from './dialects/capabilities';\nexport { detectDialect } from './dialects/detect';\nexport type { Dialect, DialectCapabilities } from './dialects/capabilities';\nexport type { ResolvedDialect } from './dialects/registry';\n\n// Structural types (for advanced wiring by consumers)\nexport type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n RowsOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from './types/delegate';\nexport type {\n ApplyInclude,\n ApplyProjection,\n ApplySelect,\n FindResultOf,\n} from './types/projection';\n\n// Public option/meta types\nexport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from './types/public';\n","/** Build-time condition assembly helpers used by the QueryBuilder core. */\n\n/**\n * Keys we refuse to write into objects we build: computed-key assignment on\n * `'__proto__'` would set a local prototype instead of an own property\n * (audit F16 — reachable via JSON-parsed request bodies).\n */\nconst DANGEROUS_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isSafeKey(key: string): boolean {\n return !DANGEROUS_KEYS.has(key);\n}\n\n/** Strip `undefined` values so optional query params can be passed directly. */\nexport function stripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && isSafeKey(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Recursive {@link stripUndefined}: rebuilds plain objects and arrays of plain\n * objects without `undefined` values at any depth. Values that are not plain\n * objects (Date, BigInt, class instances like Decimal) pass through untouched\n * and the input is never mutated. Used by `.custom()` so a later\n * `custom({ key: undefined })` cannot overwrite an earlier value (audit F15).\n */\nexport function deepStripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || !isSafeKey(key)) {\n continue;\n }\n result[key] = isDeepStrippable(value)\n ? deepStripUndefined(value)\n : Array.isArray(value)\n ? value.map((item) => (isDeepStrippable(item) ? deepStripUndefined(item) : item))\n : value;\n }\n return result;\n}\n\n/** True for objects we may rebuild when deep-stripping (prototype-owned only). */\nfunction isDeepStrippable(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** True for plain objects (not arrays, not null). */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Expand `'avatar.size'` + a leaf value into `{ avatar: { size: leaf } }`.\n * Empty segments are skipped; a path containing a `__proto__`/`constructor`/\n * `prototype` segment expands to `{}` — refused, never written (audit F16).\n */\nexport function expandDotPath(path: string, leaf: unknown): Record<string, unknown> {\n const keys = path.split('.').filter((key) => key.length > 0);\n if (keys.length === 0 || keys.some((key) => !isSafeKey(key))) {\n return {};\n }\n let current: unknown = leaf;\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n if (key === undefined) {\n continue;\n }\n current = { [key]: current };\n }\n return current as Record<string, unknown>;\n}\n\n/**\n * AND-combine accumulated conditions with an optional seeded `where`.\n * A single condition is returned unwrapped (semantically identical to an\n * `AND` of one); zero conditions yields `undefined` (no `where` at all).\n */\nexport function combineAnd(\n conditions: readonly object[],\n customWhere?: unknown,\n): object | undefined {\n const all: object[] = isPlainObject(customWhere) ? [customWhere, ...conditions] : [...conditions];\n if (all.length === 0) {\n return undefined;\n }\n if (all.length === 1) {\n return all[0];\n }\n return { AND: all };\n}\n","/**\n * Offset (\"skip/take\") and cursor (\"seek\") pagination math — pure functions,\n * fully unit-testable without any database.\n */\nimport type { CursorDirection, CursorMeta, PaginationMeta } from '../types/public';\n\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const MAX_PAGE_SIZE = 1000;\n/** Upper bound for offset `skip` so deep pages cannot hit the DB unbounded (audit F18). */\nexport const MAX_SKIP = 100_000;\n\n/** Clamp a page size to `[1, MAX_PAGE_SIZE]`; non-finite input gets the default. */\nexport function clampLimit(limit: number): number {\n if (!Number.isFinite(limit)) {\n return DEFAULT_PAGE_SIZE;\n }\n return Math.min(Math.max(1, Math.floor(limit)), MAX_PAGE_SIZE);\n}\n\n/** Clamp a 1-based page number; `0`, negatives and NaN all become page 1. */\nexport function clampPage(page: number): number {\n if (!Number.isFinite(page)) {\n return 1;\n }\n return Math.max(1, Math.floor(page));\n}\n\n/** `skip`/`take` for a 1-based page + page size (both clamped, `skip` capped). */\nexport function toOffsetArgs(\n page: number,\n limit: number,\n): { take: number; skip: number; page: number; limit: number } {\n const safePage = clampPage(page);\n const safeLimit = clampLimit(limit);\n const skip = Math.min((safePage - 1) * safeLimit, MAX_SKIP);\n return { take: safeLimit, skip, page: safePage, limit: safeLimit };\n}\n\n/** Offset pagination metadata for a known `total`. */\nexport function buildPaginationMeta(total: number, page: number, limit: number): PaginationMeta {\n const safeLimit = clampLimit(limit);\n const safePage = clampPage(page);\n return {\n page: safePage,\n limit: safeLimit,\n total,\n totalPage: Math.ceil(total / safeLimit),\n };\n}\n\n/**\n * Serialize one cursor value. Dates become ISO-8601 strings so cursors are\n * round-trippable and locale/TZ-independent (audit F4); everything else uses\n * plain string coercion.\n */\nexport function serializeCursorValue(value: unknown): string {\n return value instanceof Date ? value.toISOString() : String(value);\n}\n\n/** Everything needed to turn cursor options into `findMany` args. */\nexport interface CursorPlan {\n cursor?: string | number | Date | undefined;\n limit?: number | undefined;\n direction?: CursorDirection;\n cursorField: string;\n}\n\n/**\n * `take`/`cursor`/`skip` for seek pagination:\n * - over-fetches one row (`±(limit + 1)`) to detect the next/previous page,\n * - negative `take` walks backwards,\n * - `skip: 1` excludes the cursor row itself.\n * The cursor value is passed through raw — Prisma accepts strings, numbers\n * and Dates for the cursor field.\n */\nexport function toCursorArgs(plan: CursorPlan): {\n take: number;\n cursor?: Record<string, unknown>;\n skip?: number;\n} {\n const sign = plan.direction === 'backward' ? -1 : 1;\n const take = sign * (clampLimit(plan.limit ?? DEFAULT_PAGE_SIZE) + 1);\n if (plan.cursor === undefined) {\n return { take };\n }\n return {\n take,\n cursor: { [plan.cursorField]: plan.cursor },\n skip: 1,\n };\n}\n\n/** Exact edge flags from a strict-mode probe query (audit F10). */\nexport interface ExactCursorFlags {\n hasNextPage?: boolean | undefined;\n hasPrevPage?: boolean | undefined;\n}\n\n/** Inputs for interpreting an over-fetched cursor page. */\nexport interface CursorPageInfo {\n limit: number;\n direction: CursorDirection;\n cursorField: string;\n /** Whether a cursor was supplied (i.e. this is not the first page). */\n hadCursor: boolean;\n /**\n * Probe-derived flags (strict mode); each entry replaces the optimistic\n * approximation for that edge (audit F10 / G9).\n */\n exactFlags?: ExactCursorFlags | undefined;\n}\n\n/**\n * Slice an over-fetched result set into the page + cursor metadata. Rows are\n * always returned in the configured sort order regardless of `direction`.\n */\nexport function buildCursorPage<T extends Record<string, unknown>>(\n rows: T[],\n info: CursorPageInfo,\n): { data: T[]; meta: CursorMeta } {\n const { limit, direction, cursorField, hadCursor, exactFlags } = info;\n const safeLimit = clampLimit(limit);\n\n const hasExtra = rows.length > safeLimit;\n const pageRows = hasExtra ? rows.slice(0, safeLimit) : rows;\n const ordered = direction === 'backward' ? [...pageRows].reverse() : pageRows;\n\n const hasRows = rows.length > 0;\n const hasNextPage =\n exactFlags?.hasNextPage ?? (direction === 'forward' ? hasExtra : hadCursor && hasRows);\n const hasPrevPage =\n exactFlags?.hasPrevPage ?? (direction === 'backward' ? hasExtra : hadCursor && hasRows);\n\n const first = ordered[0];\n const last = ordered[ordered.length - 1];\n\n return {\n data: ordered,\n meta: {\n limit: safeLimit,\n nextCursor:\n hasNextPage && last !== undefined ? serializeCursorValue(last[cursorField]) : null,\n prevCursor:\n hasPrevPage && first !== undefined ? serializeCursorValue(first[cursorField]) : null,\n hasNextPage,\n hasPrevPage,\n },\n };\n}\n","/**\n * Per-database capability sets (ARCHITECTURE.md, invariant 4).\n *\n * Prisma-supported databases disagree on filter operators — most importantly,\n * `mode: 'insensitive'` is only accepted on PostgreSQL, CockroachDB and MongoDB,\n * and *throws* on MySQL, MariaDB, SQLite and SQL Server. Capability records let\n * every builder method ask \"what is allowed here?\" instead of hardcoding\n * database names.\n */\nexport interface DialectCapabilities {\n /**\n * Prisma accepts `mode: 'insensitive'` on string filters for this dialect\n * (postgresql, cockroachdb, mongodb).\n */\n caseInsensitiveMode: boolean;\n /**\n * The database's default collation makes `contains` case-insensitive without\n * any extra argument (mysql, mariadb, sqlserver). For sqlite this is `false`:\n * ASCII `LIKE` is case-sensitive there, and Prisma offers no `mode`.\n */\n caseInsensitiveCollation: boolean;\n}\n\n/** Built-in capability sets, one per database Prisma supports (plus universal). */\nexport const DIALECT_CAPABILITIES = {\n postgresql: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n cockroachdb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n mysql: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mariadb: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n sqlite: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n sqlserver: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mongodb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n /**\n * Fallback used when no dialect is configured/detected. Only emits arguments\n * that are valid on EVERY Prisma-supported database.\n */\n universal: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n} satisfies Record<string, DialectCapabilities>;\n\n/** Names of the built-in dialects. */\nexport type Dialect = keyof typeof DIALECT_CAPABILITIES;\n","import type { Dialect } from './capabilities';\n\n/**\n * Best-effort dialect auto-detection (M2 scope).\n *\n * v0 intentionally detects nothing and returns `undefined` → callers fall\n * through to `'universal'`, which never emits an invalid argument on any\n * database. Future heuristics (guarded property sniffing of the Prisma client)\n * must keep the same contract: NEVER throw, NEVER guess wrong loudly — an\n * unknown dialect must degrade to `'universal'`, not to a wrong guess.\n *\n * Users who know their database should prefer explicit configuration:\n * configQueryBuilder({ dialect: 'postgresql' })\n * or per builder:\n * new QueryBuilder(prisma.user, { dialect: 'mongodb' })\n */\nexport function detectDialect(): Dialect | undefined {\n return undefined;\n}\n","import { DIALECT_CAPABILITIES } from './capabilities';\nimport type { DialectCapabilities } from './capabilities';\nimport { detectDialect } from './detect';\n\n/*\n * Dialect registry (ARCHITECTURE.md, invariant 4).\n *\n * Resolution order (fails soft to 'universal', which is always valid):\n * 1. explicit per-builder override new QueryBuilder(prisma.user, { dialect: 'mysql' })\n * 2. global config configQueryBuilder({ dialect: 'postgresql' })\n * 3. registered auto-detector setDialectDetector(fn)\n * 4. built-in detector detectDialect() (no-op in v0 — audit G2)\n * 5. 'universal'\n */\n\n/** Mutable dialect state, shared via `globalThis` (audit F7). */\ninterface DialectState {\n registry: Map<string, DialectCapabilities>;\n globalDialect: string | undefined;\n detector: (() => string | undefined) | undefined;\n}\n\n/**\n * The state lives on `globalThis` under a registered symbol so ESM and CJS\n * copies of this package converge on ONE config — a bundler loading both\n * variants can no longer split the global dialect config (dual-package hazard,\n * audit F7). This is the only mutable module-adjacent state in the package;\n * prefer the per-builder `dialect` option anyway.\n */\nconst STATE_KEY = Symbol.for('query-builder-prisma.dialect-state');\n\nfunction state(): DialectState {\n const host = globalThis as typeof globalThis & { [STATE_KEY]?: DialectState };\n return (host[STATE_KEY] ??= {\n registry: new Map(Object.entries(DIALECT_CAPABILITIES) as [string, DialectCapabilities][]),\n globalDialect: undefined,\n detector: undefined,\n });\n}\n\n/**\n * Register capabilities for a database - including ones Prisma adds in the\n * future. No core code changes are ever required to support a new dialect.\n */\nexport function registerDialect(name: string, capabilities: DialectCapabilities): void {\n state().registry.set(name, capabilities);\n}\n\n/** Set the global default dialect for all builders that do not override it. */\nexport function configQueryBuilder(options: { dialect?: string | undefined }): void {\n state().globalDialect = options.dialect;\n}\n\n/**\n * Plug in an auto-detector (best-effort). It must never throw; an undefined\n * result simply falls through to the built-in detector and then 'universal'.\n */\nexport function setDialectDetector(detector: () => string | undefined): void {\n state().detector = detector;\n}\n\n/** A dialect name plus the capabilities resolved for it. */\nexport interface ResolvedDialect {\n name: string;\n capabilities: DialectCapabilities;\n}\n\n/**\n * Resolve the active dialect per the documented precedence. An unregistered\n * name resolves to `'universal'` — the reported name never lies about the\n * capabilities actually applied (audit G8).\n */\nexport function resolveDialect(explicit?: string | undefined): ResolvedDialect {\n const s = state();\n const requested = explicit ?? s.globalDialect ?? s.detector?.() ?? detectDialect() ?? 'universal';\n const capabilities = s.registry.get(requested);\n return capabilities\n ? { name: requested, capabilities }\n : { name: 'universal', capabilities: DIALECT_CAPABILITIES.universal };\n}\n\n/** Test helper: reset global configuration (registry entries are kept). */\nexport function resetDialectConfig(): void {\n const s = state();\n s.globalDialect = undefined;\n s.detector = undefined;\n}\n","import type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from '../types/delegate';\nimport type { ApplyProjection, FindResultOf } from '../types/projection';\nimport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from '../types/public';\nimport {\n combineAnd,\n deepStripUndefined,\n expandDotPath,\n isPlainObject,\n stripUndefined,\n} from './conditions';\nimport {\n buildCursorPage,\n buildPaginationMeta,\n clampLimit,\n clampPage,\n toCursorArgs,\n toOffsetArgs,\n DEFAULT_PAGE_SIZE,\n MAX_PAGE_SIZE,\n MAX_SKIP,\n} from './pagination';\nimport type { ExactCursorFlags } from './pagination';\nimport { resolveDialect } from '../dialects/registry';\nimport type { Dialect } from '../dialects/capabilities';\n\n/** Options accepted by the {@link QueryBuilder} constructor. */\nexport interface QueryBuilderOptions<D extends PrismaModelDelegate> {\n /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */\n initialArgs?: FindManyArgsOf<D> | undefined;\n /**\n * Per-builder dialect override. When omitted: global `configQueryBuilder()`\n * config → registered auto-detector → `'universal'` (always-valid args).\n */\n dialect?: Dialect | undefined;\n /**\n * Throw on out-of-range pagination input instead of clamping silently:\n * limits outside `[1, 1000]`, pages below 1, or a computed `skip` beyond\n * `MAX_SKIP` (audits F12 / F18). Defaults to clamping.\n */\n strictNumbers?: boolean | undefined;\n}\n\n/** Meta type of {@link QueryBuilder.executeWithMeta} for the given options. */\ntype MetaOf<O extends { includeTotal?: boolean }> = O['includeTotal'] extends false\n ? PaginationMetaNoTotal\n : PaginationMeta;\n\n/** Thrown by {@link QueryBuilder.firstOrThrow} when no row matched. */\nexport class NoResultError extends Error {\n constructor() {\n super('Query returned no rows');\n this.name = 'NoResultError';\n }\n}\n\n/**\n * Generic, reusable and fully type-safe query builder for any Prisma model\n * delegate, on every Prisma version (see ARCHITECTURE.md).\n *\n * All option types (`where`, `select`, `include`, `orderBy`, ...) are inferred\n * structurally from the delegate passed to the constructor — nothing is imported\n * from Prisma, so no Prisma upgrade can ever break this class.\n *\n * The result type of `execute()` is narrowed by `.select()` / `.include()` via a\n * structural projection engine, mirroring Prisma's own behaviour.\n *\n * @typeParam D - The Prisma model delegate, e.g. `typeof prisma.user`.\n * @typeParam TArgs - Accumulated `findMany` args. Defaults to no projection.\n *\n * @example\n * const result = await new QueryBuilder(prisma.user)\n * .search({ searchText, fields: ['email', 'username'] })\n * .filter({ role, status })\n * .range({ createdAt: { from, to }, 'avatar.size': { from: min, to: max } })\n * .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })\n * .paginate({ page: 1, limit: 10 })\n * .select({ id: true, email: true })\n * .execute();\n */\nexport class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {\n private readonly delegate: D;\n private readonly dialect: Dialect | undefined;\n private readonly strictNumbers: boolean;\n private readonly andConditions: object[] = [];\n private customArgs: Record<string, unknown> = {};\n /**\n * The `initialArgs` seed `where` plus every `.custom({ where })`, AND-merged.\n * Kept out of `customArgs` so a later `.custom({ where })` merges with the\n * seed instead of replacing it (audit F2 — the seed carries safety filters).\n */\n private customWhere: unknown;\n private orderByArg: object | undefined;\n private selectArg: object | undefined;\n private includeArg: object | undefined;\n private page: number | undefined;\n private limit: number | undefined;\n private cursorActive = false;\n private cursor: string | number | Date | undefined;\n private cursorLimit: number | undefined;\n private cursorDirection: CursorDirection = 'forward';\n private cursorField: string = 'id';\n private cursorStrict = false;\n\n /**\n * @param delegate - The Prisma delegate to query (e.g. `prisma.user`).\n * @param options - Optional seed args, a dialect override, or `strictNumbers`.\n */\n constructor(delegate: D, options?: QueryBuilderOptions<D>) {\n this.delegate = delegate;\n this.dialect = options?.dialect;\n this.strictNumbers = options?.strictNumbers ?? false;\n if (options?.initialArgs) {\n const { where, ...rest } = options.initialArgs as Record<string, unknown>;\n this.customArgs = { ...rest };\n this.customWhere = where;\n }\n }\n\n /**\n * Case-insensitive `contains` across the provided string fields. No condition\n * is added when `searchText` is empty or whitespace-only (audit G7).\n *\n * Dialect-aware: adds `mode: 'insensitive'` only where Prisma accepts it (see\n * `caseInsensitiveMode` in `src/dialects/capabilities.ts`); everywhere else\n * the bare `contains` relies on the database's collation, and where that is\n * ASCII-only matching stays case-sensitive — Prisma offers no alternative\n * there.\n */\n search(params: { searchText?: string | undefined; fields: WhereKeyOf<D>[] }): this {\n const text = params.searchText?.trim();\n const fields = params.fields;\n if (text && fields.length > 0) {\n const { capabilities } = resolveDialect(this.dialect);\n this.andConditions.push({\n OR: fields.map((field) => {\n // One match object per arm — never a shared reference (audit F13).\n const match: Record<string, unknown> = { contains: text };\n if (capabilities.caseInsensitiveMode) {\n match.mode = 'insensitive';\n }\n return { [field]: match };\n }),\n });\n }\n return this;\n }\n\n /**\n * Adds an equality/operator filter. Accepts a partial Prisma `where` object;\n * `undefined` values are ignored so optional query params are safe to pass.\n */\n filter(filters: FilterInput<D>): this {\n const cleaned = stripUndefined(filters);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Adds `gte`/`lte` range conditions. Keys may be dot-paths to reach relations\n * or nested objects (e.g. `'avatar.size'`). Bounds left `undefined` are\n * skipped; a field is only added when at least one bound is present.\n */\n range(ranges: Record<string, RangeInput>): this {\n for (const [path, bound] of Object.entries(ranges)) {\n const condition: Record<string, RangeBound> = {};\n if (bound.from !== undefined) {\n condition.gte = bound.from;\n }\n if (bound.to !== undefined) {\n condition.lte = bound.to;\n }\n if (Object.keys(condition).length > 0) {\n const expanded = expandDotPath(path, condition);\n if (Object.keys(expanded).length > 0) {\n this.andConditions.push(expanded);\n }\n }\n }\n return this;\n }\n\n /** Adds an arbitrary, fully-typed Prisma `where` condition. */\n where(condition: WhereOf<D>): this {\n const cleaned = stripUndefined(condition as Record<string, unknown>);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Sets `orderBy` from a single key. No-op when `sortBy` is not provided.\n * Dot paths expand like `.range()` (`'avatar.size'` → `{ avatar: { size } }`,\n * audit F6). For multi-key or nested relation sorts use {@link orderBy}.\n */\n sortBy(params: { sortBy?: OrderKeyOf<D> | (string & {}); sortOrder?: SortOrder }): this {\n const { sortBy, sortOrder = 'desc' } = params;\n if (sortBy) {\n const expanded = expandDotPath(sortBy, sortOrder);\n if (Object.keys(expanded).length > 0) {\n this.orderByArg = expanded;\n }\n }\n return this;\n }\n\n /**\n * Sets `orderBy` verbatim from the full Prisma shape: arrays for multi-key\n * sorts, nested relation order objects. `.sortBy()` remains the single-key\n * convenience — the latest of the two calls wins (audit G1).\n */\n orderBy(order: OrderByOf<D>): this {\n this.orderByArg = order as object;\n return this;\n }\n\n /** Configures `skip`/`take` from a 1-based page number and page size. */\n paginate(params: { page?: number; limit?: number }): this {\n this.assertPage(params.page);\n this.assertLimit(params.limit);\n this.page = params.page ?? 1;\n this.limit = params.limit ?? DEFAULT_PAGE_SIZE;\n return this;\n }\n\n /**\n * Configures cursor-based (\"seek\") pagination. Use {@link executeWithCursor}\n * to run the query and obtain `next`/`prev` cursors.\n *\n * - `cursor` is the value of `cursorField` from the edge row of the previous\n * page (omit it for the first page). Strings, numbers and Dates are\n * accepted; Dates serialize to ISO-8601 in the returned cursors (audit F4).\n * - `direction` walks `'forward'` (next) or `'backward'` (previous).\n * - `cursorField` is the unique, sequential column to seek on (default `id`).\n * Pair it with a matching {@link sortBy} for stable ordering.\n * - `strict` spends one extra 1-row probe query to make `hasNextPage` /\n * `hasPrevPage` exact instead of optimistic (audit F10).\n *\n * Takes precedence over {@link paginate} when both are set.\n */\n cursorPaginate(params: {\n cursor?: string | number | Date | undefined;\n limit?: number;\n direction?: CursorDirection;\n cursorField?: OrderKeyOf<D> | (string & {});\n strict?: boolean;\n }): this {\n this.assertLimit(params.limit);\n this.cursorActive = true;\n this.cursor = params.cursor;\n this.cursorLimit = params.limit;\n this.cursorDirection = params.direction ?? 'forward';\n this.cursorField = params.cursorField ?? 'id';\n this.cursorStrict = params.strict ?? false;\n return this;\n }\n\n /**\n * Projects fields with Prisma `select`. The result type of `execute()` is\n * narrowed to exactly the selected shape. Clears any active `.include()`.\n */\n select<TSelect extends SelectOf<D>>(\n select: TSelect,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { select: TSelect }> {\n this.selectArg = select;\n this.includeArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { select: TSelect }\n >;\n }\n\n /**\n * Eager-loads relations with Prisma `include`. The result type of `execute()`\n * is widened with the included relations. Clears any active `.select()`.\n */\n include<TInclude extends IncludeOf<D>>(\n include: TInclude,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { include: TInclude }> {\n this.includeArg = include;\n this.selectArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { include: TInclude }\n >;\n }\n\n /**\n * Merges raw `findMany` args, e.g. `cursor`, `distinct` or a custom `where`.\n * Values that are `undefined` are stripped at any depth, so\n * `custom({ distinct: undefined })` cannot overwrite an earlier value\n * (audit F15). A custom `where` is AND-ed with the `initialArgs` seed and any\n * previous custom `where` — it never replaces them (audit F2). Successive\n * custom `where`s may nest `{ AND: [...] }` groups; Prisma treats that\n * identically.\n */\n custom(args: FindManyArgsOf<D>): this {\n const { where, ...rest } = args as Record<string, unknown>;\n this.customArgs = { ...this.customArgs, ...deepStripUndefined(rest) };\n if (where !== undefined) {\n const cleaned = isPlainObject(where) ? deepStripUndefined(where) : where;\n const hasKeys = !isPlainObject(cleaned) || Object.keys(cleaned).length > 0;\n if (hasKeys) {\n this.customWhere = combineAnd([cleaned as object], this.customWhere);\n }\n }\n return this;\n }\n\n /** The fully assembled `findMany` args. Useful for debugging or reuse. */\n buildArgs(): FindManyArgsOf<D> {\n const args: Record<string, unknown> = { ...this.customArgs };\n\n const where = this.buildWhere();\n if (where) {\n args.where = where;\n }\n if (this.orderByArg) {\n args.orderBy = this.orderByArg;\n }\n if (this.selectArg) {\n args.select = this.selectArg;\n }\n if (this.includeArg) {\n args.include = this.includeArg;\n }\n\n if (this.cursorActive) {\n const cursorArgs = toCursorArgs({\n cursor: this.cursor,\n limit: this.cursorLimit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n });\n args.take = cursorArgs.take;\n if (cursorArgs.cursor) {\n args.cursor = cursorArgs.cursor;\n }\n if (cursorArgs.skip !== undefined) {\n args.skip = cursorArgs.skip;\n }\n } else if (this.limit !== undefined) {\n const page = this.page ?? 1;\n this.assertSkipCap(page, this.limit);\n const offset = toOffsetArgs(page, this.limit);\n args.take = offset.take;\n args.skip = offset.skip;\n }\n\n return args as FindManyArgsOf<D>;\n }\n\n /**\n * Executes the query and returns the rows, typed from `.select()`/`.include()`.\n *\n * Tip: for 100% Prisma-native inference you can always run the passthrough\n * `prisma.user.findMany(qb.buildArgs())` — same args, Prisma's own overloads.\n */\n async execute(): Promise<FindResultOf<D, TArgs>> {\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const data = await findMany(this.buildArgs());\n return data as FindResultOf<D, TArgs>;\n }\n\n /** Executes the query and returns the first row, or `null` when none matched. */\n async first(): Promise<ApplyProjection<RowElementOf<D>, TArgs> | null> {\n const args = { ...(this.buildArgs() as object) } as Record<string, unknown>;\n args.take = 1;\n delete args.skip;\n delete args.cursor;\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const rows = (await findMany(args)) as unknown[];\n const row = rows[0];\n return (row ?? null) as ApplyProjection<RowElementOf<D>, TArgs> | null;\n }\n\n /** Like {@link first}, but throws {@link NoResultError} when nothing matched. */\n async firstOrThrow(): Promise<ApplyProjection<RowElementOf<D>, TArgs>> {\n const row = await this.first();\n if (row === null) {\n throw new NoResultError();\n }\n return row;\n }\n\n /** Counts rows matching the current filters (ignores pagination/projection). */\n async count(): Promise<number> {\n const where = this.buildWhere();\n const countFn = this.delegate.count.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<number>;\n return countFn(where ? { where } : {});\n }\n\n /**\n * Executes the query and returns the rows plus offset pagination metadata.\n * When no pagination was configured, defaults to page 1, limit 10 so `meta`\n * always describes the data actually returned. `count` and `findMany` run in\n * parallel.\n *\n * Pass `{ includeTotal: false }` to skip the `COUNT` query entirely — `meta`\n * then carries `total: null` / `totalPage: null` (audit G3).\n *\n * Throws when cursor pagination is configured — offset meta cannot describe a\n * seek query, and the cursor over-fetch row would leak into `data` (audit F1).\n * Use {@link executeWithCursor} instead.\n */\n async executeWithMeta<O extends { includeTotal?: boolean } = { includeTotal?: boolean }>(\n opts?: O,\n ): Promise<{ meta: MetaOf<O>; data: FindResultOf<D, TArgs> }> {\n if (this.cursorActive) {\n throw new Error(\n 'executeWithMeta() is offset-mode only: this builder has cursor pagination ' +\n 'configured via cursorPaginate(). Use executeWithCursor() instead.',\n );\n }\n if (this.limit === undefined) {\n this.paginate({ page: 1, limit: DEFAULT_PAGE_SIZE });\n }\n // Fail before the COUNT goes out (strictNumbers + skip cap, audit F18).\n this.assertSkipCap(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n const offset = toOffsetArgs(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n\n if (opts?.includeTotal === false) {\n const data = await this.execute();\n return {\n meta: { page: offset.page, limit: offset.limit, total: null, totalPage: null },\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n const [total, data] = await Promise.all([this.count(), this.execute()]);\n\n return {\n meta: buildPaginationMeta(total, offset.page, offset.limit),\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n /**\n * Executes a cursor-paginated query (see {@link cursorPaginate}) and returns\n * the page rows plus `next`/`prev` cursors. Rows are always returned in the\n * configured sort order, regardless of pagination `direction`.\n *\n * Throws when a `.select()` projection drops `cursorField` — the page cursors\n * are derived from that field and would come out as `undefined` (audit F5).\n */\n async executeWithCursor(): Promise<{ meta: CursorMeta; data: FindResultOf<D, TArgs> }> {\n if (!this.cursorActive) {\n this.cursorPaginate({});\n }\n this.assertCursorFieldProjected();\n const limit = this.cursorLimit ?? DEFAULT_PAGE_SIZE;\n const hadCursor = this.cursor !== undefined;\n\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<Record<string, unknown>[]>;\n const rows = await findMany(this.buildArgs());\n\n // Strict mode spends one extra 1-row probe query to make the optimistic\n // opposite edge exact (audit F10 / G9): forward pages probe the row before\n // the cursor, backward pages the row after it. The probe mirrors the main\n // query's `where`/`orderBy` — Prisma positions the cursor within the\n // query's own sort order and filters.\n let exactFlags: ExactCursorFlags | undefined;\n if (this.cursorStrict && hadCursor) {\n const probeArgs: Record<string, unknown> = {\n take: this.cursorDirection === 'forward' ? -1 : 1,\n cursor: { [this.cursorField]: this.cursor },\n skip: 1,\n };\n const where = this.buildWhere();\n if (where) {\n probeArgs.where = where;\n }\n if (this.orderByArg) {\n probeArgs.orderBy = this.orderByArg;\n }\n const probe = await findMany(probeArgs);\n const hasEdgeRow = probe.length > 0;\n exactFlags =\n this.cursorDirection === 'forward'\n ? { hasPrevPage: hasEdgeRow }\n : { hasNextPage: hasEdgeRow };\n }\n\n const { data, meta } = buildCursorPage(rows, {\n limit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n hadCursor,\n exactFlags,\n });\n\n return { meta, data: data as unknown as FindResultOf<D, TArgs> };\n }\n\n /** strictNumbers: out-of-range limits throw instead of clamping (audit F12). */\n private assertLimit(limit: number | undefined): void {\n if (!this.strictNumbers || limit === undefined) {\n return;\n }\n if (!Number.isFinite(limit) || limit < 1 || limit > MAX_PAGE_SIZE) {\n throw new Error(`strictNumbers: limit ${String(limit)} is outside [1, ${MAX_PAGE_SIZE}].`);\n }\n }\n\n private assertPage(page: number | undefined): void {\n if (!this.strictNumbers || page === undefined) {\n return;\n }\n if (!Number.isFinite(page) || page < 1) {\n throw new Error(`strictNumbers: page ${String(page)} must be a finite number >= 1.`);\n }\n }\n\n /** strictNumbers: a computed skip beyond MAX_SKIP throws (audit F18). */\n private assertSkipCap(page: number, limit: number): void {\n if (!this.strictNumbers) {\n return;\n }\n const skip = (clampPage(page) - 1) * clampLimit(limit);\n if (skip > MAX_SKIP) {\n throw new Error(\n `strictNumbers: computed skip ${String(skip)} exceeds the ${String(MAX_SKIP)} cap — ` +\n 'use cursor pagination for deep pages.',\n );\n }\n }\n\n /** A projection without the cursor field would derive cursors from `undefined` (audit F5). */\n private assertCursorFieldProjected(): void {\n // `.custom({ select })` also feeds args.select when no `.select()` ran.\n const select = (this.selectArg ?? this.customArgs.select) as\n Record<string, unknown> | undefined;\n if (select && !select[this.cursorField]) {\n throw new Error(\n `executeWithCursor(): the projection drops cursorField \"${this.cursorField}\", so page ` +\n 'cursors would be built from undefined. Keep the field in .select() or remove the projection.',\n );\n }\n }\n\n private buildWhere(): object | undefined {\n return combineAnd(this.andConditions, this.customWhere);\n }\n}\n"],"mappings":"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","names":["data"]}
package/dist/index.d.cts CHANGED
@@ -212,7 +212,7 @@ interface QueryBuilderOptions<D extends PrismaModelDelegate> {
212
212
  /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */
213
213
  initialArgs?: FindManyArgsOf<D> | undefined;
214
214
  /**
215
- * Per-builder dialect override. When omitted: global `configureQueryBuilder()`
215
+ * Per-builder dialect override. When omitted: global `configQueryBuilder()`
216
216
  * config → registered auto-detector → `'universal'` (always-valid args).
217
217
  */
218
218
  dialect?: Dialect | undefined;
@@ -440,7 +440,7 @@ declare class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {
440
440
  */
441
441
  declare function registerDialect(name: string, capabilities: DialectCapabilities): void;
442
442
  /** Set the global default dialect for all builders that do not override it. */
443
- declare function configureQueryBuilder(options: {
443
+ declare function configQueryBuilder(options: {
444
444
  dialect?: string | undefined;
445
445
  }): void;
446
446
  /**
@@ -472,10 +472,10 @@ declare function resetDialectConfig(): void;
472
472
  * unknown dialect must degrade to `'universal'`, not to a wrong guess.
473
473
  *
474
474
  * Users who know their database should prefer explicit configuration:
475
- * configureQueryBuilder({ dialect: 'postgres' })
475
+ * configQueryBuilder({ dialect: 'postgresql' })
476
476
  * or per builder:
477
477
  * new QueryBuilder(prisma.user, { dialect: 'mongodb' })
478
478
  */
479
479
  declare function detectDialect(): Dialect | undefined;
480
480
 
481
- export { type ApplyInclude, type ApplyProjection, type ApplySelect, type CursorDirection, type CursorMeta, DIALECT_CAPABILITIES, type Dialect, type DialectCapabilities, type FilterInput, type FindManyArgsOf, type FindResultOf, type IncludeOf, NoResultError, type OrderByOf, type OrderKeyOf, type PaginationMeta, type PaginationMetaNoTotal, type PrismaModelDelegate, QueryBuilder, type QueryBuilderOptions, type RangeBound, type RangeInput, type ResolvedDialect, type RowElementOf, type RowsOf, type SelectOf, type SortOrder, type WhereKeyOf, type WhereOf, configureQueryBuilder, detectDialect, registerDialect, resetDialectConfig, resolveDialect, setDialectDetector };
481
+ export { type ApplyInclude, type ApplyProjection, type ApplySelect, type CursorDirection, type CursorMeta, DIALECT_CAPABILITIES, type Dialect, type DialectCapabilities, type FilterInput, type FindManyArgsOf, type FindResultOf, type IncludeOf, NoResultError, type OrderByOf, type OrderKeyOf, type PaginationMeta, type PaginationMetaNoTotal, type PrismaModelDelegate, QueryBuilder, type QueryBuilderOptions, type RangeBound, type RangeInput, type ResolvedDialect, type RowElementOf, type RowsOf, type SelectOf, type SortOrder, type WhereKeyOf, type WhereOf, configQueryBuilder, detectDialect, registerDialect, resetDialectConfig, resolveDialect, setDialectDetector };
package/dist/index.d.ts CHANGED
@@ -212,7 +212,7 @@ interface QueryBuilderOptions<D extends PrismaModelDelegate> {
212
212
  /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */
213
213
  initialArgs?: FindManyArgsOf<D> | undefined;
214
214
  /**
215
- * Per-builder dialect override. When omitted: global `configureQueryBuilder()`
215
+ * Per-builder dialect override. When omitted: global `configQueryBuilder()`
216
216
  * config → registered auto-detector → `'universal'` (always-valid args).
217
217
  */
218
218
  dialect?: Dialect | undefined;
@@ -440,7 +440,7 @@ declare class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {
440
440
  */
441
441
  declare function registerDialect(name: string, capabilities: DialectCapabilities): void;
442
442
  /** Set the global default dialect for all builders that do not override it. */
443
- declare function configureQueryBuilder(options: {
443
+ declare function configQueryBuilder(options: {
444
444
  dialect?: string | undefined;
445
445
  }): void;
446
446
  /**
@@ -472,10 +472,10 @@ declare function resetDialectConfig(): void;
472
472
  * unknown dialect must degrade to `'universal'`, not to a wrong guess.
473
473
  *
474
474
  * Users who know their database should prefer explicit configuration:
475
- * configureQueryBuilder({ dialect: 'postgres' })
475
+ * configQueryBuilder({ dialect: 'postgresql' })
476
476
  * or per builder:
477
477
  * new QueryBuilder(prisma.user, { dialect: 'mongodb' })
478
478
  */
479
479
  declare function detectDialect(): Dialect | undefined;
480
480
 
481
- export { type ApplyInclude, type ApplyProjection, type ApplySelect, type CursorDirection, type CursorMeta, DIALECT_CAPABILITIES, type Dialect, type DialectCapabilities, type FilterInput, type FindManyArgsOf, type FindResultOf, type IncludeOf, NoResultError, type OrderByOf, type OrderKeyOf, type PaginationMeta, type PaginationMetaNoTotal, type PrismaModelDelegate, QueryBuilder, type QueryBuilderOptions, type RangeBound, type RangeInput, type ResolvedDialect, type RowElementOf, type RowsOf, type SelectOf, type SortOrder, type WhereKeyOf, type WhereOf, configureQueryBuilder, detectDialect, registerDialect, resetDialectConfig, resolveDialect, setDialectDetector };
481
+ export { type ApplyInclude, type ApplyProjection, type ApplySelect, type CursorDirection, type CursorMeta, DIALECT_CAPABILITIES, type Dialect, type DialectCapabilities, type FilterInput, type FindManyArgsOf, type FindResultOf, type IncludeOf, NoResultError, type OrderByOf, type OrderKeyOf, type PaginationMeta, type PaginationMetaNoTotal, type PrismaModelDelegate, QueryBuilder, type QueryBuilderOptions, type RangeBound, type RangeInput, type ResolvedDialect, type RowElementOf, type RowsOf, type SelectOf, type SortOrder, type WhereKeyOf, type WhereOf, configQueryBuilder, detectDialect, registerDialect, resetDialectConfig, resolveDialect, setDialectDetector };
package/dist/index.js CHANGED
@@ -162,7 +162,7 @@ function state() {
162
162
  function registerDialect(name, capabilities) {
163
163
  state().registry.set(name, capabilities);
164
164
  }
165
- function configureQueryBuilder(options) {
165
+ function configQueryBuilder(options) {
166
166
  state().globalDialect = options.dialect;
167
167
  }
168
168
  function setDialectDetector(detector) {
@@ -591,7 +591,7 @@ export {
591
591
  DIALECT_CAPABILITIES,
592
592
  NoResultError,
593
593
  QueryBuilder,
594
- configureQueryBuilder,
594
+ configQueryBuilder,
595
595
  detectDialect,
596
596
  registerDialect,
597
597
  resetDialectConfig,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/core/conditions.ts","../src/core/pagination.ts","../src/dialects/capabilities.ts","../src/dialects/detect.ts","../src/dialects/registry.ts","../src/core/query-builder.ts"],"sourcesContent":["/** Build-time condition assembly helpers used by the QueryBuilder core. */\n\n/**\n * Keys we refuse to write into objects we build: computed-key assignment on\n * `'__proto__'` would set a local prototype instead of an own property\n * (audit F16 — reachable via JSON-parsed request bodies).\n */\nconst DANGEROUS_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isSafeKey(key: string): boolean {\n return !DANGEROUS_KEYS.has(key);\n}\n\n/** Strip `undefined` values so optional query params can be passed directly. */\nexport function stripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && isSafeKey(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Recursive {@link stripUndefined}: rebuilds plain objects and arrays of plain\n * objects without `undefined` values at any depth. Values that are not plain\n * objects (Date, BigInt, class instances like Decimal) pass through untouched\n * and the input is never mutated. Used by `.custom()` so a later\n * `custom({ key: undefined })` cannot overwrite an earlier value (audit F15).\n */\nexport function deepStripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || !isSafeKey(key)) {\n continue;\n }\n result[key] = isDeepStrippable(value)\n ? deepStripUndefined(value)\n : Array.isArray(value)\n ? value.map((item) => (isDeepStrippable(item) ? deepStripUndefined(item) : item))\n : value;\n }\n return result;\n}\n\n/** True for objects we may rebuild when deep-stripping (prototype-owned only). */\nfunction isDeepStrippable(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** True for plain objects (not arrays, not null). */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Expand `'avatar.size'` + a leaf value into `{ avatar: { size: leaf } }`.\n * Empty segments are skipped; a path containing a `__proto__`/`constructor`/\n * `prototype` segment expands to `{}` — refused, never written (audit F16).\n */\nexport function expandDotPath(path: string, leaf: unknown): Record<string, unknown> {\n const keys = path.split('.').filter((key) => key.length > 0);\n if (keys.length === 0 || keys.some((key) => !isSafeKey(key))) {\n return {};\n }\n let current: unknown = leaf;\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n if (key === undefined) {\n continue;\n }\n current = { [key]: current };\n }\n return current as Record<string, unknown>;\n}\n\n/**\n * AND-combine accumulated conditions with an optional seeded `where`.\n * A single condition is returned unwrapped (semantically identical to an\n * `AND` of one); zero conditions yields `undefined` (no `where` at all).\n */\nexport function combineAnd(\n conditions: readonly object[],\n customWhere?: unknown,\n): object | undefined {\n const all: object[] = isPlainObject(customWhere) ? [customWhere, ...conditions] : [...conditions];\n if (all.length === 0) {\n return undefined;\n }\n if (all.length === 1) {\n return all[0];\n }\n return { AND: all };\n}\n","/**\n * Offset (\"skip/take\") and cursor (\"seek\") pagination math — pure functions,\n * fully unit-testable without any database.\n */\nimport type { CursorDirection, CursorMeta, PaginationMeta } from '../types/public';\n\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const MAX_PAGE_SIZE = 1000;\n/** Upper bound for offset `skip` so deep pages cannot hit the DB unbounded (audit F18). */\nexport const MAX_SKIP = 100_000;\n\n/** Clamp a page size to `[1, MAX_PAGE_SIZE]`; non-finite input gets the default. */\nexport function clampLimit(limit: number): number {\n if (!Number.isFinite(limit)) {\n return DEFAULT_PAGE_SIZE;\n }\n return Math.min(Math.max(1, Math.floor(limit)), MAX_PAGE_SIZE);\n}\n\n/** Clamp a 1-based page number; `0`, negatives and NaN all become page 1. */\nexport function clampPage(page: number): number {\n if (!Number.isFinite(page)) {\n return 1;\n }\n return Math.max(1, Math.floor(page));\n}\n\n/** `skip`/`take` for a 1-based page + page size (both clamped, `skip` capped). */\nexport function toOffsetArgs(\n page: number,\n limit: number,\n): { take: number; skip: number; page: number; limit: number } {\n const safePage = clampPage(page);\n const safeLimit = clampLimit(limit);\n const skip = Math.min((safePage - 1) * safeLimit, MAX_SKIP);\n return { take: safeLimit, skip, page: safePage, limit: safeLimit };\n}\n\n/** Offset pagination metadata for a known `total`. */\nexport function buildPaginationMeta(total: number, page: number, limit: number): PaginationMeta {\n const safeLimit = clampLimit(limit);\n const safePage = clampPage(page);\n return {\n page: safePage,\n limit: safeLimit,\n total,\n totalPage: Math.ceil(total / safeLimit),\n };\n}\n\n/**\n * Serialize one cursor value. Dates become ISO-8601 strings so cursors are\n * round-trippable and locale/TZ-independent (audit F4); everything else uses\n * plain string coercion.\n */\nexport function serializeCursorValue(value: unknown): string {\n return value instanceof Date ? value.toISOString() : String(value);\n}\n\n/** Everything needed to turn cursor options into `findMany` args. */\nexport interface CursorPlan {\n cursor?: string | number | Date | undefined;\n limit?: number | undefined;\n direction?: CursorDirection;\n cursorField: string;\n}\n\n/**\n * `take`/`cursor`/`skip` for seek pagination:\n * - over-fetches one row (`±(limit + 1)`) to detect the next/previous page,\n * - negative `take` walks backwards,\n * - `skip: 1` excludes the cursor row itself.\n * The cursor value is passed through raw — Prisma accepts strings, numbers\n * and Dates for the cursor field.\n */\nexport function toCursorArgs(plan: CursorPlan): {\n take: number;\n cursor?: Record<string, unknown>;\n skip?: number;\n} {\n const sign = plan.direction === 'backward' ? -1 : 1;\n const take = sign * (clampLimit(plan.limit ?? DEFAULT_PAGE_SIZE) + 1);\n if (plan.cursor === undefined) {\n return { take };\n }\n return {\n take,\n cursor: { [plan.cursorField]: plan.cursor },\n skip: 1,\n };\n}\n\n/** Exact edge flags from a strict-mode probe query (audit F10). */\nexport interface ExactCursorFlags {\n hasNextPage?: boolean | undefined;\n hasPrevPage?: boolean | undefined;\n}\n\n/** Inputs for interpreting an over-fetched cursor page. */\nexport interface CursorPageInfo {\n limit: number;\n direction: CursorDirection;\n cursorField: string;\n /** Whether a cursor was supplied (i.e. this is not the first page). */\n hadCursor: boolean;\n /**\n * Probe-derived flags (strict mode); each entry replaces the optimistic\n * approximation for that edge (audit F10 / G9).\n */\n exactFlags?: ExactCursorFlags | undefined;\n}\n\n/**\n * Slice an over-fetched result set into the page + cursor metadata. Rows are\n * always returned in the configured sort order regardless of `direction`.\n */\nexport function buildCursorPage<T extends Record<string, unknown>>(\n rows: T[],\n info: CursorPageInfo,\n): { data: T[]; meta: CursorMeta } {\n const { limit, direction, cursorField, hadCursor, exactFlags } = info;\n const safeLimit = clampLimit(limit);\n\n const hasExtra = rows.length > safeLimit;\n const pageRows = hasExtra ? rows.slice(0, safeLimit) : rows;\n const ordered = direction === 'backward' ? [...pageRows].reverse() : pageRows;\n\n const hasRows = rows.length > 0;\n const hasNextPage =\n exactFlags?.hasNextPage ?? (direction === 'forward' ? hasExtra : hadCursor && hasRows);\n const hasPrevPage =\n exactFlags?.hasPrevPage ?? (direction === 'backward' ? hasExtra : hadCursor && hasRows);\n\n const first = ordered[0];\n const last = ordered[ordered.length - 1];\n\n return {\n data: ordered,\n meta: {\n limit: safeLimit,\n nextCursor:\n hasNextPage && last !== undefined ? serializeCursorValue(last[cursorField]) : null,\n prevCursor:\n hasPrevPage && first !== undefined ? serializeCursorValue(first[cursorField]) : null,\n hasNextPage,\n hasPrevPage,\n },\n };\n}\n","/**\n * Per-database capability sets (ARCHITECTURE.md, invariant 4).\n *\n * Prisma-supported databases disagree on filter operators — most importantly,\n * `mode: 'insensitive'` is only accepted on PostgreSQL, CockroachDB and MongoDB,\n * and *throws* on MySQL, MariaDB, SQLite and SQL Server. Capability records let\n * every builder method ask \"what is allowed here?\" instead of hardcoding\n * database names.\n */\nexport interface DialectCapabilities {\n /**\n * Prisma accepts `mode: 'insensitive'` on string filters for this dialect\n * (postgresql, cockroachdb, mongodb).\n */\n caseInsensitiveMode: boolean;\n /**\n * The database's default collation makes `contains` case-insensitive without\n * any extra argument (mysql, mariadb, sqlserver). For sqlite this is `false`:\n * ASCII `LIKE` is case-sensitive there, and Prisma offers no `mode`.\n */\n caseInsensitiveCollation: boolean;\n}\n\n/** Built-in capability sets, one per database Prisma supports (plus universal). */\nexport const DIALECT_CAPABILITIES = {\n postgresql: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n cockroachdb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n mysql: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mariadb: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n sqlite: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n sqlserver: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mongodb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n /**\n * Fallback used when no dialect is configured/detected. Only emits arguments\n * that are valid on EVERY Prisma-supported database.\n */\n universal: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n} satisfies Record<string, DialectCapabilities>;\n\n/** Names of the built-in dialects. */\nexport type Dialect = keyof typeof DIALECT_CAPABILITIES;\n","import type { Dialect } from './capabilities';\n\n/**\n * Best-effort dialect auto-detection (M2 scope).\n *\n * v0 intentionally detects nothing and returns `undefined` → callers fall\n * through to `'universal'`, which never emits an invalid argument on any\n * database. Future heuristics (guarded property sniffing of the Prisma client)\n * must keep the same contract: NEVER throw, NEVER guess wrong loudly — an\n * unknown dialect must degrade to `'universal'`, not to a wrong guess.\n *\n * Users who know their database should prefer explicit configuration:\n * configureQueryBuilder({ dialect: 'postgres' })\n * or per builder:\n * new QueryBuilder(prisma.user, { dialect: 'mongodb' })\n */\nexport function detectDialect(): Dialect | undefined {\n return undefined;\n}\n","import { DIALECT_CAPABILITIES } from './capabilities';\nimport type { DialectCapabilities } from './capabilities';\nimport { detectDialect } from './detect';\n\n/*\n * Dialect registry (ARCHITECTURE.md, invariant 4).\n *\n * Resolution order (fails soft to 'universal', which is always valid):\n * 1. explicit per-builder override new QueryBuilder(prisma.user, { dialect: 'mysql' })\n * 2. global config configureQueryBuilder({ dialect: 'postgres' })\n * 3. registered auto-detector setDialectDetector(fn)\n * 4. built-in detector detectDialect() (no-op in v0 — audit G2)\n * 5. 'universal'\n */\n\n/** Mutable dialect state, shared via `globalThis` (audit F7). */\ninterface DialectState {\n registry: Map<string, DialectCapabilities>;\n globalDialect: string | undefined;\n detector: (() => string | undefined) | undefined;\n}\n\n/**\n * The state lives on `globalThis` under a registered symbol so ESM and CJS\n * copies of this package converge on ONE config — a bundler loading both\n * variants can no longer split the global dialect config (dual-package hazard,\n * audit F7). This is the only mutable module-adjacent state in the package;\n * prefer the per-builder `dialect` option anyway.\n */\nconst STATE_KEY = Symbol.for('query-builder-prisma.dialect-state');\n\nfunction state(): DialectState {\n const host = globalThis as typeof globalThis & { [STATE_KEY]?: DialectState };\n return (host[STATE_KEY] ??= {\n registry: new Map(Object.entries(DIALECT_CAPABILITIES) as [string, DialectCapabilities][]),\n globalDialect: undefined,\n detector: undefined,\n });\n}\n\n/**\n * Register capabilities for a database - including ones Prisma adds in the\n * future. No core code changes are ever required to support a new dialect.\n */\nexport function registerDialect(name: string, capabilities: DialectCapabilities): void {\n state().registry.set(name, capabilities);\n}\n\n/** Set the global default dialect for all builders that do not override it. */\nexport function configureQueryBuilder(options: { dialect?: string | undefined }): void {\n state().globalDialect = options.dialect;\n}\n\n/**\n * Plug in an auto-detector (best-effort). It must never throw; an undefined\n * result simply falls through to the built-in detector and then 'universal'.\n */\nexport function setDialectDetector(detector: () => string | undefined): void {\n state().detector = detector;\n}\n\n/** A dialect name plus the capabilities resolved for it. */\nexport interface ResolvedDialect {\n name: string;\n capabilities: DialectCapabilities;\n}\n\n/**\n * Resolve the active dialect per the documented precedence. An unregistered\n * name resolves to `'universal'` — the reported name never lies about the\n * capabilities actually applied (audit G8).\n */\nexport function resolveDialect(explicit?: string | undefined): ResolvedDialect {\n const s = state();\n const requested = explicit ?? s.globalDialect ?? s.detector?.() ?? detectDialect() ?? 'universal';\n const capabilities = s.registry.get(requested);\n return capabilities\n ? { name: requested, capabilities }\n : { name: 'universal', capabilities: DIALECT_CAPABILITIES.universal };\n}\n\n/** Test helper: reset global configuration (registry entries are kept). */\nexport function resetDialectConfig(): void {\n const s = state();\n s.globalDialect = undefined;\n s.detector = undefined;\n}\n","import type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from '../types/delegate';\nimport type { ApplyProjection, FindResultOf } from '../types/projection';\nimport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from '../types/public';\nimport {\n combineAnd,\n deepStripUndefined,\n expandDotPath,\n isPlainObject,\n stripUndefined,\n} from './conditions';\nimport {\n buildCursorPage,\n buildPaginationMeta,\n clampLimit,\n clampPage,\n toCursorArgs,\n toOffsetArgs,\n DEFAULT_PAGE_SIZE,\n MAX_PAGE_SIZE,\n MAX_SKIP,\n} from './pagination';\nimport type { ExactCursorFlags } from './pagination';\nimport { resolveDialect } from '../dialects/registry';\nimport type { Dialect } from '../dialects/capabilities';\n\n/** Options accepted by the {@link QueryBuilder} constructor. */\nexport interface QueryBuilderOptions<D extends PrismaModelDelegate> {\n /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */\n initialArgs?: FindManyArgsOf<D> | undefined;\n /**\n * Per-builder dialect override. When omitted: global `configureQueryBuilder()`\n * config → registered auto-detector → `'universal'` (always-valid args).\n */\n dialect?: Dialect | undefined;\n /**\n * Throw on out-of-range pagination input instead of clamping silently:\n * limits outside `[1, 1000]`, pages below 1, or a computed `skip` beyond\n * `MAX_SKIP` (audits F12 / F18). Defaults to clamping.\n */\n strictNumbers?: boolean | undefined;\n}\n\n/** Meta type of {@link QueryBuilder.executeWithMeta} for the given options. */\ntype MetaOf<O extends { includeTotal?: boolean }> = O['includeTotal'] extends false\n ? PaginationMetaNoTotal\n : PaginationMeta;\n\n/** Thrown by {@link QueryBuilder.firstOrThrow} when no row matched. */\nexport class NoResultError extends Error {\n constructor() {\n super('Query returned no rows');\n this.name = 'NoResultError';\n }\n}\n\n/**\n * Generic, reusable and fully type-safe query builder for any Prisma model\n * delegate, on every Prisma version (see ARCHITECTURE.md).\n *\n * All option types (`where`, `select`, `include`, `orderBy`, ...) are inferred\n * structurally from the delegate passed to the constructor — nothing is imported\n * from Prisma, so no Prisma upgrade can ever break this class.\n *\n * The result type of `execute()` is narrowed by `.select()` / `.include()` via a\n * structural projection engine, mirroring Prisma's own behaviour.\n *\n * @typeParam D - The Prisma model delegate, e.g. `typeof prisma.user`.\n * @typeParam TArgs - Accumulated `findMany` args. Defaults to no projection.\n *\n * @example\n * const result = await new QueryBuilder(prisma.user)\n * .search({ searchText, fields: ['email', 'username'] })\n * .filter({ role, status })\n * .range({ createdAt: { from, to }, 'avatar.size': { from: min, to: max } })\n * .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })\n * .paginate({ page: 1, limit: 10 })\n * .select({ id: true, email: true })\n * .execute();\n */\nexport class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {\n private readonly delegate: D;\n private readonly dialect: Dialect | undefined;\n private readonly strictNumbers: boolean;\n private readonly andConditions: object[] = [];\n private customArgs: Record<string, unknown> = {};\n /**\n * The `initialArgs` seed `where` plus every `.custom({ where })`, AND-merged.\n * Kept out of `customArgs` so a later `.custom({ where })` merges with the\n * seed instead of replacing it (audit F2 — the seed carries safety filters).\n */\n private customWhere: unknown;\n private orderByArg: object | undefined;\n private selectArg: object | undefined;\n private includeArg: object | undefined;\n private page: number | undefined;\n private limit: number | undefined;\n private cursorActive = false;\n private cursor: string | number | Date | undefined;\n private cursorLimit: number | undefined;\n private cursorDirection: CursorDirection = 'forward';\n private cursorField: string = 'id';\n private cursorStrict = false;\n\n /**\n * @param delegate - The Prisma delegate to query (e.g. `prisma.user`).\n * @param options - Optional seed args, a dialect override, or `strictNumbers`.\n */\n constructor(delegate: D, options?: QueryBuilderOptions<D>) {\n this.delegate = delegate;\n this.dialect = options?.dialect;\n this.strictNumbers = options?.strictNumbers ?? false;\n if (options?.initialArgs) {\n const { where, ...rest } = options.initialArgs as Record<string, unknown>;\n this.customArgs = { ...rest };\n this.customWhere = where;\n }\n }\n\n /**\n * Case-insensitive `contains` across the provided string fields. No condition\n * is added when `searchText` is empty or whitespace-only (audit G7).\n *\n * Dialect-aware: adds `mode: 'insensitive'` only where Prisma accepts it (see\n * `caseInsensitiveMode` in `src/dialects/capabilities.ts`); everywhere else\n * the bare `contains` relies on the database's collation, and where that is\n * ASCII-only matching stays case-sensitive — Prisma offers no alternative\n * there.\n */\n search(params: { searchText?: string | undefined; fields: WhereKeyOf<D>[] }): this {\n const text = params.searchText?.trim();\n const fields = params.fields;\n if (text && fields.length > 0) {\n const { capabilities } = resolveDialect(this.dialect);\n this.andConditions.push({\n OR: fields.map((field) => {\n // One match object per arm — never a shared reference (audit F13).\n const match: Record<string, unknown> = { contains: text };\n if (capabilities.caseInsensitiveMode) {\n match.mode = 'insensitive';\n }\n return { [field]: match };\n }),\n });\n }\n return this;\n }\n\n /**\n * Adds an equality/operator filter. Accepts a partial Prisma `where` object;\n * `undefined` values are ignored so optional query params are safe to pass.\n */\n filter(filters: FilterInput<D>): this {\n const cleaned = stripUndefined(filters);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Adds `gte`/`lte` range conditions. Keys may be dot-paths to reach relations\n * or nested objects (e.g. `'avatar.size'`). Bounds left `undefined` are\n * skipped; a field is only added when at least one bound is present.\n */\n range(ranges: Record<string, RangeInput>): this {\n for (const [path, bound] of Object.entries(ranges)) {\n const condition: Record<string, RangeBound> = {};\n if (bound.from !== undefined) {\n condition.gte = bound.from;\n }\n if (bound.to !== undefined) {\n condition.lte = bound.to;\n }\n if (Object.keys(condition).length > 0) {\n const expanded = expandDotPath(path, condition);\n if (Object.keys(expanded).length > 0) {\n this.andConditions.push(expanded);\n }\n }\n }\n return this;\n }\n\n /** Adds an arbitrary, fully-typed Prisma `where` condition. */\n where(condition: WhereOf<D>): this {\n const cleaned = stripUndefined(condition as Record<string, unknown>);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Sets `orderBy` from a single key. No-op when `sortBy` is not provided.\n * Dot paths expand like `.range()` (`'avatar.size'` → `{ avatar: { size } }`,\n * audit F6). For multi-key or nested relation sorts use {@link orderBy}.\n */\n sortBy(params: { sortBy?: OrderKeyOf<D> | (string & {}); sortOrder?: SortOrder }): this {\n const { sortBy, sortOrder = 'desc' } = params;\n if (sortBy) {\n const expanded = expandDotPath(sortBy, sortOrder);\n if (Object.keys(expanded).length > 0) {\n this.orderByArg = expanded;\n }\n }\n return this;\n }\n\n /**\n * Sets `orderBy` verbatim from the full Prisma shape: arrays for multi-key\n * sorts, nested relation order objects. `.sortBy()` remains the single-key\n * convenience — the latest of the two calls wins (audit G1).\n */\n orderBy(order: OrderByOf<D>): this {\n this.orderByArg = order as object;\n return this;\n }\n\n /** Configures `skip`/`take` from a 1-based page number and page size. */\n paginate(params: { page?: number; limit?: number }): this {\n this.assertPage(params.page);\n this.assertLimit(params.limit);\n this.page = params.page ?? 1;\n this.limit = params.limit ?? DEFAULT_PAGE_SIZE;\n return this;\n }\n\n /**\n * Configures cursor-based (\"seek\") pagination. Use {@link executeWithCursor}\n * to run the query and obtain `next`/`prev` cursors.\n *\n * - `cursor` is the value of `cursorField` from the edge row of the previous\n * page (omit it for the first page). Strings, numbers and Dates are\n * accepted; Dates serialize to ISO-8601 in the returned cursors (audit F4).\n * - `direction` walks `'forward'` (next) or `'backward'` (previous).\n * - `cursorField` is the unique, sequential column to seek on (default `id`).\n * Pair it with a matching {@link sortBy} for stable ordering.\n * - `strict` spends one extra 1-row probe query to make `hasNextPage` /\n * `hasPrevPage` exact instead of optimistic (audit F10).\n *\n * Takes precedence over {@link paginate} when both are set.\n */\n cursorPaginate(params: {\n cursor?: string | number | Date | undefined;\n limit?: number;\n direction?: CursorDirection;\n cursorField?: OrderKeyOf<D> | (string & {});\n strict?: boolean;\n }): this {\n this.assertLimit(params.limit);\n this.cursorActive = true;\n this.cursor = params.cursor;\n this.cursorLimit = params.limit;\n this.cursorDirection = params.direction ?? 'forward';\n this.cursorField = params.cursorField ?? 'id';\n this.cursorStrict = params.strict ?? false;\n return this;\n }\n\n /**\n * Projects fields with Prisma `select`. The result type of `execute()` is\n * narrowed to exactly the selected shape. Clears any active `.include()`.\n */\n select<TSelect extends SelectOf<D>>(\n select: TSelect,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { select: TSelect }> {\n this.selectArg = select;\n this.includeArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { select: TSelect }\n >;\n }\n\n /**\n * Eager-loads relations with Prisma `include`. The result type of `execute()`\n * is widened with the included relations. Clears any active `.select()`.\n */\n include<TInclude extends IncludeOf<D>>(\n include: TInclude,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { include: TInclude }> {\n this.includeArg = include;\n this.selectArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { include: TInclude }\n >;\n }\n\n /**\n * Merges raw `findMany` args, e.g. `cursor`, `distinct` or a custom `where`.\n * Values that are `undefined` are stripped at any depth, so\n * `custom({ distinct: undefined })` cannot overwrite an earlier value\n * (audit F15). A custom `where` is AND-ed with the `initialArgs` seed and any\n * previous custom `where` — it never replaces them (audit F2). Successive\n * custom `where`s may nest `{ AND: [...] }` groups; Prisma treats that\n * identically.\n */\n custom(args: FindManyArgsOf<D>): this {\n const { where, ...rest } = args as Record<string, unknown>;\n this.customArgs = { ...this.customArgs, ...deepStripUndefined(rest) };\n if (where !== undefined) {\n const cleaned = isPlainObject(where) ? deepStripUndefined(where) : where;\n const hasKeys = !isPlainObject(cleaned) || Object.keys(cleaned).length > 0;\n if (hasKeys) {\n this.customWhere = combineAnd([cleaned as object], this.customWhere);\n }\n }\n return this;\n }\n\n /** The fully assembled `findMany` args. Useful for debugging or reuse. */\n buildArgs(): FindManyArgsOf<D> {\n const args: Record<string, unknown> = { ...this.customArgs };\n\n const where = this.buildWhere();\n if (where) {\n args.where = where;\n }\n if (this.orderByArg) {\n args.orderBy = this.orderByArg;\n }\n if (this.selectArg) {\n args.select = this.selectArg;\n }\n if (this.includeArg) {\n args.include = this.includeArg;\n }\n\n if (this.cursorActive) {\n const cursorArgs = toCursorArgs({\n cursor: this.cursor,\n limit: this.cursorLimit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n });\n args.take = cursorArgs.take;\n if (cursorArgs.cursor) {\n args.cursor = cursorArgs.cursor;\n }\n if (cursorArgs.skip !== undefined) {\n args.skip = cursorArgs.skip;\n }\n } else if (this.limit !== undefined) {\n const page = this.page ?? 1;\n this.assertSkipCap(page, this.limit);\n const offset = toOffsetArgs(page, this.limit);\n args.take = offset.take;\n args.skip = offset.skip;\n }\n\n return args as FindManyArgsOf<D>;\n }\n\n /**\n * Executes the query and returns the rows, typed from `.select()`/`.include()`.\n *\n * Tip: for 100% Prisma-native inference you can always run the passthrough\n * `prisma.user.findMany(qb.buildArgs())` — same args, Prisma's own overloads.\n */\n async execute(): Promise<FindResultOf<D, TArgs>> {\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const data = await findMany(this.buildArgs());\n return data as FindResultOf<D, TArgs>;\n }\n\n /** Executes the query and returns the first row, or `null` when none matched. */\n async first(): Promise<ApplyProjection<RowElementOf<D>, TArgs> | null> {\n const args = { ...(this.buildArgs() as object) } as Record<string, unknown>;\n args.take = 1;\n delete args.skip;\n delete args.cursor;\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const rows = (await findMany(args)) as unknown[];\n const row = rows[0];\n return (row ?? null) as ApplyProjection<RowElementOf<D>, TArgs> | null;\n }\n\n /** Like {@link first}, but throws {@link NoResultError} when nothing matched. */\n async firstOrThrow(): Promise<ApplyProjection<RowElementOf<D>, TArgs>> {\n const row = await this.first();\n if (row === null) {\n throw new NoResultError();\n }\n return row;\n }\n\n /** Counts rows matching the current filters (ignores pagination/projection). */\n async count(): Promise<number> {\n const where = this.buildWhere();\n const countFn = this.delegate.count.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<number>;\n return countFn(where ? { where } : {});\n }\n\n /**\n * Executes the query and returns the rows plus offset pagination metadata.\n * When no pagination was configured, defaults to page 1, limit 10 so `meta`\n * always describes the data actually returned. `count` and `findMany` run in\n * parallel.\n *\n * Pass `{ includeTotal: false }` to skip the `COUNT` query entirely — `meta`\n * then carries `total: null` / `totalPage: null` (audit G3).\n *\n * Throws when cursor pagination is configured — offset meta cannot describe a\n * seek query, and the cursor over-fetch row would leak into `data` (audit F1).\n * Use {@link executeWithCursor} instead.\n */\n async executeWithMeta<O extends { includeTotal?: boolean } = { includeTotal?: boolean }>(\n opts?: O,\n ): Promise<{ meta: MetaOf<O>; data: FindResultOf<D, TArgs> }> {\n if (this.cursorActive) {\n throw new Error(\n 'executeWithMeta() is offset-mode only: this builder has cursor pagination ' +\n 'configured via cursorPaginate(). Use executeWithCursor() instead.',\n );\n }\n if (this.limit === undefined) {\n this.paginate({ page: 1, limit: DEFAULT_PAGE_SIZE });\n }\n // Fail before the COUNT goes out (strictNumbers + skip cap, audit F18).\n this.assertSkipCap(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n const offset = toOffsetArgs(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n\n if (opts?.includeTotal === false) {\n const data = await this.execute();\n return {\n meta: { page: offset.page, limit: offset.limit, total: null, totalPage: null },\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n const [total, data] = await Promise.all([this.count(), this.execute()]);\n\n return {\n meta: buildPaginationMeta(total, offset.page, offset.limit),\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n /**\n * Executes a cursor-paginated query (see {@link cursorPaginate}) and returns\n * the page rows plus `next`/`prev` cursors. Rows are always returned in the\n * configured sort order, regardless of pagination `direction`.\n *\n * Throws when a `.select()` projection drops `cursorField` — the page cursors\n * are derived from that field and would come out as `undefined` (audit F5).\n */\n async executeWithCursor(): Promise<{ meta: CursorMeta; data: FindResultOf<D, TArgs> }> {\n if (!this.cursorActive) {\n this.cursorPaginate({});\n }\n this.assertCursorFieldProjected();\n const limit = this.cursorLimit ?? DEFAULT_PAGE_SIZE;\n const hadCursor = this.cursor !== undefined;\n\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<Record<string, unknown>[]>;\n const rows = await findMany(this.buildArgs());\n\n // Strict mode spends one extra 1-row probe query to make the optimistic\n // opposite edge exact (audit F10 / G9): forward pages probe the row before\n // the cursor, backward pages the row after it. The probe mirrors the main\n // query's `where`/`orderBy` — Prisma positions the cursor within the\n // query's own sort order and filters.\n let exactFlags: ExactCursorFlags | undefined;\n if (this.cursorStrict && hadCursor) {\n const probeArgs: Record<string, unknown> = {\n take: this.cursorDirection === 'forward' ? -1 : 1,\n cursor: { [this.cursorField]: this.cursor },\n skip: 1,\n };\n const where = this.buildWhere();\n if (where) {\n probeArgs.where = where;\n }\n if (this.orderByArg) {\n probeArgs.orderBy = this.orderByArg;\n }\n const probe = await findMany(probeArgs);\n const hasEdgeRow = probe.length > 0;\n exactFlags =\n this.cursorDirection === 'forward'\n ? { hasPrevPage: hasEdgeRow }\n : { hasNextPage: hasEdgeRow };\n }\n\n const { data, meta } = buildCursorPage(rows, {\n limit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n hadCursor,\n exactFlags,\n });\n\n return { meta, data: data as unknown as FindResultOf<D, TArgs> };\n }\n\n /** strictNumbers: out-of-range limits throw instead of clamping (audit F12). */\n private assertLimit(limit: number | undefined): void {\n if (!this.strictNumbers || limit === undefined) {\n return;\n }\n if (!Number.isFinite(limit) || limit < 1 || limit > MAX_PAGE_SIZE) {\n throw new Error(`strictNumbers: limit ${String(limit)} is outside [1, ${MAX_PAGE_SIZE}].`);\n }\n }\n\n private assertPage(page: number | undefined): void {\n if (!this.strictNumbers || page === undefined) {\n return;\n }\n if (!Number.isFinite(page) || page < 1) {\n throw new Error(`strictNumbers: page ${String(page)} must be a finite number >= 1.`);\n }\n }\n\n /** strictNumbers: a computed skip beyond MAX_SKIP throws (audit F18). */\n private assertSkipCap(page: number, limit: number): void {\n if (!this.strictNumbers) {\n return;\n }\n const skip = (clampPage(page) - 1) * clampLimit(limit);\n if (skip > MAX_SKIP) {\n throw new Error(\n `strictNumbers: computed skip ${String(skip)} exceeds the ${String(MAX_SKIP)} cap — ` +\n 'use cursor pagination for deep pages.',\n );\n }\n }\n\n /** A projection without the cursor field would derive cursors from `undefined` (audit F5). */\n private assertCursorFieldProjected(): void {\n // `.custom({ select })` also feeds args.select when no `.select()` ran.\n const select = (this.selectArg ?? this.customArgs.select) as\n Record<string, unknown> | undefined;\n if (select && !select[this.cursorField]) {\n throw new Error(\n `executeWithCursor(): the projection drops cursorField \"${this.cursorField}\", so page ` +\n 'cursors would be built from undefined. Keep the field in .select() or remove the projection.',\n );\n }\n }\n\n private buildWhere(): object | undefined {\n return combineAnd(this.andConditions, this.customWhere);\n }\n}\n"],"mappings":"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","names":["data"]}
1
+ {"version":3,"sources":["../src/core/conditions.ts","../src/core/pagination.ts","../src/dialects/capabilities.ts","../src/dialects/detect.ts","../src/dialects/registry.ts","../src/core/query-builder.ts"],"sourcesContent":["/** Build-time condition assembly helpers used by the QueryBuilder core. */\n\n/**\n * Keys we refuse to write into objects we build: computed-key assignment on\n * `'__proto__'` would set a local prototype instead of an own property\n * (audit F16 — reachable via JSON-parsed request bodies).\n */\nconst DANGEROUS_KEYS: ReadonlySet<string> = new Set(['__proto__', 'constructor', 'prototype']);\n\nfunction isSafeKey(key: string): boolean {\n return !DANGEROUS_KEYS.has(key);\n}\n\n/** Strip `undefined` values so optional query params can be passed directly. */\nexport function stripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value !== undefined && isSafeKey(key)) {\n result[key] = value;\n }\n }\n return result;\n}\n\n/**\n * Recursive {@link stripUndefined}: rebuilds plain objects and arrays of plain\n * objects without `undefined` values at any depth. Values that are not plain\n * objects (Date, BigInt, class instances like Decimal) pass through untouched\n * and the input is never mutated. Used by `.custom()` so a later\n * `custom({ key: undefined })` cannot overwrite an earlier value (audit F15).\n */\nexport function deepStripUndefined(obj: Record<string, unknown>): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (value === undefined || !isSafeKey(key)) {\n continue;\n }\n result[key] = isDeepStrippable(value)\n ? deepStripUndefined(value)\n : Array.isArray(value)\n ? value.map((item) => (isDeepStrippable(item) ? deepStripUndefined(item) : item))\n : value;\n }\n return result;\n}\n\n/** True for objects we may rebuild when deep-stripping (prototype-owned only). */\nfunction isDeepStrippable(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\n/** True for plain objects (not arrays, not null). */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Expand `'avatar.size'` + a leaf value into `{ avatar: { size: leaf } }`.\n * Empty segments are skipped; a path containing a `__proto__`/`constructor`/\n * `prototype` segment expands to `{}` — refused, never written (audit F16).\n */\nexport function expandDotPath(path: string, leaf: unknown): Record<string, unknown> {\n const keys = path.split('.').filter((key) => key.length > 0);\n if (keys.length === 0 || keys.some((key) => !isSafeKey(key))) {\n return {};\n }\n let current: unknown = leaf;\n for (let i = keys.length - 1; i >= 0; i--) {\n const key = keys[i];\n if (key === undefined) {\n continue;\n }\n current = { [key]: current };\n }\n return current as Record<string, unknown>;\n}\n\n/**\n * AND-combine accumulated conditions with an optional seeded `where`.\n * A single condition is returned unwrapped (semantically identical to an\n * `AND` of one); zero conditions yields `undefined` (no `where` at all).\n */\nexport function combineAnd(\n conditions: readonly object[],\n customWhere?: unknown,\n): object | undefined {\n const all: object[] = isPlainObject(customWhere) ? [customWhere, ...conditions] : [...conditions];\n if (all.length === 0) {\n return undefined;\n }\n if (all.length === 1) {\n return all[0];\n }\n return { AND: all };\n}\n","/**\n * Offset (\"skip/take\") and cursor (\"seek\") pagination math — pure functions,\n * fully unit-testable without any database.\n */\nimport type { CursorDirection, CursorMeta, PaginationMeta } from '../types/public';\n\nexport const DEFAULT_PAGE_SIZE = 10;\nexport const MAX_PAGE_SIZE = 1000;\n/** Upper bound for offset `skip` so deep pages cannot hit the DB unbounded (audit F18). */\nexport const MAX_SKIP = 100_000;\n\n/** Clamp a page size to `[1, MAX_PAGE_SIZE]`; non-finite input gets the default. */\nexport function clampLimit(limit: number): number {\n if (!Number.isFinite(limit)) {\n return DEFAULT_PAGE_SIZE;\n }\n return Math.min(Math.max(1, Math.floor(limit)), MAX_PAGE_SIZE);\n}\n\n/** Clamp a 1-based page number; `0`, negatives and NaN all become page 1. */\nexport function clampPage(page: number): number {\n if (!Number.isFinite(page)) {\n return 1;\n }\n return Math.max(1, Math.floor(page));\n}\n\n/** `skip`/`take` for a 1-based page + page size (both clamped, `skip` capped). */\nexport function toOffsetArgs(\n page: number,\n limit: number,\n): { take: number; skip: number; page: number; limit: number } {\n const safePage = clampPage(page);\n const safeLimit = clampLimit(limit);\n const skip = Math.min((safePage - 1) * safeLimit, MAX_SKIP);\n return { take: safeLimit, skip, page: safePage, limit: safeLimit };\n}\n\n/** Offset pagination metadata for a known `total`. */\nexport function buildPaginationMeta(total: number, page: number, limit: number): PaginationMeta {\n const safeLimit = clampLimit(limit);\n const safePage = clampPage(page);\n return {\n page: safePage,\n limit: safeLimit,\n total,\n totalPage: Math.ceil(total / safeLimit),\n };\n}\n\n/**\n * Serialize one cursor value. Dates become ISO-8601 strings so cursors are\n * round-trippable and locale/TZ-independent (audit F4); everything else uses\n * plain string coercion.\n */\nexport function serializeCursorValue(value: unknown): string {\n return value instanceof Date ? value.toISOString() : String(value);\n}\n\n/** Everything needed to turn cursor options into `findMany` args. */\nexport interface CursorPlan {\n cursor?: string | number | Date | undefined;\n limit?: number | undefined;\n direction?: CursorDirection;\n cursorField: string;\n}\n\n/**\n * `take`/`cursor`/`skip` for seek pagination:\n * - over-fetches one row (`±(limit + 1)`) to detect the next/previous page,\n * - negative `take` walks backwards,\n * - `skip: 1` excludes the cursor row itself.\n * The cursor value is passed through raw — Prisma accepts strings, numbers\n * and Dates for the cursor field.\n */\nexport function toCursorArgs(plan: CursorPlan): {\n take: number;\n cursor?: Record<string, unknown>;\n skip?: number;\n} {\n const sign = plan.direction === 'backward' ? -1 : 1;\n const take = sign * (clampLimit(plan.limit ?? DEFAULT_PAGE_SIZE) + 1);\n if (plan.cursor === undefined) {\n return { take };\n }\n return {\n take,\n cursor: { [plan.cursorField]: plan.cursor },\n skip: 1,\n };\n}\n\n/** Exact edge flags from a strict-mode probe query (audit F10). */\nexport interface ExactCursorFlags {\n hasNextPage?: boolean | undefined;\n hasPrevPage?: boolean | undefined;\n}\n\n/** Inputs for interpreting an over-fetched cursor page. */\nexport interface CursorPageInfo {\n limit: number;\n direction: CursorDirection;\n cursorField: string;\n /** Whether a cursor was supplied (i.e. this is not the first page). */\n hadCursor: boolean;\n /**\n * Probe-derived flags (strict mode); each entry replaces the optimistic\n * approximation for that edge (audit F10 / G9).\n */\n exactFlags?: ExactCursorFlags | undefined;\n}\n\n/**\n * Slice an over-fetched result set into the page + cursor metadata. Rows are\n * always returned in the configured sort order regardless of `direction`.\n */\nexport function buildCursorPage<T extends Record<string, unknown>>(\n rows: T[],\n info: CursorPageInfo,\n): { data: T[]; meta: CursorMeta } {\n const { limit, direction, cursorField, hadCursor, exactFlags } = info;\n const safeLimit = clampLimit(limit);\n\n const hasExtra = rows.length > safeLimit;\n const pageRows = hasExtra ? rows.slice(0, safeLimit) : rows;\n const ordered = direction === 'backward' ? [...pageRows].reverse() : pageRows;\n\n const hasRows = rows.length > 0;\n const hasNextPage =\n exactFlags?.hasNextPage ?? (direction === 'forward' ? hasExtra : hadCursor && hasRows);\n const hasPrevPage =\n exactFlags?.hasPrevPage ?? (direction === 'backward' ? hasExtra : hadCursor && hasRows);\n\n const first = ordered[0];\n const last = ordered[ordered.length - 1];\n\n return {\n data: ordered,\n meta: {\n limit: safeLimit,\n nextCursor:\n hasNextPage && last !== undefined ? serializeCursorValue(last[cursorField]) : null,\n prevCursor:\n hasPrevPage && first !== undefined ? serializeCursorValue(first[cursorField]) : null,\n hasNextPage,\n hasPrevPage,\n },\n };\n}\n","/**\n * Per-database capability sets (ARCHITECTURE.md, invariant 4).\n *\n * Prisma-supported databases disagree on filter operators — most importantly,\n * `mode: 'insensitive'` is only accepted on PostgreSQL, CockroachDB and MongoDB,\n * and *throws* on MySQL, MariaDB, SQLite and SQL Server. Capability records let\n * every builder method ask \"what is allowed here?\" instead of hardcoding\n * database names.\n */\nexport interface DialectCapabilities {\n /**\n * Prisma accepts `mode: 'insensitive'` on string filters for this dialect\n * (postgresql, cockroachdb, mongodb).\n */\n caseInsensitiveMode: boolean;\n /**\n * The database's default collation makes `contains` case-insensitive without\n * any extra argument (mysql, mariadb, sqlserver). For sqlite this is `false`:\n * ASCII `LIKE` is case-sensitive there, and Prisma offers no `mode`.\n */\n caseInsensitiveCollation: boolean;\n}\n\n/** Built-in capability sets, one per database Prisma supports (plus universal). */\nexport const DIALECT_CAPABILITIES = {\n postgresql: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n cockroachdb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n mysql: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mariadb: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n sqlite: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n sqlserver: { caseInsensitiveMode: false, caseInsensitiveCollation: true },\n mongodb: { caseInsensitiveMode: true, caseInsensitiveCollation: false },\n /**\n * Fallback used when no dialect is configured/detected. Only emits arguments\n * that are valid on EVERY Prisma-supported database.\n */\n universal: { caseInsensitiveMode: false, caseInsensitiveCollation: false },\n} satisfies Record<string, DialectCapabilities>;\n\n/** Names of the built-in dialects. */\nexport type Dialect = keyof typeof DIALECT_CAPABILITIES;\n","import type { Dialect } from './capabilities';\n\n/**\n * Best-effort dialect auto-detection (M2 scope).\n *\n * v0 intentionally detects nothing and returns `undefined` → callers fall\n * through to `'universal'`, which never emits an invalid argument on any\n * database. Future heuristics (guarded property sniffing of the Prisma client)\n * must keep the same contract: NEVER throw, NEVER guess wrong loudly — an\n * unknown dialect must degrade to `'universal'`, not to a wrong guess.\n *\n * Users who know their database should prefer explicit configuration:\n * configQueryBuilder({ dialect: 'postgresql' })\n * or per builder:\n * new QueryBuilder(prisma.user, { dialect: 'mongodb' })\n */\nexport function detectDialect(): Dialect | undefined {\n return undefined;\n}\n","import { DIALECT_CAPABILITIES } from './capabilities';\nimport type { DialectCapabilities } from './capabilities';\nimport { detectDialect } from './detect';\n\n/*\n * Dialect registry (ARCHITECTURE.md, invariant 4).\n *\n * Resolution order (fails soft to 'universal', which is always valid):\n * 1. explicit per-builder override new QueryBuilder(prisma.user, { dialect: 'mysql' })\n * 2. global config configQueryBuilder({ dialect: 'postgresql' })\n * 3. registered auto-detector setDialectDetector(fn)\n * 4. built-in detector detectDialect() (no-op in v0 — audit G2)\n * 5. 'universal'\n */\n\n/** Mutable dialect state, shared via `globalThis` (audit F7). */\ninterface DialectState {\n registry: Map<string, DialectCapabilities>;\n globalDialect: string | undefined;\n detector: (() => string | undefined) | undefined;\n}\n\n/**\n * The state lives on `globalThis` under a registered symbol so ESM and CJS\n * copies of this package converge on ONE config — a bundler loading both\n * variants can no longer split the global dialect config (dual-package hazard,\n * audit F7). This is the only mutable module-adjacent state in the package;\n * prefer the per-builder `dialect` option anyway.\n */\nconst STATE_KEY = Symbol.for('query-builder-prisma.dialect-state');\n\nfunction state(): DialectState {\n const host = globalThis as typeof globalThis & { [STATE_KEY]?: DialectState };\n return (host[STATE_KEY] ??= {\n registry: new Map(Object.entries(DIALECT_CAPABILITIES) as [string, DialectCapabilities][]),\n globalDialect: undefined,\n detector: undefined,\n });\n}\n\n/**\n * Register capabilities for a database - including ones Prisma adds in the\n * future. No core code changes are ever required to support a new dialect.\n */\nexport function registerDialect(name: string, capabilities: DialectCapabilities): void {\n state().registry.set(name, capabilities);\n}\n\n/** Set the global default dialect for all builders that do not override it. */\nexport function configQueryBuilder(options: { dialect?: string | undefined }): void {\n state().globalDialect = options.dialect;\n}\n\n/**\n * Plug in an auto-detector (best-effort). It must never throw; an undefined\n * result simply falls through to the built-in detector and then 'universal'.\n */\nexport function setDialectDetector(detector: () => string | undefined): void {\n state().detector = detector;\n}\n\n/** A dialect name plus the capabilities resolved for it. */\nexport interface ResolvedDialect {\n name: string;\n capabilities: DialectCapabilities;\n}\n\n/**\n * Resolve the active dialect per the documented precedence. An unregistered\n * name resolves to `'universal'` — the reported name never lies about the\n * capabilities actually applied (audit G8).\n */\nexport function resolveDialect(explicit?: string | undefined): ResolvedDialect {\n const s = state();\n const requested = explicit ?? s.globalDialect ?? s.detector?.() ?? detectDialect() ?? 'universal';\n const capabilities = s.registry.get(requested);\n return capabilities\n ? { name: requested, capabilities }\n : { name: 'universal', capabilities: DIALECT_CAPABILITIES.universal };\n}\n\n/** Test helper: reset global configuration (registry entries are kept). */\nexport function resetDialectConfig(): void {\n const s = state();\n s.globalDialect = undefined;\n s.detector = undefined;\n}\n","import type {\n FindManyArgsOf,\n IncludeOf,\n OrderByOf,\n OrderKeyOf,\n PrismaModelDelegate,\n RowElementOf,\n SelectOf,\n WhereKeyOf,\n WhereOf,\n} from '../types/delegate';\nimport type { ApplyProjection, FindResultOf } from '../types/projection';\nimport type {\n CursorDirection,\n CursorMeta,\n FilterInput,\n PaginationMeta,\n PaginationMetaNoTotal,\n RangeBound,\n RangeInput,\n SortOrder,\n} from '../types/public';\nimport {\n combineAnd,\n deepStripUndefined,\n expandDotPath,\n isPlainObject,\n stripUndefined,\n} from './conditions';\nimport {\n buildCursorPage,\n buildPaginationMeta,\n clampLimit,\n clampPage,\n toCursorArgs,\n toOffsetArgs,\n DEFAULT_PAGE_SIZE,\n MAX_PAGE_SIZE,\n MAX_SKIP,\n} from './pagination';\nimport type { ExactCursorFlags } from './pagination';\nimport { resolveDialect } from '../dialects/registry';\nimport type { Dialect } from '../dialects/capabilities';\n\n/** Options accepted by the {@link QueryBuilder} constructor. */\nexport interface QueryBuilderOptions<D extends PrismaModelDelegate> {\n /** Seed `findMany` args, e.g. `{ where: { deletedAt: null } }` (prepended to every `where`). */\n initialArgs?: FindManyArgsOf<D> | undefined;\n /**\n * Per-builder dialect override. When omitted: global `configQueryBuilder()`\n * config → registered auto-detector → `'universal'` (always-valid args).\n */\n dialect?: Dialect | undefined;\n /**\n * Throw on out-of-range pagination input instead of clamping silently:\n * limits outside `[1, 1000]`, pages below 1, or a computed `skip` beyond\n * `MAX_SKIP` (audits F12 / F18). Defaults to clamping.\n */\n strictNumbers?: boolean | undefined;\n}\n\n/** Meta type of {@link QueryBuilder.executeWithMeta} for the given options. */\ntype MetaOf<O extends { includeTotal?: boolean }> = O['includeTotal'] extends false\n ? PaginationMetaNoTotal\n : PaginationMeta;\n\n/** Thrown by {@link QueryBuilder.firstOrThrow} when no row matched. */\nexport class NoResultError extends Error {\n constructor() {\n super('Query returned no rows');\n this.name = 'NoResultError';\n }\n}\n\n/**\n * Generic, reusable and fully type-safe query builder for any Prisma model\n * delegate, on every Prisma version (see ARCHITECTURE.md).\n *\n * All option types (`where`, `select`, `include`, `orderBy`, ...) are inferred\n * structurally from the delegate passed to the constructor — nothing is imported\n * from Prisma, so no Prisma upgrade can ever break this class.\n *\n * The result type of `execute()` is narrowed by `.select()` / `.include()` via a\n * structural projection engine, mirroring Prisma's own behaviour.\n *\n * @typeParam D - The Prisma model delegate, e.g. `typeof prisma.user`.\n * @typeParam TArgs - Accumulated `findMany` args. Defaults to no projection.\n *\n * @example\n * const result = await new QueryBuilder(prisma.user)\n * .search({ searchText, fields: ['email', 'username'] })\n * .filter({ role, status })\n * .range({ createdAt: { from, to }, 'avatar.size': { from: min, to: max } })\n * .sortBy({ sortBy: 'createdAt', sortOrder: 'desc' })\n * .paginate({ page: 1, limit: 10 })\n * .select({ id: true, email: true })\n * .execute();\n */\nexport class QueryBuilder<D extends PrismaModelDelegate, TArgs = object> {\n private readonly delegate: D;\n private readonly dialect: Dialect | undefined;\n private readonly strictNumbers: boolean;\n private readonly andConditions: object[] = [];\n private customArgs: Record<string, unknown> = {};\n /**\n * The `initialArgs` seed `where` plus every `.custom({ where })`, AND-merged.\n * Kept out of `customArgs` so a later `.custom({ where })` merges with the\n * seed instead of replacing it (audit F2 — the seed carries safety filters).\n */\n private customWhere: unknown;\n private orderByArg: object | undefined;\n private selectArg: object | undefined;\n private includeArg: object | undefined;\n private page: number | undefined;\n private limit: number | undefined;\n private cursorActive = false;\n private cursor: string | number | Date | undefined;\n private cursorLimit: number | undefined;\n private cursorDirection: CursorDirection = 'forward';\n private cursorField: string = 'id';\n private cursorStrict = false;\n\n /**\n * @param delegate - The Prisma delegate to query (e.g. `prisma.user`).\n * @param options - Optional seed args, a dialect override, or `strictNumbers`.\n */\n constructor(delegate: D, options?: QueryBuilderOptions<D>) {\n this.delegate = delegate;\n this.dialect = options?.dialect;\n this.strictNumbers = options?.strictNumbers ?? false;\n if (options?.initialArgs) {\n const { where, ...rest } = options.initialArgs as Record<string, unknown>;\n this.customArgs = { ...rest };\n this.customWhere = where;\n }\n }\n\n /**\n * Case-insensitive `contains` across the provided string fields. No condition\n * is added when `searchText` is empty or whitespace-only (audit G7).\n *\n * Dialect-aware: adds `mode: 'insensitive'` only where Prisma accepts it (see\n * `caseInsensitiveMode` in `src/dialects/capabilities.ts`); everywhere else\n * the bare `contains` relies on the database's collation, and where that is\n * ASCII-only matching stays case-sensitive — Prisma offers no alternative\n * there.\n */\n search(params: { searchText?: string | undefined; fields: WhereKeyOf<D>[] }): this {\n const text = params.searchText?.trim();\n const fields = params.fields;\n if (text && fields.length > 0) {\n const { capabilities } = resolveDialect(this.dialect);\n this.andConditions.push({\n OR: fields.map((field) => {\n // One match object per arm — never a shared reference (audit F13).\n const match: Record<string, unknown> = { contains: text };\n if (capabilities.caseInsensitiveMode) {\n match.mode = 'insensitive';\n }\n return { [field]: match };\n }),\n });\n }\n return this;\n }\n\n /**\n * Adds an equality/operator filter. Accepts a partial Prisma `where` object;\n * `undefined` values are ignored so optional query params are safe to pass.\n */\n filter(filters: FilterInput<D>): this {\n const cleaned = stripUndefined(filters);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Adds `gte`/`lte` range conditions. Keys may be dot-paths to reach relations\n * or nested objects (e.g. `'avatar.size'`). Bounds left `undefined` are\n * skipped; a field is only added when at least one bound is present.\n */\n range(ranges: Record<string, RangeInput>): this {\n for (const [path, bound] of Object.entries(ranges)) {\n const condition: Record<string, RangeBound> = {};\n if (bound.from !== undefined) {\n condition.gte = bound.from;\n }\n if (bound.to !== undefined) {\n condition.lte = bound.to;\n }\n if (Object.keys(condition).length > 0) {\n const expanded = expandDotPath(path, condition);\n if (Object.keys(expanded).length > 0) {\n this.andConditions.push(expanded);\n }\n }\n }\n return this;\n }\n\n /** Adds an arbitrary, fully-typed Prisma `where` condition. */\n where(condition: WhereOf<D>): this {\n const cleaned = stripUndefined(condition as Record<string, unknown>);\n if (Object.keys(cleaned).length > 0) {\n this.andConditions.push(cleaned);\n }\n return this;\n }\n\n /**\n * Sets `orderBy` from a single key. No-op when `sortBy` is not provided.\n * Dot paths expand like `.range()` (`'avatar.size'` → `{ avatar: { size } }`,\n * audit F6). For multi-key or nested relation sorts use {@link orderBy}.\n */\n sortBy(params: { sortBy?: OrderKeyOf<D> | (string & {}); sortOrder?: SortOrder }): this {\n const { sortBy, sortOrder = 'desc' } = params;\n if (sortBy) {\n const expanded = expandDotPath(sortBy, sortOrder);\n if (Object.keys(expanded).length > 0) {\n this.orderByArg = expanded;\n }\n }\n return this;\n }\n\n /**\n * Sets `orderBy` verbatim from the full Prisma shape: arrays for multi-key\n * sorts, nested relation order objects. `.sortBy()` remains the single-key\n * convenience — the latest of the two calls wins (audit G1).\n */\n orderBy(order: OrderByOf<D>): this {\n this.orderByArg = order as object;\n return this;\n }\n\n /** Configures `skip`/`take` from a 1-based page number and page size. */\n paginate(params: { page?: number; limit?: number }): this {\n this.assertPage(params.page);\n this.assertLimit(params.limit);\n this.page = params.page ?? 1;\n this.limit = params.limit ?? DEFAULT_PAGE_SIZE;\n return this;\n }\n\n /**\n * Configures cursor-based (\"seek\") pagination. Use {@link executeWithCursor}\n * to run the query and obtain `next`/`prev` cursors.\n *\n * - `cursor` is the value of `cursorField` from the edge row of the previous\n * page (omit it for the first page). Strings, numbers and Dates are\n * accepted; Dates serialize to ISO-8601 in the returned cursors (audit F4).\n * - `direction` walks `'forward'` (next) or `'backward'` (previous).\n * - `cursorField` is the unique, sequential column to seek on (default `id`).\n * Pair it with a matching {@link sortBy} for stable ordering.\n * - `strict` spends one extra 1-row probe query to make `hasNextPage` /\n * `hasPrevPage` exact instead of optimistic (audit F10).\n *\n * Takes precedence over {@link paginate} when both are set.\n */\n cursorPaginate(params: {\n cursor?: string | number | Date | undefined;\n limit?: number;\n direction?: CursorDirection;\n cursorField?: OrderKeyOf<D> | (string & {});\n strict?: boolean;\n }): this {\n this.assertLimit(params.limit);\n this.cursorActive = true;\n this.cursor = params.cursor;\n this.cursorLimit = params.limit;\n this.cursorDirection = params.direction ?? 'forward';\n this.cursorField = params.cursorField ?? 'id';\n this.cursorStrict = params.strict ?? false;\n return this;\n }\n\n /**\n * Projects fields with Prisma `select`. The result type of `execute()` is\n * narrowed to exactly the selected shape. Clears any active `.include()`.\n */\n select<TSelect extends SelectOf<D>>(\n select: TSelect,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { select: TSelect }> {\n this.selectArg = select;\n this.includeArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { select: TSelect }\n >;\n }\n\n /**\n * Eager-loads relations with Prisma `include`. The result type of `execute()`\n * is widened with the included relations. Clears any active `.select()`.\n */\n include<TInclude extends IncludeOf<D>>(\n include: TInclude,\n ): QueryBuilder<D, Omit<TArgs, 'select' | 'include'> & { include: TInclude }> {\n this.includeArg = include;\n this.selectArg = undefined;\n return this as unknown as QueryBuilder<\n D,\n Omit<TArgs, 'select' | 'include'> & { include: TInclude }\n >;\n }\n\n /**\n * Merges raw `findMany` args, e.g. `cursor`, `distinct` or a custom `where`.\n * Values that are `undefined` are stripped at any depth, so\n * `custom({ distinct: undefined })` cannot overwrite an earlier value\n * (audit F15). A custom `where` is AND-ed with the `initialArgs` seed and any\n * previous custom `where` — it never replaces them (audit F2). Successive\n * custom `where`s may nest `{ AND: [...] }` groups; Prisma treats that\n * identically.\n */\n custom(args: FindManyArgsOf<D>): this {\n const { where, ...rest } = args as Record<string, unknown>;\n this.customArgs = { ...this.customArgs, ...deepStripUndefined(rest) };\n if (where !== undefined) {\n const cleaned = isPlainObject(where) ? deepStripUndefined(where) : where;\n const hasKeys = !isPlainObject(cleaned) || Object.keys(cleaned).length > 0;\n if (hasKeys) {\n this.customWhere = combineAnd([cleaned as object], this.customWhere);\n }\n }\n return this;\n }\n\n /** The fully assembled `findMany` args. Useful for debugging or reuse. */\n buildArgs(): FindManyArgsOf<D> {\n const args: Record<string, unknown> = { ...this.customArgs };\n\n const where = this.buildWhere();\n if (where) {\n args.where = where;\n }\n if (this.orderByArg) {\n args.orderBy = this.orderByArg;\n }\n if (this.selectArg) {\n args.select = this.selectArg;\n }\n if (this.includeArg) {\n args.include = this.includeArg;\n }\n\n if (this.cursorActive) {\n const cursorArgs = toCursorArgs({\n cursor: this.cursor,\n limit: this.cursorLimit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n });\n args.take = cursorArgs.take;\n if (cursorArgs.cursor) {\n args.cursor = cursorArgs.cursor;\n }\n if (cursorArgs.skip !== undefined) {\n args.skip = cursorArgs.skip;\n }\n } else if (this.limit !== undefined) {\n const page = this.page ?? 1;\n this.assertSkipCap(page, this.limit);\n const offset = toOffsetArgs(page, this.limit);\n args.take = offset.take;\n args.skip = offset.skip;\n }\n\n return args as FindManyArgsOf<D>;\n }\n\n /**\n * Executes the query and returns the rows, typed from `.select()`/`.include()`.\n *\n * Tip: for 100% Prisma-native inference you can always run the passthrough\n * `prisma.user.findMany(qb.buildArgs())` — same args, Prisma's own overloads.\n */\n async execute(): Promise<FindResultOf<D, TArgs>> {\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const data = await findMany(this.buildArgs());\n return data as FindResultOf<D, TArgs>;\n }\n\n /** Executes the query and returns the first row, or `null` when none matched. */\n async first(): Promise<ApplyProjection<RowElementOf<D>, TArgs> | null> {\n const args = { ...(this.buildArgs() as object) } as Record<string, unknown>;\n args.take = 1;\n delete args.skip;\n delete args.cursor;\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<unknown>;\n const rows = (await findMany(args)) as unknown[];\n const row = rows[0];\n return (row ?? null) as ApplyProjection<RowElementOf<D>, TArgs> | null;\n }\n\n /** Like {@link first}, but throws {@link NoResultError} when nothing matched. */\n async firstOrThrow(): Promise<ApplyProjection<RowElementOf<D>, TArgs>> {\n const row = await this.first();\n if (row === null) {\n throw new NoResultError();\n }\n return row;\n }\n\n /** Counts rows matching the current filters (ignores pagination/projection). */\n async count(): Promise<number> {\n const where = this.buildWhere();\n const countFn = this.delegate.count.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<number>;\n return countFn(where ? { where } : {});\n }\n\n /**\n * Executes the query and returns the rows plus offset pagination metadata.\n * When no pagination was configured, defaults to page 1, limit 10 so `meta`\n * always describes the data actually returned. `count` and `findMany` run in\n * parallel.\n *\n * Pass `{ includeTotal: false }` to skip the `COUNT` query entirely — `meta`\n * then carries `total: null` / `totalPage: null` (audit G3).\n *\n * Throws when cursor pagination is configured — offset meta cannot describe a\n * seek query, and the cursor over-fetch row would leak into `data` (audit F1).\n * Use {@link executeWithCursor} instead.\n */\n async executeWithMeta<O extends { includeTotal?: boolean } = { includeTotal?: boolean }>(\n opts?: O,\n ): Promise<{ meta: MetaOf<O>; data: FindResultOf<D, TArgs> }> {\n if (this.cursorActive) {\n throw new Error(\n 'executeWithMeta() is offset-mode only: this builder has cursor pagination ' +\n 'configured via cursorPaginate(). Use executeWithCursor() instead.',\n );\n }\n if (this.limit === undefined) {\n this.paginate({ page: 1, limit: DEFAULT_PAGE_SIZE });\n }\n // Fail before the COUNT goes out (strictNumbers + skip cap, audit F18).\n this.assertSkipCap(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n const offset = toOffsetArgs(this.page ?? 1, this.limit ?? DEFAULT_PAGE_SIZE);\n\n if (opts?.includeTotal === false) {\n const data = await this.execute();\n return {\n meta: { page: offset.page, limit: offset.limit, total: null, totalPage: null },\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n const [total, data] = await Promise.all([this.count(), this.execute()]);\n\n return {\n meta: buildPaginationMeta(total, offset.page, offset.limit),\n data,\n } as { meta: MetaOf<O>; data: FindResultOf<D, TArgs> };\n }\n\n /**\n * Executes a cursor-paginated query (see {@link cursorPaginate}) and returns\n * the page rows plus `next`/`prev` cursors. Rows are always returned in the\n * configured sort order, regardless of pagination `direction`.\n *\n * Throws when a `.select()` projection drops `cursorField` — the page cursors\n * are derived from that field and would come out as `undefined` (audit F5).\n */\n async executeWithCursor(): Promise<{ meta: CursorMeta; data: FindResultOf<D, TArgs> }> {\n if (!this.cursorActive) {\n this.cursorPaginate({});\n }\n this.assertCursorFieldProjected();\n const limit = this.cursorLimit ?? DEFAULT_PAGE_SIZE;\n const hadCursor = this.cursor !== undefined;\n\n const findMany = this.delegate.findMany.bind(this.delegate) as unknown as (\n args: object,\n ) => Promise<Record<string, unknown>[]>;\n const rows = await findMany(this.buildArgs());\n\n // Strict mode spends one extra 1-row probe query to make the optimistic\n // opposite edge exact (audit F10 / G9): forward pages probe the row before\n // the cursor, backward pages the row after it. The probe mirrors the main\n // query's `where`/`orderBy` — Prisma positions the cursor within the\n // query's own sort order and filters.\n let exactFlags: ExactCursorFlags | undefined;\n if (this.cursorStrict && hadCursor) {\n const probeArgs: Record<string, unknown> = {\n take: this.cursorDirection === 'forward' ? -1 : 1,\n cursor: { [this.cursorField]: this.cursor },\n skip: 1,\n };\n const where = this.buildWhere();\n if (where) {\n probeArgs.where = where;\n }\n if (this.orderByArg) {\n probeArgs.orderBy = this.orderByArg;\n }\n const probe = await findMany(probeArgs);\n const hasEdgeRow = probe.length > 0;\n exactFlags =\n this.cursorDirection === 'forward'\n ? { hasPrevPage: hasEdgeRow }\n : { hasNextPage: hasEdgeRow };\n }\n\n const { data, meta } = buildCursorPage(rows, {\n limit,\n direction: this.cursorDirection,\n cursorField: this.cursorField,\n hadCursor,\n exactFlags,\n });\n\n return { meta, data: data as unknown as FindResultOf<D, TArgs> };\n }\n\n /** strictNumbers: out-of-range limits throw instead of clamping (audit F12). */\n private assertLimit(limit: number | undefined): void {\n if (!this.strictNumbers || limit === undefined) {\n return;\n }\n if (!Number.isFinite(limit) || limit < 1 || limit > MAX_PAGE_SIZE) {\n throw new Error(`strictNumbers: limit ${String(limit)} is outside [1, ${MAX_PAGE_SIZE}].`);\n }\n }\n\n private assertPage(page: number | undefined): void {\n if (!this.strictNumbers || page === undefined) {\n return;\n }\n if (!Number.isFinite(page) || page < 1) {\n throw new Error(`strictNumbers: page ${String(page)} must be a finite number >= 1.`);\n }\n }\n\n /** strictNumbers: a computed skip beyond MAX_SKIP throws (audit F18). */\n private assertSkipCap(page: number, limit: number): void {\n if (!this.strictNumbers) {\n return;\n }\n const skip = (clampPage(page) - 1) * clampLimit(limit);\n if (skip > MAX_SKIP) {\n throw new Error(\n `strictNumbers: computed skip ${String(skip)} exceeds the ${String(MAX_SKIP)} cap — ` +\n 'use cursor pagination for deep pages.',\n );\n }\n }\n\n /** A projection without the cursor field would derive cursors from `undefined` (audit F5). */\n private assertCursorFieldProjected(): void {\n // `.custom({ select })` also feeds args.select when no `.select()` ran.\n const select = (this.selectArg ?? this.customArgs.select) as\n Record<string, unknown> | undefined;\n if (select && !select[this.cursorField]) {\n throw new Error(\n `executeWithCursor(): the projection drops cursorField \"${this.cursorField}\", so page ` +\n 'cursors would be built from undefined. Keep the field in .select() or remove the projection.',\n );\n }\n }\n\n private buildWhere(): object | undefined {\n return combineAnd(this.andConditions, this.customWhere);\n }\n}\n"],"mappings":"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","names":["data"]}
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "query-builder-prisma",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Zero-coupling, fluent, fully type-safe query builder for any Prisma model delegate. Works with every Prisma version (5+, by design all versions) and every database Prisma supports.",
5
5
  "license": "MIT",
6
6
  "author": "Mamun",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/almamun2b/prisma-query-builder.git"
9
+ "url": "git+https://github.com/almamun2b/query-builder-prisma.git"
10
10
  },
11
- "homepage": "https://github.com/almamun2b/prisma-query-builder#readme",
11
+ "homepage": "https://github.com/almamun2b/query-builder-prisma#readme",
12
12
  "bugs": {
13
- "url": "https://github.com/almamun2b/prisma-query-builder/issues"
13
+ "url": "https://github.com/almamun2b/query-builder-prisma/issues"
14
14
  },
15
15
  "keywords": [
16
16
  "prisma",