@pineliner/odb-client 1.0.7 → 1.0.9

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/dist/index.js CHANGED
@@ -6,6 +6,7 @@ var __webpack_modules__ = {
6
6
  __webpack_require__.r(__webpack_exports__);
7
7
  __webpack_require__.d(__webpack_exports__, {
8
8
  ORM: ()=>ORM,
9
+ Transaction: ()=>Transaction,
9
10
  and: ()=>and,
10
11
  createORM: ()=>createORM,
11
12
  eq: ()=>eq,
@@ -296,10 +297,67 @@ var __webpack_modules__ = {
296
297
  return new DeleteBuilder(this.db, this.tableName);
297
298
  }
298
299
  }
300
+ class Transaction {
301
+ orm;
302
+ isCommitted = false;
303
+ isRolledBack = false;
304
+ db;
305
+ savepointName;
306
+ constructor(db, transactionDepth = 0, savepointName){
307
+ this.db = db;
308
+ this.orm = new ORM(db, transactionDepth);
309
+ this.savepointName = savepointName;
310
+ }
311
+ select(fields) {
312
+ this.checkNotFinalized();
313
+ return this.orm.select(fields);
314
+ }
315
+ insert(tableName) {
316
+ this.checkNotFinalized();
317
+ return this.orm.insert(tableName);
318
+ }
319
+ update(tableName) {
320
+ this.checkNotFinalized();
321
+ return this.orm.update(tableName);
322
+ }
323
+ delete(tableName) {
324
+ this.checkNotFinalized();
325
+ return this.orm.delete(tableName);
326
+ }
327
+ execute(sql, params) {
328
+ this.checkNotFinalized();
329
+ return this.orm.execute(sql, params);
330
+ }
331
+ async transaction(fn) {
332
+ this.checkNotFinalized();
333
+ if (fn) return await this.orm.transaction(fn);
334
+ return await this.orm.transaction();
335
+ }
336
+ async commit() {
337
+ if (this.isCommitted) throw new Error('Transaction already committed');
338
+ if (this.isRolledBack) throw new Error('Transaction already rolled back');
339
+ if (this.savepointName) await this.db.execute(`RELEASE SAVEPOINT ${this.savepointName}`, []);
340
+ else await this.db.execute('COMMIT', []);
341
+ this.isCommitted = true;
342
+ }
343
+ async rollback() {
344
+ if (this.isCommitted) throw new Error('Transaction already committed');
345
+ if (this.isRolledBack) throw new Error('Transaction already rolled back');
346
+ if (this.savepointName) await this.db.execute(`ROLLBACK TO SAVEPOINT ${this.savepointName}`, []);
347
+ else await this.db.execute('ROLLBACK', []);
348
+ this.isRolledBack = true;
349
+ }
350
+ checkNotFinalized() {
351
+ if (this.isCommitted) throw new Error('Cannot perform operations on committed transaction');
352
+ if (this.isRolledBack) throw new Error('Cannot perform operations on rolled back transaction');
353
+ }
354
+ }
299
355
  class ORM {
300
356
  db;
301
- constructor(db){
357
+ transactionDepth = 0;
358
+ constructor(db, transactionDepth = 0){
302
359
  this.db = db;
360
+ this.transactionDepth = transactionDepth;
303
361
  }
304
362
  table(tableName) {
305
363
  return new TableQueryBuilder(this.db, tableName);
@@ -325,6 +383,33 @@ var __webpack_modules__ = {
325
383
  execute(sql, params) {
326
384
  return this.db.execute(sql, params);
327
385
  }
386
+ async transaction(fn) {
387
+ if (!fn) if (this.transactionDepth > 0) {
388
+ const savepointName = `sp_${this.transactionDepth}_${Date.now()}`;
389
+ await this.db.execute(`SAVEPOINT ${savepointName}`, []);
390
+ return new Transaction(this.db, this.transactionDepth + 1, savepointName);
391
+ } else {
392
+ await this.db.execute('BEGIN TRANSACTION', []);
393
+ return new Transaction(this.db, 1);
394
+ }
395
+ if (!(this.transactionDepth > 0)) return await this.db.transaction(async (txConnection)=>{
396
+ const txOrm = new ORM(txConnection, 1);
397
+ return await fn(txOrm);
398
+ });
399
+ {
400
+ const savepointName = `sp_${this.transactionDepth}_${Date.now()}`;
401
+ try {
402
+ await this.db.execute(`SAVEPOINT ${savepointName}`, []);
403
+ const nestedOrm = new ORM(this.db, this.transactionDepth + 1);
404
+ const result = await fn(nestedOrm);
405
+ await this.db.execute(`RELEASE SAVEPOINT ${savepointName}`, []);
406
+ return result;
407
+ } catch (error) {
408
+ await this.db.execute(`ROLLBACK TO SAVEPOINT ${savepointName}`, []);
409
+ throw error;
410
+ }
411
+ }
412
+ }
328
413
  }
329
414
  function createORM(db) {
330
415
  return new ORM(db);
@@ -1204,6 +1289,26 @@ function sql_template_where(conditions) {
1204
1289
  args: values
1205
1290
  };
1206
1291
  }
1292
+ function parseJsonColumns(rows, jsonColumns) {
1293
+ if (!jsonColumns || 0 === jsonColumns.length) return rows;
1294
+ return rows.map((row)=>{
1295
+ const parsed = {
1296
+ ...row
1297
+ };
1298
+ for (const col of jsonColumns)if (col in parsed && 'string' == typeof parsed[col]) try {
1299
+ parsed[col] = JSON.parse(parsed[col]);
1300
+ } catch {}
1301
+ return parsed;
1302
+ });
1303
+ }
1304
+ function stringifyJsonParams(params, stringifyParams) {
1305
+ if (!stringifyParams || 0 === Object.keys(stringifyParams).length) return params;
1306
+ const result = [
1307
+ ...params
1308
+ ];
1309
+ for (const [_columnName, index] of Object.entries(stringifyParams))if (index < result.length && null != result[index] && 'object' == typeof result[index]) result[index] = JSON.stringify(result[index]);
1310
+ return result;
1311
+ }
1207
1312
  class BunSQLiteAdapter {
1208
1313
  type = 'bun-sqlite';
1209
1314
  config;
@@ -1261,10 +1366,10 @@ class BunSQLiteConnection {
1261
1366
  this.sql.set = set;
1262
1367
  this.sql.where = sql_template_where;
1263
1368
  }
1264
- async query(sql, params = []) {
1265
- return this.execute(sql, params);
1369
+ async query(sql, params = [], options) {
1370
+ return this.execute(sql, params, options);
1266
1371
  }
1267
- async execute(sql, params = []) {
1372
+ async execute(sql, params = [], options) {
1268
1373
  try {
1269
1374
  let sqlStr;
1270
1375
  let sqlParams;
@@ -1283,12 +1388,14 @@ class BunSQLiteConnection {
1283
1388
  sqlStr = sql;
1284
1389
  sqlParams = params;
1285
1390
  }
1391
+ if (options?.stringifyParams) sqlParams = stringifyJsonParams(sqlParams, options.stringifyParams);
1286
1392
  const stmt = this.db.query(sqlStr);
1287
1393
  const isSelect = sqlStr.trim().toUpperCase().startsWith('SELECT') || sqlStr.trim().toUpperCase().includes('RETURNING');
1288
1394
  if (isSelect) {
1289
- const rows = stmt.all(...sqlParams);
1395
+ let rows = stmt.all(...sqlParams);
1396
+ if (options?.jsonColumns) rows = parseJsonColumns(rows, options.jsonColumns);
1290
1397
  return {
1291
- rows: rows,
1398
+ rows,
1292
1399
  rowsAffected: 0
1293
1400
  };
1294
1401
  }
@@ -1355,6 +1462,26 @@ class BunSQLiteConnection {
1355
1462
  return createORM(this);
1356
1463
  }
1357
1464
  }
1465
+ function libsql_parseJsonColumns(rows, jsonColumns) {
1466
+ if (!jsonColumns || 0 === jsonColumns.length) return rows;
1467
+ return rows.map((row)=>{
1468
+ const parsed = {
1469
+ ...row
1470
+ };
1471
+ for (const col of jsonColumns)if (col in parsed && 'string' == typeof parsed[col]) try {
1472
+ parsed[col] = JSON.parse(parsed[col]);
1473
+ } catch {}
1474
+ return parsed;
1475
+ });
1476
+ }
1477
+ function libsql_stringifyJsonParams(params, stringifyParams) {
1478
+ if (!stringifyParams || 0 === Object.keys(stringifyParams).length) return params;
1479
+ const result = [
1480
+ ...params
1481
+ ];
1482
+ for (const [_columnName, index] of Object.entries(stringifyParams))if (index < result.length && null != result[index] && 'object' == typeof result[index]) result[index] = JSON.stringify(result[index]);
1483
+ return result;
1484
+ }
1358
1485
  class LibSQLAdapter {
1359
1486
  type = 'libsql';
1360
1487
  config;
@@ -1412,10 +1539,10 @@ class LibSQLConnection {
1412
1539
  this.sql.set = set;
1413
1540
  this.sql.where = sql_template_where;
1414
1541
  }
1415
- async query(sql, params = []) {
1416
- return this.execute(sql, params);
1542
+ async query(sql, params = [], options) {
1543
+ return this.execute(sql, params, options);
1417
1544
  }
1418
- async execute(sql, params = []) {
1545
+ async execute(sql, params = [], options) {
1419
1546
  try {
1420
1547
  const target = this.txClient || this.client;
1421
1548
  let query;
@@ -1424,23 +1551,29 @@ class LibSQLConnection {
1424
1551
  console.log('[LibSQL] Executing SQL:', sql);
1425
1552
  console.log('[LibSQL] With params:', params);
1426
1553
  }
1554
+ let args = params;
1555
+ if (options?.stringifyParams) args = libsql_stringifyJsonParams(args, options.stringifyParams);
1427
1556
  query = {
1428
1557
  sql,
1429
- args: params
1558
+ args
1430
1559
  };
1431
1560
  } else {
1432
1561
  if (process.env.DEBUG_SQL) {
1433
1562
  console.log('[LibSQL] Executing SQL:', sql.sql);
1434
1563
  console.log('[LibSQL] With args:', sql.args);
1435
1564
  }
1565
+ let args = sql.args || [];
1566
+ if (options?.stringifyParams) args = libsql_stringifyJsonParams(args, options.stringifyParams);
1436
1567
  query = {
1437
1568
  sql: sql.sql,
1438
- args: sql.args || []
1569
+ args
1439
1570
  };
1440
1571
  }
1441
1572
  const result = await target.execute(query);
1573
+ let rows = result.rows;
1574
+ if (options?.jsonColumns) rows = libsql_parseJsonColumns(rows, options.jsonColumns);
1442
1575
  return {
1443
- rows: result.rows,
1576
+ rows,
1444
1577
  rowsAffected: Number(result.rowsAffected),
1445
1578
  lastInsertRowid: result.lastInsertRowid ? BigInt(result.lastInsertRowid.toString()) : void 0
1446
1579
  };
@@ -1482,6 +1615,26 @@ class LibSQLConnection {
1482
1615
  return createORM(this);
1483
1616
  }
1484
1617
  }
1618
+ function odblite_parseJsonColumns(rows, jsonColumns) {
1619
+ if (!jsonColumns || 0 === jsonColumns.length) return rows;
1620
+ return rows.map((row)=>{
1621
+ const parsed = {
1622
+ ...row
1623
+ };
1624
+ for (const col of jsonColumns)if (col in parsed && 'string' == typeof parsed[col]) try {
1625
+ parsed[col] = JSON.parse(parsed[col]);
1626
+ } catch {}
1627
+ return parsed;
1628
+ });
1629
+ }
1630
+ function odblite_stringifyJsonParams(params, stringifyParams) {
1631
+ if (!stringifyParams || 0 === Object.keys(stringifyParams).length) return params;
1632
+ const result = [
1633
+ ...params
1634
+ ];
1635
+ for (const [_columnName, index] of Object.entries(stringifyParams))if (index < result.length && null != result[index] && 'object' == typeof result[index]) result[index] = JSON.stringify(result[index]);
1636
+ return result;
1637
+ }
1485
1638
  class ODBLiteAdapter {
1486
1639
  type = 'odblite';
1487
1640
  config;
@@ -1568,32 +1721,42 @@ class ODBLiteConnection {
1568
1721
  this.sql.set = set;
1569
1722
  this.sql.where = sql_template_where;
1570
1723
  }
1571
- async query(sql, params = []) {
1572
- return this.execute(sql, params);
1724
+ async query(sql, params = [], options) {
1725
+ return this.execute(sql, params, options);
1573
1726
  }
1574
- async execute(sql, params = []) {
1727
+ async execute(sql, params = [], options) {
1575
1728
  try {
1729
+ let rows;
1730
+ let rowsAffected;
1731
+ let lastInsertRowid;
1576
1732
  if ('object' == typeof sql) {
1577
1733
  if (process.env.DEBUG_SQL) {
1578
1734
  console.log('[ODBLite] Executing SQL:', sql.sql);
1579
1735
  console.log('[ODBLite] With args:', sql.args);
1580
1736
  }
1581
- const result = await this.client.sql.execute(sql.sql, sql.args || []);
1582
- return {
1583
- rows: result.rows,
1584
- rowsAffected: result.rowsAffected || 0,
1585
- lastInsertRowid: result.lastInsertRowid
1586
- };
1587
- }
1588
- if (process.env.DEBUG_SQL) {
1589
- console.log('[ODBLite] Executing SQL:', sql);
1590
- console.log('[ODBLite] With params:', params);
1737
+ let args = sql.args || [];
1738
+ if (options?.stringifyParams) args = odblite_stringifyJsonParams(args, options.stringifyParams);
1739
+ const result = await this.client.sql.execute(sql.sql, args);
1740
+ rows = result.rows;
1741
+ rowsAffected = result.rowsAffected || 0;
1742
+ lastInsertRowid = result.lastInsertRowid;
1743
+ } else {
1744
+ if (process.env.DEBUG_SQL) {
1745
+ console.log('[ODBLite] Executing SQL:', sql);
1746
+ console.log('[ODBLite] With params:', params);
1747
+ }
1748
+ let args = params;
1749
+ if (options?.stringifyParams) args = odblite_stringifyJsonParams(args, options.stringifyParams);
1750
+ const result = await this.client.sql.execute(sql, args);
1751
+ rows = result.rows;
1752
+ rowsAffected = result.rowsAffected || 0;
1753
+ lastInsertRowid = result.lastInsertRowid;
1591
1754
  }
1592
- const result = await this.client.sql.execute(sql, params);
1755
+ if (options?.jsonColumns) rows = odblite_parseJsonColumns(rows, options.jsonColumns);
1593
1756
  return {
1594
- rows: result.rows,
1595
- rowsAffected: result.rowsAffected || 0,
1596
- lastInsertRowid: result.lastInsertRowid
1757
+ rows,
1758
+ rowsAffected,
1759
+ lastInsertRowid
1597
1760
  };
1598
1761
  } catch (error) {
1599
1762
  throw error;
@@ -1875,6 +2038,7 @@ class DatabaseManager {
1875
2038
  var orm = __webpack_require__("./src/orm/index.ts");
1876
2039
  const { raw: src_raw, identifier: src_identifier, where: src_where, insertValues: src_insertValues, updateSet: src_updateSet, join: src_join } = ODBLiteClient;
1877
2040
  var __webpack_exports__ORM = orm.ORM;
2041
+ var __webpack_exports__ORMTransaction = orm.Transaction;
1878
2042
  var __webpack_exports__and = orm.and;
1879
2043
  var __webpack_exports__createORM = orm.createORM;
1880
2044
  var __webpack_exports__eq = orm.eq;
@@ -1888,4 +2052,4 @@ var __webpack_exports__lt = orm.lt;
1888
2052
  var __webpack_exports__lte = orm.lte;
1889
2053
  var __webpack_exports__ne = orm.ne;
1890
2054
  var __webpack_exports__or = orm.or;
1891
- export { BunSQLiteAdapter, ConnectionError, DatabaseManager, HTTPClient, LibSQLAdapter, ODBLiteAdapter, ODBLiteClient, ODBLiteError, ODBLiteTransaction, types_QueryError as QueryError, sql_parser_SQLParser as SQLParser, ServiceClient, SimpleTransaction, convertTemplateToQuery, odblite as default, empty, fragment, src_identifier as identifier, src_insertValues as insertValues, src_join as join, odblite, parseSQL, src_raw as raw, sql_template_raw as rawSQL, set, splitSQLStatements, sql_parser_sql as sql, sql_template_fragment as sqlFragment, sql_template_join as sqlJoin, sql_template_sql as sqlTemplate, sql_template_where as sqlWhere, src_updateSet as updateSet, src_where as where, __webpack_exports__ORM as ORM, __webpack_exports__and as and, __webpack_exports__createORM as createORM, __webpack_exports__eq as eq, __webpack_exports__gt as gt, __webpack_exports__gte as gte, __webpack_exports__inArray as inArray, __webpack_exports__isNotNull as isNotNull, __webpack_exports__isNull as isNull, __webpack_exports__like as like, __webpack_exports__lt as lt, __webpack_exports__lte as lte, __webpack_exports__ne as ne, __webpack_exports__or as or };
2055
+ export { BunSQLiteAdapter, ConnectionError, DatabaseManager, HTTPClient, LibSQLAdapter, ODBLiteAdapter, ODBLiteClient, ODBLiteError, ODBLiteTransaction, types_QueryError as QueryError, sql_parser_SQLParser as SQLParser, ServiceClient, SimpleTransaction, convertTemplateToQuery, odblite as default, empty, fragment, src_identifier as identifier, src_insertValues as insertValues, src_join as join, odblite, parseSQL, src_raw as raw, sql_template_raw as rawSQL, set, splitSQLStatements, sql_parser_sql as sql, sql_template_fragment as sqlFragment, sql_template_join as sqlJoin, sql_template_sql as sqlTemplate, sql_template_where as sqlWhere, src_updateSet as updateSet, src_where as where, __webpack_exports__ORM as ORM, __webpack_exports__ORMTransaction as ORMTransaction, __webpack_exports__and as and, __webpack_exports__createORM as createORM, __webpack_exports__eq as eq, __webpack_exports__gt as gt, __webpack_exports__gte as gte, __webpack_exports__inArray as inArray, __webpack_exports__isNotNull as isNotNull, __webpack_exports__isNull as isNull, __webpack_exports__like as like, __webpack_exports__lt as lt, __webpack_exports__lte as lte, __webpack_exports__ne as ne, __webpack_exports__or as or };
@@ -186,13 +186,53 @@ declare class TableQueryBuilder {
186
186
  */
187
187
  delete(): DeleteBuilder;
188
188
  }
189
+ /**
190
+ * Manual Transaction Control
191
+ * Allows explicit commit/rollback control
192
+ */
193
+ export declare class Transaction {
194
+ private orm;
195
+ private isCommitted;
196
+ private isRolledBack;
197
+ private db;
198
+ private savepointName?;
199
+ constructor(db: Connection, transactionDepth?: number, savepointName?: string);
200
+ /**
201
+ * Access ORM methods (select, insert, update, delete)
202
+ */
203
+ select(fields?: Record<string, any>): {
204
+ from: (tableName: string) => SelectBuilder<any>;
205
+ };
206
+ insert(tableName: string): InsertBuilder<any>;
207
+ update(tableName: string): UpdateBuilder<any>;
208
+ delete(tableName: string): DeleteBuilder;
209
+ execute(sql: string, params?: any[]): Promise<import("../index.ts").DatabaseQueryResult<any>>;
210
+ /**
211
+ * Create nested transaction (savepoint)
212
+ */
213
+ transaction(): Promise<Transaction>;
214
+ transaction<T>(fn: (tx: ORM) => Promise<T>): Promise<T>;
215
+ /**
216
+ * Commit the transaction
217
+ */
218
+ commit(): Promise<void>;
219
+ /**
220
+ * Rollback the transaction
221
+ */
222
+ rollback(): Promise<void>;
223
+ /**
224
+ * Check if transaction is finalized
225
+ */
226
+ private checkNotFinalized;
227
+ }
189
228
  /**
190
229
  * ORM Wrapper for Connection
191
230
  * Provides Drizzle-like syntax for database operations
192
231
  */
193
232
  export declare class ORM {
194
233
  private db;
195
- constructor(db: Connection);
234
+ private transactionDepth;
235
+ constructor(db: Connection, transactionDepth?: number);
196
236
  /**
197
237
  * Access a table for querying
198
238
  */
@@ -219,6 +259,44 @@ export declare class ORM {
219
259
  * Raw query access
220
260
  */
221
261
  execute(sql: string, params?: any[]): Promise<import("../index.ts").DatabaseQueryResult<any>>;
262
+ /**
263
+ * Execute a transaction with support for nested transactions (savepoints)
264
+ * @example
265
+ * // Callback-style transaction
266
+ * const result = await orm.transaction(async (tx) => {
267
+ * const user = await tx.insert('users').values({ name: 'Alice' }).returning()
268
+ * const profile = await tx.insert('profiles').values({
269
+ * userId: user[0].id,
270
+ * bio: 'Hello world',
271
+ * }).returning()
272
+ * return { user, profile }
273
+ * })
274
+ *
275
+ * @example
276
+ * // Manual transaction control
277
+ * const tx = await orm.transaction()
278
+ * try {
279
+ * await tx.insert('users').values({ name: 'Bob' }).execute()
280
+ * await tx.insert('profiles').values({ userId: 1, bio: 'Something' }).execute()
281
+ * await tx.commit()
282
+ * } catch (err) {
283
+ * await tx.rollback()
284
+ * throw err
285
+ * }
286
+ *
287
+ * @example
288
+ * // Nested transaction (savepoint)
289
+ * await orm.transaction(async (outer) => {
290
+ * await outer.insert('users').values({ name: 'Outer' })
291
+ *
292
+ * await outer.transaction(async (inner) => {
293
+ * await inner.insert('users').values({ name: 'Inner' })
294
+ * // If this inner block throws, only the inner part rolls back
295
+ * })
296
+ * })
297
+ */
298
+ transaction(): Promise<Transaction>;
299
+ transaction<T>(fn: (tx: ORM) => Promise<T>): Promise<T>;
222
300
  }
223
301
  /**
224
302
  * Create ORM instance from Connection
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/orm/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/orm/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pineliner/odb-client",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Isomorphic client for ODB-Lite with postgres.js-like template string SQL support",
5
5
  "main": "./dist/index.cjs",
6
6
  "module": "./dist/index.js",
@@ -42,4 +42,4 @@
42
42
  "template-strings",
43
43
  "postgres-like"
44
44
  ]
45
- }
45
+ }
@@ -5,6 +5,7 @@ import type {
5
5
  QueryResult,
6
6
  PreparedStatement,
7
7
  BunSQLiteConfig,
8
+ QueryOptions,
8
9
  } from '../types'
9
10
  import {
10
11
  convertTemplateToQuery,
@@ -17,6 +18,48 @@ import {
17
18
  where
18
19
  } from '../sql-template'
19
20
 
21
+ /**
22
+ * Parse JSON columns in query results
23
+ * Only parses if the value is a string (to avoid double-parsing)
24
+ */
25
+ function parseJsonColumns<T = any>(rows: any[], jsonColumns?: string[]): T[] {
26
+ if (!jsonColumns || jsonColumns.length === 0) {
27
+ return rows
28
+ }
29
+
30
+ return rows.map(row => {
31
+ const parsed = { ...row }
32
+ for (const col of jsonColumns) {
33
+ if (col in parsed && typeof parsed[col] === 'string') {
34
+ try {
35
+ parsed[col] = JSON.parse(parsed[col])
36
+ } catch {
37
+ // Keep original value if parsing fails
38
+ }
39
+ }
40
+ }
41
+ return parsed
42
+ })
43
+ }
44
+
45
+ /**
46
+ * Stringify JSON parameters for INSERT/UPDATE queries
47
+ * Only stringifies if the value is an object/array (not already a string)
48
+ */
49
+ function stringifyJsonParams(params: any[], stringifyParams?: Record<string, number>): any[] {
50
+ if (!stringifyParams || Object.keys(stringifyParams).length === 0) {
51
+ return params
52
+ }
53
+
54
+ const result = [...params]
55
+ for (const [_columnName, index] of Object.entries(stringifyParams)) {
56
+ if (index < result.length && result[index] != null && typeof result[index] === 'object') {
57
+ result[index] = JSON.stringify(result[index])
58
+ }
59
+ }
60
+ return result
61
+ }
62
+
20
63
  /**
21
64
  * Bun SQLite adapter for DatabaseManager
22
65
  * Wraps bun:sqlite with Connection interface
@@ -117,14 +160,14 @@ class BunSQLiteConnection implements Connection {
117
160
  /**
118
161
  * Query with SQL string and parameters (alias for execute)
119
162
  */
120
- async query<T = any>(sql: string, params: any[] = []): Promise<QueryResult<T>> {
121
- return this.execute(sql, params) as Promise<QueryResult<T>>
163
+ async query<T = any>(sql: string, params: any[] = [], options?: QueryOptions): Promise<QueryResult<T>> {
164
+ return this.execute(sql, params, options) as Promise<QueryResult<T>>
122
165
  }
123
166
 
124
167
  /**
125
168
  * Execute SQL with parameters
126
169
  */
127
- async execute(sql: string | { sql: string; args?: any[] }, params: any[] = []): Promise<QueryResult> {
170
+ async execute(sql: string | { sql: string; args?: any[] }, params: any[] = [], options?: QueryOptions): Promise<QueryResult> {
128
171
  try {
129
172
  // Handle object format { sql, args }
130
173
  let sqlStr: string
@@ -147,14 +190,25 @@ class BunSQLiteConnection implements Connection {
147
190
  sqlParams = params
148
191
  }
149
192
 
193
+ // Stringify JSON parameters if specified
194
+ if (options?.stringifyParams) {
195
+ sqlParams = stringifyJsonParams(sqlParams, options.stringifyParams)
196
+ }
197
+
150
198
  const stmt = this.db.query(sqlStr)
151
199
  const isSelect = sqlStr.trim().toUpperCase().startsWith('SELECT') ||
152
200
  sqlStr.trim().toUpperCase().includes('RETURNING')
153
201
 
154
202
  if (isSelect) {
155
- const rows = stmt.all(...sqlParams)
203
+ let rows = stmt.all(...sqlParams) as any[]
204
+
205
+ // Parse JSON columns if specified
206
+ if (options?.jsonColumns) {
207
+ rows = parseJsonColumns(rows, options.jsonColumns)
208
+ }
209
+
156
210
  return {
157
- rows: rows as any[],
211
+ rows,
158
212
  rowsAffected: 0,
159
213
  }
160
214
  } else {