From 00f9a4010636e8a5e2865164fa5bd47811000767 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 30 May 2024 15:34:12 -0700 Subject: [PATCH 1/3] fix: ObservableLog no longer extends Function --- docs/CHANGELOG.md | 1 + packages/agent/src/agent/http/index.ts | 31 ++++++++++++++------------ packages/agent/src/observable.ts | 9 +------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index abc707996..86d22c812 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,7 @@ ### 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. - chore: updates dfinity/conventional-pr-title-action to v3.2.0 ## [1.3.0] - 2024-05-01 diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index 970f21cc0..b9dd2a135 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -409,7 +409,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.log( + `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. @@ -455,7 +458,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.log(`fetching "/api/v2/canister/${ecid.toString()}/query" with tries:`, { tries, backoff, delay, @@ -476,7 +479,7 @@ export class HttpAgent implements Agent { let response: ApiQueryResponse; // Make the request and retry if it throws an error try { - this.log( + this.log.log( `fetching "/api/v2/canister/${ecid.toString()}/query" with request:`, transformedRequest, ); @@ -541,7 +544,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.log('watermark and timestamp', { waterMark: this.waterMark, timestamp: timeStampInMs, }); @@ -635,8 +638,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.log(`ecid ${ecid.toString()}`); + this.log.log(`canisterId ${canisterId.toString()}`); const makeQuery = async () => { const id = await (identity !== undefined ? await identity : await this._identity); if (!id) { @@ -706,7 +709,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.log('Query response:', query); // Skip verification if the user has disabled it if (!this.#verifyQuerySignatures) { return query; @@ -852,7 +855,7 @@ export class HttpAgent implements Agent { const transformedRequest = request ?? (await this.createReadStateRequest(fields, identity)); const body = cbor.encode(transformedRequest.body); - this.log( + this.log.log( `fetching "/api/v2/canister/${canister}/read_state" with request:`, transformedRequest, ); @@ -882,10 +885,10 @@ export class HttpAgent implements Agent { } const decodedResponse: ReadStateResponse = cbor.decode(await response.arrayBuffer()); - this.log('Read state response:', decodedResponse); + this.log.log('Read state response:', decodedResponse); const parsedTime = await this.parseTimeFromResponse(decodedResponse); if (parsedTime > 0) { - this.log('Read state response time:', parsedTime); + this.log.log('Read state response time:', parsedTime); this.#waterMark = parsedTime; } @@ -910,8 +913,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)); - this.log('Time from response:', date); - this.log('Time from response in milliseconds:', Number(date)); + this.log.log('Time from response:', date); + this.log.log('Time from response in milliseconds:', Number(date)); return Number(date); } else { this.log.warn('No certificate found in response'); @@ -928,7 +931,7 @@ export class HttpAgent implements Agent { const callTime = Date.now(); try { if (!canisterId) { - this.log( + this.log.log( 'Syncing time with the IC. No canisterId provided, so falling back to ryjl3-tyaaa-aaaaa-aaaba-cai', ); } @@ -955,7 +958,7 @@ export class HttpAgent implements Agent { } : {}; - this.log(`fetching "/api/v2/status"`); + this.log.log(`fetching "/api/v2/status"`); const backoff = this.#backoffStrategy(); const response = await this.#requestAndRetry({ backoff, diff --git a/packages/agent/src/observable.ts b/packages/agent/src/observable.ts index e82789eb2..b92bf196c 100644 --- a/packages/agent/src/observable.ts +++ b/packages/agent/src/observable.ts @@ -2,15 +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[]) { @@ -44,9 +40,6 @@ 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[]) { this.notify({ message, level: 'info' }, ...rest); From c61fea45b8ff418835c50cbf0e91eb8e8b1aaf23 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Thu, 30 May 2024 15:49:20 -0700 Subject: [PATCH 2/3] remove test for function invocation --- packages/agent/src/observable.test.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/agent/src/observable.test.ts b/packages/agent/src/observable.test.ts index 65934f7b0..ce08b3359 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', () => { From d60703ad7563a892d3c752c6930d39dd5dbd7a52 Mon Sep 17 00:00:00 2001 From: Kyle Peacock Date: Wed, 5 Jun 2024 15:37:02 -0700 Subject: [PATCH 3/3] renaming log method to print --- docs/CHANGELOG.md | 1 + packages/agent/src/agent/http/index.ts | 28 +++++++++++++------------- packages/agent/src/observable.test.ts | 6 +++--- packages/agent/src/observable.ts | 9 +-------- 4 files changed, 19 insertions(+), 25 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 86d22c812..0c4d6ef64 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -5,6 +5,7 @@ ### 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: updates dfinity/conventional-pr-title-action to v3.2.0 ## [1.3.0] - 2024-05-01 diff --git a/packages/agent/src/agent/http/index.ts b/packages/agent/src/agent/http/index.ts index b9dd2a135..e158bd316 100644 --- a/packages/agent/src/agent/http/index.ts +++ b/packages/agent/src/agent/http/index.ts @@ -409,7 +409,7 @@ export class HttpAgent implements Agent { const body = cbor.encode(transformedRequest.body); - this.log.log( + this.log.print( `fetching "/api/v2/canister/${ecid.toText()}/call" with request:`, transformedRequest, ); @@ -458,7 +458,7 @@ export class HttpAgent implements Agent { const { ecid, transformedRequest, body, requestId, backoff, tries } = args; const delay = tries === 0 ? 0 : backoff.next(); - this.log.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, @@ -479,7 +479,7 @@ export class HttpAgent implements Agent { let response: ApiQueryResponse; // Make the request and retry if it throws an error try { - this.log.log( + this.log.print( `fetching "/api/v2/canister/${ecid.toString()}/query" with request:`, transformedRequest, ); @@ -544,7 +544,7 @@ export class HttpAgent implements Agent { // Convert the timestamp to milliseconds const timeStampInMs = Number(BigInt(timestamp) / BigInt(1_000_000)); - this.log.log('watermark and timestamp', { + this.log.print('watermark and timestamp', { waterMark: this.waterMark, timestamp: timeStampInMs, }); @@ -638,8 +638,8 @@ export class HttpAgent implements Agent { ? Principal.from(fields.effectiveCanisterId) : Principal.from(canisterId); - this.log.log(`ecid ${ecid.toString()}`); - this.log.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) { @@ -709,7 +709,7 @@ export class HttpAgent implements Agent { // Make query and fetch subnet keys in parallel const [query, subnetStatus] = await Promise.all([makeQuery(), getSubnetStatus()]); - this.log.log('Query response:', query); + this.log.print('Query response:', query); // Skip verification if the user has disabled it if (!this.#verifyQuerySignatures) { return query; @@ -855,7 +855,7 @@ export class HttpAgent implements Agent { const transformedRequest = request ?? (await this.createReadStateRequest(fields, identity)); const body = cbor.encode(transformedRequest.body); - this.log.log( + this.log.print( `fetching "/api/v2/canister/${canister}/read_state" with request:`, transformedRequest, ); @@ -885,10 +885,10 @@ export class HttpAgent implements Agent { } const decodedResponse: ReadStateResponse = cbor.decode(await response.arrayBuffer()); - this.log.log('Read state response:', decodedResponse); + this.log.print('Read state response:', decodedResponse); const parsedTime = await this.parseTimeFromResponse(decodedResponse); if (parsedTime > 0) { - this.log.log('Read state response time:', parsedTime); + this.log.print('Read state response time:', parsedTime); this.#waterMark = parsedTime; } @@ -913,8 +913,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)); - this.log.log('Time from response:', date); - this.log.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'); @@ -931,7 +931,7 @@ export class HttpAgent implements Agent { const callTime = Date.now(); try { if (!canisterId) { - this.log.log( + this.log.print( 'Syncing time with the IC. No canisterId provided, so falling back to ryjl3-tyaaa-aaaaa-aaaba-cai', ); } @@ -958,7 +958,7 @@ export class HttpAgent implements Agent { } : {}; - this.log.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 ce08b3359..116ef9bc6 100644 --- a/packages/agent/src/observable.test.ts +++ b/packages/agent/src/observable.test.ts @@ -42,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'); @@ -59,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(); }); @@ -71,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 b92bf196c..2d67a5182 100644 --- a/packages/agent/src/observable.ts +++ b/packages/agent/src/observable.ts @@ -9,10 +9,6 @@ export class Observable { this.observers = []; } - #call(message: T, ...rest: unknown[]) { - this.notify(message, ...rest); - } - subscribe(func: ObserveFunction) { this.observers.push(func); } @@ -41,7 +37,7 @@ export class ObservableLog extends Observable { constructor() { super(); } - log(message: string, ...rest: unknown[]) { + print(message: string, ...rest: unknown[]) { this.notify({ message, level: 'info' }, ...rest); } warn(message: string, ...rest: unknown[]) { @@ -50,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); - } }