diff --git a/.changeset/strong-flies-watch.md b/.changeset/strong-flies-watch.md new file mode 100644 index 000000000..e91b0c269 --- /dev/null +++ b/.changeset/strong-flies-watch.md @@ -0,0 +1,5 @@ +--- +'@powersync/common': major +--- + +Remove js-logger dependency in favor of a custom logger interface that needs to be passed to PowerSync databases explicitly. diff --git a/demos/angular-supabase-todolist/src/app/powersync.service.ts b/demos/angular-supabase-todolist/src/app/powersync.service.ts index 018579f72..161a689f0 100644 --- a/demos/angular-supabase-todolist/src/app/powersync.service.ts +++ b/demos/angular-supabase-todolist/src/app/powersync.service.ts @@ -3,8 +3,10 @@ import { AbstractPowerSyncDatabase, Column, ColumnType, + createConsoleLogger, Index, IndexedColumn, + LogLevels, PowerSyncBackendConnector, PowerSyncDatabase, Schema, @@ -69,7 +71,9 @@ export class PowerSyncService { dbFilename: 'test.db', vfs: WASQLiteVFS.OPFSCoopSyncVFS, // Specify the path to the worker script - worker: 'assets/@powersync/worker/WASQLiteDB.umd.js' + worker: 'assets/@powersync/worker/WASQLiteDB.umd.js', + logLevel: LogLevels.debug, + logger: createConsoleLogger({ prefix: 'powersync' }) }); this.db = new PowerSyncDatabase({ diff --git a/demos/example-capacitor/src/components/providers/SystemProvider.tsx b/demos/example-capacitor/src/components/providers/SystemProvider.tsx index 55a383d5a..8b3a1a190 100644 --- a/demos/example-capacitor/src/components/providers/SystemProvider.tsx +++ b/demos/example-capacitor/src/components/providers/SystemProvider.tsx @@ -1,15 +1,11 @@ import { CircularProgress } from '@mui/material'; import { PowerSyncDatabase } from '@powersync/capacitor'; import { PowerSyncContext } from '@powersync/react'; -import { createBaseLogger, LogLevel } from '@powersync/web'; +import { createConsoleLogger, LogLevels } from '@powersync/web'; import React, { Suspense } from 'react'; import { AppSchema } from '../../library/powersync/AppSchema.js'; import { BackendConnector } from '../../library/powersync/BackendConnector.js'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); - // Uses the Web SDK for web, and Capacitor adapters for iOS/Android. const powerSync = new PowerSyncDatabase({ database: { @@ -18,7 +14,8 @@ const powerSync = new PowerSyncDatabase({ schema: AppSchema, flags: { enableMultiTabs: typeof SharedWorker !== 'undefined' - } + }, + logger: createConsoleLogger({ minLevel: LogLevels.debug }) }); const connector = new BackendConnector(); diff --git a/demos/example-electron-node/src/main/index.ts b/demos/example-electron-node/src/main/index.ts index 7cb44813c..91973df24 100644 --- a/demos/example-electron-node/src/main/index.ts +++ b/demos/example-electron-node/src/main/index.ts @@ -1,21 +1,10 @@ import fs from 'node:fs'; import { Worker } from 'node:worker_threads'; -import { - createBaseLogger, - createLogger, - LogLevel, - PowerSyncDatabase, - SyncStreamConnectionMethod -} from '@powersync/node'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase, SyncStreamConnectionMethod } from '@powersync/node'; import { app, BrowserWindow, ipcMain, MessagePortMain } from 'electron'; import { AppSchema, BackendConnector } from './powersync'; -const baseLogger = createBaseLogger(); -baseLogger.useDefaults({ defaultLevel: LogLevel.WARN }); - -const logger = createLogger('PowerSyncDemo'); - // This allows TypeScript to pick up the magic constants that's auto-generated by Forge's Webpack // plugin that tells the Electron app where to look for the Webpack-bundled app code (depending on // whether you're running in development or production). @@ -47,7 +36,7 @@ const database = new PowerSyncDatabase({ return new Worker(new URL('./worker.ts', import.meta.url), options); } }, - logger + logger: createConsoleLogger({ minLevel: LogLevels.debug }) }); const createWindow = (): void => { diff --git a/demos/example-electron/src/components/providers/SystemProvider.tsx b/demos/example-electron/src/components/providers/SystemProvider.tsx index 0fe7aaac3..5d77fe8ea 100644 --- a/demos/example-electron/src/components/providers/SystemProvider.tsx +++ b/demos/example-electron/src/components/providers/SystemProvider.tsx @@ -1,20 +1,17 @@ import { PowerSyncContext } from '@powersync/react'; -import { createBaseLogger, LogLevel, PowerSyncDatabase } from '@powersync/web'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase } from '@powersync/web'; import { CircularProgress } from '@mui/material'; import React, { Suspense } from 'react'; import { AppSchema } from '../../library/powersync/AppSchema.js'; import { BackendConnector } from '../../library/powersync/BackendConnector.js'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); - const powerSync = new PowerSyncDatabase({ database: { dbFilename: 'powersync2.db' }, schema: AppSchema, flags: { disableSSRWarning: true - } + }, + logger: createConsoleLogger({ minLevel: LogLevels.debug }) }); const connector = new BackendConnector(); diff --git a/demos/example-nextjs/src/library/powersync/powersync-provider.tsx b/demos/example-nextjs/src/library/powersync/powersync-provider.tsx index 3c9a82876..ce92df3b1 100644 --- a/demos/example-nextjs/src/library/powersync/powersync-provider.tsx +++ b/demos/example-nextjs/src/library/powersync/powersync-provider.tsx @@ -3,22 +3,27 @@ import { AppSchema } from '@/library/powersync/schema'; import { BackendConnector } from '@/library/powersync/connector'; import { PowerSyncContext } from '@powersync/react'; -import { PowerSyncDatabase, WASQLiteOpenFactory } from '@powersync/web'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase, WASQLiteOpenFactory } from '@powersync/web'; import React, { Suspense } from 'react'; let dbInstance: PowerSyncDatabase | null = null; +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); + function getDB(): PowerSyncDatabase { if (dbInstance) return dbInstance; dbInstance = new PowerSyncDatabase({ database: new WASQLiteOpenFactory({ dbFilename: 'powersync-nextjs.db', - worker: '/@powersync/worker/WASQLiteDB.umd.js' + worker: '/@powersync/worker/WASQLiteDB.umd.js', + logger, + logLevel: LogLevels.debug }), schema: AppSchema, flags: { disableSSRWarning: true }, - sync: { worker: '/@powersync/worker/SharedSyncImplementation.umd.js' } + sync: { worker: '/@powersync/worker/SharedSyncImplementation.umd.js' }, + logger }); dbInstance.connect(new BackendConnector()); diff --git a/demos/example-node/src/main.ts b/demos/example-node/src/main.ts index bfef05d51..5649e4069 100644 --- a/demos/example-node/src/main.ts +++ b/demos/example-node/src/main.ts @@ -3,8 +3,8 @@ import repl_factory from 'node:repl'; import { Worker } from 'node:worker_threads'; import { - createBaseLogger, - createLogger, + createConsoleLogger, + LogLevels, PowerSyncDatabase, SyncClientImplementation, SyncStreamConnectionMethod @@ -15,11 +15,10 @@ import { AppSchema, DemoConnector } from './powersync.js'; import { enableUncidiDiagnostics } from './UndiciDiagnostics.js'; const main = async () => { - const baseLogger = createBaseLogger(); - const logger = createLogger('PowerSyncDemo'); const debug = process.env.POWERSYNC_DEBUG == '1'; + const logger = createConsoleLogger({ prefix: 'PowerSyncDemo', minLevel: debug ? LogLevels.trace : LogLevels.warn }); + const encryptionKey = process.env.ENCRYPTION_KEY ?? ''; - baseLogger.useDefaults({ defaultLevel: debug ? logger.TRACE : logger.WARN }); // Enable detailed request/response logging for debugging purposes. if (debug) { diff --git a/demos/example-vite-encryption/src/index.js b/demos/example-vite-encryption/src/index.js index 209005ba5..ca62bfa90 100644 --- a/demos/example-vite-encryption/src/index.js +++ b/demos/example-vite-encryption/src/index.js @@ -1,6 +1,6 @@ -import { column, Schema, Table, PowerSyncDatabase, createBaseLogger } from '@powersync/web'; +import { column, Schema, Table, PowerSyncDatabase, createConsoleLogger, LogLevels } from '@powersync/web'; -createBaseLogger().useDefaults(); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); const customers = new Table({ name: column.text }); @@ -12,7 +12,8 @@ const openDatabase = async (encryptionKey) => { PowerSync = new PowerSyncDatabase({ schema: AppSchema, database: { dbFilename: 'example-encryption.db' }, - encryptionKey: encryptionKey + encryptionKey: encryptionKey, + logger }); await PowerSync.init(); diff --git a/demos/example-vite/src/index.js b/demos/example-vite/src/index.js index 05111b12f..fd40004d8 100644 --- a/demos/example-vite/src/index.js +++ b/demos/example-vite/src/index.js @@ -1,6 +1,6 @@ -import { PowerSyncDatabase, Schema, Table, column, createBaseLogger } from '@powersync/web'; +import { PowerSyncDatabase, Schema, Table, column, createConsoleLogger, LogLevels } from '@powersync/web'; -createBaseLogger().useDefaults(); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); /** * A placeholder connector which doesn't do anything. @@ -27,7 +27,8 @@ let PowerSync; const openDatabase = async () => { PowerSync = new PowerSyncDatabase({ schema: AppSchema, - database: { dbFilename: 'test.sqlite' } + database: { dbFilename: 'test.sqlite' }, + logger }); await PowerSync.init(); diff --git a/demos/example-webpack/src/index.js b/demos/example-webpack/src/index.js index 0ec04b988..cefbe1607 100644 --- a/demos/example-webpack/src/index.js +++ b/demos/example-webpack/src/index.js @@ -1,6 +1,6 @@ -import { Schema, Table, PowerSyncDatabase, column, createBaseLogger } from '@powersync/web'; +import { Schema, Table, PowerSyncDatabase, column, createConsoleLogger, LogLevels } from '@powersync/web'; -createBaseLogger().useDefaults(); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); /** * A placeholder connector which doesn't do anything. @@ -27,7 +27,8 @@ let PowerSync; const openDatabase = async () => { PowerSync = new PowerSyncDatabase({ schema: AppSchema, - database: { dbFilename: 'test.sqlite' } + database: { dbFilename: 'test.sqlite' }, + logger }); await PowerSync.init(); diff --git a/demos/react-multi-client/src/components/providers/SystemProvider.tsx b/demos/react-multi-client/src/components/providers/SystemProvider.tsx index 0c22ca0ca..331ae8a55 100644 --- a/demos/react-multi-client/src/components/providers/SystemProvider.tsx +++ b/demos/react-multi-client/src/components/providers/SystemProvider.tsx @@ -6,11 +6,9 @@ import { PowerSyncContext, usePowerSync as _usePowerSync } from '@powersync/reac import { AppSchema } from '@/definitions/Schema'; import { SupabaseConnector } from '@/library/SupabaseConnector'; import { useSupabase } from './SupabaseProvider'; -import { createBaseLogger, LogLevel } from '@powersync/web'; +import { createConsoleLogger, LogLevels } from '@powersync/web'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export interface SystemProviderProps { dbFilename: string; @@ -27,7 +25,8 @@ const SystemProvider: React.FC> = (props) schema: AppSchema, flags: { disableSSRWarning: false - } + }, + logger: logger }).getInstance() ); @@ -35,7 +34,7 @@ const SystemProvider: React.FC> = (props) powersync.init(); const l = connector.registerListener({ - initialized: () => { }, + initialized: () => {}, sessionStarted: async () => { await powersync.connect(connector); } diff --git a/demos/react-native-supabase-background-sync/powersync/SystemContext.ts b/demos/react-native-supabase-background-sync/powersync/SystemContext.ts index 6c22fbee6..1613ed094 100644 --- a/demos/react-native-supabase-background-sync/powersync/SystemContext.ts +++ b/demos/react-native-supabase-background-sync/powersync/SystemContext.ts @@ -1,63 +1,59 @@ import React from 'react'; -import { createBaseLogger, LogLevel, PowerSyncDatabase, SyncClientImplementation } from '@powersync/react-native'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase, SyncClientImplementation } from '@powersync/react-native'; import { SupabaseConnector } from '@/supabase/SupabaseConnector'; import { AppSchema } from '@/powersync/AppSchema'; import { OPSqliteOpenFactory } from '@powersync/op-sqlite'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export class System { - connector: SupabaseConnector; - powersync: PowerSyncDatabase; - - constructor() { - this.connector = new SupabaseConnector(); - - const opSqlite = new OPSqliteOpenFactory({ - dbFilename: 'powersync.db' - }); - - this.powersync = new PowerSyncDatabase({ - schema: AppSchema, - database: opSqlite, - logger: logger - }); - } - - async init() { - await this.connector.signInAnonymously(); - - await this.powersync.init(); - - await this.powersync.connect(this.connector, { - clientImplementation: SyncClientImplementation.RUST - }); - - this.powersync.registerListener({ - statusChanged: (status) => { - const hasSynced = Boolean(status.lastSyncedAt); - const downloading = status.dataFlowStatus?.downloading || false; - const uploading = status.dataFlowStatus?.uploading || false; - console.log( - '[PowerSync] Status changed:', - hasSynced ? '✅ Synced' : '⏳ Not yet synced', - downloading ? '📥 Downloading' : '✅ Not downloading', - uploading ? '📤 Uploading' : '✅ Not uploading' - ); - }, - }); - } - - async disconnect() { - await this.powersync.disconnect(); - } + connector: SupabaseConnector; + powersync: PowerSyncDatabase; + + constructor() { + this.connector = new SupabaseConnector(); + + const opSqlite = new OPSqliteOpenFactory({ + dbFilename: 'powersync.db' + }); + + this.powersync = new PowerSyncDatabase({ + schema: AppSchema, + database: opSqlite, + logger: logger + }); + } + + async init() { + await this.connector.signInAnonymously(); + + await this.powersync.init(); + + await this.powersync.connect(this.connector, { + clientImplementation: SyncClientImplementation.RUST + }); + + this.powersync.registerListener({ + statusChanged: (status) => { + const hasSynced = Boolean(status.lastSyncedAt); + const downloading = status.dataFlowStatus?.downloading || false; + const uploading = status.dataFlowStatus?.uploading || false; + console.log( + '[PowerSync] Status changed:', + hasSynced ? '✅ Synced' : '⏳ Not yet synced', + downloading ? '📥 Downloading' : '✅ Not downloading', + uploading ? '📤 Uploading' : '✅ Not uploading' + ); + } + }); + } + + async disconnect() { + await this.powersync.disconnect(); + } } export const system = new System(); export const SystemContext = React.createContext(system); export const useSystem = () => React.useContext(SystemContext); - - diff --git a/demos/react-native-supabase-group-chat/src/providers/PowerSyncProvider.tsx b/demos/react-native-supabase-group-chat/src/providers/PowerSyncProvider.tsx index 1bd1cc882..028ba91aa 100644 --- a/demos/react-native-supabase-group-chat/src/providers/PowerSyncProvider.tsx +++ b/demos/react-native-supabase-group-chat/src/providers/PowerSyncProvider.tsx @@ -1,12 +1,12 @@ import '@azure/core-asynciterator-polyfill'; -import { createBaseLogger, PowerSyncContext, PowerSyncDatabase } from '@powersync/react-native'; +import { createConsoleLogger, LogLevels, PowerSyncContext, PowerSyncDatabase } from '@powersync/react-native'; import { ReactNode, useEffect, useMemo } from 'react'; import { useAuth } from './AuthProvider'; import { Connector } from '@/library/connector'; import { AppSchema } from '@/library/schema'; -createBaseLogger().useDefaults(); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); const connector = new Connector(); @@ -16,7 +16,9 @@ export const PowerSyncProvider = ({ children }: { children: ReactNode }) => { const powerSync = useMemo(() => { const powerSync = new PowerSyncDatabase({ schema: AppSchema, - database: { dbFilename: 'test.sqlite' } + database: { dbFilename: 'test.sqlite' }, + + logger: logger }); powerSync.init(); return powerSync; diff --git a/demos/react-native-supabase-todolist/library/powersync/system.ts b/demos/react-native-supabase-todolist/library/powersync/system.ts index 84c1194f1..6e281a2a4 100644 --- a/demos/react-native-supabase-todolist/library/powersync/system.ts +++ b/demos/react-native-supabase-todolist/library/powersync/system.ts @@ -1,13 +1,13 @@ import '@azure/core-asynciterator-polyfill'; import { - createBaseLogger, - LogLevel, + createConsoleLogger, + LogLevels, PowerSyncDatabase, SyncClientImplementation, AttachmentQueue, type AttachmentRecord, - type WatchedAttachmentItem, + type WatchedAttachmentItem } from '@powersync/react-native'; import { ReactNativeFileSystemStorageAdapter } from '@powersync/attachments-storage-react-native'; import React from 'react'; @@ -18,9 +18,7 @@ import { AppConfig } from '../supabase/AppConfig'; import { SupabaseConnector } from '../supabase/SupabaseConnector'; import { AppSchema, TODO_TABLE } from './AppSchema'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export class System { kvStorage: KVStorage; diff --git a/demos/react-native-web-supabase-todolist/library/powersync/system.ts b/demos/react-native-web-supabase-todolist/library/powersync/system.ts index 415d5c848..38fd932dc 100644 --- a/demos/react-native-web-supabase-todolist/library/powersync/system.ts +++ b/demos/react-native-web-supabase-todolist/library/powersync/system.ts @@ -1,10 +1,7 @@ import '@azure/core-asynciterator-polyfill'; import React from 'react'; -import { - PowerSyncDatabase as PowerSyncDatabaseNative, - AbstractPowerSyncDatabase -} from '@powersync/react-native'; +import { PowerSyncDatabase as PowerSyncDatabaseNative, AbstractPowerSyncDatabase } from '@powersync/react-native'; import { PowerSyncDatabase as PowerSyncDatabaseWeb, WASQLiteOpenFactory, @@ -14,8 +11,8 @@ import { ReactNativeFileSystemStorageAdapter } from '@powersync/attachments-stor import { type AttachmentRecord, AttachmentQueue, - LogLevel, - createBaseLogger, + createConsoleLogger, + LogLevels, WatchedAttachmentItem } from '@powersync/common'; import { SupabaseRemoteStorageAdapter } from '../storage/SupabaseRemoteStorageAdapter'; @@ -25,9 +22,7 @@ import { SupabaseConnector } from '../supabase/SupabaseConnector'; import { AppSchema, TODO_TABLE } from './AppSchema'; import { Platform } from 'react-native'; -const logger = createBaseLogger(); -logger.useDefaults(); -logger.setLevel(LogLevel.DEBUG); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export class System { kvStorage: ExpoKVStorage | WebKVStorage; diff --git a/demos/react-neon-tanstack-query-notes/src/lib/powersync.ts b/demos/react-neon-tanstack-query-notes/src/lib/powersync.ts index 1ea638f3b..8294d7369 100644 --- a/demos/react-neon-tanstack-query-notes/src/lib/powersync.ts +++ b/demos/react-neon-tanstack-query-notes/src/lib/powersync.ts @@ -1,37 +1,32 @@ import { AbstractPowerSyncDatabase, BaseObserver, - LogLevel, PowerSyncBackendConnector, type PowerSyncCredentials, PowerSyncDatabase, - createBaseLogger, + createConsoleLogger, + LogLevels, CrudEntry, - UpdateType, -} from "@powersync/web"; -import { client } from "@/lib/auth"; -import { - wrapPowerSyncWithDrizzle, - DrizzleAppSchema, -} from "@powersync/drizzle-driver"; + UpdateType +} from '@powersync/web'; +import { client } from '@/lib/auth'; +import { wrapPowerSyncWithDrizzle, DrizzleAppSchema } from '@powersync/drizzle-driver'; -import { drizzleSchema } from "./powersync-schema"; +import { drizzleSchema } from './powersync-schema'; /// Postgres Response codes that we cannot recover from by retrying. const FATAL_RESPONSE_CODES = [ // Class 22 — Data Exception // Examples include data type mismatch. - new RegExp("^22...$"), + new RegExp('^22...$'), // Class 23 — Integrity Constraint Violation. // Examples include NOT NULL, FOREIGN KEY and UNIQUE violations. - new RegExp("^23...$"), + new RegExp('^23...$'), // INSUFFICIENT PRIVILEGE - typically a row-level security violation - new RegExp("^42501$"), + new RegExp('^42501$') ]; -export const powersyncLogger = createBaseLogger(); -powersyncLogger.useDefaults(); -powersyncLogger.setLevel(LogLevel.DEBUG); +export const powersyncLogger = createConsoleLogger({ minLevel: LogLevels.debug }); // Type for the session returned by client.auth.getSession() export type NeonSession = { @@ -44,12 +39,9 @@ export type NeonConnectorListener = { sessionStarted: (session: NeonSession) => void; }; -const SESSION_STORAGE_KEY = "neon_session"; +const SESSION_STORAGE_KEY = 'neon_session'; -export class NeonConnector - extends BaseObserver - implements PowerSyncBackendConnector -{ +export class NeonConnector extends BaseObserver implements PowerSyncBackendConnector { ready: boolean = false; currentSession: NeonSession | null = null; @@ -66,7 +58,7 @@ export class NeonConnector this.currentSession = JSON.parse(cached); } } catch (error) { - console.debug("Could not load cached session:", error); + console.debug('Could not load cached session:', error); } } @@ -78,7 +70,7 @@ export class NeonConnector localStorage.removeItem(SESSION_STORAGE_KEY); } } catch (error) { - console.debug("Could not persist session:", error); + console.debug('Could not persist session:', error); } } @@ -89,10 +81,7 @@ export class NeonConnector const sessionResponse = await client.auth.getSession(); this.updateSession(sessionResponse.data ?? null); } catch (error) { - console.debug( - "Could not fetch session during init (most likely offline), using cached session:", - error, - ); + console.debug('Could not fetch session during init (most likely offline), using cached session:', error); } this.ready = true; @@ -117,19 +106,16 @@ export class NeonConnector } } catch (error) { // Network error - use cached session if available (offline mode) - console.debug( - "Could not refresh session (most likely offline), using cached:", - error, - ); + console.debug('Could not refresh session (most likely offline), using cached:', error); } if (!this.currentSession) { - throw new Error("Could not fetch Neon credentials."); + throw new Error('Could not fetch Neon credentials.'); } return { endpoint: import.meta.env.VITE_POWERSYNC_URL, - token: this.currentSession.session.token ?? "", + token: this.currentSession.session.token ?? '' } satisfies PowerSyncCredentials; } @@ -154,10 +140,10 @@ export class NeonConnector result = await table.upsert(record as any); break; case UpdateType.PATCH: - result = await table.update(op.opData as any).eq("id", op.id); + result = await table.update(op.opData as any).eq('id', op.id); break; case UpdateType.DELETE: - result = await table.delete().eq("id", op.id); + result = await table.delete().eq('id', op.id); break; } @@ -171,10 +157,7 @@ export class NeonConnector await transaction.complete(); } catch (ex: any) { console.debug(ex); - if ( - typeof ex.code == "string" && - FATAL_RESPONSE_CODES.some((regex) => regex.test(ex.code)) - ) { + if (typeof ex.code == 'string' && FATAL_RESPONSE_CODES.some((regex) => regex.test(ex.code))) { /** * Instead of blocking the queue with these errors, * discard the (rest of the) transaction. @@ -183,7 +166,7 @@ export class NeonConnector * If protecting against data loss is important, save the failing records * elsewhere instead of discarding, and/or notify the user. */ - console.error("Data upload error - discarding:", lastOp, ex); + console.error('Data upload error - discarding:', lastOp, ex); await transaction.complete(); } else { // Error may be retryable - e.g. network error or temporary server error. @@ -201,8 +184,8 @@ export const AppSchema = new DrizzleAppSchema(drizzleSchema); export const powersync = new PowerSyncDatabase({ schema: AppSchema, database: { - dbFilename: "powersync.db", - }, + dbFilename: 'powersync.db' + } }); export const powersyncDrizzle = wrapPowerSyncWithDrizzle(powersync); @@ -215,7 +198,7 @@ export async function connectPowerSync() { } await powersync.connect(neonConnector); isInitialized = true; - console.log("powersync connected"); + console.log('powersync connected'); } export async function disconnectPowerSync() { diff --git a/demos/react-supabase-time-based-sync/src/components/providers/SystemProvider.tsx b/demos/react-supabase-time-based-sync/src/components/providers/SystemProvider.tsx index 618fd172f..819c6d286 100644 --- a/demos/react-supabase-time-based-sync/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-time-based-sync/src/components/providers/SystemProvider.tsx @@ -2,7 +2,7 @@ import { AppSchema } from '@/library/powersync/AppSchema'; import { SupabaseConnector } from '@/library/powersync/SupabaseConnector'; import { CircularProgress } from '@mui/material'; import { PowerSyncContext } from '@powersync/react'; -import { createBaseLogger, LogLevel, PowerSyncDatabase, SyncClientImplementation } from '@powersync/web'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase } from '@powersync/web'; import React, { Suspense } from 'react'; import { NavigationPanelContextProvider } from '../navigation/NavigationPanelContext'; @@ -13,7 +13,8 @@ export const db = new PowerSyncDatabase({ schema: AppSchema, database: { dbFilename: 'time.db' - } + }, + logger: createConsoleLogger({ minLevel: LogLevels.debug }) }); export const SystemProvider = ({ children }: { children: React.ReactNode }) => { @@ -21,9 +22,6 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { const [powerSync] = React.useState(db); React.useEffect(() => { - const logger = createBaseLogger(); - logger.useDefaults(); - logger.setLevel(LogLevel.DEBUG); // For console testing purposes (window as any)._powersync = powerSync; @@ -31,7 +29,7 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { const l = connector.registerListener({ initialized: () => {}, sessionStarted: () => { - powerSync.connect(connector, { clientImplementation: SyncClientImplementation.RUST }); + powerSync.connect(connector); } }); diff --git a/demos/react-supabase-todolist-optional-sync/src/components/providers/SystemProvider.tsx b/demos/react-supabase-todolist-optional-sync/src/components/providers/SystemProvider.tsx index a77833e3f..5beb6eaf1 100644 --- a/demos/react-supabase-todolist-optional-sync/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-todolist-optional-sync/src/components/providers/SystemProvider.tsx @@ -2,7 +2,7 @@ import { makeSchema, switchToSyncedSchema } from '@/library/powersync/AppSchema' import { SupabaseConnector } from '@/library/powersync/SupabaseConnector'; import { CircularProgress } from '@mui/material'; import { PowerSyncContext } from '@powersync/react'; -import { createBaseLogger, LogLevel, PowerSyncDatabase } from '@powersync/web'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase } from '@powersync/web'; import React, { Suspense } from 'react'; import { NavigationPanelContextProvider } from '../navigation/NavigationPanelContext'; import { getSyncEnabled } from '@/library/powersync/SyncMode'; @@ -17,7 +17,8 @@ const db = new PowerSyncDatabase({ schema: makeSchema(syncEnabled), database: { dbFilename: dbName - } + }, + logger: createConsoleLogger({ minLevel: LogLevels.debug }) }); export const SystemProvider = ({ children }: { children: React.ReactNode }) => { @@ -25,15 +26,12 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { const [powerSync] = React.useState(db); React.useEffect(() => { - const logger = createBaseLogger(); - logger.useDefaults(); - logger.setLevel(LogLevel.DEBUG); // For console testing purposes (window as any)._powersync = powerSync; powerSync.init(); const l = connector.registerListener({ - initialized: () => { }, + initialized: () => {}, sessionStarted: async () => { var isSyncMode = getSyncEnabled(dbName); diff --git a/demos/react-supabase-todolist-optional-sync/src/library/powersync/SupabaseConnector.ts b/demos/react-supabase-todolist-optional-sync/src/library/powersync/SupabaseConnector.ts index eb90c4357..a69e972d2 100644 --- a/demos/react-supabase-todolist-optional-sync/src/library/powersync/SupabaseConnector.ts +++ b/demos/react-supabase-todolist-optional-sync/src/library/powersync/SupabaseConnector.ts @@ -138,7 +138,7 @@ export class SupabaseConnector extends BaseObserver i result = await table.upsert(record); break; case UpdateType.PATCH: - result = await table.update(op.opData).eq('id', op.id); + result = await table.update(op.opData ?? {}).eq('id', op.id); break; case UpdateType.DELETE: result = await table.delete().eq('id', op.id); diff --git a/demos/react-supabase-todolist-sync-streams/src/components/providers/SystemProvider.tsx b/demos/react-supabase-todolist-sync-streams/src/components/providers/SystemProvider.tsx index 3a54211ee..e4d2f1e03 100644 --- a/demos/react-supabase-todolist-sync-streams/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-todolist-sync-streams/src/components/providers/SystemProvider.tsx @@ -4,9 +4,9 @@ import { SupabaseConnector } from '@/library/powersync/SupabaseConnector'; import { CircularProgress } from '@mui/material'; import { PowerSyncContext } from '@powersync/react'; import { - createBaseLogger, + createConsoleLogger, + LogLevels, DifferentialWatchedQuery, - LogLevel, PowerSyncDatabase, SyncClientImplementation } from '@powersync/web'; @@ -16,11 +16,13 @@ import { NavigationPanelContextProvider } from '../navigation/NavigationPanelCon const SupabaseContext = React.createContext(null); export const useSupabase = () => React.useContext(SupabaseContext); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export const db = new PowerSyncDatabase({ schema: AppSchema, database: { dbFilename: 'example.db' - } + }, + logger }); export type EnhancedListRecord = ListRecord & { total_tasks: number; completed_tasks: number }; @@ -64,9 +66,6 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { }); React.useEffect(() => { - const logger = createBaseLogger(); - logger.useDefaults(); // eslint-disable-line - logger.setLevel(LogLevel.DEBUG); // For console testing purposes (window as any)._powersync = powerSync; diff --git a/demos/react-supabase-todolist-tanstackdb/src/components/providers/SystemProvider.tsx b/demos/react-supabase-todolist-tanstackdb/src/components/providers/SystemProvider.tsx index d6ac28c01..d340f7745 100644 --- a/demos/react-supabase-todolist-tanstackdb/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-todolist-tanstackdb/src/components/providers/SystemProvider.tsx @@ -4,7 +4,7 @@ import { SupabaseConnector } from '@/library/powersync/SupabaseConnector'; import { TodosDeserializationSchema, TodosSchema } from '@/library/powersync/TodosSchema'; import { CircularProgress } from '@mui/material'; import { PowerSyncContext } from '@powersync/react'; -import { createBaseLogger, LogLevel, PowerSyncDatabase, WASQLiteOpenFactory, WASQLiteVFS } from '@powersync/web'; +import { createConsoleLogger, LogLevels, PowerSyncDatabase, WASQLiteOpenFactory, WASQLiteVFS } from '@powersync/web'; import { createCollection } from '@tanstack/db'; import { powerSyncCollectionOptions } from '@tanstack/powersync-db-collection'; import React, { Suspense } from 'react'; @@ -13,12 +13,17 @@ import { NavigationPanelContextProvider } from '../navigation/NavigationPanelCon const SupabaseContext = React.createContext(null); export const useSupabase = () => React.useContext(SupabaseContext); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); + export const db = new PowerSyncDatabase({ schema: AppSchema, database: new WASQLiteOpenFactory({ dbFilename: 'example.db', - vfs: WASQLiteVFS.OPFSCoopSyncVFS - }) + vfs: WASQLiteVFS.OPFSCoopSyncVFS, + logger, + logLevel: LogLevels.debug + }), + logger }); export const listsCollection = createCollection( @@ -54,9 +59,6 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { const [powerSync] = React.useState(db); React.useEffect(() => { - const logger = createBaseLogger(); - logger.useDefaults(); // eslint-disable-line - logger.setLevel(LogLevel.DEBUG); // For console testing purposes (window as any)._powersync = powerSync; diff --git a/demos/react-supabase-todolist-tanstackdb/src/components/widgets/SearchBarWidget.tsx b/demos/react-supabase-todolist-tanstackdb/src/components/widgets/SearchBarWidget.tsx index b775354d5..3b247e20f 100644 --- a/demos/react-supabase-todolist-tanstackdb/src/components/widgets/SearchBarWidget.tsx +++ b/demos/react-supabase-todolist-tanstackdb/src/components/widgets/SearchBarWidget.tsx @@ -41,7 +41,7 @@ export const SearchBarWidget: React.FC = () => { ); const searchResults = [ - ...todoMatches.map((todo) => new SearchResult(todo.id, todo.list_name, todo.description)), + ...todoMatches.map((todo) => new SearchResult(todo.id, todo.list_name!, todo.description)), ...listMatches.map((list) => new SearchResult(list.id, list.name)) ]; diff --git a/demos/react-supabase-todolist-tanstackdb/src/library/powersync/SupabaseConnector.ts b/demos/react-supabase-todolist-tanstackdb/src/library/powersync/SupabaseConnector.ts index 07472b7e0..d7349249a 100644 --- a/demos/react-supabase-todolist-tanstackdb/src/library/powersync/SupabaseConnector.ts +++ b/demos/react-supabase-todolist-tanstackdb/src/library/powersync/SupabaseConnector.ts @@ -124,7 +124,7 @@ export class SupabaseConnector extends BaseObserver i result = await table.upsert(record); break; case UpdateType.PATCH: - result = await table.update(op.opData).eq('id', op.id); + result = await table.update(op.opData ?? {}).eq('id', op.id); break; case UpdateType.DELETE: result = await table.delete().eq('id', op.id); diff --git a/demos/react-supabase-todolist-tanstackdb/vite.config.mts b/demos/react-supabase-todolist-tanstackdb/vite.config.mts index 11c58e4ee..7a31f57db 100644 --- a/demos/react-supabase-todolist-tanstackdb/vite.config.mts +++ b/demos/react-supabase-todolist-tanstackdb/vite.config.mts @@ -82,7 +82,7 @@ export default defineConfig({ enabled: true, isolate: true, provider: 'playwright', - headless: true, + headless: false, instances: [ { browser: 'chromium' diff --git a/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx b/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx index f4e800b5f..003fb63b7 100644 --- a/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx +++ b/demos/react-supabase-todolist/src/components/providers/SystemProvider.tsx @@ -4,9 +4,9 @@ import { SupabaseConnector } from '@/library/powersync/SupabaseConnector'; import { CircularProgress } from '@mui/material'; import { PowerSyncContext } from '@powersync/react'; import { - createBaseLogger, + createConsoleLogger, + LogLevels, DifferentialWatchedQuery, - LogLevel, PowerSyncDatabase, WASQLiteOpenFactory, WASQLiteVFS @@ -18,6 +18,7 @@ declare const APP_VERSION: string; const SupabaseContext = React.createContext(null); export const useSupabase = () => React.useContext(SupabaseContext); +const logger = createConsoleLogger({ minLevel: LogLevels.debug }); export const db = new PowerSyncDatabase({ schema: AppSchema, @@ -26,11 +27,14 @@ export const db = new PowerSyncDatabase({ vfs: WASQLiteVFS.OPFSCoopSyncVFS, flags: { enableMultiTabs: typeof SharedWorker !== 'undefined' - } + }, + logger, + logLevel: LogLevels.debug }), flags: { enableMultiTabs: typeof SharedWorker !== 'undefined' - } + }, + logger }); export type EnhancedListRecord = ListRecord & { total_tasks: number; completed_tasks: number }; @@ -74,9 +78,6 @@ export const SystemProvider = ({ children }: { children: React.ReactNode }) => { }); React.useEffect(() => { - const logger = createBaseLogger(); - logger.useDefaults(); // eslint-disable-line - logger.setLevel(LogLevel.DEBUG); // For console testing purposes (window as any)._powersync = powerSync; diff --git a/demos/vue-supabase-todolist/src/App.vue b/demos/vue-supabase-todolist/src/App.vue index dde5f7bd1..81a80ab93 100644 --- a/demos/vue-supabase-todolist/src/App.vue +++ b/demos/vue-supabase-todolist/src/App.vue @@ -1,11 +1,6 @@