From 01f02e7b881cc9e9289b8929ff5116d3037235a1 Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Thu, 6 Nov 2025 14:05:57 +0200 Subject: [PATCH 1/4] Log queries in debugMode on web. --- .../db/adapters/LockedAsyncDatabaseAdapter.ts | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts index 25e0afa56..dfc50f4a3 100644 --- a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts +++ b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts @@ -67,10 +67,30 @@ export class LockedAsyncDatabaseAdapter const start = performance.now(); try { const r = await originalExecute(sql, bindings); + const duration = performance.now() - start; performance.measure(`[SQL] ${sql}`, { start }); + console.log( + '%c[SQL] %c%s %c%s', + 'color: grey; font-weight: normal', + durationStyle(duration), + `[${duration.toFixed(1)}ms]`, + 'color: grey; font-weight: normal', + sql + ); return r; } catch (e: any) { + const duration = performance.now() - start; performance.measure(`[SQL] [ERROR: ${e.message}] ${sql}`, { start }); + console.error( + '%c[SQL] %c%s %c%s %c%s', + 'color: grey; font-weight: normal', + 'color: red; font-weight: normal', + `[ERROR: ${e.message}]`, + durationStyle(duration), + `[${duration.toFixed(1)}ms]`, + 'color: grey; font-weight: normal', + sql + ); throw e; } }; @@ -356,3 +376,13 @@ export class LockedAsyncDatabaseAdapter }; }; } + +function durationStyle(duration: number) { + if (duration < 30) { + return 'color: grey; font-weight: normal'; + } else if (duration < 300) { + return 'color: blue; font-weight: normal'; + } else { + return 'color: red; font-weight: normal'; + } +} From c13334722173a14cbcf32aa03aefffdfe25bf020 Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Thu, 6 Nov 2025 14:06:36 +0200 Subject: [PATCH 2/4] Log queries in debugMode on op-sqlite. --- .../src/db/OPSQLiteConnection.ts | 28 +++++++++++++++++++ .../src/db/OPSqliteAdapter.ts | 13 +++++---- .../src/db/OPSqliteDBOpenFactory.ts | 3 +- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/packages/powersync-op-sqlite/src/db/OPSQLiteConnection.ts b/packages/powersync-op-sqlite/src/db/OPSQLiteConnection.ts index 5704a48b1..5b4986323 100644 --- a/packages/powersync-op-sqlite/src/db/OPSQLiteConnection.ts +++ b/packages/powersync-op-sqlite/src/db/OPSQLiteConnection.ts @@ -10,6 +10,8 @@ import { export type OPSQLiteConnectionOptions = { baseDB: DB; + debugMode: boolean; + connectionName: string; }; export type OPSQLiteUpdateNotification = { @@ -35,6 +37,16 @@ export class OPSQLiteConnection extends BaseObserver { this.DB.updateHook((update) => { this.addTableUpdate(update); }); + + if (options.debugMode) { + const c = this.options.connectionName; + this.execute = withDebug(this.execute.bind(this), `[SQL execute ${c}]`); + this.executeRaw = withDebug(this.executeRaw.bind(this), `[SQL executeRaw ${c}]`); + this.executeBatch = withDebug(this.executeBatch.bind(this), `[SQL executeBatch ${c}]`); + this.get = withDebug(this.get.bind(this), `[SQL get ${c}]`); + this.getAll = withDebug(this.getAll.bind(this), `[SQL getAll ${c}]`); + this.getOptional = withDebug(this.getOptional.bind(this), `[SQL getOptional ${c}]`); + } } addTableUpdate(update: OPSQLiteUpdateNotification) { @@ -133,3 +145,19 @@ export class OPSQLiteConnection extends BaseObserver { await this.get("PRAGMA table_info('sqlite_master')"); } } + +function withDebug Promise>(fn: T, name: string): T { + return (async (sql: string, ...args: any[]): Promise => { + const start = performance.now(); + try { + const r = await fn(sql, ...args); + const duration = performance.now() - start; + console.log(name, `[${duration.toFixed(1)}ms]`, sql); + return r; + } catch (e: any) { + const duration = performance.now() - start; + console.error(name, `[ERROR: ${e.message}]`, `[${duration.toFixed(1)}ms]`, sql); + throw e; + } + }) as T; +} diff --git a/packages/powersync-op-sqlite/src/db/OPSqliteAdapter.ts b/packages/powersync-op-sqlite/src/db/OPSqliteAdapter.ts index 60d4a4eeb..f00d6ccb6 100644 --- a/packages/powersync-op-sqlite/src/db/OPSqliteAdapter.ts +++ b/packages/powersync-op-sqlite/src/db/OPSqliteAdapter.ts @@ -12,6 +12,7 @@ export type OPSQLiteAdapterOptions = { name: string; dbLocation?: string; sqliteOptions?: SqliteOptions; + debugMode?: boolean; }; enum LockType { @@ -50,7 +51,7 @@ export class OPSQLiteDBAdapter extends BaseObserver implement this.options.sqliteOptions!; const dbFilename = this.options.name; - this.writeConnection = await this.openConnection(dbFilename); + this.writeConnection = await this.openConnection('w'); const baseStatements = [ `PRAGMA busy_timeout = ${lockTimeoutMs}`, @@ -89,7 +90,7 @@ export class OPSQLiteDBAdapter extends BaseObserver implement this.readConnections = []; for (let i = 0; i < READ_CONNECTIONS; i++) { - const conn = await this.openConnection(dbFilename); + const conn = await this.openConnection(`r-${i}`); for (let statement of readConnectionStatements) { await conn.execute(statement); } @@ -97,8 +98,8 @@ export class OPSQLiteDBAdapter extends BaseObserver implement } } - protected async openConnection(filenameOverride?: string): Promise { - const dbFilename = filenameOverride ?? this.options.name; + protected async openConnection(connectionName: string): Promise { + const dbFilename = this.options.name; const DB: DB = this.openDatabase(dbFilename, this.options.sqliteOptions?.encryptionKey ?? undefined); //Load extensions for all connections @@ -108,7 +109,9 @@ export class OPSQLiteDBAdapter extends BaseObserver implement await DB.execute('SELECT powersync_init()'); return new OPSQLiteConnection({ - baseDB: DB + baseDB: DB, + debugMode: this.options.debugMode ?? false, + connectionName }); } diff --git a/packages/powersync-op-sqlite/src/db/OPSqliteDBOpenFactory.ts b/packages/powersync-op-sqlite/src/db/OPSqliteDBOpenFactory.ts index e6527887d..59195e5ef 100644 --- a/packages/powersync-op-sqlite/src/db/OPSqliteDBOpenFactory.ts +++ b/packages/powersync-op-sqlite/src/db/OPSqliteDBOpenFactory.ts @@ -19,7 +19,8 @@ export class OPSqliteOpenFactory implements SQLOpenFactory { return new OPSQLiteDBAdapter({ name: this.options.dbFilename, dbLocation: this.options.dbLocation, - sqliteOptions: this.sqliteOptions + sqliteOptions: this.sqliteOptions, + debugMode: this.options.debugMode }); } } From 6cb33e92e7bf24ed79dd69e18fff3c00893541b4 Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Thu, 6 Nov 2025 14:07:25 +0200 Subject: [PATCH 3/4] Changeset. --- .changeset/kind-badgers-watch.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/kind-badgers-watch.md diff --git a/.changeset/kind-badgers-watch.md b/.changeset/kind-badgers-watch.md new file mode 100644 index 000000000..ea43ec3f9 --- /dev/null +++ b/.changeset/kind-badgers-watch.md @@ -0,0 +1,6 @@ +--- +'@powersync/op-sqlite': patch +'@powersync/web': patch +--- + +Log queries to console in debugMode. From d5fbef973f6a159491efd19fae19421b2be7d8dc Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Thu, 6 Nov 2025 14:39:42 +0200 Subject: [PATCH 4/4] Fix attachments packages build. --- packages/attachments/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/attachments/package.json b/packages/attachments/package.json index 7e8449643..c1b7ec3b1 100644 --- a/packages/attachments/package.json +++ b/packages/attachments/package.json @@ -39,7 +39,7 @@ ], "scripts": { "build": "tsc -b && rollup --config", - "build:prod": "tsc -b --sourceMap false && rollup", + "build:prod": "tsc -b --sourceMap false && rollup --config", "clean": "rm -rf lib dist tsconfig.tsbuildinfo", "watch": "tsc -b -w", "test": "pnpm build && vitest", @@ -54,4 +54,4 @@ "vite": "^6.1.0", "vite-plugin-top-level-await": "^1.4.4" } -} +} \ No newline at end of file