@dockstat/sqlite-wrapper 1.3.0 → 1.3.2
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 +1 -0
- package/index.ts +50 -38
- package/package.json +3 -2
- package/query-builder/base.ts +9 -5
- package/query-builder/delete.ts +9 -3
- package/query-builder/index.ts +6 -5
- package/query-builder/insert.ts +9 -3
- package/query-builder/select.ts +8 -6
- package/query-builder/update.ts +9 -3
- package/utils/index.ts +2 -0
- package/utils/logger.ts +39 -4
- package/utils/transformer.ts +5 -2
package/README.md
CHANGED
|
@@ -13,6 +13,7 @@ Schema-first table helpers, an expressive chainable QueryBuilder, safe defaults
|
|
|
13
13
|
|
|
14
14
|
### Bug Fixes
|
|
15
15
|
- **Fixed Boolean parsing** — Boolean columns now correctly convert SQLite's `0`/`1` to JavaScript `true`/`false`
|
|
16
|
+
- **Fixed Wrong packing** — Before the `publish` script was added, workspace dependencies were not correctly propagated
|
|
16
17
|
|
|
17
18
|
### New Features
|
|
18
19
|
- **Auto-detection of JSON & Boolean columns** — No more manual parser configuration! Columns using `column.json()` or `column.boolean()` are automatically detected from schema
|
package/index.ts
CHANGED
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import { Database, type SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import { Logger } from "@dockstat/logger"
|
|
2
3
|
import { QueryBuilder } from "./query-builder/index"
|
|
3
4
|
import type { ColumnDefinition, Parser, TableConstraints, TableOptions, TableSchema } from "./types"
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
// Re-export logger utilities for external use
|
|
7
|
-
export const logger = sqliteLogger
|
|
8
|
-
export const addLoggerParents = addParents
|
|
9
|
-
|
|
10
|
-
// Internal loggers for different components
|
|
11
|
-
const dbLog = createLogger("db")
|
|
12
|
-
const backupLog = createLogger("backup")
|
|
13
|
-
const tableLog = createLogger("table")
|
|
5
|
+
import { createLogger, type SqliteLogger } from "./utils"
|
|
14
6
|
|
|
15
7
|
/**
|
|
16
8
|
* Re-export all types and utilities
|
|
@@ -92,6 +84,10 @@ class DB {
|
|
|
92
84
|
protected dbPath: string
|
|
93
85
|
private autoBackupTimer: ReturnType<typeof setInterval> | null = null
|
|
94
86
|
private autoBackupOptions: AutoBackupOptions | null = null
|
|
87
|
+
private baseLogger: Logger
|
|
88
|
+
private dbLog: SqliteLogger
|
|
89
|
+
private backupLog: SqliteLogger
|
|
90
|
+
private tableLog: SqliteLogger
|
|
95
91
|
|
|
96
92
|
/**
|
|
97
93
|
* Open or create a SQLite database at `path`.
|
|
@@ -99,8 +95,20 @@ class DB {
|
|
|
99
95
|
* @param path - Path to the SQLite file (e.g. "app.db"). Use ":memory:" for in-memory DB.
|
|
100
96
|
* @param options - Optional database configuration
|
|
101
97
|
*/
|
|
102
|
-
constructor(path: string, options?: DBOptions) {
|
|
103
|
-
|
|
98
|
+
constructor(path: string, options?: DBOptions, baseLogger?: Logger) {
|
|
99
|
+
if (!baseLogger) {
|
|
100
|
+
this.baseLogger = new Logger("Sqlite-Wrapper")
|
|
101
|
+
} else {
|
|
102
|
+
this.baseLogger = baseLogger
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Wire base logger so sqlite-wrapper logs inherit the same LogHook/parents as the consumer.
|
|
106
|
+
this.dbLog = createLogger("DB", this.baseLogger)
|
|
107
|
+
this.backupLog = createLogger("Backup", this.baseLogger)
|
|
108
|
+
this.tableLog = createLogger("Table", this.baseLogger)
|
|
109
|
+
|
|
110
|
+
this.dbLog.connection(path, "open")
|
|
111
|
+
|
|
104
112
|
this.dbPath = path
|
|
105
113
|
this.db = new Database(path)
|
|
106
114
|
|
|
@@ -129,8 +137,7 @@ class DB {
|
|
|
129
137
|
*/
|
|
130
138
|
private setupAutoBackup(options: AutoBackupOptions): void {
|
|
131
139
|
if (this.dbPath === ":memory:") {
|
|
132
|
-
backupLog.warn("Auto-backup is not available for in-memory databases")
|
|
133
|
-
return
|
|
140
|
+
this.backupLog.warn("Auto-backup is not available for in-memory databases")
|
|
134
141
|
}
|
|
135
142
|
|
|
136
143
|
this.autoBackupOptions = {
|
|
@@ -146,7 +153,7 @@ class DB {
|
|
|
146
153
|
const fs = require("node:fs")
|
|
147
154
|
if (!fs.existsSync(this.autoBackupOptions.directory)) {
|
|
148
155
|
fs.mkdirSync(this.autoBackupOptions.directory, { recursive: true })
|
|
149
|
-
backupLog.info(`Created backup directory: ${this.autoBackupOptions.directory}`)
|
|
156
|
+
this.backupLog.info(`Created backup directory: ${this.autoBackupOptions.directory}`)
|
|
150
157
|
}
|
|
151
158
|
|
|
152
159
|
// Create initial backup
|
|
@@ -157,7 +164,7 @@ class DB {
|
|
|
157
164
|
this.backup()
|
|
158
165
|
}, this.autoBackupOptions.intervalMs)
|
|
159
166
|
|
|
160
|
-
backupLog.info(
|
|
167
|
+
this.backupLog.info(
|
|
161
168
|
`Auto-backup enabled: interval=${this.autoBackupOptions.intervalMs}ms, maxBackups=${this.autoBackupOptions.maxBackups}`
|
|
162
169
|
)
|
|
163
170
|
}
|
|
@@ -194,7 +201,7 @@ class DB {
|
|
|
194
201
|
// Use SQLite's backup API via VACUUM INTO for a consistent backup
|
|
195
202
|
try {
|
|
196
203
|
this.db.run(`VACUUM INTO '${backupPath.replace(/'/g, "''")}'`)
|
|
197
|
-
backupLog.backup("create", backupPath)
|
|
204
|
+
this.backupLog.backup("create", backupPath)
|
|
198
205
|
|
|
199
206
|
// Apply retention policy if auto-backup is enabled
|
|
200
207
|
if (this.autoBackupOptions) {
|
|
@@ -203,7 +210,7 @@ class DB {
|
|
|
203
210
|
|
|
204
211
|
return backupPath
|
|
205
212
|
} catch (error) {
|
|
206
|
-
backupLog.error(`Failed to create backup: ${error}`)
|
|
213
|
+
this.backupLog.error(`Failed to create backup: ${error}`)
|
|
207
214
|
throw error
|
|
208
215
|
}
|
|
209
216
|
}
|
|
@@ -238,12 +245,12 @@ class DB {
|
|
|
238
245
|
const toDelete = files.slice(maxBackups)
|
|
239
246
|
for (const file of toDelete) {
|
|
240
247
|
fs.unlinkSync(file.path)
|
|
241
|
-
backupLog.debug(`Removed old backup: ${file.name}`)
|
|
248
|
+
this.backupLog.debug(`Removed old backup: ${file.name}`)
|
|
242
249
|
}
|
|
243
|
-
backupLog.info(`Retention policy applied: removed ${toDelete.length} old backup(s)`)
|
|
250
|
+
this.backupLog.info(`Retention policy applied: removed ${toDelete.length} old backup(s)`)
|
|
244
251
|
}
|
|
245
252
|
} catch (error) {
|
|
246
|
-
backupLog.error(`Failed to apply retention policy: ${error}`)
|
|
253
|
+
this.backupLog.error(`Failed to apply retention policy: ${error}`)
|
|
247
254
|
}
|
|
248
255
|
}
|
|
249
256
|
|
|
@@ -254,7 +261,8 @@ class DB {
|
|
|
254
261
|
*/
|
|
255
262
|
listBackups(): Array<{ filename: string; path: string; size: number; created: Date }> {
|
|
256
263
|
if (!this.autoBackupOptions) {
|
|
257
|
-
backupLog.warn("Auto-backup is not configured. Use backup() with a custom path instead.")
|
|
264
|
+
this.backupLog.warn("Auto-backup is not configured. Use backup() with a custom path instead.")
|
|
265
|
+
|
|
258
266
|
return []
|
|
259
267
|
}
|
|
260
268
|
|
|
@@ -282,7 +290,7 @@ class DB {
|
|
|
282
290
|
(a: { created: Date }, b: { created: Date }) => b.created.getTime() - a.created.getTime()
|
|
283
291
|
)
|
|
284
292
|
} catch (error) {
|
|
285
|
-
backupLog.error(`Failed to list backups: ${error}`)
|
|
293
|
+
this.backupLog.error(`Failed to list backups: ${error}`)
|
|
286
294
|
return []
|
|
287
295
|
}
|
|
288
296
|
}
|
|
@@ -313,15 +321,15 @@ class DB {
|
|
|
313
321
|
|
|
314
322
|
try {
|
|
315
323
|
fs.copyFileSync(backupPath, restorePath)
|
|
316
|
-
backupLog.backup("restore", backupPath)
|
|
324
|
+
this.backupLog.backup("restore", backupPath)
|
|
317
325
|
|
|
318
326
|
// Reopen database if we closed it
|
|
319
327
|
if (restorePath === this.dbPath) {
|
|
320
328
|
this.db = new Database(this.dbPath)
|
|
321
|
-
dbLog.info("Database connection reopened after restore")
|
|
329
|
+
this.dbLog.info("Database connection reopened after restore")
|
|
322
330
|
}
|
|
323
331
|
} catch (error) {
|
|
324
|
-
backupLog.error(`Failed to restore backup: ${error}`)
|
|
332
|
+
this.backupLog.error(`Failed to restore backup: ${error}`)
|
|
325
333
|
throw error
|
|
326
334
|
}
|
|
327
335
|
}
|
|
@@ -333,7 +341,7 @@ class DB {
|
|
|
333
341
|
if (this.autoBackupTimer) {
|
|
334
342
|
clearInterval(this.autoBackupTimer)
|
|
335
343
|
this.autoBackupTimer = null
|
|
336
|
-
backupLog.info("Auto-backup stopped")
|
|
344
|
+
this.backupLog.info("Auto-backup stopped")
|
|
337
345
|
}
|
|
338
346
|
}
|
|
339
347
|
|
|
@@ -350,7 +358,7 @@ class DB {
|
|
|
350
358
|
*/
|
|
351
359
|
table<T extends Record<string, unknown>>(
|
|
352
360
|
tableName: string,
|
|
353
|
-
parser: Partial<Parser<T>>
|
|
361
|
+
parser: Partial<Parser<T>> = {}
|
|
354
362
|
): QueryBuilder<T> {
|
|
355
363
|
const pObj: Parser<T> = {
|
|
356
364
|
JSON: parser.JSON || [],
|
|
@@ -358,8 +366,8 @@ class DB {
|
|
|
358
366
|
BOOLEAN: parser.BOOLEAN || [],
|
|
359
367
|
}
|
|
360
368
|
|
|
361
|
-
tableLog.debug(`Creating QueryBuilder for: ${tableName}`)
|
|
362
|
-
return new QueryBuilder<T>(this.db, tableName, pObj)
|
|
369
|
+
this.tableLog.debug(`Creating QueryBuilder for: ${tableName}`)
|
|
370
|
+
return new QueryBuilder<T>(this.db, tableName, pObj, this.baseLogger)
|
|
363
371
|
}
|
|
364
372
|
|
|
365
373
|
/**
|
|
@@ -367,7 +375,7 @@ class DB {
|
|
|
367
375
|
* Also stops auto-backup if it's running.
|
|
368
376
|
*/
|
|
369
377
|
close(): void {
|
|
370
|
-
dbLog.connection(this.dbPath, "close")
|
|
378
|
+
this.dbLog.connection(this.dbPath, "close")
|
|
371
379
|
this.stopAutoBackup()
|
|
372
380
|
this.db.close()
|
|
373
381
|
}
|
|
@@ -521,7 +529,7 @@ class DB {
|
|
|
521
529
|
const allDefinitions = [columnDefs, ...tableConstraints].join(", ")
|
|
522
530
|
|
|
523
531
|
const columnNames = Object.keys(columns)
|
|
524
|
-
tableLog.tableCreate(tableName, columnNames)
|
|
532
|
+
this.tableLog.tableCreate(tableName, columnNames)
|
|
525
533
|
|
|
526
534
|
const sql = `CREATE ${temp}TABLE ${ifNot}${quoteIdent(
|
|
527
535
|
tableName
|
|
@@ -564,7 +572,11 @@ class DB {
|
|
|
564
572
|
BOOLEAN: mergedBoolean,
|
|
565
573
|
}
|
|
566
574
|
|
|
567
|
-
tableLog.parserConfig(
|
|
575
|
+
this.tableLog.parserConfig(
|
|
576
|
+
pObj.JSON.map(String),
|
|
577
|
+
pObj.BOOLEAN.map(String),
|
|
578
|
+
Object.keys(pObj.MODULE)
|
|
579
|
+
)
|
|
568
580
|
|
|
569
581
|
return this.table<_T>(tableName, pObj)
|
|
570
582
|
}
|
|
@@ -883,7 +895,7 @@ class DB {
|
|
|
883
895
|
stmt.run(tableName, comment)
|
|
884
896
|
} catch (error) {
|
|
885
897
|
// Silently ignore if we can't create metadata table
|
|
886
|
-
|
|
898
|
+
this.tableLog.warn(`Could not store table comment for ${tableName}: ${error}`)
|
|
887
899
|
}
|
|
888
900
|
}
|
|
889
901
|
|
|
@@ -906,7 +918,7 @@ class DB {
|
|
|
906
918
|
* runute a raw SQL statement
|
|
907
919
|
*/
|
|
908
920
|
run(sql: string): void {
|
|
909
|
-
|
|
921
|
+
this.tableLog.debug(`Running SQL: ${sql}`)
|
|
910
922
|
this.db.run(sql)
|
|
911
923
|
}
|
|
912
924
|
|
|
@@ -936,7 +948,7 @@ class DB {
|
|
|
936
948
|
* Commit a transaction
|
|
937
949
|
*/
|
|
938
950
|
commit(): void {
|
|
939
|
-
dbLog.transaction("commit")
|
|
951
|
+
this.dbLog.transaction("commit")
|
|
940
952
|
this.run("COMMIT")
|
|
941
953
|
}
|
|
942
954
|
|
|
@@ -944,7 +956,7 @@ class DB {
|
|
|
944
956
|
* Rollback a transaction
|
|
945
957
|
*/
|
|
946
958
|
rollback(): void {
|
|
947
|
-
dbLog.transaction("rollback")
|
|
959
|
+
this.dbLog.transaction("rollback")
|
|
948
960
|
this.run("ROLLBACK")
|
|
949
961
|
}
|
|
950
962
|
|
|
@@ -977,7 +989,7 @@ class DB {
|
|
|
977
989
|
*/
|
|
978
990
|
vacuum() {
|
|
979
991
|
const result = this.db.run("VACUUM")
|
|
980
|
-
dbLog.debug("Vacuum completed")
|
|
992
|
+
this.dbLog.debug("Vacuum completed")
|
|
981
993
|
return result
|
|
982
994
|
}
|
|
983
995
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dockstat/sqlite-wrapper",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.2",
|
|
4
4
|
"description": "A TypeScript wrapper around bun:sqlite with type-safe query building",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./index.ts",
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
"lint:fix": "biome lint --write .",
|
|
24
24
|
"lint:gh": "turbo run lint -- --reporter=github",
|
|
25
25
|
"check-types": "bunx tsc --noEmit",
|
|
26
|
+
"publish": "bun pm pack --destination ./dist && npm publish --access public ./dist/*.tgz ; rm -r ./dist",
|
|
26
27
|
"test": "DOCKSTAT_LOGGER_IGNORE_MESSAGES='Logger Status: active - ignoring messages:' bun test"
|
|
27
28
|
},
|
|
28
29
|
"keywords": [
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"bun": ">=1.0.0"
|
|
49
50
|
},
|
|
50
51
|
"dependencies": {
|
|
51
|
-
"@dockstat/logger": "
|
|
52
|
+
"@dockstat/logger": "2.0.0"
|
|
52
53
|
},
|
|
53
54
|
"peerDependencies": {
|
|
54
55
|
"typescript": "^5.9.3"
|
package/query-builder/base.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
2
3
|
import type { Parser, QueryBuilderState } from "../types"
|
|
3
4
|
import {
|
|
4
5
|
createLogger,
|
|
@@ -20,9 +21,9 @@ import {
|
|
|
20
21
|
*/
|
|
21
22
|
export abstract class BaseQueryBuilder<T extends Record<string, unknown>> {
|
|
22
23
|
protected state: QueryBuilderState<T>
|
|
23
|
-
protected log
|
|
24
|
+
protected log: ReturnType<typeof createLogger>
|
|
24
25
|
|
|
25
|
-
constructor(db: Database, tableName: string, parser?: Parser<T
|
|
26
|
+
constructor(db: Database, tableName: string, parser?: Parser<T>, baseLogger?: Logger) {
|
|
26
27
|
this.state = {
|
|
27
28
|
db,
|
|
28
29
|
tableName,
|
|
@@ -32,6 +33,9 @@ export abstract class BaseQueryBuilder<T extends Record<string, unknown>> {
|
|
|
32
33
|
parser,
|
|
33
34
|
}
|
|
34
35
|
|
|
36
|
+
// If a base logger is provided, this will inherit the consumer's LogHook/parents.
|
|
37
|
+
this.log = createLogger("Query", baseLogger)
|
|
38
|
+
|
|
35
39
|
this.log.debug(`QueryBuilder initialized for table: ${tableName}`)
|
|
36
40
|
}
|
|
37
41
|
|
|
@@ -163,14 +167,14 @@ export abstract class BaseQueryBuilder<T extends Record<string, unknown>> {
|
|
|
163
167
|
* (deserialize JSON, convert booleans, etc.)
|
|
164
168
|
*/
|
|
165
169
|
protected transformRowFromDb(row: unknown): T {
|
|
166
|
-
return transformFromDb<T>(row, { parser: this.state.parser })
|
|
170
|
+
return transformFromDb<T>(row, { parser: this.state.parser, logger: this.log })
|
|
167
171
|
}
|
|
168
172
|
|
|
169
173
|
/**
|
|
170
174
|
* Transform multiple rows FROM the database
|
|
171
175
|
*/
|
|
172
176
|
protected transformRowsFromDb(rows: unknown[]): T[] {
|
|
173
|
-
return transformRowsFromDb<T>(rows, { parser: this.state.parser })
|
|
177
|
+
return transformRowsFromDb<T>(rows, { parser: this.state.parser, logger: this.log })
|
|
174
178
|
}
|
|
175
179
|
|
|
176
180
|
/**
|
|
@@ -178,6 +182,6 @@ export abstract class BaseQueryBuilder<T extends Record<string, unknown>> {
|
|
|
178
182
|
* (serialize JSON, stringify functions, etc.)
|
|
179
183
|
*/
|
|
180
184
|
protected transformRowToDb(row: Partial<T>): RowData {
|
|
181
|
-
return transformToDb<T>(row, { parser: this.state.parser })
|
|
185
|
+
return transformToDb<T>(row, { parser: this.state.parser, logger: this.log })
|
|
182
186
|
}
|
|
183
187
|
}
|
package/query-builder/delete.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SQLQueryBindings } from "bun:sqlite"
|
|
2
|
-
import type {
|
|
1
|
+
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
3
|
+
import type { DeleteResult, Parser } from "../types"
|
|
3
4
|
import { createLogger, quoteIdentifier } from "../utils"
|
|
4
5
|
import { SelectQueryBuilder } from "./select"
|
|
5
6
|
|
|
@@ -17,7 +18,12 @@ import { SelectQueryBuilder } from "./select"
|
|
|
17
18
|
* - Truncate (explicit full-table delete)
|
|
18
19
|
*/
|
|
19
20
|
export class DeleteQueryBuilder<T extends Record<string, unknown>> extends SelectQueryBuilder<T> {
|
|
20
|
-
private deleteLog
|
|
21
|
+
private deleteLog: ReturnType<typeof createLogger>
|
|
22
|
+
|
|
23
|
+
constructor(db: Database, tableName: string, parser: Parser<T>, baseLogger?: Logger) {
|
|
24
|
+
super(db, tableName, parser, baseLogger)
|
|
25
|
+
this.deleteLog = createLogger("Delete", baseLogger)
|
|
26
|
+
}
|
|
21
27
|
|
|
22
28
|
// ===== Public Delete Methods =====
|
|
23
29
|
|
package/query-builder/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
2
3
|
import type {
|
|
3
4
|
ColumnNames,
|
|
4
5
|
DeleteResult,
|
|
@@ -32,12 +33,12 @@ export class QueryBuilder<T extends Record<string, unknown> = Record<string, unk
|
|
|
32
33
|
private updateBuilder: UpdateQueryBuilder<T>
|
|
33
34
|
private deleteBuilder: DeleteQueryBuilder<T>
|
|
34
35
|
|
|
35
|
-
constructor(db: Database, tableName: string, parser: Parser<T
|
|
36
|
+
constructor(db: Database, tableName: string, parser: Parser<T>, baseLogger?: Logger) {
|
|
36
37
|
// Create instances of each specialized builder
|
|
37
|
-
this.selectBuilder = new SelectQueryBuilder<T>(db, tableName, parser)
|
|
38
|
-
this.insertBuilder = new InsertQueryBuilder<T>(db, tableName, parser)
|
|
39
|
-
this.updateBuilder = new UpdateQueryBuilder<T>(db, tableName, parser)
|
|
40
|
-
this.deleteBuilder = new DeleteQueryBuilder<T>(db, tableName, parser)
|
|
38
|
+
this.selectBuilder = new SelectQueryBuilder<T>(db, tableName, parser, baseLogger)
|
|
39
|
+
this.insertBuilder = new InsertQueryBuilder<T>(db, tableName, parser, baseLogger)
|
|
40
|
+
this.updateBuilder = new UpdateQueryBuilder<T>(db, tableName, parser, baseLogger)
|
|
41
|
+
this.deleteBuilder = new DeleteQueryBuilder<T>(db, tableName, parser, baseLogger)
|
|
41
42
|
|
|
42
43
|
// Ensure all builders share the same state for WHERE conditions
|
|
43
44
|
this.syncBuilderStates()
|
package/query-builder/insert.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SQLQueryBindings } from "bun:sqlite"
|
|
2
|
-
import type {
|
|
1
|
+
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
3
|
+
import type { InsertOptions, InsertResult, Parser } from "../types"
|
|
3
4
|
import {
|
|
4
5
|
buildPlaceholders,
|
|
5
6
|
createLogger,
|
|
@@ -20,7 +21,12 @@ import { WhereQueryBuilder } from "./where"
|
|
|
20
21
|
* - Automatic JSON/Boolean serialization
|
|
21
22
|
*/
|
|
22
23
|
export class InsertQueryBuilder<T extends Record<string, unknown>> extends WhereQueryBuilder<T> {
|
|
23
|
-
private insertLog
|
|
24
|
+
private insertLog: ReturnType<typeof createLogger>
|
|
25
|
+
|
|
26
|
+
constructor(db: Database, tableName: string, parser: Parser<T>, baseLogger?: Logger) {
|
|
27
|
+
super(db, tableName, parser, baseLogger)
|
|
28
|
+
this.insertLog = createLogger("Insert", baseLogger)
|
|
29
|
+
}
|
|
24
30
|
|
|
25
31
|
// ===== Private Helpers =====
|
|
26
32
|
|
package/query-builder/select.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SQLQueryBindings } from "bun:sqlite"
|
|
2
|
-
import type {
|
|
1
|
+
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
3
|
+
import type { ColumnNames, OrderDirection, Parser } from "../types"
|
|
3
4
|
import { createLogger, quoteIdentifier } from "../utils"
|
|
4
5
|
import { WhereQueryBuilder } from "./where"
|
|
5
6
|
|
|
@@ -20,11 +21,12 @@ export class SelectQueryBuilder<T extends Record<string, unknown>> extends Where
|
|
|
20
21
|
private limitValue?: number
|
|
21
22
|
private offsetValue?: number
|
|
22
23
|
|
|
23
|
-
private selectLog
|
|
24
|
+
private selectLog: ReturnType<typeof createLogger>
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
super(db, tableName, parser)
|
|
27
|
-
|
|
26
|
+
constructor(db: Database, tableName: string, parser: Parser<T>, baseLogger?: Logger) {
|
|
27
|
+
super(db, tableName, parser, baseLogger)
|
|
28
|
+
this.selectLog = createLogger("Select", baseLogger)
|
|
29
|
+
}
|
|
28
30
|
|
|
29
31
|
// ===== Query Building Methods =====
|
|
30
32
|
|
package/query-builder/update.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type { SQLQueryBindings } from "bun:sqlite"
|
|
2
|
-
import type {
|
|
1
|
+
import type { Database, SQLQueryBindings } from "bun:sqlite"
|
|
2
|
+
import type { Logger } from "@dockstat/logger"
|
|
3
|
+
import type { Parser, UpdateResult } from "../types"
|
|
3
4
|
import { buildSetClause, createLogger, quoteIdentifier, type RowData } from "../utils"
|
|
4
5
|
import { SelectQueryBuilder } from "./select"
|
|
5
6
|
|
|
@@ -15,7 +16,12 @@ import { SelectQueryBuilder } from "./select"
|
|
|
15
16
|
* - Automatic JSON serialization
|
|
16
17
|
*/
|
|
17
18
|
export class UpdateQueryBuilder<T extends Record<string, unknown>> extends SelectQueryBuilder<T> {
|
|
18
|
-
private updateLog
|
|
19
|
+
private updateLog: ReturnType<typeof createLogger>
|
|
20
|
+
|
|
21
|
+
constructor(db: Database, tableName: string, parser: Parser<T>, baseLogger?: Logger) {
|
|
22
|
+
super(db, tableName, parser, baseLogger)
|
|
23
|
+
this.updateLog = createLogger("Update", baseLogger)
|
|
24
|
+
}
|
|
19
25
|
|
|
20
26
|
// ===== Public Update Methods =====
|
|
21
27
|
|
package/utils/index.ts
CHANGED
package/utils/logger.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import Logger from "@dockstat/logger"
|
|
1
|
+
import { Logger, type LogHook } from "@dockstat/logger"
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Centralized logging for sqlite-wrapper
|
|
@@ -31,8 +31,18 @@ export class SqliteLogger {
|
|
|
31
31
|
private logger: Logger
|
|
32
32
|
private tableName?: string
|
|
33
33
|
|
|
34
|
-
constructor(name: string, parent?: Logger, tableName?: string) {
|
|
35
|
-
|
|
34
|
+
constructor(name: string, parent?: Logger, tableName?: string, logHook?: LogHook) {
|
|
35
|
+
try {
|
|
36
|
+
if (parent && typeof parent.spawn === "function") {
|
|
37
|
+
this.logger = parent.spawn(name)
|
|
38
|
+
} else {
|
|
39
|
+
this.logger = new Logger(name, [], logHook)
|
|
40
|
+
}
|
|
41
|
+
} catch (error) {
|
|
42
|
+
this.logger = new Logger(name, [], logHook)
|
|
43
|
+
console.error(error)
|
|
44
|
+
}
|
|
45
|
+
|
|
36
46
|
this.tableName = tableName
|
|
37
47
|
}
|
|
38
48
|
|
|
@@ -173,7 +183,12 @@ export const logger = new SqliteLogger("Sqlite")
|
|
|
173
183
|
/**
|
|
174
184
|
* Create a new logger for a specific module
|
|
175
185
|
*/
|
|
176
|
-
export function createLogger(name: string): SqliteLogger {
|
|
186
|
+
export function createLogger(name: string, baseLogger?: Logger): SqliteLogger {
|
|
187
|
+
// If a base logger is provided (recommended for apps/packages that want shared LogHook/parents),
|
|
188
|
+
// derive a sqlite-scoped child logger from it.
|
|
189
|
+
if (baseLogger) return new SqliteLogger(name, baseLogger)
|
|
190
|
+
|
|
191
|
+
// Fallback to the package-level logger (works, but won't automatically inherit app hooks)
|
|
177
192
|
return logger.child(name)
|
|
178
193
|
}
|
|
179
194
|
|
|
@@ -181,4 +196,24 @@ export function addLoggerParents(parents: string[]): void {
|
|
|
181
196
|
logger.addParents(parents)
|
|
182
197
|
}
|
|
183
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Configure a shared LogHook for sqlite-wrapper's root logger.
|
|
201
|
+
*
|
|
202
|
+
* Useful when consumers (e.g. `apps/api`, `packages/db`) want sqlite-wrapper logs
|
|
203
|
+
* to be routed through the same sink/formatter as the rest of the app.
|
|
204
|
+
*/
|
|
205
|
+
export function setSqliteLogHook(logHook: LogHook): void {
|
|
206
|
+
logger.getBaseLogger().setLogHook(logHook)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Optional convenience for consumers: create a sqlite-scoped base Logger that shares a LogHook.
|
|
211
|
+
*
|
|
212
|
+
* This is handy if you want to pass a base logger into `createLogger()` / `DB` and have
|
|
213
|
+
* everything inherit the same hook.
|
|
214
|
+
*/
|
|
215
|
+
export function createSqliteBaseLogger(logHook?: LogHook): Logger {
|
|
216
|
+
return new Logger("Sqlite", [], logHook)
|
|
217
|
+
}
|
|
218
|
+
|
|
184
219
|
export default logger
|
package/utils/transformer.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { SQLQueryBindings } from "bun:sqlite"
|
|
2
2
|
import type { Parser } from "../types"
|
|
3
|
-
import { createLogger } from "./logger"
|
|
3
|
+
import { createLogger, type SqliteLogger } from "./logger"
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Row Transformer for sqlite-wrapper
|
|
@@ -9,7 +9,7 @@ import { createLogger } from "./logger"
|
|
|
9
9
|
* including JSON columns, Boolean columns, and Module columns.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
const
|
|
12
|
+
const defaultLogger = createLogger("Transformer")
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Generic row data type
|
|
@@ -21,6 +21,7 @@ export type RowData = Record<string, SQLQueryBindings>
|
|
|
21
21
|
*/
|
|
22
22
|
export interface TransformOptions<T> {
|
|
23
23
|
parser?: Parser<T>
|
|
24
|
+
logger?: SqliteLogger
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -43,6 +44,7 @@ export function transformFromDb<T extends Record<string, unknown>>(
|
|
|
43
44
|
return row as T
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
const logger = options?.logger || defaultLogger
|
|
46
48
|
const transformed = { ...row } as RowData
|
|
47
49
|
const transformedColumns: string[] = []
|
|
48
50
|
|
|
@@ -166,6 +168,7 @@ export function transformToDb<T extends Record<string, unknown>>(
|
|
|
166
168
|
return row as RowData
|
|
167
169
|
}
|
|
168
170
|
|
|
171
|
+
const logger = options?.logger || defaultLogger
|
|
169
172
|
const transformed = { ...row } as RowData
|
|
170
173
|
const transformedColumns: string[] = []
|
|
171
174
|
|