turbine-orm 0.49.0 → 0.50.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 +122 -39
- package/dist/cjs/adapters/cockroachdb.d.ts +39 -0
- package/dist/cjs/adapters/index.d.ts +110 -0
- package/dist/cjs/adapters/yugabytedb.d.ts +51 -0
- package/dist/cjs/cli/config.d.ts +181 -0
- package/dist/cjs/cli/config.js +32 -6
- package/dist/cjs/cli/destructive.d.ts +38 -0
- package/dist/cjs/cli/index.d.ts +359 -0
- package/dist/cjs/cli/index.js +228 -56
- package/dist/cjs/cli/loader.d.ts +61 -0
- package/dist/cjs/cli/mcp.d.ts +42 -0
- package/dist/cjs/cli/migrate.d.ts +356 -0
- package/dist/cjs/cli/migrate.js +131 -40
- package/dist/cjs/cli/observe-ui.d.ts +1 -0
- package/dist/cjs/cli/observe-ui.js +14 -5
- package/dist/cjs/cli/observe.d.ts +25 -0
- package/dist/cjs/cli/observe.js +49 -12
- package/dist/cjs/cli/pii-tags.d.ts +53 -0
- package/dist/cjs/cli/prisma-report.d.ts +33 -0
- package/dist/cjs/cli/prisma-report.js +73 -0
- package/dist/cjs/cli/prisma-resolve.d.ts +106 -0
- package/dist/cjs/cli/prisma-resolve.js +1 -0
- package/dist/cjs/cli/prisma-schema.d.ts +176 -0
- package/dist/cjs/cli/prisma-schema.js +82 -4
- package/dist/cjs/cli/rate-limit.d.ts +32 -0
- package/dist/cjs/cli/rate-limit.js +45 -0
- package/dist/cjs/cli/studio-demo.d.ts +43 -0
- package/dist/cjs/cli/studio-ui.generated.d.ts +1 -0
- package/dist/cjs/cli/studio.d.ts +207 -0
- package/dist/cjs/cli/studio.js +136 -71
- package/dist/cjs/cli/ui.d.ts +73 -0
- package/dist/cjs/cli/ui.js +51 -9
- package/dist/cjs/client.d.ts +837 -0
- package/dist/cjs/client.js +3 -0
- package/dist/cjs/dialect.d.ts +516 -0
- package/dist/cjs/dialect.js +37 -12
- package/dist/cjs/errors.d.ts +370 -0
- package/dist/cjs/generate.d.ts +137 -0
- package/dist/cjs/generate.js +39 -6
- package/dist/cjs/index-advisor.d.ts +153 -0
- package/dist/cjs/index-stats.d.ts +384 -0
- package/dist/cjs/index.d.ts +55 -0
- package/dist/cjs/index.js +7 -2
- package/dist/cjs/introspect.d.ts +269 -0
- package/dist/cjs/mssql.d.ts +232 -0
- package/dist/cjs/mssql.js +6 -0
- package/dist/cjs/mysql.d.ts +173 -0
- package/dist/cjs/mysql.js +16 -0
- package/dist/cjs/nested-write.d.ts +96 -0
- package/dist/cjs/nested-write.js +414 -24
- package/dist/cjs/observe.d.ts +115 -0
- package/dist/cjs/optional-peer-import.d.cts +72 -0
- package/dist/cjs/pipeline-submittable.d.ts +93 -0
- package/dist/cjs/pipeline.d.ts +71 -0
- package/dist/cjs/powdb-introspect.d.ts +84 -0
- package/dist/cjs/powdb.d.ts +931 -0
- package/dist/cjs/powdb.js +106 -21
- package/dist/cjs/powql.d.ts +592 -0
- package/dist/cjs/powql.js +42 -6
- package/dist/cjs/prisma-compat.d.ts +283 -0
- package/dist/cjs/prisma-compat.js +167 -9
- package/dist/cjs/query/aggregates.d.ts +92 -0
- package/dist/cjs/query/aggregates.js +7 -3
- package/dist/cjs/query/batched-loader.d.ts +193 -0
- package/dist/cjs/query/builder.d.ts +849 -0
- package/dist/cjs/query/builder.js +571 -65
- package/dist/cjs/query/compound-unique.d.ts +51 -0
- package/dist/cjs/query/deferred.d.ts +223 -0
- package/dist/cjs/query/filters.d.ts +201 -0
- package/dist/cjs/query/index.d.ts +14 -0
- package/dist/cjs/query/index.js +6 -1
- package/dist/cjs/query/relations.d.ts +609 -0
- package/dist/cjs/query/relations.js +693 -46
- package/dist/cjs/query/types.d.ts +1300 -0
- package/dist/cjs/query/utils.d.ts +209 -0
- package/dist/cjs/query/utils.js +208 -1
- package/dist/cjs/query/warn-registry.d.ts +68 -0
- package/dist/cjs/query/warn-registry.js +9 -0
- package/dist/cjs/query/where-compile.d.ts +139 -0
- package/dist/cjs/query/where.d.ts +548 -0
- package/dist/cjs/query/where.js +58 -22
- package/dist/cjs/query/writes.d.ts +172 -0
- package/dist/cjs/query/writes.js +105 -12
- package/dist/cjs/realtime.d.ts +70 -0
- package/dist/cjs/schema-builder.d.ts +354 -0
- package/dist/cjs/schema-metadata.d.ts +83 -0
- package/dist/cjs/schema-sql.d.ts +217 -0
- package/dist/cjs/schema-sql.js +23 -5
- package/dist/cjs/schema.d.ts +356 -0
- package/dist/cjs/schema.js +125 -0
- package/dist/cjs/seed.d.ts +15 -0
- package/dist/cjs/serverless.d.ts +142 -0
- package/dist/cjs/sqlite.d.ts +143 -0
- package/dist/cjs/sqlite.js +4 -0
- package/dist/cjs/typed-sql.d.ts +102 -0
- package/dist/cli/config.d.ts +18 -4
- package/dist/cli/config.js +31 -6
- package/dist/cli/index.d.ts +123 -0
- package/dist/cli/index.js +223 -58
- package/dist/cli/migrate.d.ts +59 -10
- package/dist/cli/migrate.js +128 -41
- package/dist/cli/observe-ui.d.ts +1 -1
- package/dist/cli/observe-ui.js +14 -5
- package/dist/cli/observe.d.ts +7 -1
- package/dist/cli/observe.js +48 -12
- package/dist/cli/prisma-report.d.ts +14 -0
- package/dist/cli/prisma-report.js +72 -0
- package/dist/cli/prisma-resolve.d.ts +6 -0
- package/dist/cli/prisma-resolve.js +1 -0
- package/dist/cli/prisma-schema.d.ts +62 -2
- package/dist/cli/prisma-schema.js +81 -4
- package/dist/cli/rate-limit.d.ts +32 -0
- package/dist/cli/rate-limit.js +40 -0
- package/dist/cli/studio.d.ts +5 -5
- package/dist/cli/studio.js +135 -70
- package/dist/cli/ui.d.ts +1 -1
- package/dist/cli/ui.js +51 -9
- package/dist/client.d.ts +40 -0
- package/dist/client.js +3 -0
- package/dist/dialect.d.ts +17 -1
- package/dist/dialect.js +37 -12
- package/dist/generate.js +40 -7
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mssql.js +6 -0
- package/dist/mysql.js +16 -0
- package/dist/nested-write.d.ts +2 -0
- package/dist/nested-write.js +415 -25
- package/dist/powdb.d.ts +4 -2
- package/dist/powdb.js +106 -21
- package/dist/powql.d.ts +5 -0
- package/dist/powql.js +42 -6
- package/dist/prisma-compat.d.ts +2 -0
- package/dist/prisma-compat.js +166 -8
- package/dist/query/aggregates.js +7 -3
- package/dist/query/builder.d.ts +292 -21
- package/dist/query/builder.js +570 -64
- package/dist/query/deferred.d.ts +39 -0
- package/dist/query/index.d.ts +1 -1
- package/dist/query/index.js +1 -1
- package/dist/query/relations.d.ts +173 -5
- package/dist/query/relations.js +688 -47
- package/dist/query/types.d.ts +123 -39
- package/dist/query/utils.d.ts +116 -0
- package/dist/query/utils.js +198 -0
- package/dist/query/warn-registry.d.ts +9 -0
- package/dist/query/warn-registry.js +9 -0
- package/dist/query/where.d.ts +38 -1
- package/dist/query/where.js +58 -23
- package/dist/query/writes.d.ts +42 -1
- package/dist/query/writes.js +104 -13
- package/dist/schema-sql.d.ts +14 -0
- package/dist/schema-sql.js +23 -5
- package/dist/schema.d.ts +38 -0
- package/dist/schema.js +123 -0
- package/dist/sqlite.js +4 -0
- package/package.json +77 -28
|
@@ -0,0 +1,1300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* turbine-orm — Query builder types
|
|
3
|
+
*
|
|
4
|
+
* All exported type and interface definitions for the query builder module.
|
|
5
|
+
*/
|
|
6
|
+
export type OrderDirection = 'asc' | 'desc';
|
|
7
|
+
/**
|
|
8
|
+
* How a query resolves its `with` relations.
|
|
9
|
+
*
|
|
10
|
+
* - `'join'`: one SQL statement with correlated
|
|
11
|
+
* `json_agg(json_build_object(...))` subqueries. One round-trip, an index
|
|
12
|
+
* seek per parent row when the child FK is indexed. On PowDB, `'join'`
|
|
13
|
+
* instead opts into native PowQL server-side joins where eligible.
|
|
14
|
+
* - `'batched'`: run the base query, then ONE flat follow-up query per
|
|
15
|
+
* relation (`WHERE fk = ANY($1)`), stitching children client-side. D levels
|
|
16
|
+
* cost D extra round-trips, but each is a single key-set lookup and rows come
|
|
17
|
+
* back flat (a win when FK columns are unindexed or result sets are huge).
|
|
18
|
+
* - `'auto'` (the implicit default on SQL engines since 0.41): per relation,
|
|
19
|
+
* use `'join'` unless the introspected metadata PROVES the probe columns are
|
|
20
|
+
* unindexed, in which case that relation falls back to the batched loader
|
|
21
|
+
* (where a correlated per-parent scan would be pathological). Requires
|
|
22
|
+
* DB-backed index metadata (a generated / introspected client); a code-first
|
|
23
|
+
* `defineSchema`-only client has no index info to prove anything, so `'auto'`
|
|
24
|
+
* behaves exactly like `'join'` there. An EXPLICIT `'join'` or `'batched'` at
|
|
25
|
+
* the client or query level always wins and disables the per-relation
|
|
26
|
+
* fallback. Output is byte-for-byte identical to `'join'` (the batched loader
|
|
27
|
+
* guarantees the same result SHAPE); child-array order for a to-many relation
|
|
28
|
+
* WITHOUT an `orderBy` may differ from the join plan (order was never
|
|
29
|
+
* guaranteed without `orderBy`, see `stableRelationOrder` to pin it).
|
|
30
|
+
* Composite-key relations stay on the join plan (the batched loader does not
|
|
31
|
+
* support them). Engagement emits a once-per-relation dev note and a
|
|
32
|
+
* `strategy` tag on the query event.
|
|
33
|
+
*
|
|
34
|
+
* Precedence: per-query arg > client `relationLoadStrategy` config > the engine
|
|
35
|
+
* default. On SQL engines the default is `'auto'`; on PowDB the default is the
|
|
36
|
+
* batched loaders (an ineligible relation falls back to them per-relation and
|
|
37
|
+
* silently even when `'join'` is requested). On PowDB, `'auto'` resolves to
|
|
38
|
+
* PowDB's own existing default (loaders / nested projections); it never selects
|
|
39
|
+
* a distinct PowQL code path.
|
|
40
|
+
*/
|
|
41
|
+
export type RelationLoadStrategy = 'join' | 'batched' | 'auto' | 'flatten';
|
|
42
|
+
/**
|
|
43
|
+
* Reference to ANOTHER COLUMN of the same table inside a where operator,
|
|
44
|
+
* enabling column-to-column comparison:
|
|
45
|
+
*
|
|
46
|
+
* ```ts
|
|
47
|
+
* where: { currentVersionId: { equals: { col: 'publishedVersionId' } } }
|
|
48
|
+
* // → WHERE "current_version_id" = "published_version_id"
|
|
49
|
+
* ```
|
|
50
|
+
*
|
|
51
|
+
* Accepted by `equals`, `not`, `gt`, `gte`, `lt`, and `lte`. The referenced
|
|
52
|
+
* field resolves through the table's columnMap (camelCase accepted, same as a
|
|
53
|
+
* where key) and compiles to a quoted identifier: NO parameter is bound.
|
|
54
|
+
* An unknown referenced field throws {@link ValidationError} (E003).
|
|
55
|
+
*
|
|
56
|
+
* Notes:
|
|
57
|
+
* - `mode: 'insensitive'` cannot be combined with a column reference: it
|
|
58
|
+
* throws E003 (use `client.sql` for `lower(a) = lower(b)`).
|
|
59
|
+
* - On json/jsonb columns `equals` routes to the JSONB containment filter
|
|
60
|
+
* first, so `{ equals: { col } }` there is treated as a JSON value, not a
|
|
61
|
+
* column reference.
|
|
62
|
+
*
|
|
63
|
+
* `F` narrows the referenced name to the table's field names when the
|
|
64
|
+
* surrounding {@link WhereClause} knows the entity type.
|
|
65
|
+
*/
|
|
66
|
+
export interface ColumnRef<F extends string = string> {
|
|
67
|
+
col: F;
|
|
68
|
+
}
|
|
69
|
+
/** Operator object for advanced where filtering */
|
|
70
|
+
export interface WhereOperator<V = unknown, F extends string = string> {
|
|
71
|
+
/**
|
|
72
|
+
* Explicit equality: `{ equals: value }` → `column = $n`.
|
|
73
|
+
* `{ equals: null }` → `column IS NULL`.
|
|
74
|
+
* `{ equals: { col: 'otherField' } }` → `column = "other_field"` ({@link ColumnRef}).
|
|
75
|
+
* On json/jsonb columns `equals` routes to the JSONB containment filter
|
|
76
|
+
* ({@link JsonFilter}) instead.
|
|
77
|
+
*/
|
|
78
|
+
equals?: V | ColumnRef<F> | null;
|
|
79
|
+
gt?: V | ColumnRef<F>;
|
|
80
|
+
gte?: V | ColumnRef<F>;
|
|
81
|
+
lt?: V | ColumnRef<F>;
|
|
82
|
+
lte?: V | ColumnRef<F>;
|
|
83
|
+
not?: V | ColumnRef<F> | null;
|
|
84
|
+
in?: V[];
|
|
85
|
+
notIn?: V[];
|
|
86
|
+
contains?: string;
|
|
87
|
+
startsWith?: string;
|
|
88
|
+
endsWith?: string;
|
|
89
|
+
/** Set to 'insensitive' to use ILIKE instead of LIKE for string comparisons */
|
|
90
|
+
mode?: 'default' | 'insensitive';
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* A where value can be:
|
|
94
|
+
* - A plain value (equality: column = $N)
|
|
95
|
+
* - null (column IS NULL)
|
|
96
|
+
* - An operator object ({ gt: 5, lte: 10 })
|
|
97
|
+
* - A JSONB filter object ({ contains, equals, path, hasKey })
|
|
98
|
+
* - An array filter object ({ has, hasEvery, hasSome, isEmpty })
|
|
99
|
+
* - A text search filter object ({ search, config? })
|
|
100
|
+
* - A vector distance filter object ({ distance: { to, metric, lt } }) for pgvector columns
|
|
101
|
+
*/
|
|
102
|
+
export type WhereValue<V = unknown, F extends string = string> = (V extends Array<infer U> ? TypedRelationFilter<U> : V extends Date ? V : V extends object ? V | TypedToOneFilter<V> | WhereClause<V> : V) | WhereOperator<V, F> | JsonFilter | ArrayFilter | TextSearchFilter | VectorFilter | null;
|
|
103
|
+
/**
|
|
104
|
+
* Relation filter on a to-many relation property.
|
|
105
|
+
*
|
|
106
|
+
* `UR` is the target entity's own relations map, so a nested relation filter
|
|
107
|
+
* (`posts: { some: { comments: { some: ... } } }`) stays key-checked at depth.
|
|
108
|
+
* It defaults to `{}` so the legacy single-generic spelling still works.
|
|
109
|
+
*/
|
|
110
|
+
export interface TypedRelationFilter<U, UR extends object = {}> {
|
|
111
|
+
some?: WhereClause<U, UR>;
|
|
112
|
+
every?: WhereClause<U, UR>;
|
|
113
|
+
none?: WhereClause<U, UR>;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Relation filter on a to-one relation property. A bare object on a to-one
|
|
117
|
+
* relation key is also accepted at runtime (implicit `is`, Prisma-compatible).
|
|
118
|
+
*
|
|
119
|
+
* `VR` is the target entity's own relations map (see {@link TypedRelationFilter}).
|
|
120
|
+
*/
|
|
121
|
+
export interface TypedToOneFilter<V, VR extends object = {}> {
|
|
122
|
+
is?: WhereClause<V, VR>;
|
|
123
|
+
isNot?: WhereClause<V, VR>;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* The where-value accepted on a RELATION key, derived from the generated
|
|
127
|
+
* {@link RelationDescriptor} brand: to-many relations take `some`/`every`/`none`,
|
|
128
|
+
* to-one relations take `is`/`isNot` or a bare sub-where (implicit `is`).
|
|
129
|
+
*
|
|
130
|
+
* Legacy generated shapes (`posts: Post[]`, `profile: Profile | null`) carry no
|
|
131
|
+
* brand, so they degrade to `unknown` — the key is still recognised (no typo
|
|
132
|
+
* false-positive) but its value is not checked.
|
|
133
|
+
*/
|
|
134
|
+
type RelationWhereValue<Rel> = Rel extends RelationDescriptor<infer Target, infer Cardinality, infer TR> ? Cardinality extends 'many' ? TypedRelationFilter<Target, TR & object> : TypedToOneFilter<Target, TR & object> | WhereClause<Target, TR & object> : unknown;
|
|
135
|
+
/**
|
|
136
|
+
* Where clause type: each field can be a plain value, null, or operator object.
|
|
137
|
+
* Special keys: OR / AND / NOT.
|
|
138
|
+
*
|
|
139
|
+
* **Key checking.** Historically this type carried a
|
|
140
|
+
* `[relationName: string]: unknown` index signature so relation filters
|
|
141
|
+
* (`where: { posts: { some: ... } }`) would typecheck — the relation names are
|
|
142
|
+
* NOT keys of the entity `T`. That index signature also annihilated
|
|
143
|
+
* excess-property checking, so `where: { emial: 'x' }` compiled silently.
|
|
144
|
+
*
|
|
145
|
+
* Passing `R` (the generated `*Relations` map, which every typed client
|
|
146
|
+
* already threads through `QueryInterface<T, R>`) removes the need for the
|
|
147
|
+
* index signature: the relation keys become real, explicitly enumerated
|
|
148
|
+
* properties, so a misspelled column OR relation is a compile error at the
|
|
149
|
+
* offending key while every legitimate filter shape still typechecks.
|
|
150
|
+
*
|
|
151
|
+
* When `R` is omitted / `{}` (the untyped escape hatch, `defineSchema`-only
|
|
152
|
+
* clients, and any call site that does not thread the relations map) the type
|
|
153
|
+
* degrades to exactly its historical permissive form.
|
|
154
|
+
*/
|
|
155
|
+
export type WhereClause<T, R extends object = {}> = [keyof R] extends [never] ? LooseWhereClause<T> : StrictWhereClause<T, R>;
|
|
156
|
+
/** The historical, index-signature-carrying where clause. See {@link WhereClause}. */
|
|
157
|
+
export type LooseWhereClause<T> = {
|
|
158
|
+
[K in keyof T]?: WhereValue<T[K], Extract<keyof T, string>>;
|
|
159
|
+
} & {
|
|
160
|
+
OR?: LooseWhereClause<T>[];
|
|
161
|
+
AND?: LooseWhereClause<T>[];
|
|
162
|
+
NOT?: LooseWhereClause<T>;
|
|
163
|
+
/** Relation filters — keyed by relation name, value is { some, every, none } */
|
|
164
|
+
[relationName: string]: unknown;
|
|
165
|
+
};
|
|
166
|
+
/** Key-checked where clause: column keys from `T`, relation keys from `R`, no index signature. */
|
|
167
|
+
type StrictWhereClause<T, R extends object> = {
|
|
168
|
+
[K in keyof T]?: WhereValue<T[K], Extract<keyof T, string>>;
|
|
169
|
+
} & {
|
|
170
|
+
[K in keyof R]?: RelationWhereValue<R[K]>;
|
|
171
|
+
} & {
|
|
172
|
+
OR?: WhereClause<T, R>[];
|
|
173
|
+
AND?: WhereClause<T, R>[];
|
|
174
|
+
NOT?: WhereClause<T, R>;
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* Client-level automatic WHERE filters, keyed by table accessor (the name used
|
|
178
|
+
* in `db[name]` / `client.table(name)`). Each value is AND-merged into the
|
|
179
|
+
* compiled WHERE of every read and mutation on that table, and into every
|
|
180
|
+
* relation subquery that targets it — the mechanism behind soft-delete and
|
|
181
|
+
* multi-tenancy. A function value is evaluated at query-build time (per query),
|
|
182
|
+
* so a closure over per-request state (e.g. the current tenant id) enables
|
|
183
|
+
* request-scoped filters. `create`/`createMany` are never filtered.
|
|
184
|
+
*/
|
|
185
|
+
export type GlobalFilters = {
|
|
186
|
+
[tableAccessor: string]: WhereClause<any> | (() => WhereClause<any>);
|
|
187
|
+
};
|
|
188
|
+
/**
|
|
189
|
+
* Per-query opt-out of the configured {@link GlobalFilters}. `true` skips the
|
|
190
|
+
* global filter on the query's own table AND on every relation target it
|
|
191
|
+
* touches; an array skips only the named table accessors (own table and/or
|
|
192
|
+
* relation targets). Global filters never satisfy the empty-`where` guard for
|
|
193
|
+
* `update`/`delete` — that guard always checks the user-supplied `where`.
|
|
194
|
+
*/
|
|
195
|
+
export type SkipGlobalFilters = true | readonly string[];
|
|
196
|
+
/**
|
|
197
|
+
* Reserved key in a `with` clause that requests correlated relation counts.
|
|
198
|
+
* `_count: true` counts every to-many relation of the table; a record form
|
|
199
|
+
* (`_count: { posts: true }`) counts only the named to-many relations. Each
|
|
200
|
+
* selected relation resolves to a number on the result row's `_count` object.
|
|
201
|
+
*/
|
|
202
|
+
export type WithCount = true | Record<string, true>;
|
|
203
|
+
/**
|
|
204
|
+
* Unparameterized with clause — accepts any relation name.
|
|
205
|
+
* Used internally by the query builder at runtime.
|
|
206
|
+
*
|
|
207
|
+
* The reserved `_count` key (see {@link WithCount}) is also accepted at runtime;
|
|
208
|
+
* the builder reads it via a cast so the narrow `true | WithOptions` element
|
|
209
|
+
* type is preserved for the relation-subquery machinery. Typed callers get a
|
|
210
|
+
* fully-typed `_count` through {@link TypedWithClause}.
|
|
211
|
+
*/
|
|
212
|
+
export interface WithClause {
|
|
213
|
+
[relation: string]: true | WithOptions;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Relation-aware with clause. When R (the relations map) is provided,
|
|
217
|
+
* only keys from R are autocompleted. Used in public method signatures
|
|
218
|
+
* so the compiler can narrow the return type.
|
|
219
|
+
*
|
|
220
|
+
* For typed maps, each relation accepts either `true` (default include) or a
|
|
221
|
+
* {@link WithOptions} object whose nested `with` is keyed against the relation
|
|
222
|
+
* target's own relations interface — this is what enables deep
|
|
223
|
+
* `WithResult` inference.
|
|
224
|
+
*/
|
|
225
|
+
export type TypedWithClause<R extends object = {}> = [keyof R] extends [never] ? WithClause : {
|
|
226
|
+
[K in keyof R]?: true | WithOptions<RelationRelations<R[K]> & object, RelationTarget<R[K]>>;
|
|
227
|
+
} & {
|
|
228
|
+
/** Reserved: correlated relation counts. `true` counts all to-many relations. */
|
|
229
|
+
_count?: true | {
|
|
230
|
+
[K in keyof R]?: true;
|
|
231
|
+
};
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Options for an included relation.
|
|
235
|
+
*
|
|
236
|
+
* Generic over `NestedR` — the relations interface of the *target* entity —
|
|
237
|
+
* so the nested `with` clause is autocompleted with the correct relation keys
|
|
238
|
+
* and so {@link WithResult} can recursively infer the return type. Defaults to
|
|
239
|
+
* `{}` (no relation suggestions) for callers that use the unparameterized
|
|
240
|
+
* {@link WithClause}.
|
|
241
|
+
*/
|
|
242
|
+
/**
|
|
243
|
+
* A single relation-`with` orderBy object: field → direction / sort spec /
|
|
244
|
+
* JSON-path ordering / relation ordering. The Prisma-style array form on
|
|
245
|
+
* {@link WithOptions.orderBy} is `WithOrderByObject[]`.
|
|
246
|
+
*/
|
|
247
|
+
export type WithOrderByObject = Record<string, OrderDirection | OrderBySpec | JsonPathOrderBy | RelationOrderBy>;
|
|
248
|
+
/**
|
|
249
|
+
* The `where` accepted inside a relation `with` block. When the relation
|
|
250
|
+
* target entity is known (a typed client, via the {@link RelationDescriptor}
|
|
251
|
+
* brand the generator emits) this is a key-checked {@link WhereClause} over the
|
|
252
|
+
* TARGET entity and its own relations, so `with: { posts: { where: { titel } } }`
|
|
253
|
+
* is a compile error. When the target is unknown (the untyped
|
|
254
|
+
* {@link WithClause} escape hatch) it degrades to the historical open record.
|
|
255
|
+
*/
|
|
256
|
+
export type WithWhere<NestedT, NestedR extends object> = [unknown] extends [NestedT] ? Record<string, unknown> : WhereClause<NestedT & object, NestedR>;
|
|
257
|
+
export interface WithOptions<NestedR extends object = {}, NestedT = unknown> {
|
|
258
|
+
with?: TypedWithClause<NestedR>;
|
|
259
|
+
/** Filter the related rows. Keys are checked against the relation target when it is known (see {@link WithWhere}). */
|
|
260
|
+
where?: WithWhere<NestedT, NestedR>;
|
|
261
|
+
/**
|
|
262
|
+
* Order the related rows. Accepts a single object (`{ a: 'asc', b: 'desc' }`)
|
|
263
|
+
* or a Prisma-style array of objects (`[{ a: 'asc' }, { b: 'desc' }]`, whose
|
|
264
|
+
* element order is the authoritative multi-key sort precedence).
|
|
265
|
+
*/
|
|
266
|
+
orderBy?: WithOrderByObject | WithOrderByObject[];
|
|
267
|
+
limit?: number;
|
|
268
|
+
/** Only include these fields from the relation */
|
|
269
|
+
select?: Record<string, boolean>;
|
|
270
|
+
/** Exclude these fields from the relation */
|
|
271
|
+
omit?: Record<string, boolean>;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* A relation descriptor used by generated `*Relations` interfaces to make deep
|
|
275
|
+
* `with` clause inference work. It bundles three pieces of information that
|
|
276
|
+
* `WithResult` needs to recurse through nested relations:
|
|
277
|
+
*
|
|
278
|
+
* - `__target` — the target entity type (e.g. `Post`)
|
|
279
|
+
* - `__cardinality`— `'many'` for hasMany, `'one'` for belongsTo / hasOne
|
|
280
|
+
* - `__relations` — the target entity's relations interface (for further recursion)
|
|
281
|
+
*
|
|
282
|
+
* **Generator contract (Track 3):** the code generator emits `*Relations`
|
|
283
|
+
* interfaces in the following shape so that `WithResult` can walk arbitrary
|
|
284
|
+
* nesting depth:
|
|
285
|
+
*
|
|
286
|
+
* ```ts
|
|
287
|
+
* export interface UserRelations {
|
|
288
|
+
* posts: RelationDescriptor<Post, 'many', PostRelations>;
|
|
289
|
+
* profile: RelationDescriptor<Profile, 'one', ProfileRelations>;
|
|
290
|
+
* }
|
|
291
|
+
* ```
|
|
292
|
+
*
|
|
293
|
+
* The brand fields are phantom — they exist only for type inference and have
|
|
294
|
+
* no runtime representation. The runtime always sees the parsed entity values
|
|
295
|
+
* (arrays for hasMany, single object or null for belongsTo / hasOne) — see the
|
|
296
|
+
* cardinality projection inside {@link WithResult}.
|
|
297
|
+
*
|
|
298
|
+
* **Backward compatibility:** legacy generated code emitted bare types
|
|
299
|
+
* (`posts: Post[]`, `profile: Profile | null`). `WithResult` still accepts that
|
|
300
|
+
* shape via a fallback branch — it just cannot recurse into nested `with` for
|
|
301
|
+
* those relations until the generator is updated.
|
|
302
|
+
*
|
|
303
|
+
* @typeParam Target - The entity type the relation points at.
|
|
304
|
+
* @typeParam Cardinality - `'many'` (array) or `'one'` (single object | null).
|
|
305
|
+
* @typeParam Relations - The target entity's own `*Relations` interface, or
|
|
306
|
+
* `{}` if the target has no relations of its own.
|
|
307
|
+
*/
|
|
308
|
+
export interface RelationDescriptor<Target, Cardinality extends 'one' | 'many', Relations extends object = {}> {
|
|
309
|
+
readonly __target?: Target;
|
|
310
|
+
readonly __cardinality?: Cardinality;
|
|
311
|
+
readonly __relations?: Relations;
|
|
312
|
+
}
|
|
313
|
+
/** Extract the target entity from a relation descriptor or bare relation type. */
|
|
314
|
+
type RelationTarget<Rel> = Rel extends RelationDescriptor<infer Target, infer _C, infer _R> ? Target : Rel extends Array<infer Item> ? Item : Rel extends infer One | null ? One : Rel;
|
|
315
|
+
/** Extract the target's relations map from a relation descriptor (or `{}` for bare types). */
|
|
316
|
+
type RelationRelations<Rel> = Rel extends RelationDescriptor<infer _T, infer _C, infer R> ? R : {};
|
|
317
|
+
/** Project the target type into its runtime shape (array for many, single for one). */
|
|
318
|
+
type ApplyCardinality<Rel, Resolved> = Rel extends RelationDescriptor<infer _T, infer Cardinality, infer _R> ? Cardinality extends 'many' ? Resolved[] : Resolved | null : Rel extends Array<infer _Item> ? Resolved[] : Resolved | null;
|
|
319
|
+
/**
|
|
320
|
+
* Compute the result type when relations are included via `with`.
|
|
321
|
+
*
|
|
322
|
+
* Recursively walks the `with` clause, looking up each relation in `R` and:
|
|
323
|
+
*
|
|
324
|
+
* 1. If the relation is included with `true` (or no nested `with`), the
|
|
325
|
+
* relation's bare resolved type is grafted onto `T` (e.g. `posts: Post[]`).
|
|
326
|
+
* 2. If the relation is included with a nested `with: {...}`, the recursion
|
|
327
|
+
* looks up the target entity's relations interface (via the
|
|
328
|
+
* {@link RelationDescriptor} brand fields the generator emits) and
|
|
329
|
+
* recursively applies `WithResult` to the nested target. Cardinality is
|
|
330
|
+
* re-applied at each level so a hasMany relation stays an array even after
|
|
331
|
+
* deep nesting.
|
|
332
|
+
*
|
|
333
|
+
* **When `R` is `{}` (the default):** the recursion short-circuits and the
|
|
334
|
+
* function returns plain `T` — preserving the existing untyped escape hatch
|
|
335
|
+
* for callers that have not generated typed clients.
|
|
336
|
+
*
|
|
337
|
+
* **When `R` does not contain the requested relations:** the unknown keys are
|
|
338
|
+
* ignored (the runtime will throw a `RelationError`, but the type system stays
|
|
339
|
+
* permissive so the legacy `WithClause` index signature still typechecks).
|
|
340
|
+
*
|
|
341
|
+
* @typeParam T - Base entity type (e.g. `User`).
|
|
342
|
+
* @typeParam R - Relations map for `T` (e.g.
|
|
343
|
+
* `{ posts: RelationDescriptor<Post, 'many', PostRelations>; ... }`).
|
|
344
|
+
* Legacy bare shapes (`{ posts: Post[]; profile: Profile | null }`)
|
|
345
|
+
* are also accepted, but cannot recurse beyond one level.
|
|
346
|
+
* @typeParam W - The `with` clause the user passed (e.g. `{ posts: true }` or
|
|
347
|
+
* `{ posts: { with: { comments: true } } }`).
|
|
348
|
+
*/
|
|
349
|
+
export type WithResult<T, R extends object, W> = [keyof R] extends [never] ? T : W extends object ? W extends {
|
|
350
|
+
_count: infer C;
|
|
351
|
+
} ? // `_count` requested — add the typed count object alongside any relations.
|
|
352
|
+
WithRelationAdditions<T, R, W> & {
|
|
353
|
+
_count: CountResult<C>;
|
|
354
|
+
} : WithRelationAdditions<T, R, W> : T;
|
|
355
|
+
/**
|
|
356
|
+
* The relation additions grafted onto `T` by a `with` clause (the `_count`
|
|
357
|
+
* reserved key is handled separately by {@link WithResult}). Kept as its own
|
|
358
|
+
* alias so the no-`_count` path stays byte-identical to the pre-`_count` type.
|
|
359
|
+
*/
|
|
360
|
+
type WithRelationAdditions<T, R extends object, W> = [keyof W & keyof R] extends [never] ? T : T & {
|
|
361
|
+
[K in keyof W & keyof R]: W[K] extends true ? ApplyCardinality<R[K], RelationTarget<R[K]>> : W[K] extends {
|
|
362
|
+
with?: infer NestedW;
|
|
363
|
+
} ? NestedW extends object ? ApplyCardinality<R[K], WithResult<RelationTarget<R[K]>, RelationRelations<R[K]> & object, NestedW>> : ApplyCardinality<R[K], RelationTarget<R[K]>> : ApplyCardinality<R[K], RelationTarget<R[K]>>;
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* Compute the shape of the `_count` object on a result row. `_count: true`
|
|
367
|
+
* counts every to-many relation (keys unknown at the type level → an open
|
|
368
|
+
* `Record<string, number>`); the record form (`_count: { posts: true }`) yields
|
|
369
|
+
* `{ [K in selected]: number }`.
|
|
370
|
+
*/
|
|
371
|
+
type CountResult<C> = C extends true ? Record<string, number> : C extends object ? {
|
|
372
|
+
[K in keyof C]: number;
|
|
373
|
+
} : Record<string, number>;
|
|
374
|
+
/**
|
|
375
|
+
* Key-validating companion for an inferred `select` / `omit` flag map.
|
|
376
|
+
*
|
|
377
|
+
* `select?: S` alone can never reject a typo: `S` is inferred FROM the object
|
|
378
|
+
* literal, so `{ emial: true }` simply becomes the inferred type and a
|
|
379
|
+
* misspelled column silently narrows the result to `Pick<T, never>`. Writing
|
|
380
|
+
* the property as `S & FieldFlags<T, S>` keeps `S` inferred exactly as before
|
|
381
|
+
* (the naked `S` member is still the inference site, so literal `true` values
|
|
382
|
+
* and the `TrueKeys` result narrowing are unchanged) while the mapped member
|
|
383
|
+
* maps every key that is NOT a field of `T` to `never`, which makes the
|
|
384
|
+
* supplied `true` unassignable and reports the typo at the offending key.
|
|
385
|
+
*
|
|
386
|
+
* A key that IS a field of `T` maps to plain `boolean`, so every legitimate
|
|
387
|
+
* flag map (`{ id: true }`, `{ id: true, email: false }`, `{}`) is unaffected.
|
|
388
|
+
*
|
|
389
|
+
* An OPEN flag map (`Record<string, boolean>`, which is what the internal
|
|
390
|
+
* pass-through signatures instantiate `S` with) has nothing to validate: it is
|
|
391
|
+
* returned unchanged so those instantiations stay assignable to each other.
|
|
392
|
+
*/
|
|
393
|
+
export type FieldFlags<T, S> = S extends object ? string extends keyof S ? S : {
|
|
394
|
+
[K in keyof S]: K extends keyof T ? boolean : never;
|
|
395
|
+
} : S;
|
|
396
|
+
/** Extract keys from a boolean record where the value is `true`. */
|
|
397
|
+
type TrueKeys<S extends Record<string, boolean>> = {
|
|
398
|
+
[K in keyof S]: S[K] extends true ? K : never;
|
|
399
|
+
}[keyof S];
|
|
400
|
+
/** Pick only the fields from T that are selected (value = true) in S. */
|
|
401
|
+
export type SelectResult<T, S extends Record<string, boolean> | undefined> = S extends Record<string, boolean> ? Pick<T, Extract<keyof T, TrueKeys<S>>> : T;
|
|
402
|
+
/** Omit the fields from T that are marked (value = true) in O. */
|
|
403
|
+
export type OmitResult<T, O extends Record<string, boolean> | undefined> = O extends Record<string, boolean> ? Omit<T, Extract<keyof T, TrueKeys<O>>> : T;
|
|
404
|
+
/**
|
|
405
|
+
* Apply select or omit field narrowing to a base type. Select takes priority —
|
|
406
|
+
* when both are provided, only select is applied (matching runtime behavior).
|
|
407
|
+
*/
|
|
408
|
+
export type FieldResult<T, S extends Record<string, boolean> | undefined, O extends Record<string, boolean> | undefined> = S extends Record<string, boolean> ? SelectResult<T, S> : OmitResult<T, O>;
|
|
409
|
+
/**
|
|
410
|
+
* Compute the full query result type: apply field narrowing to the base entity,
|
|
411
|
+
* then add relation additions from the `with` clause. Relations are unaffected
|
|
412
|
+
* by select/omit (they are separate JSON subqueries at the SQL level).
|
|
413
|
+
*
|
|
414
|
+
* Short-circuits to plain WithResult when neither select nor omit is provided,
|
|
415
|
+
* preserving exact type equality with the pre-narrowing era.
|
|
416
|
+
*/
|
|
417
|
+
export type QueryResult<T, R extends object, W, S extends Record<string, boolean> | undefined, O extends Record<string, boolean> | undefined> = S extends undefined ? O extends undefined ? WithResult<T, R, W> : O extends Record<string, boolean> ? Omit<WithResult<T, R, W>, Exclude<Extract<keyof T, TrueKeys<O>>, keyof W>> : WithResult<T, R, W> : S extends Record<string, boolean> ? Pick<WithResult<T, R, W>, Extract<keyof T, TrueKeys<S>> | Exclude<keyof WithResult<T, R, W>, keyof T> | Extract<keyof W, keyof WithResult<T, R, W>>> : WithResult<T, R, W>;
|
|
418
|
+
export interface FindUniqueArgs<T, R extends object = {}, W extends TypedWithClause<R> = TypedWithClause<R>, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined> {
|
|
419
|
+
/** Row selector. Keys are checked against `T` and `R` (see {@link WhereClause}). */
|
|
420
|
+
where: WhereClause<T, R>;
|
|
421
|
+
/** Only return these fields. Keys are checked against `T` (see {@link FieldFlags}). */
|
|
422
|
+
select?: S & FieldFlags<T, S>;
|
|
423
|
+
/** Exclude these fields. Keys are checked against `T` (see {@link FieldFlags}). */
|
|
424
|
+
omit?: O & FieldFlags<T, O>;
|
|
425
|
+
with?: W;
|
|
426
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
427
|
+
timeout?: number;
|
|
428
|
+
/** Override the client's relation-loading strategy for this query. See {@link RelationLoadStrategy}. */
|
|
429
|
+
relationLoadStrategy?: RelationLoadStrategy;
|
|
430
|
+
/** Override the client's {@link TurbineConfig.stableRelationOrder} for this query. */
|
|
431
|
+
stableRelationOrder?: boolean;
|
|
432
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
433
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
434
|
+
/** Include PII-tagged columns in the result. See {@link FindManyArgs.includePii}. */
|
|
435
|
+
includePii?: boolean;
|
|
436
|
+
}
|
|
437
|
+
export interface FindManyArgs<T, R extends object = {}, W extends TypedWithClause<R> = TypedWithClause<R>, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined> {
|
|
438
|
+
/** Row filter. Keys are checked against `T` and `R` (see {@link WhereClause}). */
|
|
439
|
+
where?: WhereClause<T, R>;
|
|
440
|
+
/** Only return these fields. Keys are checked against `T` (see {@link FieldFlags}). */
|
|
441
|
+
select?: S & FieldFlags<T, S>;
|
|
442
|
+
/** Exclude these fields. Keys are checked against `T` (see {@link FieldFlags}). */
|
|
443
|
+
omit?: O & FieldFlags<T, O>;
|
|
444
|
+
orderBy?: OrderByClause;
|
|
445
|
+
limit?: number;
|
|
446
|
+
offset?: number;
|
|
447
|
+
with?: W;
|
|
448
|
+
/** Cursor-based pagination: start after this row */
|
|
449
|
+
cursor?: Partial<T>;
|
|
450
|
+
/** Number of records to take (used with cursor) */
|
|
451
|
+
take?: number;
|
|
452
|
+
/** De-duplicate results by specified fields */
|
|
453
|
+
distinct?: (keyof T & string)[];
|
|
454
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
455
|
+
timeout?: number;
|
|
456
|
+
/** Override the client's relation-loading strategy for this query. See {@link RelationLoadStrategy}. */
|
|
457
|
+
relationLoadStrategy?: RelationLoadStrategy;
|
|
458
|
+
/**
|
|
459
|
+
* Override the client's {@link TurbineConfig.stableRelationOrder} for this
|
|
460
|
+
* query. When `true`, every to-many `with` relation that has no explicit
|
|
461
|
+
* `orderBy` is loaded ordered by the target table's primary key ascending, so
|
|
462
|
+
* unordered child arrays come back in a deterministic order. An explicit
|
|
463
|
+
* per-relation `orderBy` always wins. Off by default; when off the emitted SQL
|
|
464
|
+
* is byte-identical to before.
|
|
465
|
+
*/
|
|
466
|
+
stableRelationOrder?: boolean;
|
|
467
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
468
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
469
|
+
/**
|
|
470
|
+
* Per-call override of the unbounded-findMany warning. Pass `false` when
|
|
471
|
+
* this call intentionally reads the full table (the config-level
|
|
472
|
+
* `warnOnUnlimited` stays in effect for every other call); pass `true` to
|
|
473
|
+
* force the warning even when it is disabled in config.
|
|
474
|
+
*/
|
|
475
|
+
warnOnUnlimited?: boolean;
|
|
476
|
+
/**
|
|
477
|
+
* Include PII-tagged columns (`defineSchema` `pii: true`) in the result.
|
|
478
|
+
*
|
|
479
|
+
* PII columns are EXCLUDED from default projections: they come back only when
|
|
480
|
+
* explicitly named in `select`, or when this flag is `true`. Set it to `true`
|
|
481
|
+
* to return every PII column at the top level AND at every nested `with`
|
|
482
|
+
* level of this query. Default `false`. Schemas with no PII-tagged columns are
|
|
483
|
+
* unaffected (the emitted SQL is byte-identical either way).
|
|
484
|
+
*
|
|
485
|
+
* Referencing a PII column in `where` / `orderBy` / `groupBy` / aggregates is
|
|
486
|
+
* always allowed regardless of this flag (the reference is explicit).
|
|
487
|
+
*/
|
|
488
|
+
includePii?: boolean;
|
|
489
|
+
}
|
|
490
|
+
export interface FindManyStreamArgs<T, R extends object = {}, W extends TypedWithClause<R> = TypedWithClause<R>, S extends Record<string, boolean> | undefined = undefined, O extends Record<string, boolean> | undefined = undefined> extends FindManyArgs<T, R, W, S, O> {
|
|
491
|
+
/**
|
|
492
|
+
* Number of rows to fetch per internal FETCH batch (default: 1000).
|
|
493
|
+
*
|
|
494
|
+
* Trade-off: larger batches reduce network round-trips (important for
|
|
495
|
+
* high-latency connections like Neon) but increase per-batch memory.
|
|
496
|
+
* At 1000 rows x ~500 bytes/row the default is ~500 KB per batch.
|
|
497
|
+
*
|
|
498
|
+
* When the total result set fits within one batch, the stream avoids
|
|
499
|
+
* cursor overhead entirely (no BEGIN / DECLARE / CLOSE / COMMIT) by
|
|
500
|
+
* using a speculative `SELECT ... LIMIT batchSize+1` first.
|
|
501
|
+
*/
|
|
502
|
+
batchSize?: number;
|
|
503
|
+
}
|
|
504
|
+
export interface CreateArgs<T, R extends object = {}> {
|
|
505
|
+
/**
|
|
506
|
+
* Row data. On typed clients, relation names additionally accept nested
|
|
507
|
+
* write ops ({@link NestedCreateOp}): `create` / `connect` / `connectOrCreate`.
|
|
508
|
+
*/
|
|
509
|
+
data: CreateDataInput<T, R>;
|
|
510
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
511
|
+
timeout?: number;
|
|
512
|
+
}
|
|
513
|
+
export interface CreateManyArgs<T> {
|
|
514
|
+
data: Partial<T>[];
|
|
515
|
+
/** When true, adds ON CONFLICT DO NOTHING to skip duplicate rows */
|
|
516
|
+
skipDuplicates?: boolean;
|
|
517
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
518
|
+
timeout?: number;
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Atomic update operators for a field.
|
|
522
|
+
*
|
|
523
|
+
* `set` works on any type; `increment`, `decrement`, `multiply`, and `divide`
|
|
524
|
+
* are only valid on numeric fields. They generate SQL like
|
|
525
|
+
* `col = col + $n` (and the corresponding `-`, `*`, `/` variants) instead of
|
|
526
|
+
* plain absolute assignments, so they are safe against concurrent writers —
|
|
527
|
+
* the database performs the math atomically.
|
|
528
|
+
*
|
|
529
|
+
* @example
|
|
530
|
+
* db.posts.update({ where: { id: 5 }, data: { viewCount: { increment: 1 } } });
|
|
531
|
+
*/
|
|
532
|
+
export type UpdateOperatorInput<V> = {
|
|
533
|
+
set: V;
|
|
534
|
+
} | (V extends number ? {
|
|
535
|
+
increment: number;
|
|
536
|
+
} : never) | (V extends number ? {
|
|
537
|
+
decrement: number;
|
|
538
|
+
} : never) | (V extends number ? {
|
|
539
|
+
multiply: number;
|
|
540
|
+
} : never) | (V extends number ? {
|
|
541
|
+
divide: number;
|
|
542
|
+
} : never);
|
|
543
|
+
/**
|
|
544
|
+
* Update data — each field can be a plain value or an atomic operator object.
|
|
545
|
+
* Back-compatible with `Partial<T>`: plain values still typecheck unchanged.
|
|
546
|
+
*/
|
|
547
|
+
export type UpdateInput<T> = {
|
|
548
|
+
[K in keyof T]?: T[K] | UpdateOperatorInput<T[K]>;
|
|
549
|
+
};
|
|
550
|
+
export interface UpdateArgs<T, R extends object = {}> {
|
|
551
|
+
/** Row selector. Keys are checked against `T` and `R` (see {@link WhereClause}). */
|
|
552
|
+
where: WhereClause<T, R>;
|
|
553
|
+
/**
|
|
554
|
+
* Update data. On typed clients, relation names additionally accept nested
|
|
555
|
+
* write ops ({@link NestedUpdateOp}): `create` / `connect` / `connectOrCreate`
|
|
556
|
+
* / `disconnect` / `set` / `delete` / `update` / `upsert`.
|
|
557
|
+
*/
|
|
558
|
+
data: UpdateDataInput<T, R>;
|
|
559
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
560
|
+
timeout?: number;
|
|
561
|
+
/**
|
|
562
|
+
* Opt in to running this mutation when `where` resolves to an empty
|
|
563
|
+
* predicate (e.g. `{}` or `{ id: undefined }`). Default `false` — an
|
|
564
|
+
* empty predicate throws `ValidationError` to catch the common case of
|
|
565
|
+
* a filter value accidentally being `undefined`. Set this to `true` only
|
|
566
|
+
* when an unconditional mutation is the intended behaviour.
|
|
567
|
+
*/
|
|
568
|
+
allowFullTableScan?: boolean;
|
|
569
|
+
/**
|
|
570
|
+
* Optimistic locking — prevents lost updates in concurrent scenarios.
|
|
571
|
+
* Specify the version field and its expected value. The update adds a
|
|
572
|
+
* WHERE check on the version and auto-increments it. If the row was
|
|
573
|
+
* modified by another transaction, throws `OptimisticLockError`.
|
|
574
|
+
*
|
|
575
|
+
* @example
|
|
576
|
+
* ```ts
|
|
577
|
+
* await db.posts.update({
|
|
578
|
+
* where: { id: 1 },
|
|
579
|
+
* data: { title: 'new title' },
|
|
580
|
+
* optimisticLock: { field: 'version', expected: 3 },
|
|
581
|
+
* });
|
|
582
|
+
* // Generates: UPDATE posts SET title=$1, version=version+1
|
|
583
|
+
* // WHERE id=$2 AND version=$3 RETURNING *
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
optimisticLock?: {
|
|
587
|
+
field: keyof T & string;
|
|
588
|
+
expected: number;
|
|
589
|
+
};
|
|
590
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
591
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
592
|
+
}
|
|
593
|
+
export interface UpdateManyArgs<T, R extends object = {}> {
|
|
594
|
+
where: WhereClause<T, R>;
|
|
595
|
+
data: UpdateInput<T>;
|
|
596
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
597
|
+
timeout?: number;
|
|
598
|
+
/** See {@link UpdateArgs.allowFullTableScan}. */
|
|
599
|
+
allowFullTableScan?: boolean;
|
|
600
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
601
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
602
|
+
}
|
|
603
|
+
export interface DeleteArgs<T, R extends object = {}> {
|
|
604
|
+
where: WhereClause<T, R>;
|
|
605
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
606
|
+
timeout?: number;
|
|
607
|
+
/** See {@link UpdateArgs.allowFullTableScan}. */
|
|
608
|
+
allowFullTableScan?: boolean;
|
|
609
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
610
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
611
|
+
}
|
|
612
|
+
export interface DeleteManyArgs<T, R extends object = {}> {
|
|
613
|
+
where: WhereClause<T, R>;
|
|
614
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
615
|
+
timeout?: number;
|
|
616
|
+
/** See {@link UpdateArgs.allowFullTableScan}. */
|
|
617
|
+
allowFullTableScan?: boolean;
|
|
618
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
619
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
620
|
+
}
|
|
621
|
+
export interface UpsertArgs<T, R extends object = {}> {
|
|
622
|
+
where: WhereClause<T, R>;
|
|
623
|
+
create: Partial<T>;
|
|
624
|
+
update: Partial<T>;
|
|
625
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
626
|
+
timeout?: number;
|
|
627
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
628
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
629
|
+
}
|
|
630
|
+
/** `connectOrCreate` op: connect to the row matching `where`, or create it. */
|
|
631
|
+
export interface ConnectOrCreateOp<T, TR extends object = {}> {
|
|
632
|
+
where: Partial<T>;
|
|
633
|
+
create: CreateDataInput<T, TR>;
|
|
634
|
+
}
|
|
635
|
+
/** Nested write ops valid inside `create()` data for a relation field. */
|
|
636
|
+
export interface NestedCreateOp<T, TR extends object = {}> {
|
|
637
|
+
create?: CreateDataInput<T, TR> | CreateDataInput<T, TR>[];
|
|
638
|
+
connect?: Partial<T> | Partial<T>[];
|
|
639
|
+
connectOrCreate?: ConnectOrCreateOp<T, TR> | ConnectOrCreateOp<T, TR>[];
|
|
640
|
+
}
|
|
641
|
+
/** A nested `update` op item: update the related row(s) matching `where`. `where` is optional for belongsTo relations (derived from the parent's FK). */
|
|
642
|
+
export interface NestedUpdateOpItem<T, TR extends object = {}> {
|
|
643
|
+
where?: Partial<T>;
|
|
644
|
+
data: UpdateDataInput<T, TR>;
|
|
645
|
+
}
|
|
646
|
+
/** A nested `upsert` op item: update the row matching `where` or create it. */
|
|
647
|
+
export interface NestedUpsertOpItem<T, TR extends object = {}> {
|
|
648
|
+
where: Partial<T>;
|
|
649
|
+
create: CreateDataInput<T, TR>;
|
|
650
|
+
update: UpdateDataInput<T, TR>;
|
|
651
|
+
}
|
|
652
|
+
/** Nested write ops valid inside `update()` data for a relation field. */
|
|
653
|
+
export interface NestedUpdateOp<T, TR extends object = {}> {
|
|
654
|
+
create?: CreateDataInput<T, TR> | CreateDataInput<T, TR>[];
|
|
655
|
+
connect?: Partial<T> | Partial<T>[];
|
|
656
|
+
connectOrCreate?: ConnectOrCreateOp<T, TR> | ConnectOrCreateOp<T, TR>[];
|
|
657
|
+
disconnect?: Partial<T> | Partial<T>[];
|
|
658
|
+
set?: Partial<T>[];
|
|
659
|
+
delete?: Partial<T> | Partial<T>[];
|
|
660
|
+
update?: NestedUpdateOpItem<T, TR> | NestedUpdateOpItem<T, TR>[];
|
|
661
|
+
upsert?: NestedUpsertOpItem<T, TR> | NestedUpsertOpItem<T, TR>[];
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* `create()` data input. When the relations map `R` is known (typed clients),
|
|
665
|
+
* each relation name additionally accepts a {@link NestedCreateOp} for the
|
|
666
|
+
* relation's target entity — recursively, via the target's own relations map.
|
|
667
|
+
* When `R` is `{}` (untyped escape hatch) this collapses to plain `Partial<T>`.
|
|
668
|
+
*/
|
|
669
|
+
export type CreateDataInput<T, R extends object = {}> = [keyof R] extends [never] ? Partial<T> : Partial<T> & {
|
|
670
|
+
[K in keyof R]?: NestedCreateOp<RelationTarget<R[K]> & object, RelationRelations<R[K]> & object>;
|
|
671
|
+
};
|
|
672
|
+
/**
|
|
673
|
+
* `update()` data input. Like {@link CreateDataInput} but relation fields
|
|
674
|
+
* accept the full {@link NestedUpdateOp} surface (disconnect / set / delete /
|
|
675
|
+
* update / upsert in addition to the create-context ops), and scalar fields
|
|
676
|
+
* accept atomic {@link UpdateOperatorInput} objects.
|
|
677
|
+
*/
|
|
678
|
+
export type UpdateDataInput<T, R extends object = {}> = [keyof R] extends [never] ? UpdateInput<T> : UpdateInput<T> & {
|
|
679
|
+
[K in keyof R]?: NestedUpdateOp<RelationTarget<R[K]> & object, RelationRelations<R[K]> & object>;
|
|
680
|
+
};
|
|
681
|
+
export interface CountArgs<T, R extends object = {}> {
|
|
682
|
+
where?: WhereClause<T, R>;
|
|
683
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
684
|
+
timeout?: number;
|
|
685
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
686
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Numeric comparison operators usable inside a `having` filter. A bare number
|
|
690
|
+
* is shorthand for equality (`COUNT(*) = $n`); the operator object supports
|
|
691
|
+
* range and inequality comparisons. Mirrors the numeric subset of
|
|
692
|
+
* {@link WhereOperator} so the same SQL machinery can be reused.
|
|
693
|
+
*/
|
|
694
|
+
export interface HavingNumericOperator {
|
|
695
|
+
equals?: number;
|
|
696
|
+
not?: number;
|
|
697
|
+
gt?: number;
|
|
698
|
+
gte?: number;
|
|
699
|
+
lt?: number;
|
|
700
|
+
lte?: number;
|
|
701
|
+
in?: number[];
|
|
702
|
+
notIn?: number[];
|
|
703
|
+
}
|
|
704
|
+
/** A single having predicate value: a bare number (equality) or an operator object. */
|
|
705
|
+
export type HavingFilter = number | HavingNumericOperator;
|
|
706
|
+
/**
|
|
707
|
+
* Per-field aggregate filters inside a {@link HavingClause}. Each aggregate
|
|
708
|
+
* function maps to a {@link HavingFilter} comparison on that field.
|
|
709
|
+
*
|
|
710
|
+
* @example
|
|
711
|
+
* viewCount: { _sum: { gt: 100 }, _avg: { lte: 50 } }
|
|
712
|
+
*/
|
|
713
|
+
export interface HavingAggregateFilter {
|
|
714
|
+
_sum?: HavingFilter;
|
|
715
|
+
_avg?: HavingFilter;
|
|
716
|
+
_min?: HavingFilter;
|
|
717
|
+
_max?: HavingFilter;
|
|
718
|
+
_count?: HavingFilter;
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* HAVING clause for `groupBy` — filters whole groups by their aggregate values
|
|
722
|
+
* (the SQL `HAVING` clause). Follows Prisma's shape: each aggregable field maps
|
|
723
|
+
* to a {@link HavingAggregateFilter} (`field → aggregate → operator → value`),
|
|
724
|
+
* and the special top-level `_count` key (no field) filters on `COUNT(*)`.
|
|
725
|
+
*
|
|
726
|
+
* Implemented as a mapped type so the special `_count` key can carry a
|
|
727
|
+
* {@link HavingFilter} while every entity field carries a
|
|
728
|
+
* {@link HavingAggregateFilter} — without the index-signature conflict an
|
|
729
|
+
* intersection type would produce when `T` is a broad `Record<string, unknown>`.
|
|
730
|
+
*
|
|
731
|
+
* @example
|
|
732
|
+
* // groups with more than 5 rows whose summed viewCount is at least 100
|
|
733
|
+
* having: { _count: { gt: 5 }, viewCount: { _sum: { gte: 100 } } }
|
|
734
|
+
*/
|
|
735
|
+
export type HavingClause<T> = {
|
|
736
|
+
/** Filter on `COUNT(*)` for the whole group. */
|
|
737
|
+
_count?: HavingFilter;
|
|
738
|
+
} & {
|
|
739
|
+
[K in keyof T & string]?: HavingAggregateFilter;
|
|
740
|
+
};
|
|
741
|
+
/**
|
|
742
|
+
* A JSON-path group key in {@link GroupByArgs.by}: groups by the value
|
|
743
|
+
* extracted at `path` from a json/jsonb column. Emits
|
|
744
|
+
* `(col #>> $n::text[]) AS "alias"` in SELECT and the same expression in
|
|
745
|
+
* GROUP BY (the path is bound as one text[] param, never interpolated).
|
|
746
|
+
* Result rows key by `alias` (default: the last path segment; a collision
|
|
747
|
+
* with another result key throws {@link ValidationError} E003).
|
|
748
|
+
*/
|
|
749
|
+
export interface JsonPathGroupKey {
|
|
750
|
+
/** json/jsonb column (camelCase field name, columnMap-resolved). */
|
|
751
|
+
field: string;
|
|
752
|
+
/** JSON path into the column (each element a key or array index). Bound as one text[] param. */
|
|
753
|
+
path: (string | number)[];
|
|
754
|
+
/** Result key for the group value. Defaults to the last path segment. */
|
|
755
|
+
alias?: string;
|
|
756
|
+
}
|
|
757
|
+
/**
|
|
758
|
+
* A JSON-path aggregate target inside `_sum` / `_avg` / `_min` / `_max` of
|
|
759
|
+
* {@link GroupByArgs}: aggregates the value extracted at `path` from a
|
|
760
|
+
* json/jsonb column, e.g. `SUM((col #>> $n::text[])::numeric)`. The arg key
|
|
761
|
+
* is the result alias. `_sum`/`_avg` always cast numeric (a text sum is
|
|
762
|
+
* meaningless); `_min`/`_max` compare as text unless `type: 'numeric'`.
|
|
763
|
+
*
|
|
764
|
+
* Engine note: when a group has NO value at the path, SQL engines return
|
|
765
|
+
* `null` for `_sum` (SUM over zero rows), while PowDB returns `0` (engine
|
|
766
|
+
* sum semantics). Treat `null` and `0` totals as equivalent when a group can
|
|
767
|
+
* be empty at the path.
|
|
768
|
+
*/
|
|
769
|
+
export interface JsonPathAggregateTarget {
|
|
770
|
+
/** json/jsonb column (camelCase field name, columnMap-resolved). */
|
|
771
|
+
field: string;
|
|
772
|
+
/** JSON path into the column (each element a key or array index). Bound as one text[] param. */
|
|
773
|
+
path: (string | number)[];
|
|
774
|
+
/** Comparison/aggregation kind. `_sum`/`_avg` are always numeric; `_min`/`_max` default to text. */
|
|
775
|
+
type?: 'numeric' | 'text';
|
|
776
|
+
}
|
|
777
|
+
/**
|
|
778
|
+
* Per-aggregate spec map for `_sum` / `_avg` / `_min` / `_max` in
|
|
779
|
+
* {@link GroupByArgs}: `true` keeps the existing plain-column behavior (the
|
|
780
|
+
* key is a column field name); a {@link JsonPathAggregateTarget} aggregates a
|
|
781
|
+
* JSON path (the key doubles as the result alias).
|
|
782
|
+
*/
|
|
783
|
+
export type GroupByAggregateSpec<T> = Partial<Record<keyof T & string, boolean>> | Record<string, boolean | JsonPathAggregateTarget>;
|
|
784
|
+
/**
|
|
785
|
+
* DISTINCT ON row source for {@link GroupByArgs} (PostgreSQL only: other
|
|
786
|
+
* engines throw {@link UnsupportedFeatureError} E017): the groupBy runs over
|
|
787
|
+
* one representative row per `columns` combination instead of the raw table.
|
|
788
|
+
*
|
|
789
|
+
* ```sql
|
|
790
|
+
* FROM (
|
|
791
|
+
* SELECT DISTINCT ON ("instance_id") * FROM "versions"
|
|
792
|
+
* WHERE <args.where> ORDER BY "instance_id", "created_at" DESC
|
|
793
|
+
* ) AS "versions"
|
|
794
|
+
* ```
|
|
795
|
+
*
|
|
796
|
+
* `orderBy` is REQUIRED (it decides which row survives per combination:
|
|
797
|
+
* without it the picked row would be nondeterministic); the wrapper ORDER BY
|
|
798
|
+
* is `columns` first, then this orderBy. `args.where` applies INSIDE the
|
|
799
|
+
* wrapper (filter before picking).
|
|
800
|
+
*/
|
|
801
|
+
export interface GroupByDistinctOn<T> {
|
|
802
|
+
/** DISTINCT ON columns: one surviving row per combination. */
|
|
803
|
+
columns: (keyof T & string)[];
|
|
804
|
+
/** Which row survives per combination (required for determinism). */
|
|
805
|
+
orderBy: Record<string, OrderDirection | OrderBySpec | JsonPathOrderBy>;
|
|
806
|
+
}
|
|
807
|
+
/** A per-field aggregate ordering block: field/alias → direction or sort spec. */
|
|
808
|
+
export type GroupByAggregateOrderBy = Record<string, OrderDirection | OrderBySpec>;
|
|
809
|
+
/**
|
|
810
|
+
* {@link GroupByArgs.orderBy}: order the result groups by any column the
|
|
811
|
+
* groupBy result contains.
|
|
812
|
+
*
|
|
813
|
+
* - A plain **by-column** field name, or a **JSON group-key alias** (explicit
|
|
814
|
+
* `alias`, else the last path segment): `{ region: 'asc' }`.
|
|
815
|
+
* - An **aggregate block**: `_count` takes a direction/spec directly
|
|
816
|
+
* (`{ _count: 'desc' }`); `_sum`/`_avg`/`_min`/`_max` take a field map keyed
|
|
817
|
+
* by a requested aggregate field/alias (`{ _sum: { amount: 'desc' } }`).
|
|
818
|
+
*
|
|
819
|
+
* An aggregate ordering that references an aggregate not requested in the same
|
|
820
|
+
* call (or an unknown by-key) throws {@link ValidationError} (E003). Every
|
|
821
|
+
* value accepts an {@link OrderBySpec} for `NULLS FIRST/LAST` placement
|
|
822
|
+
* (PostgreSQL / SQLite only).
|
|
823
|
+
*/
|
|
824
|
+
export interface GroupByOrderBy {
|
|
825
|
+
/** Order by the group's row count (requires `_count` to be selected). */
|
|
826
|
+
_count?: OrderDirection | OrderBySpec;
|
|
827
|
+
/** Order by a requested `_sum` aggregate, keyed by its field/alias. */
|
|
828
|
+
_sum?: GroupByAggregateOrderBy;
|
|
829
|
+
/** Order by a requested `_avg` aggregate, keyed by its field/alias. */
|
|
830
|
+
_avg?: GroupByAggregateOrderBy;
|
|
831
|
+
/** Order by a requested `_min` aggregate, keyed by its field/alias. */
|
|
832
|
+
_min?: GroupByAggregateOrderBy;
|
|
833
|
+
/** Order by a requested `_max` aggregate, keyed by its field/alias. */
|
|
834
|
+
_max?: GroupByAggregateOrderBy;
|
|
835
|
+
/** A by-column field name or JSON group-key alias → direction or sort spec. */
|
|
836
|
+
[key: string]: OrderDirection | OrderBySpec | GroupByAggregateOrderBy | undefined;
|
|
837
|
+
}
|
|
838
|
+
export interface GroupByArgs<T, R extends object = {}> {
|
|
839
|
+
/** Group keys: plain column field names and/or JSON-path keys ({@link JsonPathGroupKey}). */
|
|
840
|
+
by: ((keyof T & string) | JsonPathGroupKey)[];
|
|
841
|
+
where?: WhereClause<T, R>;
|
|
842
|
+
/**
|
|
843
|
+
* PostgreSQL only: group over one representative row per column combination
|
|
844
|
+
* (`SELECT DISTINCT ON … ORDER BY …` row source). See {@link GroupByDistinctOn}.
|
|
845
|
+
*/
|
|
846
|
+
distinctOn?: GroupByDistinctOn<T>;
|
|
847
|
+
/**
|
|
848
|
+
* Count each group. `true` (or omitted) → `_count: number` (COUNT(*)). The
|
|
849
|
+
* record form counts per selection: the reserved `_all: true` key → COUNT(*),
|
|
850
|
+
* and each entity field key → COUNT(that column), yielding
|
|
851
|
+
* `_count: { _all: n, field: n }` (Prisma parity). Ordering/HAVING on `_count`
|
|
852
|
+
* stays available whenever COUNT(*) is selected (`true`, omitted, or `_all`).
|
|
853
|
+
*/
|
|
854
|
+
_count?: true | ({
|
|
855
|
+
_all?: true;
|
|
856
|
+
} & Partial<Record<keyof T & string, boolean>>);
|
|
857
|
+
/** Sum of numeric fields (or JSON paths: see {@link JsonPathAggregateTarget}) in each group */
|
|
858
|
+
_sum?: GroupByAggregateSpec<T>;
|
|
859
|
+
/** Average of numeric fields (or JSON paths) in each group */
|
|
860
|
+
_avg?: GroupByAggregateSpec<T>;
|
|
861
|
+
/** Minimum value of fields (or JSON paths) in each group */
|
|
862
|
+
_min?: GroupByAggregateSpec<T>;
|
|
863
|
+
/** Maximum value of fields (or JSON paths) in each group */
|
|
864
|
+
_max?: GroupByAggregateSpec<T>;
|
|
865
|
+
/** Filter whole groups by their aggregate values (SQL HAVING). JSON-path aggregates key by their alias. */
|
|
866
|
+
having?: HavingClause<T>;
|
|
867
|
+
/**
|
|
868
|
+
* Order the result groups. Keys may be any column the groupBy result actually
|
|
869
|
+
* contains: a plain by-column field name, a JSON group-key alias (explicit
|
|
870
|
+
* `alias`, or the last path segment when unaliased), or an aggregate block
|
|
871
|
+
* (`_count`, or `_sum`/`_avg`/`_min`/`_max` mapping a requested field/alias to
|
|
872
|
+
* its direction). Every value supports {@link OrderBySpec} for NULLS
|
|
873
|
+
* placement. See {@link GroupByOrderBy}.
|
|
874
|
+
*
|
|
875
|
+
* Accepts a single object or a Prisma-style array of objects
|
|
876
|
+
* (`[{ region: 'asc' }, { _count: 'desc' }]`, array order authoritative).
|
|
877
|
+
*/
|
|
878
|
+
orderBy?: GroupByOrderBy | GroupByOrderBy[];
|
|
879
|
+
/**
|
|
880
|
+
* Cap the number of result groups (`LIMIT`, applied after `ORDER BY`). Useful
|
|
881
|
+
* for "top N groups" queries; pair with `orderBy` for a deterministic set.
|
|
882
|
+
*/
|
|
883
|
+
limit?: number;
|
|
884
|
+
/**
|
|
885
|
+
* Skip this many result groups (`OFFSET`, applied after `ORDER BY`). Paginates
|
|
886
|
+
* grouped results; combine with `limit` and a deterministic `orderBy`.
|
|
887
|
+
*/
|
|
888
|
+
offset?: number;
|
|
889
|
+
/**
|
|
890
|
+
* Opt in to grouping on / aggregating PII-tagged (`defineSchema` `pii: true`)
|
|
891
|
+
* columns. A PII column in `by`, and `_min` / `_max` over a PII column, return
|
|
892
|
+
* STORED VALUES, so without this they throw `ValidationError` (E003).
|
|
893
|
+
* `_count` (a count, not a value), `_sum` / `_avg`, and `where` / `orderBy` /
|
|
894
|
+
* `having` on PII columns stay allowed.
|
|
895
|
+
*/
|
|
896
|
+
includePii?: boolean;
|
|
897
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
898
|
+
timeout?: number;
|
|
899
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
900
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
901
|
+
}
|
|
902
|
+
/** The by-key union of a groupBy args type (array element type of `by`). */
|
|
903
|
+
type GroupByKeys<A> = A extends {
|
|
904
|
+
by: infer BY;
|
|
905
|
+
} ? (BY extends readonly unknown[] ? BY[number] : never) : never;
|
|
906
|
+
/** The subset of `by` keys that are plain string field names on the entity `T`. */
|
|
907
|
+
type GroupByFieldKeys<T, A> = Extract<GroupByKeys<A>, keyof T & string>;
|
|
908
|
+
/**
|
|
909
|
+
* `_sum` / `_avg` result block: every requested key maps to `number | null`
|
|
910
|
+
* (an aggregate over zero matching rows is null). Present only when the args
|
|
911
|
+
* actually requested the block. A JSON-path aggregate target keys by its arg
|
|
912
|
+
* key (the alias), so `keyof S` covers both plain columns and JSON aliases.
|
|
913
|
+
*/
|
|
914
|
+
type GroupBySumAvgPart<A, Key extends '_sum' | '_avg'> = A extends {
|
|
915
|
+
[P in Key]: infer S;
|
|
916
|
+
} ? [S] extends [object] ? {
|
|
917
|
+
[P in Key]: {
|
|
918
|
+
[K in keyof S & string]: number | null;
|
|
919
|
+
};
|
|
920
|
+
} : unknown : unknown;
|
|
921
|
+
/**
|
|
922
|
+
* `_min` / `_max` result block: a requested key that is a real entity field
|
|
923
|
+
* carries that field's own type; a JSON-path alias (or unknown key) carries
|
|
924
|
+
* `unknown`.
|
|
925
|
+
*/
|
|
926
|
+
type GroupByMinMaxPart<T, A, Key extends '_min' | '_max'> = A extends {
|
|
927
|
+
[P in Key]: infer S;
|
|
928
|
+
} ? [S] extends [object] ? {
|
|
929
|
+
[P in Key]: {
|
|
930
|
+
[K in keyof S & string]: K extends keyof T ? T[K] : unknown;
|
|
931
|
+
};
|
|
932
|
+
} : unknown : unknown;
|
|
933
|
+
/**
|
|
934
|
+
* The typed result-row shape of a `groupBy(args)` call, computed from the args
|
|
935
|
+
* literal `A` (Prisma / Drizzle parity). Each `by` field carries the entity's
|
|
936
|
+
* field type; `_count` is always present (a group always has a row count); and
|
|
937
|
+
* each requested `_sum` / `_avg` / `_min` / `_max` block maps its selected
|
|
938
|
+
* fields to properly typed values.
|
|
939
|
+
*
|
|
940
|
+
* JSON-path group keys (objects in `by`) resolve to a runtime alias that is not
|
|
941
|
+
* knowable at the type level, so they are not projected onto the row type: cast
|
|
942
|
+
* the result when grouping by a JSON path. Intersections with `unknown` (an
|
|
943
|
+
* absent aggregate block) collapse away, so an args literal with no aggregates
|
|
944
|
+
* yields exactly `{ [byField]: T[field] } & { _count: number }`.
|
|
945
|
+
*/
|
|
946
|
+
export type GroupByResult<T, A> = {
|
|
947
|
+
[K in GroupByFieldKeys<T, A>]: T[K];
|
|
948
|
+
} & GroupByCountPart<A> & GroupBySumAvgPart<A, '_sum'> & GroupBySumAvgPart<A, '_avg'> & GroupByMinMaxPart<T, A, '_min'> & GroupByMinMaxPart<T, A, '_max'>;
|
|
949
|
+
/**
|
|
950
|
+
* The `_count` block on a groupBy result row. Scalar `_count: true` (or an
|
|
951
|
+
* omitted `_count`, which still selects COUNT(*) by default) yields a plain
|
|
952
|
+
* `number`; the record form (`_count: { _all: true, field: true }`) yields a
|
|
953
|
+
* per-selection object `{ _all: number, field: number }` (Prisma parity). Kept
|
|
954
|
+
* additive: existing `_count: true` / no-`_count` calls still infer `number`.
|
|
955
|
+
*/
|
|
956
|
+
type GroupByCountPart<A> = A extends {
|
|
957
|
+
_count: infer C;
|
|
958
|
+
} ? C extends true ? {
|
|
959
|
+
_count: number;
|
|
960
|
+
} : [C] extends [object] ? {
|
|
961
|
+
_count: {
|
|
962
|
+
[K in keyof C & string]: number;
|
|
963
|
+
};
|
|
964
|
+
} : {
|
|
965
|
+
_count: number;
|
|
966
|
+
} : {
|
|
967
|
+
_count: number;
|
|
968
|
+
};
|
|
969
|
+
/** Arguments for the standalone aggregate method */
|
|
970
|
+
export interface AggregateArgs<T, R extends object = {}> {
|
|
971
|
+
where?: WhereClause<T, R>;
|
|
972
|
+
/**
|
|
973
|
+
* Count rows. `true` → `_count: number` (COUNT(*)). The record form counts per
|
|
974
|
+
* selection: the reserved `_all: true` key → COUNT(*), and each entity field
|
|
975
|
+
* key → COUNT(that column) (non-null count), yielding
|
|
976
|
+
* `_count: { _all: n, field: n }` (Prisma parity).
|
|
977
|
+
*/
|
|
978
|
+
_count?: true | ({
|
|
979
|
+
_all?: true;
|
|
980
|
+
} & Partial<Record<keyof T & string, boolean>>);
|
|
981
|
+
/** Sum of numeric fields */
|
|
982
|
+
_sum?: Partial<Record<keyof T & string, boolean>>;
|
|
983
|
+
/** Average of numeric fields */
|
|
984
|
+
_avg?: Partial<Record<keyof T & string, boolean>>;
|
|
985
|
+
/** Minimum value of fields */
|
|
986
|
+
_min?: Partial<Record<keyof T & string, boolean>>;
|
|
987
|
+
/** Maximum value of fields */
|
|
988
|
+
_max?: Partial<Record<keyof T & string, boolean>>;
|
|
989
|
+
/**
|
|
990
|
+
* Opt in to aggregating PII-tagged (`defineSchema` `pii: true`) columns.
|
|
991
|
+
* `_min` / `_max` return a STORED VALUE, so without this they throw
|
|
992
|
+
* `ValidationError` (E003) on a PII column. `_count` (a count, not a value)
|
|
993
|
+
* and `_sum` / `_avg` (a computed total over many rows) stay allowed, as do
|
|
994
|
+
* `where` filters on PII columns.
|
|
995
|
+
*/
|
|
996
|
+
includePii?: boolean;
|
|
997
|
+
/** Query timeout in milliseconds. Rejects with an error if exceeded. */
|
|
998
|
+
timeout?: number;
|
|
999
|
+
/** Opt out of configured {@link GlobalFilters}. See {@link SkipGlobalFilters}. */
|
|
1000
|
+
skipGlobalFilters?: SkipGlobalFilters;
|
|
1001
|
+
}
|
|
1002
|
+
/** Result type for aggregate queries */
|
|
1003
|
+
export interface AggregateResult<T> {
|
|
1004
|
+
_count?: number | Record<string, number>;
|
|
1005
|
+
_sum?: Partial<Record<keyof T & string, number | null>>;
|
|
1006
|
+
_avg?: Partial<Record<keyof T & string, number | null>>;
|
|
1007
|
+
_min?: Partial<Record<keyof T & string, unknown>>;
|
|
1008
|
+
_max?: Partial<Record<keyof T & string, unknown>>;
|
|
1009
|
+
}
|
|
1010
|
+
/** Relation filter operators for where clauses */
|
|
1011
|
+
export interface RelationFilter {
|
|
1012
|
+
some?: Record<string, unknown>;
|
|
1013
|
+
every?: Record<string, unknown>;
|
|
1014
|
+
none?: Record<string, unknown>;
|
|
1015
|
+
/** To-one relation match (bare objects on to-one keys are implicit `is`). */
|
|
1016
|
+
is?: Record<string, unknown>;
|
|
1017
|
+
isNot?: Record<string, unknown>;
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* JSONB query operators for where clauses.
|
|
1021
|
+
*
|
|
1022
|
+
* PowDB (`turbine-orm/powdb`) semantic deltas. The PowDB engine evaluates
|
|
1023
|
+
* `->` path filters with full type knowledge, so a few behaviours differ from
|
|
1024
|
+
* the Postgres `#>>`-text driver (documented, never silently wrong):
|
|
1025
|
+
* - `{ path, equals: null }` matches JSON null OR a MISSING key on PowDB
|
|
1026
|
+
* (compiles to `is null`), whereas the PG driver compares extracted text
|
|
1027
|
+
* against the string `'null'` and matches only a JSON string `"null"`.
|
|
1028
|
+
* - equality is TYPE-STRICT on PowDB: `{ path, equals: 7 }` matches a stored
|
|
1029
|
+
* JSON int `7` but not `7.0` or the JSON string `"7"` (PG text-extraction
|
|
1030
|
+
* matches `equals: 7` against the string `"7"`). Range ops (`gt`/`lt`/…)
|
|
1031
|
+
* still coerce int/float numerically.
|
|
1032
|
+
* - a digit-only path segment (`path: ['tags', '0']`) is an ARRAY INDEX on
|
|
1033
|
+
* both PowDB and the SQL engines (a json object key that is literally `"0"`
|
|
1034
|
+
* is likewise addressed by index).
|
|
1035
|
+
* - `contains`, and `equals` WITHOUT a `path` (whole-document containment),
|
|
1036
|
+
* throw `UnsupportedFeatureError` (E017) on PowDB: PowQL has no containment
|
|
1037
|
+
* operator.
|
|
1038
|
+
*/
|
|
1039
|
+
export interface JsonFilter {
|
|
1040
|
+
/**
|
|
1041
|
+
* Access nested path via `#>>` operator (Postgres) / `->` path (PowDB). A
|
|
1042
|
+
* digit-only segment (`'0'`) is treated as an array index on every engine.
|
|
1043
|
+
*/
|
|
1044
|
+
path?: string[];
|
|
1045
|
+
/** Exact match: `column @> value::jsonb` (containment). On PowDB, requires `path` and compares the typed value (throws E017 without `path`). */
|
|
1046
|
+
equals?: unknown;
|
|
1047
|
+
/** Containment check: `column @> value::jsonb`. Unsupported on PowDB (E017: PowQL has no containment operator). */
|
|
1048
|
+
contains?: unknown;
|
|
1049
|
+
/** Key existence check: `column ? key`. */
|
|
1050
|
+
hasKey?: string;
|
|
1051
|
+
/**
|
|
1052
|
+
* Greater-than comparison of the value at `path` (required). Numbers cast
|
|
1053
|
+
* the extracted text to numeric — `(col #>> path)::numeric > $n` — while
|
|
1054
|
+
* strings compare as text.
|
|
1055
|
+
*/
|
|
1056
|
+
gt?: number | string;
|
|
1057
|
+
/** Greater-than-or-equal comparison of the value at `path` (required). See {@link JsonFilter.gt}. */
|
|
1058
|
+
gte?: number | string;
|
|
1059
|
+
/** Less-than comparison of the value at `path` (required). See {@link JsonFilter.gt}. */
|
|
1060
|
+
lt?: number | string;
|
|
1061
|
+
/** Less-than-or-equal comparison of the value at `path` (required). See {@link JsonFilter.gt}. */
|
|
1062
|
+
lte?: number | string;
|
|
1063
|
+
}
|
|
1064
|
+
/** Array query operators for where clauses */
|
|
1065
|
+
export interface ArrayFilter {
|
|
1066
|
+
/** Check if array contains a single value: value = ANY(column) */
|
|
1067
|
+
has?: unknown;
|
|
1068
|
+
/** Check if array contains ALL values: column @> ARRAY[...] */
|
|
1069
|
+
hasEvery?: unknown[];
|
|
1070
|
+
/** Check if array has ANY of the values: column && ARRAY[...] */
|
|
1071
|
+
hasSome?: unknown[];
|
|
1072
|
+
/** Check if array is empty: array_length(column, 1) IS NULL */
|
|
1073
|
+
isEmpty?: boolean;
|
|
1074
|
+
}
|
|
1075
|
+
/** Full-text search filter using PostgreSQL to_tsvector / to_tsquery */
|
|
1076
|
+
export interface TextSearchFilter {
|
|
1077
|
+
/** The search query string passed to to_tsquery */
|
|
1078
|
+
search: string;
|
|
1079
|
+
/** PostgreSQL text search configuration name (defaults to 'english') */
|
|
1080
|
+
config?: string;
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Vector distance metric. Maps to a pgvector distance operator:
|
|
1084
|
+
*
|
|
1085
|
+
* - `'l2'` → `<->` (Euclidean / L2 distance)
|
|
1086
|
+
* - `'cosine'` → `<=>` (cosine distance)
|
|
1087
|
+
* - `'ip'` → `<#>` (negative inner product)
|
|
1088
|
+
*
|
|
1089
|
+
* This is a fixed allow-list — a value outside it is rejected with a
|
|
1090
|
+
* `ValidationError` so a user-supplied string can never become a SQL operator.
|
|
1091
|
+
*/
|
|
1092
|
+
export type VectorMetric = 'l2' | 'cosine' | 'ip';
|
|
1093
|
+
/**
|
|
1094
|
+
* Distance threshold filter for a pgvector column inside a `where` clause:
|
|
1095
|
+
*
|
|
1096
|
+
* ```ts
|
|
1097
|
+
* where: { embedding: { distance: { to: [0.1, 0.2, 0.3], metric: 'l2', lt: 0.3 } } }
|
|
1098
|
+
* // → WHERE "embedding" <-> $1::vector < $2
|
|
1099
|
+
* ```
|
|
1100
|
+
*
|
|
1101
|
+
* `to` is always bound as a single `$n::vector` param (never interpolated) and
|
|
1102
|
+
* each element must be a finite number. Exactly one comparison
|
|
1103
|
+
* (`lt` / `lte` / `gt` / `gte`) is applied; the threshold is also a bound param.
|
|
1104
|
+
*/
|
|
1105
|
+
export interface VectorDistanceFilter {
|
|
1106
|
+
/** The query vector to measure distance against. */
|
|
1107
|
+
to: number[];
|
|
1108
|
+
/** Distance metric → operator. */
|
|
1109
|
+
metric: VectorMetric;
|
|
1110
|
+
/** distance < threshold */
|
|
1111
|
+
lt?: number;
|
|
1112
|
+
/** distance <= threshold */
|
|
1113
|
+
lte?: number;
|
|
1114
|
+
/** distance > threshold */
|
|
1115
|
+
gt?: number;
|
|
1116
|
+
/** distance >= threshold */
|
|
1117
|
+
gte?: number;
|
|
1118
|
+
}
|
|
1119
|
+
/** Vector query operators for where clauses (pgvector). */
|
|
1120
|
+
export interface VectorFilter {
|
|
1121
|
+
/** Filter rows by distance from a query vector. */
|
|
1122
|
+
distance: VectorDistanceFilter;
|
|
1123
|
+
}
|
|
1124
|
+
/**
|
|
1125
|
+
* KNN ordering spec for a pgvector column inside an `orderBy` clause:
|
|
1126
|
+
*
|
|
1127
|
+
* ```ts
|
|
1128
|
+
* orderBy: { embedding: { distance: { to: [...], metric: 'cosine' } } }
|
|
1129
|
+
* // → ORDER BY "embedding" <=> $1::vector ASC
|
|
1130
|
+
* ```
|
|
1131
|
+
*
|
|
1132
|
+
* `distance` ASC ranks nearest-first (the default). Pass `direction: 'desc'`
|
|
1133
|
+
* to invert. The query vector `to` is bound as a `$n::vector` param.
|
|
1134
|
+
*/
|
|
1135
|
+
export interface VectorOrderByDistance {
|
|
1136
|
+
to: number[];
|
|
1137
|
+
metric: VectorMetric;
|
|
1138
|
+
/** Sort direction for the computed distance. Defaults to `'asc'` (nearest first). */
|
|
1139
|
+
direction?: OrderDirection;
|
|
1140
|
+
}
|
|
1141
|
+
/** Per-column orderBy value: a plain direction or a vector-distance ordering. */
|
|
1142
|
+
export interface VectorOrderBy {
|
|
1143
|
+
distance: VectorOrderByDistance;
|
|
1144
|
+
}
|
|
1145
|
+
/**
|
|
1146
|
+
* Explicit ordering spec for a column: a direction plus an optional NULLS
|
|
1147
|
+
* placement. `{ sort: 'desc', nulls: 'last' }` compiles to
|
|
1148
|
+
* `ORDER BY "col" DESC NULLS LAST`. The plain `'asc' | 'desc'` shorthand is
|
|
1149
|
+
* still accepted and unchanged. `nulls` is only emitted on engines that
|
|
1150
|
+
* support the `NULLS FIRST/LAST` grammar (PostgreSQL, SQLite); requesting it
|
|
1151
|
+
* elsewhere throws {@link UnsupportedFeatureError} (E017).
|
|
1152
|
+
*/
|
|
1153
|
+
export interface OrderBySpec {
|
|
1154
|
+
sort: OrderDirection;
|
|
1155
|
+
nulls?: 'first' | 'last';
|
|
1156
|
+
}
|
|
1157
|
+
/**
|
|
1158
|
+
* Ordering by a JSON path on a json/jsonb column of the SAME table:
|
|
1159
|
+
*
|
|
1160
|
+
* ```ts
|
|
1161
|
+
* orderBy: { data: { path: ['weight'], direction: 'asc', type: 'numeric' } }
|
|
1162
|
+
* // → ORDER BY ("data" #>> $n::text[])::numeric ASC
|
|
1163
|
+
* ```
|
|
1164
|
+
*
|
|
1165
|
+
* The path is bound as a single text[] parameter (never interpolated).
|
|
1166
|
+
* Comparison rule: values extracted from the path compare as TEXT by default;
|
|
1167
|
+
* pass `type: 'numeric'` to cast for numeric comparison (`::numeric` on
|
|
1168
|
+
* PostgreSQL). The column must be json/jsonb: anything else throws
|
|
1169
|
+
* {@link ValidationError} (E003). Non-Postgres engines route through the same
|
|
1170
|
+
* dialect JSON-extract hook the JSON where-filters use. Cross-relation
|
|
1171
|
+
* (lateral) JSON ordering is NOT supported: same-table columns only.
|
|
1172
|
+
*/
|
|
1173
|
+
export interface JsonPathOrderBy {
|
|
1174
|
+
/** JSON path into the column (each element a key or array index). Bound as one text[] param. */
|
|
1175
|
+
path: (string | number)[];
|
|
1176
|
+
/** Sort direction. Defaults to `'asc'`. */
|
|
1177
|
+
direction?: OrderDirection;
|
|
1178
|
+
/** Comparison kind for the extracted value. Defaults to `'text'`; `'numeric'` adds a numeric cast. */
|
|
1179
|
+
type?: 'numeric' | 'text';
|
|
1180
|
+
/**
|
|
1181
|
+
* NULLS placement (PostgreSQL / SQLite only: see {@link OrderBySpec}).
|
|
1182
|
+
* Rows whose document lacks the path extract to NULL and sort LAST in BOTH
|
|
1183
|
+
* directions by default (matching pick-row ordering and the PowDB engine
|
|
1184
|
+
* contract, so ordering is predictable across drivers); set `nulls` to
|
|
1185
|
+
* override on PostgreSQL / SQLite.
|
|
1186
|
+
*/
|
|
1187
|
+
nulls?: 'first' | 'last';
|
|
1188
|
+
}
|
|
1189
|
+
/**
|
|
1190
|
+
* Ordering by a relation, keyed by the relation name in an {@link OrderByClause}:
|
|
1191
|
+
*
|
|
1192
|
+
* - to-many (hasMany / manyToMany): `{ posts: { _count: 'desc' } }` — orders by
|
|
1193
|
+
* a correlated `COUNT(*)` of the related rows.
|
|
1194
|
+
* - to-one (belongsTo / hasOne): `{ author: { name: 'asc' } }` — orders by a
|
|
1195
|
+
* correlated scalar subquery on the target column (an {@link OrderBySpec} with
|
|
1196
|
+
* `nulls` is accepted too).
|
|
1197
|
+
*/
|
|
1198
|
+
export type RelationOrderBy = {
|
|
1199
|
+
_count: OrderDirection;
|
|
1200
|
+
} | Record<string, OrderDirection | OrderBySpec>;
|
|
1201
|
+
/**
|
|
1202
|
+
* The ordering value extracted from the picked row in a
|
|
1203
|
+
* {@link RelationPickOrderBy}: either a plain target column name (camelCase,
|
|
1204
|
+
* columnMap-resolved) or a JSON path into a json/jsonb target column.
|
|
1205
|
+
* Values extracted from a JSON path compare as TEXT by default; pass
|
|
1206
|
+
* `type: 'numeric'` to add a numeric cast.
|
|
1207
|
+
*/
|
|
1208
|
+
export type RelationPickBy = string | {
|
|
1209
|
+
/** json/jsonb column on the relation target. */
|
|
1210
|
+
field: string;
|
|
1211
|
+
/**
|
|
1212
|
+
* JSON path into the column (each element a key or array index). Bound
|
|
1213
|
+
* as ONE param: a text[] on PostgreSQL, a `'$'`-rooted JSONPath string
|
|
1214
|
+
* on engines whose JSON functions take one (SQLite/MySQL/SQL Server).
|
|
1215
|
+
*/
|
|
1216
|
+
path: (string | number)[];
|
|
1217
|
+
/** Comparison kind for the extracted value. Defaults to `'text'`. */
|
|
1218
|
+
type?: 'numeric' | 'text';
|
|
1219
|
+
};
|
|
1220
|
+
/**
|
|
1221
|
+
* Pick-row relation ordering: order a parent query by a value read from ONE
|
|
1222
|
+
* related row of a hasMany relation, keyed by the relation name in an
|
|
1223
|
+
* {@link OrderByClause}. Compiles to a correlated scalar subquery in ORDER BY:
|
|
1224
|
+
*
|
|
1225
|
+
* ```ts
|
|
1226
|
+
* orderBy: {
|
|
1227
|
+
* versions: {
|
|
1228
|
+
* pick: { orderBy: { createdAt: 'desc' } }, // which related row
|
|
1229
|
+
* by: { field: 'data', path: ['title'] }, // value to sort the parents by
|
|
1230
|
+
* direction: 'asc',
|
|
1231
|
+
* nulls: 'last',
|
|
1232
|
+
* },
|
|
1233
|
+
* }
|
|
1234
|
+
* // → ORDER BY (SELECT ord0."data" #>> $n::text[] FROM "versions" ord0
|
|
1235
|
+
* // WHERE ord0."instance_id" = "instances"."id"
|
|
1236
|
+
* // ORDER BY ord0."created_at" DESC LIMIT 1) ASC NULLS LAST
|
|
1237
|
+
* ```
|
|
1238
|
+
*
|
|
1239
|
+
* `pick.orderBy` is REQUIRED (it makes the picked row deterministic) and
|
|
1240
|
+
* supports the same surface as a relation `with` orderBy on the target (plain
|
|
1241
|
+
* columns, {@link OrderBySpec} nulls, {@link JsonPathOrderBy}). `pick.where`
|
|
1242
|
+
* optionally filters the candidate rows before picking. hasMany relations
|
|
1243
|
+
* only; top-level findMany orderBy only (manyToMany, to-one relations, and
|
|
1244
|
+
* nested `with` orderBy throw {@link ValidationError} E003).
|
|
1245
|
+
*/
|
|
1246
|
+
export interface RelationPickOrderBy {
|
|
1247
|
+
/** Which related row supplies the value. */
|
|
1248
|
+
pick: {
|
|
1249
|
+
/** Inner ORDER BY choosing the row (required for determinism). */
|
|
1250
|
+
orderBy: Record<string, OrderDirection | OrderBySpec | JsonPathOrderBy>;
|
|
1251
|
+
/** Optional filter on the candidate rows before picking. */
|
|
1252
|
+
where?: Record<string, unknown>;
|
|
1253
|
+
};
|
|
1254
|
+
/** The value on the picked row to order the parents by. */
|
|
1255
|
+
by: RelationPickBy;
|
|
1256
|
+
/** Sort direction for the parents. Defaults to `'asc'`. */
|
|
1257
|
+
direction?: OrderDirection;
|
|
1258
|
+
/**
|
|
1259
|
+
* NULLS placement (PostgreSQL / SQLite only: see {@link OrderBySpec}).
|
|
1260
|
+
*
|
|
1261
|
+
* A parent with NO related rows sorts by NULL. When `nulls` is not set,
|
|
1262
|
+
* pick ordering defaults to `NULLS LAST` in BOTH directions, so parents
|
|
1263
|
+
* with zero related rows always come last (Postgres's own DESC default is
|
|
1264
|
+
* NULLS FIRST, which would put every childless parent at the top of a
|
|
1265
|
+
* "highest first" sort). Set `nulls` explicitly to override.
|
|
1266
|
+
*/
|
|
1267
|
+
nulls?: 'first' | 'last';
|
|
1268
|
+
/**
|
|
1269
|
+
* Physical plan for the pick. `'subquery'` (default) compiles a correlated
|
|
1270
|
+
* scalar subquery in ORDER BY. `'lateral'` (PostgreSQL only, E017 elsewhere)
|
|
1271
|
+
* compiles a `LEFT JOIN LATERAL (... LIMIT 1) ON true` and orders by the
|
|
1272
|
+
* joined value. Identical results; the lateral form can be significantly
|
|
1273
|
+
* faster on large parent sets where the ordering subquery dominates the plan.
|
|
1274
|
+
* Never falls back silently: contexts that cannot take a lateral (non-Postgres
|
|
1275
|
+
* engines, `distinct`, nested `with` orderBy, a parent column literally named
|
|
1276
|
+
* `__turbine_pick`) throw.
|
|
1277
|
+
*/
|
|
1278
|
+
plan?: 'subquery' | 'lateral';
|
|
1279
|
+
}
|
|
1280
|
+
/**
|
|
1281
|
+
* A single orderBy object: maps each key to one of:
|
|
1282
|
+
* - a plain direction (`'asc'` / `'desc'`),
|
|
1283
|
+
* - an {@link OrderBySpec} (`{ sort, nulls }`) for NULLS placement,
|
|
1284
|
+
* - for json/jsonb columns, a JSON-path ordering ({@link JsonPathOrderBy}),
|
|
1285
|
+
* - for pgvector columns, a KNN distance ordering ({@link VectorOrderBy}),
|
|
1286
|
+
* - for a relation name, a {@link RelationOrderBy} (`_count` for to-many, a
|
|
1287
|
+
* target column for to-one) or a pick-row ordering
|
|
1288
|
+
* ({@link RelationPickOrderBy}, hasMany only).
|
|
1289
|
+
*/
|
|
1290
|
+
export type OrderByObject = Record<string, OrderDirection | OrderBySpec | JsonPathOrderBy | VectorOrderBy | RelationOrderBy | RelationPickOrderBy>;
|
|
1291
|
+
/**
|
|
1292
|
+
* An orderBy clause. Either a single {@link OrderByObject}
|
|
1293
|
+
* (`{ a: 'asc', b: 'desc' }`, insertion order authoritative) or a Prisma-style
|
|
1294
|
+
* array of them (`[{ a: 'asc' }, { b: 'desc' }]`, array order authoritative).
|
|
1295
|
+
* The array form makes multi-key ordering independent of JS object key
|
|
1296
|
+
* iteration order. Both forms flatten through `orderByEntries` so build,
|
|
1297
|
+
* param-collect, and cache-fingerprint paths stay in lockstep.
|
|
1298
|
+
*/
|
|
1299
|
+
export type OrderByClause = OrderByObject | OrderByObject[];
|
|
1300
|
+
export {};
|