@dockstat/sqlite-wrapper 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +578 -0
- package/dist/index.d.ts +412 -0
- package/dist/index.js +12 -0
- package/package.json +58 -0
package/README.md
ADDED
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
# @dockstat/sql-wrapper
|
|
2
|
+
|
|
3
|
+
A tiny TypeScript wrapper around Bun's `bun:sqlite` (`Database`) that gives you:
|
|
4
|
+
|
|
5
|
+
* **`DB`** (default export) — open/close DB, create tables, run `PRAGMA` statements, load extensions, and get a typed `QueryBuilder<T>`.
|
|
6
|
+
* **`QueryBuilder<T>`** — expressive, chainable query builder with:
|
|
7
|
+
|
|
8
|
+
**SELECT operations:**
|
|
9
|
+
* plain equality `.where(...)`
|
|
10
|
+
* regex `.whereRgx(...)` (applied client-side)
|
|
11
|
+
* raw fragments `.whereRaw(...)` / `.whereExpr(...)`
|
|
12
|
+
* `IN` helper `.whereIn(...)`
|
|
13
|
+
* operator helper `.whereOp(...)`
|
|
14
|
+
* ordering, limit, offset, and result helpers: `all()`, `get()`, `first()`, `count()`
|
|
15
|
+
|
|
16
|
+
**INSERT operations:**
|
|
17
|
+
* single/bulk inserts `.insert(...)`
|
|
18
|
+
* conflict resolution `.insertOrIgnore(...)`, `.insertOrReplace(...)`
|
|
19
|
+
|
|
20
|
+
**UPDATE operations:**
|
|
21
|
+
* safe updates `.update(...)` (requires WHERE conditions)
|
|
22
|
+
|
|
23
|
+
**DELETE operations:**
|
|
24
|
+
* safe deletes `.delete()` (requires WHERE conditions)
|
|
25
|
+
|
|
26
|
+
> **Important** — Bun's `bun:sqlite` currently doesn't provide a JS `registerFunction` to add custom SQL functions. Regex conditions added with `whereRgx()` are collected and applied **in JavaScript** after fetching rows that match the non-regex SQL conditions. See the **Performance** section below for implications.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Quick start
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import DB, { QueryBuilder } from "./db";
|
|
34
|
+
|
|
35
|
+
interface User {
|
|
36
|
+
id: number;
|
|
37
|
+
name: string;
|
|
38
|
+
email: string;
|
|
39
|
+
type: string;
|
|
40
|
+
created_at: number;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Create DB with PRAGMA settings and an extension
|
|
44
|
+
const db = new DB("app.db", {
|
|
45
|
+
pragmas: [
|
|
46
|
+
["journal_mode", "WAL"],
|
|
47
|
+
["synchronous", "NORMAL"],
|
|
48
|
+
["foreign_keys", "ON"]
|
|
49
|
+
],
|
|
50
|
+
loadExtensions: [
|
|
51
|
+
"/absolute/path/to/my_extension" // optional compiled SQLite extension
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// create table (object style)
|
|
56
|
+
db.createTable(
|
|
57
|
+
"users",
|
|
58
|
+
{
|
|
59
|
+
id: "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
60
|
+
name: "TEXT NOT NULL",
|
|
61
|
+
email: "TEXT UNIQUE NOT NULL",
|
|
62
|
+
type: "TEXT NOT NULL",
|
|
63
|
+
created_at: "INTEGER NOT NULL DEFAULT (strftime('%s','now'))"
|
|
64
|
+
},
|
|
65
|
+
{ ifNotExists: true }
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
// SELECT - basic select (SQL filter only)
|
|
69
|
+
const containers = db
|
|
70
|
+
.table<User>("users")
|
|
71
|
+
.select(["id", "name", "email"])
|
|
72
|
+
.where({ type: "container" }) // SQL: type = 'container'
|
|
73
|
+
.orderBy("id")
|
|
74
|
+
.desc()
|
|
75
|
+
.limit(10)
|
|
76
|
+
.all();
|
|
77
|
+
|
|
78
|
+
console.log(containers);
|
|
79
|
+
|
|
80
|
+
// SELECT - regex + SQL filters together
|
|
81
|
+
const gmailUsers = db
|
|
82
|
+
.table<User>("users")
|
|
83
|
+
.select(["id", "email"])
|
|
84
|
+
.where({ type: "container" }) // SQL
|
|
85
|
+
.whereRgx({ email: /@gmail\.com$/i }) // client-side regex
|
|
86
|
+
.all();
|
|
87
|
+
|
|
88
|
+
console.log(gmailUsers);
|
|
89
|
+
|
|
90
|
+
// INSERT - single row
|
|
91
|
+
const insertResult = db
|
|
92
|
+
.table<User>("users")
|
|
93
|
+
.insert({
|
|
94
|
+
name: "John Doe",
|
|
95
|
+
email: "john@example.com",
|
|
96
|
+
type: "container"
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
console.log(`Inserted user with ID: ${insertResult.insertId}`);
|
|
100
|
+
|
|
101
|
+
// INSERT - multiple rows with conflict resolution
|
|
102
|
+
const bulkResult = db
|
|
103
|
+
.table<User>("users")
|
|
104
|
+
.insertOrIgnore([
|
|
105
|
+
{ name: "Alice", email: "alice@example.com", type: "container" },
|
|
106
|
+
{ name: "Bob", email: "bob@example.com", type: "container" }
|
|
107
|
+
]);
|
|
108
|
+
|
|
109
|
+
console.log(`Inserted ${bulkResult.changes} users`);
|
|
110
|
+
|
|
111
|
+
// UPDATE - with WHERE conditions
|
|
112
|
+
const updateResult = db
|
|
113
|
+
.table<User>("users")
|
|
114
|
+
.where({ type: "container" })
|
|
115
|
+
.whereRgx({ email: /@gmail\.com$/i })
|
|
116
|
+
.update({ type: "gmail_user" });
|
|
117
|
+
|
|
118
|
+
console.log(`Updated ${updateResult.changes} users`);
|
|
119
|
+
|
|
120
|
+
// DELETE - with WHERE conditions
|
|
121
|
+
const deleteResult = db
|
|
122
|
+
.table<User>("users")
|
|
123
|
+
.where({ type: "gmail_user" })
|
|
124
|
+
.delete();
|
|
125
|
+
|
|
126
|
+
console.log(`Deleted ${deleteResult.changes} users`);
|
|
127
|
+
|
|
128
|
+
db.close();
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## 1) Creating tables
|
|
134
|
+
|
|
135
|
+
**Object style (recommended):**
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
db.createTable("posts", {
|
|
139
|
+
id: "INTEGER PRIMARY KEY AUTOINCREMENT",
|
|
140
|
+
title: "TEXT NOT NULL",
|
|
141
|
+
body: "TEXT",
|
|
142
|
+
author_id: "INTEGER NOT NULL",
|
|
143
|
+
published: "INTEGER NOT NULL DEFAULT 0"
|
|
144
|
+
}, { ifNotExists: true });
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**String style:**
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
db.createTable(
|
|
151
|
+
"events",
|
|
152
|
+
`id INTEGER PRIMARY KEY,
|
|
153
|
+
name TEXT NOT NULL,
|
|
154
|
+
occurred_at INTEGER NOT NULL`
|
|
155
|
+
);
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 2) Running PRAGMA statements
|
|
161
|
+
|
|
162
|
+
You can pass PRAGMAs at construction:
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const db = new DB("app.db", {
|
|
166
|
+
pragmas: [
|
|
167
|
+
["journal_mode", "WAL"],
|
|
168
|
+
["cache_size", -64000]
|
|
169
|
+
]
|
|
170
|
+
});
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Or run them later:
|
|
174
|
+
|
|
175
|
+
```ts
|
|
176
|
+
db.pragma("cache_size", -32000);
|
|
177
|
+
const foreignKeysOn = db.pragma("foreign_keys");
|
|
178
|
+
console.log(foreignKeysOn); // should print ON
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## 3) Loading SQLite extensions
|
|
184
|
+
|
|
185
|
+
At DB construction:
|
|
186
|
+
|
|
187
|
+
```ts
|
|
188
|
+
const db = new DB("app.db", {
|
|
189
|
+
loadExtensions: [
|
|
190
|
+
"/absolute/path/to/regexp_extension"
|
|
191
|
+
]
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Or after creation:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
db.loadExtension("/absolute/path/to/my_extension");
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## 4) Basic QueryBuilder usage
|
|
204
|
+
|
|
205
|
+
**Select specific columns:**
|
|
206
|
+
|
|
207
|
+
```ts
|
|
208
|
+
const users = db
|
|
209
|
+
.table<User>("users")
|
|
210
|
+
.select(["id", "name"])
|
|
211
|
+
.where({ type: "container" })
|
|
212
|
+
.all();
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Select all columns:**
|
|
216
|
+
|
|
217
|
+
```ts
|
|
218
|
+
const allUsers = db.table<User>("users").select(["*"]).all();
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Get a single row:**
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
const userOrNull = db.table<User>("users").where({ id: 1 }).get();
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**Get first matching row:**
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
const first = db.table<User>("users").where({ type: "container" }).first();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Count rows:**
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
const count = db.table<User>("users").where({ type: "container" }).count();
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 5) Mixing equality and regex
|
|
242
|
+
|
|
243
|
+
Plain equality uses `.where()` (SQL). Regex uses `.whereRgx()` (client-side):
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
const matches = db
|
|
247
|
+
.table<User>("users")
|
|
248
|
+
.select(["id", "name", "email", "type"])
|
|
249
|
+
.where({ type: "container" }) // SQL
|
|
250
|
+
.whereRgx({ email: /@example\.com$/i }) // JS regex after SQL fetch
|
|
251
|
+
.orderBy("created_at")
|
|
252
|
+
.desc()
|
|
253
|
+
.limit(50)
|
|
254
|
+
.all();
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
> **Note:** If `.whereRgx()` is used, ordering, offset, and limit are applied in JS after regex filtering.
|
|
258
|
+
|
|
259
|
+
---
|
|
260
|
+
|
|
261
|
+
## 6) Raw expressions, IN, and operators
|
|
262
|
+
|
|
263
|
+
**Raw WHERE fragment:**
|
|
264
|
+
|
|
265
|
+
```ts
|
|
266
|
+
const rows = db
|
|
267
|
+
.table<User>("users")
|
|
268
|
+
.whereRaw("created_at > ? AND published = ?", [1625097600, 1])
|
|
269
|
+
.all();
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
**IN clause:**
|
|
273
|
+
|
|
274
|
+
```ts
|
|
275
|
+
const some = db.table<User>("users").whereIn("id", [1, 2, 5, 7]).all();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**Operator helper:**
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
db.table<User>("users")
|
|
282
|
+
.whereOp("created_at", ">", 1622505600)
|
|
283
|
+
.whereOp("email", "LIKE", "%@gmail.com")
|
|
284
|
+
.all();
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## 7) Pagination
|
|
290
|
+
|
|
291
|
+
```ts
|
|
292
|
+
const page = 2;
|
|
293
|
+
const pageSize = 20;
|
|
294
|
+
|
|
295
|
+
const paged = db
|
|
296
|
+
.table<User>("users")
|
|
297
|
+
.where({ type: "container" })
|
|
298
|
+
.orderBy("created_at")
|
|
299
|
+
.desc()
|
|
300
|
+
.offset((page - 1) * pageSize)
|
|
301
|
+
.limit(pageSize)
|
|
302
|
+
.all();
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
> With `.whereRgx()`, paging happens in JS after filtering.
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## 8) INSERT operations
|
|
310
|
+
|
|
311
|
+
**Single row insert:**
|
|
312
|
+
|
|
313
|
+
```ts
|
|
314
|
+
const result = db
|
|
315
|
+
.table<User>("users")
|
|
316
|
+
.insert({
|
|
317
|
+
name: "John Doe",
|
|
318
|
+
email: "john@example.com",
|
|
319
|
+
type: "container"
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
console.log(result.insertId, result.changes);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
**Bulk insert:**
|
|
326
|
+
|
|
327
|
+
```ts
|
|
328
|
+
const users = [
|
|
329
|
+
{ name: "Alice", email: "alice@example.com", type: "container" },
|
|
330
|
+
{ name: "Bob", email: "bob@example.com", type: "container" }
|
|
331
|
+
];
|
|
332
|
+
|
|
333
|
+
const result = db.table<User>("users").insert(users);
|
|
334
|
+
console.log(`Inserted ${result.changes} users`);
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
**Insert with conflict resolution:**
|
|
338
|
+
|
|
339
|
+
```ts
|
|
340
|
+
// INSERT OR IGNORE - skip duplicates
|
|
341
|
+
const result1 = db.table<User>("users").insertOrIgnore({
|
|
342
|
+
name: "Duplicate User",
|
|
343
|
+
email: "existing@example.com"
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
// INSERT OR REPLACE - replace duplicates
|
|
347
|
+
const result2 = db.table<User>("users").insertOrReplace({
|
|
348
|
+
name: "Updated User",
|
|
349
|
+
email: "existing@example.com"
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
// Custom conflict resolution
|
|
353
|
+
const result3 = db.table<User>("users").insert(userData, {
|
|
354
|
+
orIgnore: true,
|
|
355
|
+
// or: orReplace, orAbort, orFail, orRollback
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
361
|
+
## 9) UPDATE operations
|
|
362
|
+
|
|
363
|
+
**Basic update (requires WHERE conditions):**
|
|
364
|
+
|
|
365
|
+
```ts
|
|
366
|
+
const result = db
|
|
367
|
+
.table<User>("users")
|
|
368
|
+
.where({ id: 1 })
|
|
369
|
+
.update({ name: "Updated Name", type: "admin" });
|
|
370
|
+
|
|
371
|
+
console.log(`Updated ${result.changes} rows`);
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Update with complex conditions:**
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
const result = db
|
|
378
|
+
.table<User>("users")
|
|
379
|
+
.where({ type: "container" })
|
|
380
|
+
.whereRgx({ email: /@gmail\.com$/i })
|
|
381
|
+
.update({ type: "gmail_container" });
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Update with raw WHERE conditions:**
|
|
385
|
+
|
|
386
|
+
```ts
|
|
387
|
+
const result = db
|
|
388
|
+
.table<User>("users")
|
|
389
|
+
.whereRaw("created_at > ? AND active = ?", [Date.now() - 86400000, true])
|
|
390
|
+
.update({ last_active: Date.now() });
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
> **Safety Note:** UPDATE operations require at least one WHERE condition to prevent accidental full table updates.
|
|
394
|
+
|
|
395
|
+
---
|
|
396
|
+
|
|
397
|
+
## 10) DELETE operations
|
|
398
|
+
|
|
399
|
+
**Basic delete (requires WHERE conditions):**
|
|
400
|
+
|
|
401
|
+
```ts
|
|
402
|
+
const result = db
|
|
403
|
+
.table<User>("users")
|
|
404
|
+
.where({ active: false })
|
|
405
|
+
.delete();
|
|
406
|
+
|
|
407
|
+
console.log(`Deleted ${result.changes} rows`);
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
**Delete with complex conditions:**
|
|
411
|
+
|
|
412
|
+
```ts
|
|
413
|
+
const result = db
|
|
414
|
+
.table<User>("users")
|
|
415
|
+
.where({ type: "temporary" })
|
|
416
|
+
.whereOp("created_at", "<", Date.now() - 604800000) // older than 1 week
|
|
417
|
+
.delete();
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
**Delete with regex conditions:**
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
const result = db
|
|
424
|
+
.table<User>("users")
|
|
425
|
+
.whereRgx({ email: /^test.*@example\.com$/i })
|
|
426
|
+
.delete();
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
> **Safety Note:** DELETE operations require at least one WHERE condition to prevent accidental full table deletion.
|
|
430
|
+
|
|
431
|
+
---
|
|
432
|
+
|
|
433
|
+
## 11) Complex query example
|
|
434
|
+
|
|
435
|
+
```ts
|
|
436
|
+
const results = db
|
|
437
|
+
.table<User>("users")
|
|
438
|
+
.select(["id", "name", "email", "created_at"])
|
|
439
|
+
.whereRaw("created_at > ?", [1672531200])
|
|
440
|
+
.whereIn("id", [10, 20, 30, 40])
|
|
441
|
+
.whereRgx({ email: /\b(hey@example|test@example)\.com$/i })
|
|
442
|
+
.orderBy("created_at")
|
|
443
|
+
.desc()
|
|
444
|
+
.limit(100)
|
|
445
|
+
.all();
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
---
|
|
449
|
+
|
|
450
|
+
## 12) Result types and error handling
|
|
451
|
+
|
|
452
|
+
**INSERT results:**
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
interface InsertResult {
|
|
456
|
+
insertId: number; // rowid of the last inserted row
|
|
457
|
+
changes: number; // number of rows inserted
|
|
458
|
+
}
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
**UPDATE/DELETE results:**
|
|
462
|
+
|
|
463
|
+
```ts
|
|
464
|
+
interface UpdateResult {
|
|
465
|
+
changes: number; // number of rows affected
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
interface DeleteResult {
|
|
469
|
+
changes: number; // number of rows deleted
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
**Error handling:**
|
|
474
|
+
|
|
475
|
+
```ts
|
|
476
|
+
try {
|
|
477
|
+
// This will throw - UPDATE without WHERE conditions
|
|
478
|
+
db.table<User>("users").update({ active: true });
|
|
479
|
+
} catch (error) {
|
|
480
|
+
console.error("UPDATE operation requires WHERE conditions");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
try {
|
|
484
|
+
// This will throw - empty insert data
|
|
485
|
+
db.table<User>("users").insert({});
|
|
486
|
+
} catch (error) {
|
|
487
|
+
console.error("Insert data cannot be empty");
|
|
488
|
+
}
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
---
|
|
492
|
+
|
|
493
|
+
## Advanced: Native `REGEXP` support
|
|
494
|
+
|
|
495
|
+
If you load a compiled SQLite extension that adds `REGEXP`, you can do regex filtering directly in SQL:
|
|
496
|
+
|
|
497
|
+
```ts
|
|
498
|
+
db.loadExtension("/path/to/regexp_extension");
|
|
499
|
+
const rows = db
|
|
500
|
+
.table<User>("users")
|
|
501
|
+
.whereExpr("email REGEXP ?", ["@example\\.com$"])
|
|
502
|
+
.all();
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Performance & Practical tips
|
|
508
|
+
|
|
509
|
+
### SELECT performance:
|
|
510
|
+
* Prefer `.where()` SQL filters for large datasets — `.whereRgx()` fetches rows and filters in JS.
|
|
511
|
+
* Use `.whereIn()` and `.whereRaw()` to reduce rows before regex filtering.
|
|
512
|
+
* Use indexes on frequently queried columns.
|
|
513
|
+
|
|
514
|
+
### INSERT performance:
|
|
515
|
+
* Use bulk inserts with arrays for multiple rows instead of individual insert calls.
|
|
516
|
+
* Consider transaction wrapping for large batch operations.
|
|
517
|
+
* Use appropriate conflict resolution (`OR IGNORE`, `OR REPLACE`) to avoid exception handling.
|
|
518
|
+
|
|
519
|
+
### UPDATE/DELETE with regex:
|
|
520
|
+
* When using `.whereRgx()`, the operation fetches candidate rows first, then applies regex filtering client-side.
|
|
521
|
+
* For better performance with regex conditions, consider using SQL `LIKE` patterns where possible.
|
|
522
|
+
|
|
523
|
+
### General tips:
|
|
524
|
+
* Use PRAGMAs to tune performance (e.g. WAL mode, cache size).
|
|
525
|
+
* Load extensions to enable advanced SQLite features without manual filtering.
|
|
526
|
+
* Always use WHERE conditions for UPDATE/DELETE to prevent accidents.
|
|
527
|
+
* The library automatically handles parameter binding to prevent SQL injection.
|
|
528
|
+
|
|
529
|
+
---
|
|
530
|
+
|
|
531
|
+
## API Reference
|
|
532
|
+
|
|
533
|
+
### `DB` (default export)
|
|
534
|
+
|
|
535
|
+
* `constructor(path: string, opts?: { pragmas?: [string, any][], loadExtensions?: string[] })`
|
|
536
|
+
* `table<T>(tableName: string): QueryBuilder<T>`
|
|
537
|
+
* `createTable(tableName: string, columns: string | Record<string,string>, options?: { ifNotExists?: boolean; withoutRowId?: boolean })`
|
|
538
|
+
* `pragma(name: string, value?: any): any`
|
|
539
|
+
* `loadExtension(path: string): void`
|
|
540
|
+
* `close(): void`
|
|
541
|
+
|
|
542
|
+
### `QueryBuilder<T>` (named export)
|
|
543
|
+
|
|
544
|
+
**WHERE methods (shared across operations):**
|
|
545
|
+
* `where(cond: Partial<Record<keyof T, string | number | boolean | null>>)`
|
|
546
|
+
* `whereRgx(cond: Partial<Record<keyof T, string | RegExp>>)`
|
|
547
|
+
* `whereExpr(expr: string, params?: any[])`
|
|
548
|
+
* `whereRaw(expr: string, params?: any[])`
|
|
549
|
+
* `whereIn(column: keyof T, values: any[])`
|
|
550
|
+
* `whereOp(column: keyof T, op: string, value: any)`
|
|
551
|
+
|
|
552
|
+
**SELECT methods:**
|
|
553
|
+
* `select(columns: Array<keyof T> | ["*"])`
|
|
554
|
+
* `orderBy(column: keyof T)`
|
|
555
|
+
* `asc()`, `desc()`
|
|
556
|
+
* `limit(n)`, `offset(n)`
|
|
557
|
+
* `all(): T[]`, `get(): T | null`, `first(): T | null`, `count(): number`
|
|
558
|
+
|
|
559
|
+
**INSERT methods:**
|
|
560
|
+
* `insert(data: Partial<T> | Partial<T>[], options?: InsertOptions): InsertResult`
|
|
561
|
+
* `insertOrIgnore(data: Partial<T> | Partial<T>[]): InsertResult`
|
|
562
|
+
* `insertOrReplace(data: Partial<T> | Partial<T>[]): InsertResult`
|
|
563
|
+
|
|
564
|
+
**UPDATE methods:**
|
|
565
|
+
* `update(data: Partial<T>): UpdateResult` *(requires WHERE conditions)*
|
|
566
|
+
|
|
567
|
+
**DELETE methods:**
|
|
568
|
+
* `delete(): DeleteResult` *(requires WHERE conditions)*
|
|
569
|
+
|
|
570
|
+
### Types (named exports)
|
|
571
|
+
|
|
572
|
+
* `InsertResult` — `{ insertId: number, changes: number }`
|
|
573
|
+
* `UpdateResult` — `{ changes: number }`
|
|
574
|
+
* `DeleteResult` — `{ changes: number }`
|
|
575
|
+
* `InsertOptions` — conflict resolution options
|
|
576
|
+
* `ColumnNames<T>` — column selection type
|
|
577
|
+
* `WhereCondition<T>` — WHERE condition type
|
|
578
|
+
* `RegexCondition<T>` — regex condition type
|