fix(deno): return numbers from sqlite driver (#62)

This commit is contained in:
alina sireneva 2024-07-12 17:46:09 +03:00 committed by GitHub
commit 1ca3348dc6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 72 additions and 6 deletions

View file

@ -55,7 +55,7 @@ export abstract class BaseStorageDriver implements IStorageDriver {
protected _log!: Logger protected _log!: Logger
setup(log: Logger): void { setup(log: Logger): void {
this._log = log this._log = log.create('sqlite')
} }
protected get loaded(): boolean { protected get loaded(): boolean {

View file

@ -1,4 +1,9 @@
import { BaseSqliteStorageDriver, ISqliteDatabase } from '@mtcute/core' /* eslint-disable @typescript-eslint/no-explicit-any */
import { BaseSqliteStorageDriver, ISqliteDatabase, ISqliteStatement } from '@mtcute/core'
import { Logger } from '../utils.js'
import type { BindParameters, Database as TDatabase, Statement as TStatement } from '@db/sqlite'
let Database: typeof import('@db/sqlite').Database let Database: typeof import('@db/sqlite').Database
@ -16,6 +21,66 @@ export interface SqliteStorageDriverOptions {
disableWal?: boolean disableWal?: boolean
} }
function replaceBigintsWithNumber(obj?: object): object | undefined {
if (!obj) return obj
for (const [key, value] of Object.entries(obj)) {
if (typeof value === 'bigint') {
(obj as any)[key] = Number(value)
}
}
return obj
}
class WrappedStatement implements ISqliteStatement {
constructor(
private stmt: TStatement,
private sql: string,
private log: Logger,
) {}
run(...params: unknown[]): void {
this.log.verbose('RUN %s %o', this.sql, params)
this.stmt.run(...(params as BindParameters[]))
}
get(...params: unknown[]): unknown {
this.log.verbose('GET %s %o', this.sql, params)
return replaceBigintsWithNumber(this.stmt.get(...(params as BindParameters[])))
}
all(...params: unknown[]): unknown[] {
this.log.verbose('ALL %s %o', this.sql, params)
return this.stmt.all(...(params as BindParameters[])).map(replaceBigintsWithNumber)
}
}
class WrappedDatabase implements ISqliteDatabase {
constructor(
private db: TDatabase,
private log: Logger,
) {}
transaction(fn: any): any {
return this.db.transaction(fn)
}
prepare<BindParameters extends unknown[]>(sql: string): ISqliteStatement<BindParameters> {
return new WrappedStatement(this.db.prepare(sql), sql, this.log)
}
exec(sql: string): void {
this.db.exec(sql)
}
close(): void {
this.db.close()
}
}
export class SqliteStorageDriver extends BaseSqliteStorageDriver { export class SqliteStorageDriver extends BaseSqliteStorageDriver {
constructor( constructor(
readonly filename = ':memory:', readonly filename = ':memory:',
@ -34,14 +99,15 @@ export class SqliteStorageDriver extends BaseSqliteStorageDriver {
} }
_createDatabase(): ISqliteDatabase { _createDatabase(): ISqliteDatabase {
const db = new Database(this.filename, { // non-int64 mode trims numbers to 32 bits, and we don't want that
int64: true, // but int64 mode returns all numbers as bigints, but mtcute expects them
}) // as numbers, so we need to convert them... thx deno
const db = new Database(this.filename, { int64: true })
if (!this.params?.disableWal) { if (!this.params?.disableWal) {
db.exec('PRAGMA journal_mode = WAL;') db.exec('PRAGMA journal_mode = WAL;')
} }
return db as ISqliteDatabase return new WrappedDatabase(db, this._log)
} }
} }