diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 6721977a..d12079e7 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -9,6 +9,8 @@ ### Changed +- fix: ObservableLog no longer extends Function and class instance can no longer be called. Fixes an issue when running in a browser extension context. +- feat!: ObservableLog's `log` method is renamed to `print` to avoind calling `log.log`. - chore: update management canister interface with latest bitcoin features - fix: publish script will correctly update the `package-lock.json` file with the correct dependencies when making a new release - chore: updates agent error response to read "Gateway returns error" instead of "Server"` diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index 8ec0a195..2cc13755 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -414,7 +414,10 @@ export class HttpAgent implements Agent { const body = cbor.encode(transformedRequest.body); - this.log(`fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest); + this.log.print( + `fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, + transformedRequest, + ); // Run both in parallel. The fetch is quite expensive, so we have plenty of time to // calculate the requestId locally. @@ -460,7 +463,7 @@ export class HttpAgent implements Agent { const { ecid, transformedRequest, body, requestId, backoff, tries } = args; const delay = tries === 0 ? 0 : backoff.next(); - this.log(`fetching "/api/v2/canister/${ecid.toString()}/query" with tries:`, { + this.log.print(`fetching "/api/v2/canister/${ecid.toString()}/query" with tries:`, { tries, backoff, delay, @@ -481,7 +484,7 @@ export class HttpAgent implements Agent { let response: ApiQueryResponse; // Make the request and retry if it throws an error try { - this.log( + this.log.print( `fetching "/api/v2/canister/${ecid.toString()}/query" with request:`, transformedRequest, ); @@ -546,7 +549,7 @@ export class HttpAgent implements Agent { // Convert the timestamp to milliseconds const timeStampInMs = Number(BigInt(timestamp) / BigInt(1_000_000)); - this.log('watermark and timestamp', { + this.log.print('watermark and timestamp', { waterMark: this.waterMark, timestamp: timeStampInMs, }); @@ -640,8 +643,8 @@ export class HttpAgent implements Agent { ? Principal.from(fields.effectiveCanisterId) : Principal.from(canisterId); - this.log(`ecid ${ecid.toString()}`); - this.log(`canisterId ${canisterId.toString()}`); + this.log.print(`ecid ${ecid.toString()}`); + this.log.print(`canisterId ${canisterId.toString()}`); const makeQuery = async () => { const id = await (identity !== undefined ? await identity : await this._identity); if (!id) { @@ -711,7 +714,7 @@ export class HttpAgent implements Agent { // Make query and fetch subnet keys in parallel const [query, subnetStatus] = await Promise.all([makeQuery(), getSubnetStatus()]); - this.log('Query response:', query); + this.log.print('Query response:', query); // Skip verification if the user has disabled it if (!this.#verifyQuerySignatures) { return query; @@ -857,7 +860,7 @@ export class HttpAgent implements Agent { const transformedRequest = request ?? (await this.createReadStateRequest(fields, identity)); const body = cbor.encode(transformedRequest.body); - this.log( + this.log.print( `fetching "/api/v2/canister/${canister}/read_state" with request:`, transformedRequest, ); @@ -887,10 +890,10 @@ export class HttpAgent implements Agent { } const decodedResponse: ReadStateResponse = cbor.decode(await response.arrayBuffer()); - this.log('Read state response:', decodedResponse); + this.log.print('Read state response:', decodedResponse); const parsedTime = await this.parseTimeFromResponse(decodedResponse); if (parsedTime > 0) { - this.log('Read state response time:', parsedTime); + this.log.print('Read state response time:', parsedTime); this.#waterMark = parsedTime; } @@ -915,8 +918,8 @@ export class HttpAgent implements Agent { throw new Error('Time was not found in the response or was not in its expected format.'); } const date = decodeTime(bufFromBufLike(timeLookup.value as ArrayBuffer)); - this.log('Time from response:', date); - this.log('Time from response in milliseconds:', Number(date)); + this.log.print('Time from response:', date); + this.log.print('Time from response in milliseconds:', Number(date)); return Number(date); } else { this.log.warn('No certificate found in response'); @@ -933,7 +936,7 @@ export class HttpAgent implements Agent { const callTime = Date.now(); try { if (!canisterId) { - this.log( + this.log.print( 'Syncing time with the IC. No canisterId provided, so falling back to ryjl3-tyaaa-aaaaa-aaaba-cai', ); } @@ -960,7 +963,7 @@ export class HttpAgent implements Agent { } : {}; - this.log(`fetching "/api/v2/status"`); + this.log.print(`fetching "/api/v2/status"`); const backoff = this.#backoffStrategy(); const response = await this.#requestAndRetry({ backoff, diff --git a/packages/agent/src/observable.test.ts b/packages/agent/src/observable.test.ts index 65934f7b..116ef9bc 100644 --- a/packages/agent/src/observable.test.ts +++ b/packages/agent/src/observable.test.ts @@ -10,9 +10,6 @@ describe('Observable', () => { observable.notify(42); expect(observer1).toHaveBeenCalledWith(42); expect(observer2).toHaveBeenCalledWith(42); - observable(24); - expect(observer1).toHaveBeenCalledWith(24); - expect(observer2).toHaveBeenCalledWith(24); }); it('should notify only subscribed observers', () => { @@ -45,7 +42,7 @@ describe('ObservableLog', () => { const observer2 = jest.fn(); observable.subscribe(observer1); observable.subscribe(observer2); - observable.log('info'); + observable.print('info'); expect(observer1).toHaveBeenCalledWith({ message: 'info', level: 'info' }); expect(observer2).toHaveBeenCalledWith({ message: 'info', level: 'info' }); observable.warn('warning'); @@ -62,7 +59,7 @@ describe('ObservableLog', () => { const observer1 = jest.fn(); const observer2 = jest.fn(); observable.subscribe(observer1); - observable.log('info'); + observable.print('info'); expect(observer1).toHaveBeenCalledWith({ message: 'info', level: 'info' }); expect(observer2).not.toHaveBeenCalled(); }); @@ -74,7 +71,7 @@ describe('ObservableLog', () => { observable.subscribe(observer1); observable.subscribe(observer2); observable.unsubscribe(observer2); - observable.log('info'); + observable.print('info'); expect(observer1).toHaveBeenCalledWith({ message: 'info', level: 'info' }); expect(observer2).not.toHaveBeenCalled(); }); diff --git a/packages/agent/src/observable.ts b/packages/agent/src/observable.ts index e82789eb..2d67a518 100644 --- a/packages/agent/src/observable.ts +++ b/packages/agent/src/observable.ts @@ -2,19 +2,11 @@ import { AgentError } from './errors'; export type ObserveFunction = (data: T, ...rest: unknown[]) => void; -export class Observable extends Function { +export class Observable { observers: ObserveFunction[]; constructor() { - super(); this.observers = []; - return new Proxy(this, { - apply: (target, _, args) => target.#call(args[0], ...args.slice(1)), - }); - } - - #call(message: T, ...rest: unknown[]) { - this.notify(message, ...rest); } subscribe(func: ObserveFunction) { @@ -44,11 +36,8 @@ export type AgentLog = export class ObservableLog extends Observable { constructor() { super(); - return new Proxy(this, { - apply: (target, _, args) => target.#call(args[0], ...args.slice(1)), - }); } - log(message: string, ...rest: unknown[]) { + print(message: string, ...rest: unknown[]) { this.notify({ message, level: 'info' }, ...rest); } warn(message: string, ...rest: unknown[]) { @@ -57,7 +46,4 @@ export class ObservableLog extends Observable { error(message: string, error: AgentError, ...rest: unknown[]) { this.notify({ message, level: 'error', error }, ...rest); } - #call(message: string, ...rest: unknown[]) { - this.log(message, ...rest); - } }