@cleverbrush/knex-schema 3.1.0 → 4.1.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 +156 -1
- package/dist/SchemaQueryBuilder.d.ts +72 -575
- package/dist/chunk-V4TH6K42.js +2 -0
- package/dist/chunk-V4TH6K42.js.map +1 -0
- package/dist/columns.d.ts +73 -4
- package/dist/ddl.d.ts +66 -0
- package/dist/entity.d.ts +264 -0
- package/dist/extension.d.ts +1176 -1
- package/dist/extension.js +2 -0
- package/dist/extension.js.map +1 -0
- package/dist/index.d.ts +10 -3
- package/dist/index.js +60 -1
- package/dist/index.js.map +1 -1
- package/dist/migration.d.ts +160 -0
- package/dist/operations/delete.d.ts +6 -0
- package/dist/operations/helpers.d.ts +57 -0
- package/dist/operations/insert.d.ts +26 -0
- package/dist/operations/join.d.ts +6 -0
- package/dist/operations/pagination.d.ts +15 -0
- package/dist/operations/select.d.ts +15 -0
- package/dist/operations/state.d.ts +39 -0
- package/dist/operations/update.d.ts +7 -0
- package/dist/operations/where.d.ts +29 -0
- package/dist/raw.d.ts +35 -0
- package/dist/snapshot.d.ts +39 -0
- package/dist/types.d.ts +269 -0
- package/package.json +6 -2
|
@@ -1,640 +1,137 @@
|
|
|
1
1
|
import type { InferType } from '@cleverbrush/schema';
|
|
2
|
-
import { ObjectSchemaBuilder } from '@cleverbrush/schema';
|
|
2
|
+
import { EXTRA_TYPE_BRAND, METHOD_LITERAL_BRAND, type ObjectSchemaBuilder } from '@cleverbrush/schema';
|
|
3
3
|
import type { Knex } from 'knex';
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
* write `await query(db, Schema)` without calling {@link execute} explicitly.
|
|
18
|
-
*
|
|
19
|
-
* Create instances via the {@link query} factory function rather than
|
|
20
|
-
* calling the constructor directly.
|
|
21
|
-
*
|
|
22
|
-
* @typeParam TLocalSchema - The `ObjectSchemaBuilder` describing the main table.
|
|
23
|
-
* @typeParam TResult - The inferred row type, widened automatically as joins
|
|
24
|
-
* are registered via {@link joinOne} / {@link joinMany}.
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* ```ts
|
|
28
|
-
* import knex from 'knex';
|
|
29
|
-
* import { query, object, string, number } from '@cleverbrush/knex-schema';
|
|
30
|
-
*
|
|
31
|
-
* const UserSchema = object({
|
|
32
|
-
* id: number(),
|
|
33
|
-
* name: string(),
|
|
34
|
-
* age: number().optional(),
|
|
35
|
-
* }).hasTableName('users');
|
|
36
|
-
*
|
|
37
|
-
* const db = knex({ client: 'pg', connection: process.env.DB_URL });
|
|
38
|
-
*
|
|
39
|
-
* // Fetch all users older than 18, ordered by name
|
|
40
|
-
* const adults = await query(db, UserSchema)
|
|
41
|
-
* .where(t => t.age, '>', 18)
|
|
42
|
-
* .orderBy(t => t.name);
|
|
43
|
-
* // adults: Array<{ id: number; name: string; age?: number }>
|
|
44
|
-
* ```
|
|
45
|
-
*/
|
|
4
|
+
import { POLYMORPHIC_TYPE_BRAND } from './extension.js';
|
|
5
|
+
import type { ColumnRef, CursorPaginationResult, InsertType, JoinManySpec, JoinOneSpec, PaginationResult, SelectProjection, SelectSelector } from './types.js';
|
|
6
|
+
export { OnConflictBuilder } from './operations/insert.js';
|
|
7
|
+
type ScopesOf<S> = S extends {
|
|
8
|
+
readonly [METHOD_LITERAL_BRAND]?: infer N;
|
|
9
|
+
} ? Extract<N, string> : never;
|
|
10
|
+
type ProjectionsOf<S> = S extends {
|
|
11
|
+
readonly [EXTRA_TYPE_BRAND]?: infer P;
|
|
12
|
+
} ? P extends Record<string, readonly string[]> ? P : Record<never, never> : Record<never, never>;
|
|
13
|
+
type ProjectionKeysOf<S, K extends keyof ProjectionsOf<S> & string> = ProjectionsOf<S>[K] extends readonly (infer T extends string)[] ? T : string;
|
|
14
|
+
type QueryResultType<TLocalSchema> = TLocalSchema extends {
|
|
15
|
+
readonly [POLYMORPHIC_TYPE_BRAND]?: infer U;
|
|
16
|
+
} ? NonNullable<U> : InferType<TLocalSchema>;
|
|
46
17
|
export declare class SchemaQueryBuilder<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>, TResult> {
|
|
47
|
-
#private;
|
|
48
|
-
/**
|
|
49
|
-
* @param knex - A configured Knex instance.
|
|
50
|
-
* @param localSchema - The `ObjectSchemaBuilder` for the primary table.
|
|
51
|
-
* Must have a table name set via `.hasTableName()`.
|
|
52
|
-
* @param baseQuery - Optional pre-configured `Knex.QueryBuilder` to use as
|
|
53
|
-
* the base query instead of the default `knex(tableName)`. Useful when you
|
|
54
|
-
* need custom joins, CTEs, or other Knex features not exposed by this API.
|
|
55
|
-
*/
|
|
56
18
|
constructor(knex: Knex, localSchema: TLocalSchema, baseQuery?: Knex.QueryBuilder);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
* record are excluded (inner join); if `false`, they are included with
|
|
71
|
-
* `null` (left join).
|
|
72
|
-
* - `foreignQuery` — optional pre-filtered `Knex.QueryBuilder` for the
|
|
73
|
-
* foreign table (e.g. to apply scopes).
|
|
74
|
-
*
|
|
75
|
-
* @returns `this` (with an updated `TResult` type that includes the new field)
|
|
76
|
-
* for chaining.
|
|
77
|
-
*
|
|
78
|
-
* @example
|
|
79
|
-
* ```ts
|
|
80
|
-
* const PostSchema = object({
|
|
81
|
-
* id: number(),
|
|
82
|
-
* title: string(),
|
|
83
|
-
* authorId: number(),
|
|
84
|
-
* }).hasTableName('posts');
|
|
85
|
-
*
|
|
86
|
-
* const AuthorSchema = object({
|
|
87
|
-
* id: number(),
|
|
88
|
-
* name: string(),
|
|
89
|
-
* }).hasTableName('authors');
|
|
90
|
-
*
|
|
91
|
-
* const posts = await query(db, PostSchema)
|
|
92
|
-
* .joinOne({
|
|
93
|
-
* foreignSchema: AuthorSchema,
|
|
94
|
-
* localColumn: t => t.authorId,
|
|
95
|
-
* foreignColumn: t => t.id,
|
|
96
|
-
* as: 'author',
|
|
97
|
-
* });
|
|
98
|
-
* // posts[0].author.name — typed as string ✓
|
|
99
|
-
* ```
|
|
100
|
-
*/
|
|
101
|
-
joinOne<TForeignSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>, TFieldName extends string, TRequired extends boolean = true>(spec: JoinOneSpec<TLocalSchema, TForeignSchema, TFieldName, TRequired>): SchemaQueryBuilder<TLocalSchema, WithJoinedOne<TResult, TFieldName, TForeignSchema, TRequired>>;
|
|
102
|
-
/**
|
|
103
|
-
* Eager-load a collection of related rows (one-to-many relationship).
|
|
104
|
-
*
|
|
105
|
-
* Related rows are fetched via a single CTE + `jsonb_agg` query. The
|
|
106
|
-
* collection is attached to each result row under the field name specified
|
|
107
|
-
* by `spec.as`. Supports `limit`, `offset`, and `orderBy` per-parent
|
|
108
|
-
* using a `row_number()` window function to avoid fetching the full
|
|
109
|
-
* relation before slicing.
|
|
110
|
-
*
|
|
111
|
-
* @param spec - Join specification. Key fields:
|
|
112
|
-
* - `foreignSchema` — the `ObjectSchemaBuilder` of the related table.
|
|
113
|
-
* - `localColumn` — the primary/unique key on the local table.
|
|
114
|
-
* - `foreignColumn` — the column on the foreign table that references `localColumn`.
|
|
115
|
-
* - `as` — the property name to attach the array under.
|
|
116
|
-
* - `limit` / `offset` — optional pagination per parent row.
|
|
117
|
-
* - `orderBy` — optional `{ column, direction }` for the sub-collection.
|
|
118
|
-
* - `foreignQuery` — optional pre-filtered `Knex.QueryBuilder`.
|
|
119
|
-
*
|
|
120
|
-
* @returns `this` (with an updated `TResult` type that includes the new field)
|
|
121
|
-
* for chaining.
|
|
122
|
-
*
|
|
123
|
-
* @example
|
|
124
|
-
* ```ts
|
|
125
|
-
* const UserSchema = object({
|
|
126
|
-
* id: number(),
|
|
127
|
-
* name: string(),
|
|
128
|
-
* }).hasTableName('users');
|
|
129
|
-
*
|
|
130
|
-
* const PostSchema = object({
|
|
131
|
-
* id: number(),
|
|
132
|
-
* title: string(),
|
|
133
|
-
* authorId: number(),
|
|
134
|
-
* }).hasTableName('posts');
|
|
135
|
-
*
|
|
136
|
-
* const users = await query(db, UserSchema)
|
|
137
|
-
* .joinMany({
|
|
138
|
-
* foreignSchema: PostSchema,
|
|
139
|
-
* localColumn: t => t.id,
|
|
140
|
-
* foreignColumn: t => t.authorId,
|
|
141
|
-
* as: 'posts',
|
|
142
|
-
* limit: 5,
|
|
143
|
-
* orderBy: { column: t => t.id, direction: 'desc' },
|
|
144
|
-
* });
|
|
145
|
-
* // users[0].posts — typed as Array<{ id: number; title: string; authorId: number }>
|
|
146
|
-
* ```
|
|
147
|
-
*/
|
|
148
|
-
joinMany<TForeignSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>, TFieldName extends string>(spec: JoinManySpec<TLocalSchema, TForeignSchema, TFieldName>): SchemaQueryBuilder<TLocalSchema, WithJoinedMany<TResult, TFieldName, TForeignSchema>>;
|
|
149
|
-
/**
|
|
150
|
-
* Add a `WHERE` clause to the query.
|
|
151
|
-
*
|
|
152
|
-
* Accepts a column reference, an optional operator, and a value:
|
|
153
|
-
* - `where(t => t.age, '>', 18)` — property accessor + operator + value.
|
|
154
|
-
* - `where('age', 18)` — string key + value (defaults to `=`).
|
|
155
|
-
* - `where({ name: 'Alice' })` — record object; property keys are mapped
|
|
156
|
-
* to column names automatically.
|
|
157
|
-
* - `where(builder => { ... })` — Knex sub-builder callback for grouped
|
|
158
|
-
* conditions.
|
|
159
|
-
* - `where(knex.raw('...'))` — raw SQL expression.
|
|
160
|
-
*
|
|
161
|
-
* Multiple `.where()` calls are combined with `AND`.
|
|
162
|
-
*
|
|
163
|
-
* @returns `this` for chaining.
|
|
164
|
-
*/
|
|
19
|
+
select(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;
|
|
20
|
+
select<TSel extends SelectSelector<TLocalSchema>>(selector: TSel): SchemaQueryBuilder<TLocalSchema, SelectProjection<ReturnType<TSel>>>;
|
|
21
|
+
distinct(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;
|
|
22
|
+
count(column?: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
23
|
+
countDistinct(column?: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
24
|
+
min(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
25
|
+
max(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
26
|
+
sum(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
27
|
+
avg(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
28
|
+
selectRaw(sql: string, bindings?: any[]): this;
|
|
29
|
+
projected<K extends keyof ProjectionsOf<TLocalSchema> & string>(name: K): SchemaQueryBuilder<TLocalSchema, Pick<TResult, ProjectionKeysOf<TLocalSchema, K> & keyof TResult>>;
|
|
30
|
+
scoped<K extends ScopesOf<TLocalSchema>>(name: K): this;
|
|
31
|
+
unscoped(): this;
|
|
165
32
|
where(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;
|
|
166
33
|
where(column: ColumnRef<TLocalSchema>, value: any): this;
|
|
167
34
|
where(raw: Knex.Raw, operator: string, value: any): this;
|
|
168
35
|
where(callback: (builder: Knex.QueryBuilder) => void): this;
|
|
169
36
|
where(record: Record<string, any>): this;
|
|
170
37
|
where(raw: Knex.Raw): this;
|
|
171
|
-
/**
|
|
172
|
-
* Alias for {@link where} — explicitly adds an `AND WHERE` clause.
|
|
173
|
-
* Identical to calling `.where()` when no logical-OR grouping is needed.
|
|
174
|
-
* @returns `this` for chaining.
|
|
175
|
-
*/
|
|
176
38
|
andWhere(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;
|
|
177
39
|
andWhere(column: ColumnRef<TLocalSchema>, value: any): this;
|
|
178
40
|
andWhere(record: Record<string, any>): this;
|
|
179
41
|
andWhere(callback: (builder: Knex.QueryBuilder) => void): this;
|
|
180
42
|
andWhere(raw: Knex.Raw): this;
|
|
181
|
-
/**
|
|
182
|
-
* Add an `OR WHERE` clause. Use this to create alternative filter branches.
|
|
183
|
-
* @returns `this` for chaining.
|
|
184
|
-
*/
|
|
185
43
|
orWhere(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;
|
|
186
44
|
orWhere(column: ColumnRef<TLocalSchema>, value: any): this;
|
|
187
45
|
orWhere(record: Record<string, any>): this;
|
|
188
46
|
orWhere(callback: (builder: Knex.QueryBuilder) => void): this;
|
|
189
47
|
orWhere(raw: Knex.Raw): this;
|
|
190
|
-
/**
|
|
191
|
-
* Add a `WHERE NOT` clause — negates the condition.
|
|
192
|
-
* @returns `this` for chaining.
|
|
193
|
-
*/
|
|
194
48
|
whereNot(column: ColumnRef<TLocalSchema>, operator: string, value: any): this;
|
|
195
49
|
whereNot(column: ColumnRef<TLocalSchema>, value: any): this;
|
|
196
50
|
whereNot(record: Record<string, any>): this;
|
|
197
51
|
whereNot(callback: (builder: Knex.QueryBuilder) => void): this;
|
|
198
52
|
whereNot(raw: Knex.Raw): this;
|
|
199
|
-
/**
|
|
200
|
-
* Add a `WHERE column IN (values)` clause.
|
|
201
|
-
* @param column - Column reference (property accessor or string key).
|
|
202
|
-
* @param values - Array of values or a sub-query.
|
|
203
|
-
* @returns `this` for chaining.
|
|
204
|
-
*/
|
|
205
53
|
whereIn(column: ColumnRef<TLocalSchema>, values: readonly any[] | Knex.QueryBuilder): this;
|
|
206
|
-
/**
|
|
207
|
-
* Add a `WHERE column NOT IN (values)` clause.
|
|
208
|
-
* @param column - Column reference.
|
|
209
|
-
* @param values - Array of values or a sub-query.
|
|
210
|
-
* @returns `this` for chaining.
|
|
211
|
-
*/
|
|
212
54
|
whereNotIn(column: ColumnRef<TLocalSchema>, values: readonly any[] | Knex.QueryBuilder): this;
|
|
213
|
-
/**
|
|
214
|
-
* Add an `OR WHERE column IN (values)` clause.
|
|
215
|
-
* @returns `this` for chaining.
|
|
216
|
-
*/
|
|
217
55
|
orWhereIn(column: ColumnRef<TLocalSchema>, values: readonly any[] | Knex.QueryBuilder): this;
|
|
218
|
-
/**
|
|
219
|
-
* Add an `OR WHERE column NOT IN (values)` clause.
|
|
220
|
-
* @returns `this` for chaining.
|
|
221
|
-
*/
|
|
222
56
|
orWhereNotIn(column: ColumnRef<TLocalSchema>, values: readonly any[] | Knex.QueryBuilder): this;
|
|
223
|
-
/**
|
|
224
|
-
* Add a `WHERE column IS NULL` clause.
|
|
225
|
-
* @returns `this` for chaining.
|
|
226
|
-
*/
|
|
227
57
|
whereNull(column: ColumnRef<TLocalSchema>): this;
|
|
228
|
-
/**
|
|
229
|
-
* Add a `WHERE column IS NOT NULL` clause.
|
|
230
|
-
* @returns `this` for chaining.
|
|
231
|
-
*/
|
|
232
58
|
whereNotNull(column: ColumnRef<TLocalSchema>): this;
|
|
233
|
-
/**
|
|
234
|
-
* Add an `OR WHERE column IS NULL` clause.
|
|
235
|
-
* @returns `this` for chaining.
|
|
236
|
-
*/
|
|
237
59
|
orWhereNull(column: ColumnRef<TLocalSchema>): this;
|
|
238
|
-
/**
|
|
239
|
-
* Add an `OR WHERE column IS NOT NULL` clause.
|
|
240
|
-
* @returns `this` for chaining.
|
|
241
|
-
*/
|
|
242
60
|
orWhereNotNull(column: ColumnRef<TLocalSchema>): this;
|
|
243
|
-
/**
|
|
244
|
-
* Add a `WHERE column BETWEEN low AND high` clause.
|
|
245
|
-
* @param range - A two-element tuple `[low, high]`.
|
|
246
|
-
* @returns `this` for chaining.
|
|
247
|
-
*/
|
|
248
61
|
whereBetween(column: ColumnRef<TLocalSchema>, range: readonly [any, any]): this;
|
|
249
|
-
/**
|
|
250
|
-
* Add a `WHERE column NOT BETWEEN low AND high` clause.
|
|
251
|
-
* @param range - A two-element tuple `[low, high]`.
|
|
252
|
-
* @returns `this` for chaining.
|
|
253
|
-
*/
|
|
254
62
|
whereNotBetween(column: ColumnRef<TLocalSchema>, range: readonly [any, any]): this;
|
|
255
|
-
/**
|
|
256
|
-
* Add a case-sensitive `WHERE column LIKE value` clause.
|
|
257
|
-
* @param value - A SQL LIKE pattern (e.g. `'Alice%'`).
|
|
258
|
-
* @returns `this` for chaining.
|
|
259
|
-
*/
|
|
260
63
|
whereLike(column: ColumnRef<TLocalSchema>, value: string): this;
|
|
261
|
-
/**
|
|
262
|
-
* Add a case-insensitive `WHERE column ILIKE value` clause (PostgreSQL).
|
|
263
|
-
* @param value - A SQL LIKE pattern (e.g. `'alice%'`).
|
|
264
|
-
* @returns `this` for chaining.
|
|
265
|
-
*/
|
|
266
64
|
whereILike(column: ColumnRef<TLocalSchema>, value: string): this;
|
|
267
|
-
/**
|
|
268
|
-
* Add a raw `WHERE` clause. Useful for database-specific expressions.
|
|
269
|
-
* @param sql - Raw SQL string with optional `:binding:` or `?` placeholders.
|
|
270
|
-
* @param bindings - Values for the placeholders.
|
|
271
|
-
* @returns `this` for chaining.
|
|
272
|
-
*/
|
|
273
65
|
whereRaw(sql: string, ...bindings: any[]): this;
|
|
274
|
-
/**
|
|
275
|
-
* Add a `WHERE EXISTS (subquery)` clause.
|
|
276
|
-
* @param callback - A Knex query callback or sub-query builder.
|
|
277
|
-
* @returns `this` for chaining.
|
|
278
|
-
*/
|
|
279
66
|
whereExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this;
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
* @param column - Column reference or raw expression.
|
|
283
|
-
* @param direction - `'asc'` (default) or `'desc'`.
|
|
284
|
-
* @returns `this` for chaining.
|
|
285
|
-
*
|
|
286
|
-
* @example
|
|
287
|
-
* ```ts
|
|
288
|
-
* query(db, UserSchema).orderBy(t => t.name).orderBy(t => t.createdAt, 'desc');
|
|
289
|
-
* ```
|
|
290
|
-
*/
|
|
67
|
+
whereNotExists(callback: Knex.QueryCallback | Knex.QueryBuilder): this;
|
|
68
|
+
whereJsonPath(column: ColumnRef<TLocalSchema>, path: string, operator?: string, value?: any): this;
|
|
291
69
|
orderBy(column: ColumnRef<TLocalSchema> | Knex.Raw, direction?: 'asc' | 'desc'): this;
|
|
292
|
-
/**
|
|
293
|
-
* Order the results by a raw SQL expression.
|
|
294
|
-
* @param sql - Raw SQL (e.g. `'LOWER(name) ASC'`).
|
|
295
|
-
* @returns `this` for chaining.
|
|
296
|
-
*/
|
|
297
70
|
orderByRaw(sql: string, ...bindings: any[]): this;
|
|
298
|
-
/**
|
|
299
|
-
* Add a `GROUP BY` clause.
|
|
300
|
-
* @param columns - One or more column references or raw expressions.
|
|
301
|
-
* @returns `this` for chaining.
|
|
302
|
-
*/
|
|
303
71
|
groupBy(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;
|
|
304
|
-
/**
|
|
305
|
-
* Add a raw `GROUP BY` expression.
|
|
306
|
-
* @returns `this` for chaining.
|
|
307
|
-
*/
|
|
308
72
|
groupByRaw(sql: string, ...bindings: any[]): this;
|
|
309
|
-
/**
|
|
310
|
-
* Add a `HAVING column operator value` clause (used with `GROUP BY`).
|
|
311
|
-
* @returns `this` for chaining.
|
|
312
|
-
*/
|
|
313
73
|
having(column: ColumnRef<TLocalSchema> | Knex.Raw, operator: string, value: any): this;
|
|
314
|
-
/**
|
|
315
|
-
* Add a raw `HAVING` expression.
|
|
316
|
-
* @returns `this` for chaining.
|
|
317
|
-
*/
|
|
318
74
|
havingRaw(sql: string, ...bindings: any[]): this;
|
|
319
|
-
/**
|
|
320
|
-
* Limit the number of rows returned.
|
|
321
|
-
* @param n - Maximum number of rows.
|
|
322
|
-
* @returns `this` for chaining.
|
|
323
|
-
*/
|
|
324
75
|
limit(n: number): this;
|
|
325
|
-
/**
|
|
326
|
-
* Skip the first `n` rows in the result set (for cursor/offset pagination).
|
|
327
|
-
* @param n - Number of rows to skip.
|
|
328
|
-
* @returns `this` for chaining.
|
|
329
|
-
*/
|
|
330
76
|
offset(n: number): this;
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
* @returns `this` for chaining.
|
|
342
|
-
*/
|
|
343
|
-
distinct(...columns: (ColumnRef<TLocalSchema> | Knex.Raw)[]): this;
|
|
344
|
-
/**
|
|
345
|
-
* Add a `COUNT(*)` or `COUNT(column)` aggregate to the select list.
|
|
346
|
-
* @param column - Optional column to count (defaults to `*`).
|
|
347
|
-
* @returns `this` for chaining.
|
|
348
|
-
*/
|
|
349
|
-
count(column?: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
350
|
-
/**
|
|
351
|
-
* Add a `COUNT(DISTINCT column)` aggregate to the select list.
|
|
352
|
-
* @param column - Optional column (defaults to `*`).
|
|
353
|
-
* @returns `this` for chaining.
|
|
354
|
-
*/
|
|
355
|
-
countDistinct(column?: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
356
|
-
/**
|
|
357
|
-
* Add a `MIN(column)` aggregate.
|
|
358
|
-
* @returns `this` for chaining.
|
|
359
|
-
*/
|
|
360
|
-
min(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
361
|
-
/**
|
|
362
|
-
* Add a `MAX(column)` aggregate.
|
|
363
|
-
* @returns `this` for chaining.
|
|
364
|
-
*/
|
|
365
|
-
max(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
366
|
-
/**
|
|
367
|
-
* Add a `SUM(column)` aggregate.
|
|
368
|
-
* @returns `this` for chaining.
|
|
369
|
-
*/
|
|
370
|
-
sum(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
371
|
-
/**
|
|
372
|
-
* Add an `AVG(column)` aggregate.
|
|
373
|
-
* @returns `this` for chaining.
|
|
374
|
-
*/
|
|
375
|
-
avg(column: ColumnRef<TLocalSchema> | Knex.Raw): this;
|
|
376
|
-
/**
|
|
377
|
-
* Insert a single row into the table and return the inserted record.
|
|
378
|
-
*
|
|
379
|
-
* Property keys are mapped to SQL column names via the schema's
|
|
380
|
-
* `hasColumnName()` metadata before the `INSERT` is executed. The
|
|
381
|
-
* returned row is mapped back to property names.
|
|
382
|
-
*
|
|
383
|
-
* @param data - The object to insert. Keys must be valid schema property names.
|
|
384
|
-
* @returns The full inserted row (including database-generated fields).
|
|
385
|
-
*
|
|
386
|
-
* @example
|
|
387
|
-
* ```ts
|
|
388
|
-
* const user = await query(db, UserSchema).insert({ name: 'Alice', age: 30 });
|
|
389
|
-
* // user.id is populated by the database DEFAULT / SERIAL
|
|
390
|
-
* ```
|
|
391
|
-
*/
|
|
77
|
+
paginate(opts: {
|
|
78
|
+
page: number;
|
|
79
|
+
pageSize: number;
|
|
80
|
+
}): Promise<PaginationResult<TResult>>;
|
|
81
|
+
paginateAfter(opts: {
|
|
82
|
+
cursor?: any;
|
|
83
|
+
limit: number;
|
|
84
|
+
column?: ColumnRef<TLocalSchema>;
|
|
85
|
+
direction?: 'asc' | 'desc';
|
|
86
|
+
}): Promise<CursorPaginationResult<TResult>>;
|
|
392
87
|
insert(data: InsertType<TLocalSchema>): Promise<TResult>;
|
|
393
|
-
/**
|
|
394
|
-
* Insert multiple rows in a single `INSERT` statement and return all
|
|
395
|
-
* inserted records.
|
|
396
|
-
*
|
|
397
|
-
* @param data - Array of objects to insert.
|
|
398
|
-
* @returns The full inserted rows in insertion order.
|
|
399
|
-
*/
|
|
400
88
|
insertMany(data: InsertType<TLocalSchema>[]): Promise<TResult[]>;
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
* .update({ name: 'Bob' });
|
|
416
|
-
* ```
|
|
417
|
-
*/
|
|
89
|
+
onConflict(...conflictColumns: ColumnRef<TLocalSchema>[]): import('./operations/insert.js').OnConflictBuilder<TLocalSchema, TResult>;
|
|
90
|
+
upsert(data: InsertType<TLocalSchema>, opts: {
|
|
91
|
+
conflictColumns: ColumnRef<TLocalSchema>[];
|
|
92
|
+
updateColumns?: ColumnRef<TLocalSchema>[];
|
|
93
|
+
}): Promise<TResult>;
|
|
94
|
+
bulkInsert(rows: InsertType<TLocalSchema>[], opts?: {
|
|
95
|
+
chunkSize?: number;
|
|
96
|
+
onConflict?: 'ignore' | 'merge';
|
|
97
|
+
conflictColumns?: ColumnRef<TLocalSchema>[];
|
|
98
|
+
}): Promise<TResult[]>;
|
|
99
|
+
bulkUpsert(rows: InsertType<TLocalSchema>[], opts: {
|
|
100
|
+
conflictColumns: ColumnRef<TLocalSchema>[];
|
|
101
|
+
chunkSize?: number;
|
|
102
|
+
}): Promise<TResult[]>;
|
|
418
103
|
update(data: Partial<InferType<TLocalSchema>>): Promise<TResult[]>;
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
* @example
|
|
424
|
-
* ```ts
|
|
425
|
-
* const count = await query(db, UserSchema).where(t => t.id, id).delete();
|
|
426
|
-
* ```
|
|
427
|
-
*/
|
|
104
|
+
bulkUpdate(updates: ReadonlyArray<{
|
|
105
|
+
where: Partial<InferType<TLocalSchema>>;
|
|
106
|
+
set: Partial<InferType<TLocalSchema>>;
|
|
107
|
+
}>): Promise<number>;
|
|
428
108
|
delete(): Promise<number>;
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
* @example
|
|
440
|
-
* ```ts
|
|
441
|
-
* query(db, UserSchema).apply(qb => qb.forUpdate().noWait());
|
|
442
|
-
* ```
|
|
443
|
-
*/
|
|
109
|
+
withDeleted(): this;
|
|
110
|
+
onlyDeleted(): this;
|
|
111
|
+
hardDelete(): Promise<number>;
|
|
112
|
+
restore(): Promise<TResult[]>;
|
|
113
|
+
joinOne<TForeignSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>, TFieldName extends string, TRequired extends boolean = true>(spec: JoinOneSpec<TLocalSchema, TForeignSchema, TFieldName, TRequired>): SchemaQueryBuilder<TLocalSchema, import('./types.js').WithJoinedOne<TResult, TFieldName, TForeignSchema, TRequired>>;
|
|
114
|
+
joinMany<TForeignSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>, TFieldName extends string>(spec: JoinManySpec<TLocalSchema, TForeignSchema, TFieldName>): SchemaQueryBuilder<TLocalSchema, import('./types.js').WithJoinedMany<TResult, TFieldName, TForeignSchema>>;
|
|
115
|
+
include(relationName: string, customize?: (q: SchemaQueryBuilder<any, any>) => void): this;
|
|
116
|
+
includeVariant(variantKey: string, relationName: string, customize?: (q: SchemaQueryBuilder<any, any>) => void): this;
|
|
117
|
+
whereVariant(key: string, column: string, operator: string, value: any): this;
|
|
118
|
+
selectVariants(keys: string[]): this;
|
|
444
119
|
apply(fn: (builder: Knex.QueryBuilder) => void): this;
|
|
445
|
-
/**
|
|
446
|
-
* Bind this query builder to a Knex transaction.
|
|
447
|
-
*
|
|
448
|
-
* Returns a **new** builder that runs all operations — SELECT, INSERT,
|
|
449
|
-
* UPDATE, DELETE, and eager-loaded sub-queries — within the given
|
|
450
|
-
* transaction. The original builder is left unchanged.
|
|
451
|
-
*
|
|
452
|
-
* Use this when you already have a transaction obtained from
|
|
453
|
-
* `knex.transaction()` and want all operations performed by the returned
|
|
454
|
-
* builder to participate in that transaction.
|
|
455
|
-
*
|
|
456
|
-
* @param trx - The Knex transaction obtained from `knex.transaction()`.
|
|
457
|
-
* @returns A new {@link SchemaQueryBuilder} bound to the transaction.
|
|
458
|
-
*
|
|
459
|
-
* @example
|
|
460
|
-
* ```ts
|
|
461
|
-
* async function createUser(
|
|
462
|
-
* data: InsertType<typeof UserSchema>,
|
|
463
|
-
* trx: Knex.Transaction
|
|
464
|
-
* ) {
|
|
465
|
-
* return query(db, UserSchema).transacting(trx).insert(data);
|
|
466
|
-
* }
|
|
467
|
-
*
|
|
468
|
-
* await db.transaction(async trx => {
|
|
469
|
-
* const user = await createUser({ name: 'Alice' }, trx);
|
|
470
|
-
* await query(db, PostSchema).transacting(trx).insert({ authorId: user.id, title: 'Hello' });
|
|
471
|
-
* });
|
|
472
|
-
* ```
|
|
473
|
-
*/
|
|
474
120
|
transacting(trx: Knex.Transaction): SchemaQueryBuilder<TLocalSchema, TResult>;
|
|
475
|
-
/**
|
|
476
|
-
* Return the raw SQL string that would be executed, for debugging.
|
|
477
|
-
* Does not execute the query against the database.
|
|
478
|
-
*/
|
|
479
121
|
toQuery(): string;
|
|
480
|
-
/**
|
|
481
|
-
* Returns the underlying Knex query builder. Useful when passing this
|
|
482
|
-
* query as a `foreignQuery` in `.joinOne()` / `.joinMany()`, or any context
|
|
483
|
-
* that expects a raw `Knex.QueryBuilder`.
|
|
484
|
-
*/
|
|
485
122
|
toKnexQuery(): Knex.QueryBuilder;
|
|
486
|
-
/**
|
|
487
|
-
* Alias for {@link toQuery} — returns the raw SQL string.
|
|
488
|
-
*/
|
|
489
123
|
toString(): string;
|
|
490
|
-
/**
|
|
491
|
-
* Execute the query and return all matching rows, mapped back to schema
|
|
492
|
-
* property names.
|
|
493
|
-
*
|
|
494
|
-
* @returns A promise that resolves to an array of result objects typed as
|
|
495
|
-
* `TResult[]`.
|
|
496
|
-
*
|
|
497
|
-
* @example
|
|
498
|
-
* ```ts
|
|
499
|
-
* const users = await query(db, UserSchema).execute();
|
|
500
|
-
* ```
|
|
501
|
-
*/
|
|
502
124
|
execute(): Promise<TResult[]>;
|
|
503
|
-
/**
|
|
504
|
-
* Execute the query and return only the first row, or `undefined` if no
|
|
505
|
-
* rows match.
|
|
506
|
-
*
|
|
507
|
-
* @example
|
|
508
|
-
* ```ts
|
|
509
|
-
* const user = await query(db, UserSchema).where(t => t.id, id).first();
|
|
510
|
-
* if (user) { /* ... *\/ }
|
|
511
|
-
* ```
|
|
512
|
-
*/
|
|
513
125
|
first(): Promise<TResult | undefined>;
|
|
514
|
-
|
|
515
|
-
* Thenable implementation — allows the builder to be awaited directly
|
|
516
|
-
* without calling {@link execute} explicitly.
|
|
517
|
-
*
|
|
518
|
-
* @example
|
|
519
|
-
* ```ts
|
|
520
|
-
* const users = await query(db, UserSchema).where(t => t.name, 'Alice');
|
|
521
|
-
* // Equivalent to: await query(db, UserSchema).where(...).execute()
|
|
522
|
-
* ```
|
|
523
|
-
*/
|
|
126
|
+
pluck<K extends keyof TResult & string>(column: ColumnRef<TLocalSchema>): Promise<TResult[K][]>;
|
|
524
127
|
then<TReturn1 = TResult[], TReturn2 = never>(onfulfilled?: ((value: TResult[]) => TReturn1 | PromiseLike<TReturn1>) | null, onrejected?: ((reason: any) => TReturn2 | PromiseLike<TReturn2>) | null): Promise<TReturn1 | TReturn2>;
|
|
525
128
|
}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
*
|
|
529
|
-
* The schema must have a table name configured via `.hasTableName()`.
|
|
530
|
-
* Column name mappings set via `.hasColumnName()` are applied automatically
|
|
531
|
-
* to all query methods. The returned builder is thenable — you can `await` it
|
|
532
|
-
* directly to execute the query and get `TResult[]`.
|
|
533
|
-
*
|
|
534
|
-
* @param knex - A configured Knex instance.
|
|
535
|
-
* @param schema - The `ObjectSchemaBuilder` describing the table.
|
|
536
|
-
* @returns A new {@link SchemaQueryBuilder} ready for chaining.
|
|
537
|
-
*
|
|
538
|
-
* @example
|
|
539
|
-
* ```ts
|
|
540
|
-
* import knex from 'knex';
|
|
541
|
-
* import { query, object, string, number } from '@cleverbrush/knex-schema';
|
|
542
|
-
*
|
|
543
|
-
* const UserSchema = object({ id: number(), name: string() }).hasTableName('users');
|
|
544
|
-
* const db = knex({ client: 'pg', connection: process.env.DB_URL });
|
|
545
|
-
*
|
|
546
|
-
* const users = await query(db, UserSchema).where(t => t.name, 'like', 'A%');
|
|
547
|
-
* ```
|
|
548
|
-
*/
|
|
549
|
-
export declare function query<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(knex: Knex, schema: TLocalSchema): SchemaQueryBuilder<TLocalSchema, InferType<TLocalSchema>>;
|
|
550
|
-
/**
|
|
551
|
-
* Create a typed {@link SchemaQueryBuilder} from an existing Knex query builder.
|
|
552
|
-
*
|
|
553
|
-
* Use this overload when you need to supply a pre-configured base query —
|
|
554
|
-
* for example one that already has a sub-query, CTE, or a schema scope applied.
|
|
555
|
-
*
|
|
556
|
-
* @param knex - A configured Knex instance.
|
|
557
|
-
* @param schema - The `ObjectSchemaBuilder` describing the table.
|
|
558
|
-
* @param baseQuery - An existing `Knex.QueryBuilder` to use as the base.
|
|
559
|
-
* @returns A new {@link SchemaQueryBuilder} wrapping `baseQuery`.
|
|
560
|
-
*
|
|
561
|
-
* @example
|
|
562
|
-
* ```ts
|
|
563
|
-
* // Use a scoped base query (e.g. soft-delete filter applied globally)
|
|
564
|
-
* const base = db('users').where('deleted_at', null);
|
|
565
|
-
* const activeUsers = await query(db, UserSchema, base).where(t => t.age, '>', 18);
|
|
566
|
-
* ```
|
|
567
|
-
*/
|
|
568
|
-
export declare function query<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(knex: Knex, schema: TLocalSchema, baseQuery: Knex.QueryBuilder): SchemaQueryBuilder<TLocalSchema, InferType<TLocalSchema>>;
|
|
569
|
-
/** Bound query function returned by {@link createQuery}. */
|
|
129
|
+
export declare function query<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(knex: Knex, schema: TLocalSchema): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;
|
|
130
|
+
export declare function query<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(knex: Knex, schema: TLocalSchema, baseQuery: Knex.QueryBuilder): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;
|
|
570
131
|
export interface BoundQuery {
|
|
571
|
-
<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(schema: TLocalSchema): SchemaQueryBuilder<TLocalSchema,
|
|
572
|
-
<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(schema: TLocalSchema, baseQuery: Knex.QueryBuilder): SchemaQueryBuilder<TLocalSchema,
|
|
573
|
-
/**
|
|
574
|
-
* Return a version of this bound factory whose queries all run within the
|
|
575
|
-
* given Knex transaction. Equivalent to calling `.transacting(trx)` on
|
|
576
|
-
* each individual builder, but more convenient when every query in a block
|
|
577
|
-
* must share the same transaction.
|
|
578
|
-
*
|
|
579
|
-
* @example
|
|
580
|
-
* ```ts
|
|
581
|
-
* const db = createQuery(knex);
|
|
582
|
-
*
|
|
583
|
-
* await knex.transaction(async trx => {
|
|
584
|
-
* const dbTrx = db.withTransaction(trx);
|
|
585
|
-
* const user = await dbTrx(UserSchema).insert({ name: 'Alice' });
|
|
586
|
-
* await dbTrx(PostSchema).insert({ authorId: user.id, title: 'Hello' });
|
|
587
|
-
* });
|
|
588
|
-
* ```
|
|
589
|
-
*/
|
|
132
|
+
<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(schema: TLocalSchema): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;
|
|
133
|
+
<TLocalSchema extends ObjectSchemaBuilder<any, any, any, any, any, any, any>>(schema: TLocalSchema, baseQuery: Knex.QueryBuilder): SchemaQueryBuilder<TLocalSchema, QueryResultType<TLocalSchema>>;
|
|
590
134
|
withTransaction(trx: Knex.Transaction): BoundQuery;
|
|
591
|
-
/**
|
|
592
|
-
* Start a Knex transaction and run `callback` inside it, passing a
|
|
593
|
-
* transaction-bound `BoundQuery` factory as the argument. The transaction
|
|
594
|
-
* is committed when the callback resolves and rolled back if it rejects.
|
|
595
|
-
*
|
|
596
|
-
* This is the callback-style counterpart to {@link withTransaction} — you
|
|
597
|
-
* don't need to obtain a `Knex.Transaction` object yourself.
|
|
598
|
-
*
|
|
599
|
-
* @param callback - An async function that receives a transaction-bound
|
|
600
|
-
* `BoundQuery` and returns a value. The returned value is forwarded as
|
|
601
|
-
* the resolved value of the outer `Promise`.
|
|
602
|
-
* @returns A `Promise` that resolves with the value returned by `callback`.
|
|
603
|
-
*
|
|
604
|
-
* @example
|
|
605
|
-
* ```ts
|
|
606
|
-
* const db = createQuery(knex);
|
|
607
|
-
*
|
|
608
|
-
* const user = await db.transaction(async dbTrx => {
|
|
609
|
-
* const newUser = await dbTrx(UserSchema).insert({ name: 'Alice' });
|
|
610
|
-
* await dbTrx(PostSchema).insert({ authorId: newUser.id, title: 'Hello' });
|
|
611
|
-
* return newUser;
|
|
612
|
-
* });
|
|
613
|
-
* ```
|
|
614
|
-
*/
|
|
615
135
|
transaction<T>(callback: (db: BoundQuery) => Promise<T>): Promise<T>;
|
|
616
136
|
}
|
|
617
|
-
/**
|
|
618
|
-
* Bind a Knex instance once and get back a `query(schema)` function that
|
|
619
|
-
* doesn't require repeating the knex argument on every call.
|
|
620
|
-
*
|
|
621
|
-
* @param knex - A configured Knex instance.
|
|
622
|
-
* @returns A bound query factory: `(schema, baseQuery?) => SchemaQueryBuilder`.
|
|
623
|
-
*
|
|
624
|
-
* @example
|
|
625
|
-
* ```ts
|
|
626
|
-
* import Knex from 'knex';
|
|
627
|
-
* import { createQuery } from '@cleverbrush/knex-schema';
|
|
628
|
-
*
|
|
629
|
-
* const knex = Knex({ client: 'pg', connection: process.env.DB_URL });
|
|
630
|
-
* const query = createQuery(knex);
|
|
631
|
-
*
|
|
632
|
-
* // No knex argument needed from here on
|
|
633
|
-
* const users = await query(UserSchema).where(t => t.role, '=', 'admin');
|
|
634
|
-
* const post = await query(PostSchema).where(t => t.id, '=', 42).first();
|
|
635
|
-
*
|
|
636
|
-
* // Optional base query (e.g. soft-delete scope applied globally)
|
|
637
|
-
* const active = query(UserSchema, knex('users').where('deleted_at', null));
|
|
638
|
-
* ```
|
|
639
|
-
*/
|
|
640
137
|
export declare function createQuery(knexInstance: Knex): BoundQuery;
|