flint-orm 0.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/API.md +620 -0
- package/README.md +0 -0
- package/dist/entries/expressions.d.ts +5 -0
- package/dist/entries/expressions.js +1184 -0
- package/dist/entries/table.d.ts +4 -0
- package/dist/entries/table.js +302 -0
- package/dist/errors.d.ts +13 -0
- package/dist/flint.d.ts +128 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +1485 -0
- package/dist/query/aggregates.d.ts +47 -0
- package/dist/query/builder.d.ts +256 -0
- package/dist/query/conditions.d.ts +176 -0
- package/dist/schema/columns.d.ts +137 -0
- package/dist/schema/table.d.ts +44 -0
- package/dist/src/entries/expressions.d.ts +5 -0
- package/dist/src/entries/table.d.ts +4 -0
- package/dist/src/errors.d.ts +13 -0
- package/dist/src/flint.d.ts +128 -0
- package/dist/src/index.d.ts +9 -0
- package/dist/src/query/aggregates.d.ts +47 -0
- package/dist/src/query/builder.d.ts +256 -0
- package/dist/src/query/conditions.d.ts +176 -0
- package/dist/src/schema/columns.d.ts +137 -0
- package/dist/src/schema/table.d.ts +44 -0
- package/package.json +40 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Database } from 'bun:sqlite';
|
|
2
|
+
import type { ColumnDef } from '../schema/columns';
|
|
3
|
+
import type { AnyTable } from '../schema/table';
|
|
4
|
+
import type { Condition } from './conditions';
|
|
5
|
+
/**
|
|
6
|
+
* Count all rows in a table, optionally filtered by a condition.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* const total = db.count(users);
|
|
10
|
+
* const active = db.count(users, eq(users.active, true));
|
|
11
|
+
*/
|
|
12
|
+
export declare function count<T extends AnyTable>(client: Database, table: T, condition?: Condition): number;
|
|
13
|
+
/**
|
|
14
|
+
* Count non-null values of a column, optionally filtered by a condition.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const count = db.countColumn(users, users.email);
|
|
18
|
+
*/
|
|
19
|
+
export declare function countColumn<T extends AnyTable, C extends ColumnDef<any, any>>(client: Database, table: T, column: C, condition?: Condition): number;
|
|
20
|
+
/**
|
|
21
|
+
* Sum non-null values of a column, optionally filtered by a condition.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const total = db.sum(orders, orders.amount);
|
|
25
|
+
*/
|
|
26
|
+
export declare function sum<T extends AnyTable, C extends ColumnDef<any, any>>(client: Database, table: T, column: C, condition?: Condition): number | null;
|
|
27
|
+
/**
|
|
28
|
+
* Average non-null values of a column, optionally filtered by a condition.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const avgAge = db.avg(users, users.age);
|
|
32
|
+
*/
|
|
33
|
+
export declare function avg<T extends AnyTable, C extends ColumnDef<any, any>>(client: Database, table: T, column: C, condition?: Condition): number | null;
|
|
34
|
+
/**
|
|
35
|
+
* Find the minimum non-null value of a column, optionally filtered by a condition.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const minAge = db.min(users, users.age);
|
|
39
|
+
*/
|
|
40
|
+
export declare function min<T extends AnyTable, C extends ColumnDef<any, any>>(client: Database, table: T, column: C, condition?: Condition): number | null;
|
|
41
|
+
/**
|
|
42
|
+
* Find the maximum non-null value of a column, optionally filtered by a condition.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const maxAge = db.max(users, users.age);
|
|
46
|
+
*/
|
|
47
|
+
export declare function max<T extends AnyTable, C extends ColumnDef<any, any>>(client: Database, table: T, column: C, condition?: Condition): number | null;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import type { ColumnDef } from '../schema/columns';
|
|
2
|
+
import type { Condition } from './conditions';
|
|
3
|
+
import type { AnyTable, InferRow, InsertRow } from '../schema/table';
|
|
4
|
+
/**
|
|
5
|
+
* Narrow a row type to specific columns using a mapped type.
|
|
6
|
+
* Unlike Pick, TypeScript eagerly evaluates { [K in C]: T[K] } to a concrete
|
|
7
|
+
* shape in hover info: { id: string; name: string } instead of Pick<...>.
|
|
8
|
+
*/
|
|
9
|
+
export type NarrowRow<T, C extends keyof T> = {
|
|
10
|
+
[K in C]: T[K];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Force TypeScript to expand intersection/mapped types into a flat object
|
|
14
|
+
* in hover info: Prettify<{ id: string } & { name: string }> → { id: string; name: string }.
|
|
15
|
+
*/
|
|
16
|
+
export type Prettify<T> = {
|
|
17
|
+
[K in keyof T]: T[K];
|
|
18
|
+
} & {};
|
|
19
|
+
/** Anything that can produce SQL — used by `db.batch()`. */
|
|
20
|
+
export interface Executable {
|
|
21
|
+
toSQL(): {
|
|
22
|
+
sql: string;
|
|
23
|
+
params: unknown[];
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Phase 1 of a SELECT — only `.from()` is available. */
|
|
27
|
+
export interface SelectStage1 {
|
|
28
|
+
from<U extends AnyTable>(table: U): SelectBuilder<U>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Full SELECT builder — available after `.from()`.
|
|
32
|
+
* Returns `InferRow<T>[]` (all columns) from `execute()`.
|
|
33
|
+
* Call `.columns()` to narrow — returns a `NarrowedSelectBuilder`.
|
|
34
|
+
*/
|
|
35
|
+
export declare class SelectBuilder<T extends AnyTable> implements Executable {
|
|
36
|
+
#private;
|
|
37
|
+
constructor(client: DatabaseClient, tableName: string, table: T, conditions?: Condition[], selectedColumns?: (keyof InferRow<T>)[] | null, orderByClauses?: {
|
|
38
|
+
column: ColumnDef<any, any>;
|
|
39
|
+
direction: 'asc' | 'desc';
|
|
40
|
+
}[], limitValue?: number | null, offsetValue?: number | null, distinct?: boolean);
|
|
41
|
+
/** Add a WHERE condition. Multiple calls stack. */
|
|
42
|
+
where(condition: Condition): SelectBuilder<T>;
|
|
43
|
+
/**
|
|
44
|
+
* Narrow which columns appear in the result.
|
|
45
|
+
* Returns a `NarrowedSelectBuilder` with a clean `{ id: string; name: string }` return type.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* db.select().from(users).columns(["id", "name"]).execute()
|
|
49
|
+
* // ^? { id: string; name: string }[]
|
|
50
|
+
*/
|
|
51
|
+
columns<K extends keyof InferRow<T>>(keys: K[]): NarrowedSelectBuilder<T, K>;
|
|
52
|
+
/** Return a single row or null instead of an array. Adds `LIMIT 1` to the SQL. */
|
|
53
|
+
single(): SingleSelectBuilder<T>;
|
|
54
|
+
/** Return only distinct (unique) rows. */
|
|
55
|
+
distinct(): SelectBuilder<T>;
|
|
56
|
+
/** Add an ORDER BY clause. Multiple calls stack. */
|
|
57
|
+
orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): SelectBuilder<T>;
|
|
58
|
+
/** Limit the number of results. */
|
|
59
|
+
limit(n: number): SelectBuilder<T>;
|
|
60
|
+
/** Skip N rows before returning results. */
|
|
61
|
+
offset(n: number): SelectBuilder<T>;
|
|
62
|
+
toSQL(): {
|
|
63
|
+
sql: string;
|
|
64
|
+
params: unknown[];
|
|
65
|
+
};
|
|
66
|
+
/** Execute the query and return all matching rows. */
|
|
67
|
+
execute(): InferRow<T>[];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Narrowed SELECT builder — after `.columns()` has been called.
|
|
71
|
+
* Returns `NarrowRow<InferRow<T>, C>[]` from `execute()` — a clean
|
|
72
|
+
* `{ id: string; name: string }` shape, no Pick wrapper.
|
|
73
|
+
*/
|
|
74
|
+
export declare class NarrowedSelectBuilder<T extends AnyTable, C extends keyof InferRow<T>> implements Executable {
|
|
75
|
+
#private;
|
|
76
|
+
constructor(client: DatabaseClient, tableName: string, table: T, conditions: Condition[], selectedColumns: C[], orderByClauses: {
|
|
77
|
+
column: ColumnDef<any, any>;
|
|
78
|
+
direction: 'asc' | 'desc';
|
|
79
|
+
}[], limitValue: number | null, offsetValue: number | null, distinct: boolean);
|
|
80
|
+
where(condition: Condition): NarrowedSelectBuilder<T, C>;
|
|
81
|
+
distinct(): NarrowedSelectBuilder<T, C>;
|
|
82
|
+
single(): NarrowedSingleSelectBuilder<T, C>;
|
|
83
|
+
orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): NarrowedSelectBuilder<T, C>;
|
|
84
|
+
limit(n: number): NarrowedSelectBuilder<T, C>;
|
|
85
|
+
offset(n: number): NarrowedSelectBuilder<T, C>;
|
|
86
|
+
toSQL(): {
|
|
87
|
+
sql: string;
|
|
88
|
+
params: unknown[];
|
|
89
|
+
};
|
|
90
|
+
/** Execute the query and return narrowed rows. */
|
|
91
|
+
execute(): Prettify<NarrowRow<InferRow<T>, C>>[];
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Single-row SELECT builder — after `.single()` on a `SelectBuilder`.
|
|
95
|
+
* Returns `InferRow<T> | null` from `execute()`.
|
|
96
|
+
*/
|
|
97
|
+
export declare class SingleSelectBuilder<T extends AnyTable> implements Executable {
|
|
98
|
+
#private;
|
|
99
|
+
constructor(client: DatabaseClient, tableName: string, table: T, conditions: Condition[], selectedColumns?: (keyof InferRow<T>)[] | null, orderByClauses?: {
|
|
100
|
+
column: ColumnDef<any, any>;
|
|
101
|
+
direction: 'asc' | 'desc';
|
|
102
|
+
}[], offsetValue?: number | null, distinct?: boolean);
|
|
103
|
+
where(condition: Condition): SingleSelectBuilder<T>;
|
|
104
|
+
orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): SingleSelectBuilder<T>;
|
|
105
|
+
offset(n: number): SingleSelectBuilder<T>;
|
|
106
|
+
toSQL(): {
|
|
107
|
+
sql: string;
|
|
108
|
+
params: unknown[];
|
|
109
|
+
};
|
|
110
|
+
/** Returns a single row or null, never throws on empty results. */
|
|
111
|
+
execute(): InferRow<T> | null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Narrowed single-row SELECT builder — after `.single()` on a `NarrowedSelectBuilder`.
|
|
115
|
+
* Returns `NarrowRow<InferRow<T>, C> | null` from `execute()`.
|
|
116
|
+
*/
|
|
117
|
+
export declare class NarrowedSingleSelectBuilder<T extends AnyTable, C extends keyof InferRow<T>> implements Executable {
|
|
118
|
+
#private;
|
|
119
|
+
constructor(client: DatabaseClient, tableName: string, table: T, conditions: Condition[], selectedColumns: C[], orderByClauses: {
|
|
120
|
+
column: ColumnDef<any, any>;
|
|
121
|
+
direction: 'asc' | 'desc';
|
|
122
|
+
}[], offsetValue: number | null, distinct: boolean);
|
|
123
|
+
where(condition: Condition): NarrowedSingleSelectBuilder<T, C>;
|
|
124
|
+
orderBy<K extends keyof InferRow<T>>(key: K, direction?: 'asc' | 'desc'): NarrowedSingleSelectBuilder<T, C>;
|
|
125
|
+
offset(n: number): NarrowedSingleSelectBuilder<T, C>;
|
|
126
|
+
toSQL(): {
|
|
127
|
+
sql: string;
|
|
128
|
+
params: unknown[];
|
|
129
|
+
};
|
|
130
|
+
/** Returns a single narrowed row or null. */
|
|
131
|
+
execute(): Prettify<NarrowRow<InferRow<T>, C>> | null;
|
|
132
|
+
}
|
|
133
|
+
/** Phase 1 of a JOIN — only `.on()` is available. */
|
|
134
|
+
export interface JoinSelectStage1<Parent extends AnyTable> {
|
|
135
|
+
on<Child extends AnyTable>(child: Child, condition: Condition): JoinBuilder<Parent, [Child]>;
|
|
136
|
+
/** Auto-join: infer condition from foreign key references. */
|
|
137
|
+
on<Child extends AnyTable>(child: Child): JoinBuilder<Parent, [Child]>;
|
|
138
|
+
}
|
|
139
|
+
/** Full join builder — chain more `.on()` calls or call `.execute()`. */
|
|
140
|
+
export interface JoinBuilder<Parent extends AnyTable, Joined extends AnyTable[], ParentCols extends keyof InferRow<Parent> = keyof InferRow<Parent>> {
|
|
141
|
+
on<NewChild extends AnyTable>(child: NewChild, condition: Condition): JoinBuilder<Parent, [...Joined, NewChild], ParentCols>;
|
|
142
|
+
/** Auto-join: infer condition from foreign key references. */
|
|
143
|
+
on<NewChild extends AnyTable>(child: NewChild): JoinBuilder<Parent, [...Joined, NewChild], ParentCols>;
|
|
144
|
+
columns<K extends keyof InferRow<Parent>>(keys: K[]): JoinBuilder<Parent, Joined, K>;
|
|
145
|
+
where(condition: Condition): JoinBuilder<Parent, Joined, ParentCols>;
|
|
146
|
+
orderBy<K extends keyof InferRow<Parent>>(key: K, direction?: 'asc' | 'desc'): JoinBuilder<Parent, Joined, ParentCols>;
|
|
147
|
+
limit(n: number): JoinBuilder<Parent, Joined, ParentCols>;
|
|
148
|
+
offset(n: number): JoinBuilder<Parent, Joined, ParentCols>;
|
|
149
|
+
single(): SingleJoinBuilder<Parent, Joined, ParentCols>;
|
|
150
|
+
toSQL(): {
|
|
151
|
+
sql: string;
|
|
152
|
+
params: unknown[];
|
|
153
|
+
};
|
|
154
|
+
execute(): JoinResult<Parent, Joined, ParentCols>[];
|
|
155
|
+
}
|
|
156
|
+
/** The result type for joined queries. Parent fields are narrowed by `.columns()`; each joined table's data is nested under its table name. */
|
|
157
|
+
export type JoinResult<Parent extends AnyTable, _Joined extends AnyTable[], ParentCols extends keyof InferRow<Parent> = keyof InferRow<Parent>> = Prettify<Pick<InferRow<Parent>, ParentCols>> & Record<string, unknown>;
|
|
158
|
+
/** Phase 1 of an INSERT — only `.values()` is available. */
|
|
159
|
+
export interface InsertStage1<T extends AnyTable> {
|
|
160
|
+
values(row: InsertRow<T>): InsertBuilder<T>;
|
|
161
|
+
values(rows: InsertRow<T>[]): InsertBuilder<T>;
|
|
162
|
+
}
|
|
163
|
+
type OnConflictDoUpdate<T extends AnyTable> = {
|
|
164
|
+
mode: 'update';
|
|
165
|
+
target: ColumnDef<any, any> | ColumnDef<any, any>[];
|
|
166
|
+
set: Partial<InferRow<T>>;
|
|
167
|
+
};
|
|
168
|
+
type OnConflictStrategy<T extends AnyTable> = OnConflictDoNothing | OnConflictDoUpdate<T>;
|
|
169
|
+
/** Full INSERT builder — available after `.values()` has been called. */
|
|
170
|
+
export declare class InsertBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
|
|
171
|
+
#private;
|
|
172
|
+
constructor(client: DatabaseClient, tableName: string, table: T, rowOrRows: InsertRow<T> | InsertRow<T>[], returning?: boolean | K[], onConflict?: OnConflictStrategy<T>);
|
|
173
|
+
/**
|
|
174
|
+
* Return the inserted row(s) instead of void.
|
|
175
|
+
* Pass an array of column names to narrow the result shape.
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
* db.insert(users).values({ id: "u1", name: "Alice" }).returning()
|
|
179
|
+
* db.insert(users).values({ id: "u1", name: "Alice" }).returning(["id", "name"])
|
|
180
|
+
*/
|
|
181
|
+
returning(): InsertBuilder<T, true>;
|
|
182
|
+
returning<NewK extends keyof InferRow<T>>(keys: NewK[]): InsertBuilder<T, true, NewK>;
|
|
183
|
+
/**
|
|
184
|
+
* On conflict, do nothing (ignore the insert).
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* db.insert(users).values(row).onConflictDoNothing()
|
|
188
|
+
*/
|
|
189
|
+
onConflictDoNothing(): InsertBuilder<T, R, K>;
|
|
190
|
+
/**
|
|
191
|
+
* On conflict, update specified columns with the proposed values.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* db.insert(users).values(row).onConflictDoUpdate({
|
|
195
|
+
* target: users.id,
|
|
196
|
+
* set: { name: "Alice" },
|
|
197
|
+
* })
|
|
198
|
+
*/
|
|
199
|
+
onConflictDoUpdate<C extends ColumnDef<any, any>>(options: {
|
|
200
|
+
target: C | C[];
|
|
201
|
+
set: Partial<InferRow<T>>;
|
|
202
|
+
}): InsertBuilder<T, R, K>;
|
|
203
|
+
toSQL(): {
|
|
204
|
+
sql: string;
|
|
205
|
+
params: unknown[];
|
|
206
|
+
};
|
|
207
|
+
execute(): R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : void;
|
|
208
|
+
}
|
|
209
|
+
/** Phase 1 of an UPDATE — only `.set()` is available. */
|
|
210
|
+
export interface UpdateStage1<T extends AnyTable> {
|
|
211
|
+
set(partial: Partial<InferRow<T>>): UpdateBuilder<T>;
|
|
212
|
+
}
|
|
213
|
+
/** Full UPDATE builder — available after `.set()` has been called. */
|
|
214
|
+
export declare class UpdateBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
|
|
215
|
+
#private;
|
|
216
|
+
constructor(client: DatabaseClient, tableName: string, table: T, set: Partial<InferRow<T>>, conditions?: Condition[], returning?: boolean | K[]);
|
|
217
|
+
set(partial: Partial<InferRow<T>>): UpdateBuilder<T, R, K>;
|
|
218
|
+
where(condition: Condition): UpdateBuilder<T, R, K>;
|
|
219
|
+
/**
|
|
220
|
+
* Return the updated row(s) instead of void.
|
|
221
|
+
* Pass an array of column names to narrow the result shape.
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* db.update(users).set({ name: "Bob" }).where(eq(users.id, "u1")).returning()
|
|
225
|
+
* db.update(users).set({ name: "Bob" }).where(eq(users.id, "u1")).returning(["id", "name"])
|
|
226
|
+
*/
|
|
227
|
+
returning(): UpdateBuilder<T, true>;
|
|
228
|
+
returning<NewK extends keyof InferRow<T>>(keys: NewK[]): UpdateBuilder<T, true, NewK>;
|
|
229
|
+
toSQL(): {
|
|
230
|
+
sql: string;
|
|
231
|
+
params: unknown[];
|
|
232
|
+
};
|
|
233
|
+
execute(): R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : void;
|
|
234
|
+
}
|
|
235
|
+
/** Full DELETE builder — chain `.where()` calls then `.execute()`. */
|
|
236
|
+
export declare class DeleteBuilder<T extends AnyTable, R extends boolean = false, K extends keyof InferRow<T> = keyof InferRow<T>> implements Executable {
|
|
237
|
+
#private;
|
|
238
|
+
constructor(client: DatabaseClient, tableName: string, table: T, conditions?: Condition[], returning?: boolean | K[]);
|
|
239
|
+
where(condition: Condition): DeleteBuilder<T, R, K>;
|
|
240
|
+
/**
|
|
241
|
+
* Return the deleted row(s) instead of void.
|
|
242
|
+
* Pass an array of column names to narrow the result shape.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* db.delete(users).where(eq(users.id, "u1")).returning()
|
|
246
|
+
* db.delete(users).where(eq(users.id, "u1")).returning(["id", "name"])
|
|
247
|
+
*/
|
|
248
|
+
returning(): DeleteBuilder<T, true>;
|
|
249
|
+
returning<NewK extends keyof InferRow<T>>(keys: NewK[]): DeleteBuilder<T, true, NewK>;
|
|
250
|
+
toSQL(): {
|
|
251
|
+
sql: string;
|
|
252
|
+
params: unknown[];
|
|
253
|
+
};
|
|
254
|
+
execute(): R extends true ? Prettify<NarrowRow<InferRow<T>, K>>[] : void;
|
|
255
|
+
}
|
|
256
|
+
export {};
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import type { ColumnDef } from '../schema/columns';
|
|
2
|
+
/** A condition node used in WHERE clauses. */
|
|
3
|
+
export type Condition = {
|
|
4
|
+
type: 'eq';
|
|
5
|
+
column: ColumnDef<any, any>;
|
|
6
|
+
value: unknown;
|
|
7
|
+
} | {
|
|
8
|
+
type: 'eqColumn';
|
|
9
|
+
left: ColumnDef<any, any>;
|
|
10
|
+
right: ColumnDef<any, any>;
|
|
11
|
+
} | {
|
|
12
|
+
type: 'gt';
|
|
13
|
+
column: ColumnDef<any, any>;
|
|
14
|
+
value: unknown;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'gte';
|
|
17
|
+
column: ColumnDef<any, any>;
|
|
18
|
+
value: unknown;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'lt';
|
|
21
|
+
column: ColumnDef<any, any>;
|
|
22
|
+
value: unknown;
|
|
23
|
+
} | {
|
|
24
|
+
type: 'lte';
|
|
25
|
+
column: ColumnDef<any, any>;
|
|
26
|
+
value: unknown;
|
|
27
|
+
} | {
|
|
28
|
+
type: 'neq';
|
|
29
|
+
column: ColumnDef<any, any>;
|
|
30
|
+
value: unknown;
|
|
31
|
+
} | {
|
|
32
|
+
type: 'in';
|
|
33
|
+
column: ColumnDef<any, any>;
|
|
34
|
+
values: unknown[];
|
|
35
|
+
} | {
|
|
36
|
+
type: 'notIn';
|
|
37
|
+
column: ColumnDef<any, any>;
|
|
38
|
+
values: unknown[];
|
|
39
|
+
} | {
|
|
40
|
+
type: 'isNull';
|
|
41
|
+
column: ColumnDef<any, any>;
|
|
42
|
+
} | {
|
|
43
|
+
type: 'isNotNull';
|
|
44
|
+
column: ColumnDef<any, any>;
|
|
45
|
+
} | {
|
|
46
|
+
type: 'like';
|
|
47
|
+
column: ColumnDef<any, any>;
|
|
48
|
+
pattern: string;
|
|
49
|
+
} | {
|
|
50
|
+
type: 'glob';
|
|
51
|
+
column: ColumnDef<any, any>;
|
|
52
|
+
pattern: string;
|
|
53
|
+
} | {
|
|
54
|
+
type: 'between';
|
|
55
|
+
column: ColumnDef<any, any>;
|
|
56
|
+
low: unknown;
|
|
57
|
+
high: unknown;
|
|
58
|
+
} | {
|
|
59
|
+
type: 'and';
|
|
60
|
+
conditions: Condition[];
|
|
61
|
+
} | {
|
|
62
|
+
type: 'or';
|
|
63
|
+
conditions: Condition[];
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Check if a column equals a value, or if two columns are equal.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* // Value comparison
|
|
70
|
+
* where(eq(users.name, "Alice"))
|
|
71
|
+
*
|
|
72
|
+
* // Column-to-column comparison
|
|
73
|
+
* where(eq(orders.userId, users.id))
|
|
74
|
+
*/
|
|
75
|
+
export declare function eq<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
76
|
+
export declare function eq<T>(left: ColumnDef<T, any>, right: ColumnDef<T, any>): Condition;
|
|
77
|
+
/**
|
|
78
|
+
* Combine conditions with AND.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* where(and(eq(users.name, "Alice"), eq(users.active, true)))
|
|
82
|
+
*/
|
|
83
|
+
export declare function and(...conditions: Condition[]): Condition;
|
|
84
|
+
/**
|
|
85
|
+
* Combine conditions with OR.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* where(or(eq(users.role, "admin"), eq(users.role, "moderator")))
|
|
89
|
+
*/
|
|
90
|
+
export declare function or(...conditions: Condition[]): Condition;
|
|
91
|
+
/**
|
|
92
|
+
* Check if a column's value is in the given array.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* where(isIn(users.id, ["u1", "u2", "u3"]))
|
|
96
|
+
*/
|
|
97
|
+
export declare function isIn<T>(column: ColumnDef<T, any>, values: T[]): Condition;
|
|
98
|
+
/**
|
|
99
|
+
* Check if a column's value is not in the given array.
|
|
100
|
+
*
|
|
101
|
+
* @example
|
|
102
|
+
* where(isNotIn(users.id, ["u4", "u5"]))
|
|
103
|
+
*/
|
|
104
|
+
export declare function isNotIn<T>(column: ColumnDef<T, any>, values: T[]): Condition;
|
|
105
|
+
/**
|
|
106
|
+
* Check if a column is NULL.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* where(isNull(users.deletedAt))
|
|
110
|
+
*/
|
|
111
|
+
export declare function isNull(column: ColumnDef<any, any>): Condition;
|
|
112
|
+
/**
|
|
113
|
+
* Check if a column is NOT NULL.
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* where(isNotNull(users.name))
|
|
117
|
+
*/
|
|
118
|
+
export declare function isNotNull(column: ColumnDef<any, any>): Condition;
|
|
119
|
+
/**
|
|
120
|
+
* Pattern match using SQL `LIKE`. Use `%` for any sequence of characters, `_` for a single character.
|
|
121
|
+
*
|
|
122
|
+
* @example
|
|
123
|
+
* where(like(users.name, "A%"))
|
|
124
|
+
*/
|
|
125
|
+
export declare function like(column: ColumnDef<any, any>, pattern: string): Condition;
|
|
126
|
+
/**
|
|
127
|
+
* Pattern match using SQL `GLOB`. Use `*` for any sequence of characters, `?` for a single character.
|
|
128
|
+
*
|
|
129
|
+
* @example
|
|
130
|
+
* where(glob(users.name, "A*"))
|
|
131
|
+
*/
|
|
132
|
+
export declare function glob(column: ColumnDef<any, any>, pattern: string): Condition;
|
|
133
|
+
/**
|
|
134
|
+
* Check if a column's value is between `low` and `high` (inclusive).
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* where(between(users.age, 18, 65))
|
|
138
|
+
*/
|
|
139
|
+
export declare function between<T>(column: ColumnDef<T, any>, low: T, high: T): Condition;
|
|
140
|
+
/**
|
|
141
|
+
* Check if a column's value is greater than a value.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* where(gt(users.age, 18))
|
|
145
|
+
*/
|
|
146
|
+
export declare function gt<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
147
|
+
/**
|
|
148
|
+
* Check if a column's value is greater than or equal to a value.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* where(gte(users.age, 18))
|
|
152
|
+
*/
|
|
153
|
+
export declare function gte<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
154
|
+
/**
|
|
155
|
+
* Check if a column's value is less than a value.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* where(lt(users.age, 65))
|
|
159
|
+
*/
|
|
160
|
+
export declare function lt<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
161
|
+
/**
|
|
162
|
+
* Check if a column's value is less than or equal to a value.
|
|
163
|
+
*
|
|
164
|
+
* @example
|
|
165
|
+
* where(lte(users.age, 65))
|
|
166
|
+
*/
|
|
167
|
+
export declare function lte<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
168
|
+
/**
|
|
169
|
+
* Check if a column's value is not equal to a value.
|
|
170
|
+
*
|
|
171
|
+
* @example
|
|
172
|
+
* where(neq(users.id, "u1"))
|
|
173
|
+
*/
|
|
174
|
+
export declare function neq<T>(column: ColumnDef<T, any>, value: T): Condition;
|
|
175
|
+
export declare function compileCondition(cond: Condition, params: unknown[]): string;
|
|
176
|
+
export declare function compileConditions(conditions: Condition[], params: unknown[]): string;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A column definition with chainable modifiers.
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* const name = text("name").notNull().default("unnamed");
|
|
6
|
+
*/
|
|
7
|
+
export interface ColumnDef<T, S extends string = string> {
|
|
8
|
+
readonly name: string;
|
|
9
|
+
primaryKey(): ColumnDef<T, S>;
|
|
10
|
+
notNull(): ColumnDef<T, S>;
|
|
11
|
+
unique(): ColumnDef<T, S>;
|
|
12
|
+
/** Set a static default value used when the value is omitted during insert. */
|
|
13
|
+
default(value: T): ColumnDef<T, S>;
|
|
14
|
+
/** Set a dynamic default function called when the value is omitted during insert. */
|
|
15
|
+
defaultFn(fn: () => T): ColumnDef<T, S>;
|
|
16
|
+
/**
|
|
17
|
+
* Define a foreign key reference to another table's column.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* text("userId").references(users.id)
|
|
21
|
+
*/
|
|
22
|
+
references(target: ColumnDef<any, any>): ColumnDef<T, S>;
|
|
23
|
+
readonly __internal: {
|
|
24
|
+
/** Phantom — exists only at the type level, never accessed at runtime. */
|
|
25
|
+
readonly _type: T;
|
|
26
|
+
/** SQLite storage class: "text" | "integer" | "real" | "blob". */
|
|
27
|
+
readonly sqlType: S;
|
|
28
|
+
/** Column constraint flags — set via modifiers, read by migration generator. */
|
|
29
|
+
readonly isPrimaryKey: boolean;
|
|
30
|
+
readonly isNotNull: boolean;
|
|
31
|
+
readonly isUnique: boolean;
|
|
32
|
+
readonly hasDefault: boolean;
|
|
33
|
+
readonly defaultValue: T | undefined;
|
|
34
|
+
readonly defaultFn: (() => T) | undefined;
|
|
35
|
+
readonly isAutoIncrement: boolean;
|
|
36
|
+
readonly hasDefaultNow: boolean;
|
|
37
|
+
readonly hasOnUpdate: boolean;
|
|
38
|
+
/** Foreign key reference — table and column names. */
|
|
39
|
+
readonly referencesTable: string | null;
|
|
40
|
+
readonly referencesColumn: string | null;
|
|
41
|
+
/** Converts logical value → storage value. Called by the builder. */
|
|
42
|
+
readonly encode: (value: T) => unknown;
|
|
43
|
+
/** Converts storage value → logical value. Called by the builder. */
|
|
44
|
+
readonly decode: (value: unknown) => T;
|
|
45
|
+
/** Table name — set by table() when the column is attached. Used for join disambiguation. */
|
|
46
|
+
readonly tableName: string | null;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** An integer column definition with auto-increment support. */
|
|
50
|
+
export interface IntegerColumnDef<S extends string = 'integer'> extends ColumnDef<number, S> {
|
|
51
|
+
primaryKey(): IntegerColumnDef<S>;
|
|
52
|
+
notNull(): IntegerColumnDef<S>;
|
|
53
|
+
unique(): IntegerColumnDef<S>;
|
|
54
|
+
default(value: number): IntegerColumnDef<S>;
|
|
55
|
+
defaultFn(fn: () => number): IntegerColumnDef<S>;
|
|
56
|
+
/**
|
|
57
|
+
* Mark as auto-increment (SQLite ROWID alias).
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const id = integer("id").primaryKey().autoIncrement();
|
|
61
|
+
*/
|
|
62
|
+
autoIncrement(): IntegerColumnDef<S>;
|
|
63
|
+
}
|
|
64
|
+
/** A date column that stores a unix timestamp (milliseconds) in SQLite. Nullable in results unless `.defaultNow()` is called. */
|
|
65
|
+
export interface DateColumnDef extends ColumnDef<Date, 'integer'> {
|
|
66
|
+
primaryKey(): DateColumnDef;
|
|
67
|
+
notNull(): DateColumnDef;
|
|
68
|
+
unique(): DateColumnDef;
|
|
69
|
+
default(value: Date): DateColumnDef;
|
|
70
|
+
defaultFn(fn: () => Date): DateColumnDef;
|
|
71
|
+
/**
|
|
72
|
+
* Use `Date.now()` as the default when the value is omitted during insert.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* const createdAt = date("created_at").defaultNow();
|
|
76
|
+
*/
|
|
77
|
+
defaultNow(): DateColumnDefWithDefault;
|
|
78
|
+
/**
|
|
79
|
+
* Always set to `Date.now()` on update, regardless of the provided value.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* const updatedAt = date("updated_at").onUpdate();
|
|
83
|
+
*/
|
|
84
|
+
onUpdate(): DateColumnDef;
|
|
85
|
+
}
|
|
86
|
+
/** A date column with a guaranteed default value, making it non-nullable in query results. */
|
|
87
|
+
export interface DateColumnDefWithDefault extends DateColumnDef {
|
|
88
|
+
primaryKey(): DateColumnDefWithDefault;
|
|
89
|
+
notNull(): DateColumnDefWithDefault;
|
|
90
|
+
unique(): DateColumnDefWithDefault;
|
|
91
|
+
default(value: Date): DateColumnDefWithDefault;
|
|
92
|
+
defaultFn(fn: () => Date): DateColumnDefWithDefault;
|
|
93
|
+
defaultNow(): DateColumnDefWithDefault;
|
|
94
|
+
onUpdate(): DateColumnDefWithDefault;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Create a text column.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* const name = text("name").notNull();
|
|
101
|
+
*/
|
|
102
|
+
export declare function text(name?: string): ColumnDef<string, 'text'>;
|
|
103
|
+
/**
|
|
104
|
+
* Create an integer column.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* const id = integer("id").primaryKey().autoIncrement();
|
|
108
|
+
*/
|
|
109
|
+
export declare function integer(name?: string): IntegerColumnDef<'integer'>;
|
|
110
|
+
/**
|
|
111
|
+
* Create a boolean column. Stores `0`/`1` in SQLite, exposed as `boolean` in TypeScript.
|
|
112
|
+
*
|
|
113
|
+
* @example
|
|
114
|
+
* const active = boolean("active").notNull().default(true);
|
|
115
|
+
*/
|
|
116
|
+
export declare function boolean(name?: string): ColumnDef<boolean, 'integer'>;
|
|
117
|
+
/**
|
|
118
|
+
* Create a JSON column. Stores JSON text in SQLite, exposed as `T` in TypeScript.
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* const meta = json<Record<string, unknown>>("meta").default({});
|
|
122
|
+
*/
|
|
123
|
+
export declare function json<T>(name?: string): ColumnDef<T, 'text'>;
|
|
124
|
+
/**
|
|
125
|
+
* Create a date column. Stores a unix timestamp (milliseconds) in SQLite, exposed as `Date` in TypeScript.
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* const createdAt = date("created_at").defaultNow().notNull();
|
|
129
|
+
*/
|
|
130
|
+
export declare function date(name?: string): DateColumnDef;
|
|
131
|
+
/**
|
|
132
|
+
* Create a real (floating-point) column.
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
* const price = real("price").notNull();
|
|
136
|
+
*/
|
|
137
|
+
export declare function real(name?: string): ColumnDef<number, 'real'>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ColumnDef, DateColumnDef, DateColumnDefWithDefault } from './columns';
|
|
2
|
+
/** A table definition mapping column names to their `ColumnDef`s. */
|
|
3
|
+
export type TableDef<T> = T & {
|
|
4
|
+
readonly _: {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
};
|
|
7
|
+
};
|
|
8
|
+
export declare function table<T extends Record<string, ColumnDef<any, any>>>(name: string, columns: T): TableDef<T>;
|
|
9
|
+
/**
|
|
10
|
+
* Derive the row shape from a table's column definitions.
|
|
11
|
+
* DateColumnDef → Date | null (nullable unless defaultNow() was called)
|
|
12
|
+
* DateColumnDefWithDefault → Date (non-nullable, has a guaranteed default)
|
|
13
|
+
* All other columns → their _type as-is.
|
|
14
|
+
*
|
|
15
|
+
* Uses `infer C` to extract the column record from TableDef<T> so TypeScript
|
|
16
|
+
* evaluates the mapped type against the concrete columns, not the intersection.
|
|
17
|
+
* This produces cleaner hover info: { id: string; name: string } instead of
|
|
18
|
+
* Pick<InferRow<TableDef<{...}>>, ...>.
|
|
19
|
+
*/
|
|
20
|
+
export type InferRow<T extends TableDef<any>> = T extends TableDef<infer C> ? {
|
|
21
|
+
[K in keyof Omit<C, '_'>]: C[K] extends DateColumnDefWithDefault ? Date : C[K] extends DateColumnDef ? Date | null : C[K] extends ColumnDef<any, any> ? C[K]['__internal']['_type'] : never;
|
|
22
|
+
} : never;
|
|
23
|
+
/** The row type for inserts — columns with auto-defaults (integer, date) are optional. */
|
|
24
|
+
export type InsertRow<T extends TableDef<any>> = {
|
|
25
|
+
[K in keyof Omit<T, '_'> as HasAutoDefault<T[K]> extends true ? never : K]: T[K] extends ColumnDef<any, any> ? T[K]['__internal']['_type'] : never;
|
|
26
|
+
} & {
|
|
27
|
+
[K in keyof Omit<T, '_'> as HasAutoDefault<T[K]> extends true ? K : never]?: T[K] extends ColumnDef<any, any> ? T[K]['__internal']['_type'] : never;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Define a table with auto snake_case column names.
|
|
31
|
+
* Column names are inferred from object keys and converted to snake_case.
|
|
32
|
+
* Column constructors can be called without a name.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* const users = snakeCase.table("users", {
|
|
36
|
+
* id: text().primaryKey(),
|
|
37
|
+
* firstName: text(),
|
|
38
|
+
* });
|
|
39
|
+
*/
|
|
40
|
+
export declare function snakeCaseTable<T extends Record<string, ColumnDef<any, any>>>(tableName: string, columns: T): TableDef<T>;
|
|
41
|
+
/** Provides `snakeCase.table()` for auto snake_case column naming. */
|
|
42
|
+
export declare const snakeCase: {
|
|
43
|
+
table: typeof snakeCaseTable;
|
|
44
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { eq, and, or, gt, gte, lt, lte, neq, isIn, isNotIn, isNull, isNotNull, like, glob, between } from '../query/conditions';
|
|
2
|
+
export type { Condition } from '../query/conditions';
|
|
3
|
+
export { sql } from '../flint';
|
|
4
|
+
export type { SQLExpression } from '../flint';
|
|
5
|
+
export { count, countColumn, sum, avg, min, max } from '../query/aggregates';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { text, integer, boolean, json, date, real } from '../schema/columns';
|
|
2
|
+
export type { ColumnDef, IntegerColumnDef, DateColumnDef, DateColumnDefWithDefault } from '../schema/columns';
|
|
3
|
+
export { table, snakeCase } from '../schema/table';
|
|
4
|
+
export type { InferRow, InsertRow, TableDef, AnyTable } from '../schema/table';
|