diff --git a/.changeset/giant-moose-crash.md b/.changeset/giant-moose-crash.md new file mode 100644 index 000000000..f42152f0b --- /dev/null +++ b/.changeset/giant-moose-crash.md @@ -0,0 +1,5 @@ +--- +'@powersync/web': minor +--- + +Removed `js-logger` dependency, using the logger helper exposed by `@powersync/common`. diff --git a/.changeset/lemon-shrimps-pretend.md b/.changeset/lemon-shrimps-pretend.md new file mode 100644 index 000000000..5d878d85c --- /dev/null +++ b/.changeset/lemon-shrimps-pretend.md @@ -0,0 +1,5 @@ +--- +'@powersync/common': minor +--- + +Added logger helpers, which can be used instead of the `js-logger` dependency. diff --git a/packages/common/rollup.config.mjs b/packages/common/rollup.config.mjs index e3c948079..ad05faf6a 100644 --- a/packages/common/rollup.config.mjs +++ b/packages/common/rollup.config.mjs @@ -32,9 +32,7 @@ export default (commandLineArgs) => { // This makes life easier external: [ // This has dynamic logic - makes bundling hard - 'cross-fetch', - // TODO: make the useDefaults logic better. Currently need access to this package directly - 'js-logger' + 'cross-fetch' ] }; }; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 99497d151..667cd7232 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -34,6 +34,7 @@ export * from './db/DBAdapter.js'; export * from './utils/AbortOperation.js'; export * from './utils/BaseObserver.js'; export * from './utils/DataStream.js'; +export * from './utils/Logger.js'; export * from './utils/parseQuery.js'; export * from './types/types.js'; diff --git a/packages/common/src/utils/Logger.ts b/packages/common/src/utils/Logger.ts new file mode 100644 index 000000000..f954622ef --- /dev/null +++ b/packages/common/src/utils/Logger.ts @@ -0,0 +1,47 @@ +import Logger, { type ILogger, type ILogLevel } from 'js-logger'; + +export { GlobalLogger, ILogger, ILoggerOpts, ILogHandler, ILogLevel } from 'js-logger'; + +const TypedLogger: ILogger = Logger as any; + +export const LogLevel = { + TRACE: TypedLogger.TRACE, + DEBUG: TypedLogger.DEBUG, + INFO: TypedLogger.INFO, + TIME: TypedLogger.TIME, + WARN: TypedLogger.WARN, + ERROR: TypedLogger.ERROR, + OFF: TypedLogger.OFF +}; + +export interface CreateLoggerOptions { + logLevel?: ILogLevel; +} + +/** + * Retrieves the base (default) logger instance. + * + * This base logger controls the default logging configuration and is shared + * across all loggers created with `createLogger`. Adjusting settings on this + * base logger affects all loggers derived from it unless explicitly overridden. + * + */ +export function createBaseLogger() { + return Logger; +} + +/** + * Creates and configures a new named logger based on the base logger. + * + * Named loggers allow specific modules or areas of your application to have + * their own logging levels and behaviors. These loggers inherit configuration + * from the base logger by default but can override settings independently. + */ +export function createLogger(name: string, options: CreateLoggerOptions = {}): ILogger { + const logger = Logger.get(name); + if (options.logLevel) { + logger.setLevel(options.logLevel); + } + + return logger; +} diff --git a/packages/web/package.json b/packages/web/package.json index 06b5fd305..36885356a 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -68,8 +68,7 @@ "async-mutex": "^0.4.0", "bson": "^6.6.0", "comlink": "^4.4.2", - "commander": "^12.1.0", - "js-logger": "^1.6.1" + "commander": "^12.1.0" }, "devDependencies": { "@journeyapps/wa-sqlite": "^1.2.2", diff --git a/packages/web/src/db/adapters/AbstractWebSQLOpenFactory.ts b/packages/web/src/db/adapters/AbstractWebSQLOpenFactory.ts index 2e1755e3f..0f4e6647f 100644 --- a/packages/web/src/db/adapters/AbstractWebSQLOpenFactory.ts +++ b/packages/web/src/db/adapters/AbstractWebSQLOpenFactory.ts @@ -1,5 +1,4 @@ -import { DBAdapter, SQLOpenFactory } from '@powersync/common'; -import Logger, { ILogger } from 'js-logger'; +import { type ILogger, createLogger, DBAdapter, SQLOpenFactory } from '@powersync/common'; import { SSRDBAdapter } from './SSRDBAdapter'; import { ResolvedWebSQLFlags, WebSQLOpenFactoryOptions, isServerSide, resolveWebSQLFlags } from './web-sql-flags'; @@ -9,7 +8,7 @@ export abstract class AbstractWebSQLOpenFactory implements SQLOpenFactory { constructor(protected options: WebSQLOpenFactoryOptions) { this.resolvedFlags = resolveWebSQLFlags(options.flags); - this.logger = options.logger ?? Logger.get(`AbstractWebSQLOpenFactory - ${this.options.dbFilename}`); + this.logger = options.logger ?? createLogger(`AbstractWebSQLOpenFactory - ${this.options.dbFilename}`); } /** diff --git a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts index 8e585ed08..bd41da199 100644 --- a/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts +++ b/packages/web/src/db/adapters/LockedAsyncDatabaseAdapter.ts @@ -1,5 +1,7 @@ import { + type ILogger, BaseObserver, + createLogger, DBAdapter, DBAdapterListener, DBGetUtils, @@ -8,7 +10,6 @@ import { QueryResult, Transaction } from '@powersync/common'; -import Logger, { ILogger } from 'js-logger'; import { getNavigatorLocks } from '../..//shared/navigator'; import { AsyncDatabaseConnection } from './AsyncDatabaseConnection'; import { SharedConnectionWorker, WebDBAdapter } from './WebDBAdapter'; @@ -50,7 +51,7 @@ export class LockedAsyncDatabaseAdapter constructor(protected options: LockedAsyncDatabaseAdapterOptions) { super(); this._dbIdentifier = options.name; - this.logger = options.logger ?? Logger.get(`LockedAsyncDatabaseAdapter - ${this._dbIdentifier}`); + this.logger = options.logger ?? createLogger(`LockedAsyncDatabaseAdapter - ${this._dbIdentifier}`); // Set the name if provided. We can query for the name if not available yet this.debugMode = options.debugMode ?? false; if (this.debugMode) { diff --git a/packages/web/src/db/adapters/web-sql-flags.ts b/packages/web/src/db/adapters/web-sql-flags.ts index b2fdb4e4d..9ddf8fea6 100644 --- a/packages/web/src/db/adapters/web-sql-flags.ts +++ b/packages/web/src/db/adapters/web-sql-flags.ts @@ -1,5 +1,4 @@ -import { SQLOpenOptions } from '@powersync/common'; -import { ILogger } from 'js-logger'; +import { type ILogger, SQLOpenOptions } from '@powersync/common'; /** * Common settings used when creating SQL connections on web. diff --git a/packages/web/src/db/sync/WebRemote.ts b/packages/web/src/db/sync/WebRemote.ts index b5e8d580e..3b4dcda0e 100644 --- a/packages/web/src/db/sync/WebRemote.ts +++ b/packages/web/src/db/sync/WebRemote.ts @@ -1,5 +1,3 @@ -import { type ILogger } from 'js-logger'; - import { AbstractRemote, AbstractRemoteOptions, @@ -7,6 +5,7 @@ import { DEFAULT_REMOTE_LOGGER, FetchImplementation, FetchImplementationProvider, + ILogger, RemoteConnector } from '@powersync/common'; diff --git a/packages/web/src/worker/sync/BroadcastLogger.ts b/packages/web/src/worker/sync/BroadcastLogger.ts index 099f65d72..2cb6b1d1e 100644 --- a/packages/web/src/worker/sync/BroadcastLogger.ts +++ b/packages/web/src/worker/sync/BroadcastLogger.ts @@ -1,4 +1,4 @@ -import Logger, { type ILogLevel, type ILogger } from 'js-logger'; +import { type ILogger, type ILogLevel, LogLevel } from '@powersync/common'; import { type WrappedSyncPort } from './SharedSyncImplementation'; /** @@ -14,13 +14,13 @@ export class BroadcastLogger implements ILogger { OFF: ILogLevel; constructor(protected clients: WrappedSyncPort[]) { - this.TRACE = Logger.TRACE; - this.DEBUG = Logger.DEBUG; - this.INFO = Logger.INFO; - this.TIME = Logger.TIME; - this.WARN = Logger.WARN; - this.ERROR = Logger.ERROR; - this.OFF = Logger.OFF; + this.TRACE = LogLevel.TRACE; + this.DEBUG = LogLevel.DEBUG; + this.INFO = LogLevel.INFO; + this.TIME = LogLevel.TIME; + this.WARN = LogLevel.WARN; + this.ERROR = LogLevel.ERROR; + this.OFF = LogLevel.OFF; } trace(...x: any[]): void { @@ -75,7 +75,7 @@ export class BroadcastLogger implements ILogger { getLevel(): ILogLevel { // Levels are not adjustable on this level. - return Logger.INFO; + return LogLevel.INFO; } enabledFor(level: ILogLevel): boolean { diff --git a/packages/web/src/worker/sync/SharedSyncImplementation.ts b/packages/web/src/worker/sync/SharedSyncImplementation.ts index f5c7c5bdc..13ec31709 100644 --- a/packages/web/src/worker/sync/SharedSyncImplementation.ts +++ b/packages/web/src/worker/sync/SharedSyncImplementation.ts @@ -1,5 +1,6 @@ import { type AbstractStreamingSyncImplementation, + type ILogger, type LockOptions, type PowerSyncConnectionOptions, type StreamingSyncImplementation, @@ -7,13 +8,13 @@ import { type SyncStatusOptions, AbortOperation, BaseObserver, + createLogger, DBAdapter, SqliteBucketStorage, SyncStatus } from '@powersync/common'; import { Mutex } from 'async-mutex'; import * as Comlink from 'comlink'; -import Logger, { type ILogger } from 'js-logger'; import { WebRemote } from '../../db/sync/WebRemote'; import { WebStreamingSyncImplementation, @@ -107,7 +108,7 @@ export class SharedSyncImplementation this.dbAdapter = null; this.syncParams = null; this.syncStreamClient = null; - this.logger = Logger.get('shared-sync'); + this.logger = createLogger('shared-sync'); this.lastConnectOptions = undefined; this.isInitialized = new Promise((resolve) => { diff --git a/packages/web/src/worker/sync/SharedSyncImplementation.worker.ts b/packages/web/src/worker/sync/SharedSyncImplementation.worker.ts index 8c8e12663..9716aa4d9 100644 --- a/packages/web/src/worker/sync/SharedSyncImplementation.worker.ts +++ b/packages/web/src/worker/sync/SharedSyncImplementation.worker.ts @@ -4,10 +4,12 @@ import { SharedSyncClientEvent, type ManualSharedSyncPayload } from './SharedSyncImplementation'; -import Logger from 'js-logger'; +import { createBaseLogger } from '@powersync/common'; const _self: SharedWorkerGlobalScope = self as any; -Logger.useDefaults(); +const logger = createBaseLogger(); +logger.useDefaults(); + const sharedSyncImplementation = new SharedSyncImplementation(); _self.onconnect = function (event: MessageEvent) { diff --git a/packages/web/tests/multiple_instances.test.ts b/packages/web/tests/multiple_instances.test.ts index 87c8dceb9..4e11704f8 100644 --- a/packages/web/tests/multiple_instances.test.ts +++ b/packages/web/tests/multiple_instances.test.ts @@ -1,11 +1,17 @@ -import { AbstractPowerSyncDatabase, SqliteBucketStorage, SyncStatus } from '@powersync/common'; +import { + AbstractPowerSyncDatabase, + createBaseLogger, + createLogger, + SqliteBucketStorage, + SyncStatus +} from '@powersync/common'; import { SharedWebStreamingSyncImplementation, SharedWebStreamingSyncImplementationOptions, WebRemote } from '@powersync/web'; import { Mutex } from 'async-mutex'; -import Logger from 'js-logger'; + import { beforeAll, describe, expect, it, vi } from 'vitest'; import { WebDBAdapter } from '../src/db/adapters/WebDBAdapter'; import { TestConnector } from './utils/MockStreamOpenFactory'; @@ -20,7 +26,7 @@ describe('Multiple Instances', { sequential: true }, () => { schema: testSchema }); - beforeAll(() => Logger.useDefaults()); + beforeAll(() => createBaseLogger().useDefaults()); function createAsset(powersync: AbstractPowerSyncDatabase) { return powersync.execute('INSERT INTO assets(id, description) VALUES(uuid(), ?)', ['test']); @@ -39,7 +45,7 @@ describe('Multiple Instances', { sequential: true }, () => { }); it('should broadcast logs from shared sync worker', { timeout: 20000 }, async () => { - const logger = Logger.get('test-logger'); + const logger = createLogger('test-logger'); const spiedErrorLogger = vi.spyOn(logger, 'error'); const spiedDebugLogger = vi.spyOn(logger, 'debug'); diff --git a/packages/web/tests/uploads.test.ts b/packages/web/tests/uploads.test.ts index c853c90a3..264b0767c 100644 --- a/packages/web/tests/uploads.test.ts +++ b/packages/web/tests/uploads.test.ts @@ -1,5 +1,4 @@ -import { WebPowerSyncDatabaseOptions } from '@powersync/web'; -import Logger from 'js-logger'; +import { createBaseLogger, createLogger, WebPowerSyncDatabaseOptions } from '@powersync/web'; import p from 'p-defer'; import { v4 } from 'uuid'; import { beforeAll, describe, expect, it, vi } from 'vitest'; @@ -40,10 +39,10 @@ describe( function describeCrudUploadTests(getDatabaseOptions: () => WebPowerSyncDatabaseOptions) { return () => { - beforeAll(() => Logger.useDefaults()); + beforeAll(() => createBaseLogger().useDefaults()); it('should warn for missing upload operations in uploadData', async () => { - const logger = Logger.get('crud-logger'); + const logger = createLogger('crud-logger'); const options = getDatabaseOptions(); @@ -83,7 +82,7 @@ function describeCrudUploadTests(getDatabaseOptions: () => WebPowerSyncDatabaseO }); it('should immediately upload sequential transactions', async () => { - const logger = Logger.get('crud-logger'); + const logger = createLogger('crud-logger'); const options = getDatabaseOptions(); diff --git a/packages/web/webpack.config.js b/packages/web/webpack.config.js index cbffa2898..0deddafed 100644 --- a/packages/web/webpack.config.js +++ b/packages/web/webpack.config.js @@ -49,7 +49,6 @@ module.exports = () => { '@powersync/common': '@powersync/common', 'async-mutex': 'async-mutex', comlink: 'comlink', - 'js-logger': 'js-logger', lodash: 'lodash' }, devtool: production ? 'source-map' : 'cheap-module-source-map', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0c173d811..8a8dd6afd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2018,9 +2018,6 @@ importers: commander: specifier: ^12.1.0 version: 12.1.0 - js-logger: - specifier: ^1.6.1 - version: 1.6.1 devDependencies: '@journeyapps/wa-sqlite': specifier: ^1.2.2