From 0e5887a3c561db662c4244d9c72936be58a3bbcc Mon Sep 17 00:00:00 2001 From: Seweryn Kras Date: Thu, 14 Dec 2023 10:33:05 +0100 Subject: [PATCH 1/2] chore: enable noImplicitAny --- package-lock.json | 7 +++++++ package.json | 1 + src/activity/activity.ts | 3 ++- src/agreement/factory.ts | 5 +++-- src/agreement/service.ts | 6 +++--- src/events/events.ts | 16 ++++++++++++---- src/executor/config.ts | 2 ++ src/market/builder.ts | 8 ++++---- src/market/demand.ts | 4 ++-- src/market/proposal.ts | 2 +- src/market/service.ts | 6 ++++-- src/network/node.ts | 2 +- src/payment/payments.ts | 23 ++++++++++++----------- src/payment/service.ts | 2 +- src/script/command.ts | 18 +++++++++--------- src/stats/abstract_aggregator.ts | 2 +- src/stats/activities.ts | 2 +- src/stats/agreements.ts | 2 +- src/stats/allocations.ts | 2 +- src/stats/debit_notes.ts | 2 +- src/stats/invoices.ts | 2 +- src/stats/payments.ts | 2 +- src/stats/proposals.ts | 2 +- src/stats/providers.ts | 4 ++-- src/stats/tasks.ts | 2 +- src/stats/times.ts | 2 +- src/task/work.ts | 2 +- src/utils/logger/consoleLogger.ts | 2 +- src/utils/logger/logger.ts | 12 ++++++------ tests/tsconfig.json | 3 ++- tsconfig.json | 4 ++-- 31 files changed, 88 insertions(+), 64 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5370a832b..f23ab9d78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@types/jest": "^29.5.10", "@types/node": "^20.10.0", "@types/supertest": "^2.0.16", + "@types/tmp": "^0.2.6", "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", @@ -3529,6 +3530,12 @@ "@types/superagent": "*" } }, + "node_modules/@types/tmp": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/@types/tmp/-/tmp-0.2.6.tgz", + "integrity": "sha512-chhaNf2oKHlRkDGt+tiKE2Z5aJ6qalm7Z9rlLdBwmOiAAf09YQvvoLXjWK4HWPF1xU/fqvMgfNfpVoBscA/tKA==", + "dev": true + }, "node_modules/@types/uuid": { "version": "9.0.7", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.7.tgz", diff --git a/package.json b/package.json index ed81dc687..29edd15e1 100644 --- a/package.json +++ b/package.json @@ -75,6 +75,7 @@ "@types/jest": "^29.5.10", "@types/node": "^20.10.0", "@types/supertest": "^2.0.16", + "@types/tmp": "^0.2.6", "@types/uuid": "^9.0.7", "@typescript-eslint/eslint-plugin": "^6.13.1", "@typescript-eslint/parser": "^6.13.1", diff --git a/src/activity/activity.ts b/src/activity/activity.ts index 08101d0b4..09f525e39 100644 --- a/src/activity/activity.ts +++ b/src/activity/activity.ts @@ -350,7 +350,8 @@ export class Activity { } } - private isTimeoutError(error) { + private isTimeoutError(error: Error | AxiosError) { + if (!("isAxiosError" in error)) return false; const timeoutMsg = error.message && error.message.includes("timeout"); return ( (error.response && error.response.status === 408) || diff --git a/src/agreement/factory.ts b/src/agreement/factory.ts index 92222666d..c76806d39 100644 --- a/src/agreement/factory.ts +++ b/src/agreement/factory.ts @@ -4,6 +4,7 @@ import { AgreementConfig } from "./config"; import { Events } from "../events"; import { YagnaApi } from "../utils/yagna/yagna"; import { GolemError } from "../error/golem-error"; +import { ProposalProperties } from "../market/proposal"; /** * AgreementFactory @@ -43,8 +44,8 @@ export class AgreementFactory { }); const { data } = await this.yagnaApi.market.getAgreement(agreementId); const provider = { - name: data?.offer.properties["golem.node.id.name"], - id: data?.offer.providerId, + name: (data.offer.properties as ProposalProperties)["golem.node.id.name"], + id: data.offer.providerId, }; if (!provider.id || !provider.name) throw new GolemError("Unable to get provider info"); const agreement = new Agreement(agreementId, provider, this.yagnaApi, this.options); diff --git a/src/agreement/service.ts b/src/agreement/service.ts index 220ed59c5..b4e9466ea 100644 --- a/src/agreement/service.ts +++ b/src/agreement/service.ts @@ -106,14 +106,14 @@ export class AgreementPoolService { * @return Agreement */ async getAgreement(): Promise { - let agreement; + let agreement: Agreement | undefined; while (!agreement && this.isServiceRunning) { agreement = await this.getAgreementFormPool(); if (!agreement) { await sleep(2); } } - if (!agreement && !this.isServiceRunning) { + if (!agreement || !this.isServiceRunning) { throw new GolemError("Unable to get agreement. Agreement service is not running"); } return agreement; @@ -172,7 +172,7 @@ export class AgreementPoolService { ); } - async createAgreement(candidate) { + async createAgreement(candidate: AgreementCandidate) { try { let agreement = await Agreement.create(candidate.proposal.id, this.yagnaApi, this.config.options); agreement = await this.waitForAgreementApproval(agreement); diff --git a/src/events/events.ts b/src/events/events.ts index 71874cce3..66cf3e888 100644 --- a/src/events/events.ts +++ b/src/events/events.ts @@ -16,7 +16,7 @@ class CustomEvent extends Event { readonly detail: DataType; readonly name: string; readonly timestamp: number; - constructor(type, data) { + constructor(type: string, data: { detail: DataType } & EventInit) { super(type, data); this.detail = data.detail; this.name = this.constructor.name; @@ -25,13 +25,21 @@ class CustomEvent extends Event { } export abstract class BaseEvent extends CustomEvent { - constructor(data?: DataType) { + constructor(data: DataType) { super(EventType, { detail: data }); } } -export class ComputationStarted extends BaseEvent {} -export class ComputationFinished extends BaseEvent {} +export class ComputationStarted extends BaseEvent { + constructor() { + super(undefined); + } +} +export class ComputationFinished extends BaseEvent { + constructor() { + super(undefined); + } +} export class ComputationFailed extends BaseEvent<{ reason?: string }> {} export class TaskStarted extends BaseEvent<{ id: string; diff --git a/src/executor/config.ts b/src/executor/config.ts index 0140a5c04..46b04aea7 100644 --- a/src/executor/config.ts +++ b/src/executor/config.ts @@ -48,6 +48,8 @@ export class ExecutorConfig { YAGNA_SUBNET: null, }, }; + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore FIXME: this weirdness may not be needed anymore? Object.keys(options).forEach((key) => (this[key] = options[key])); this.activityExecuteTimeout = options.activityExecuteTimeout || options.taskTimeout; const apiKey = options?.yagnaOptions?.apiKey || processEnv.env.YAGNA_APPKEY; diff --git a/src/market/builder.ts b/src/market/builder.ts index 272056014..2015a0dc7 100644 --- a/src/market/builder.ts +++ b/src/market/builder.ts @@ -60,19 +60,19 @@ export class DecorationsBuilder { if (!decorations.constraints.length) constraints = "(&)"; else if (decorations.constraints.length == 1) constraints = decorations.constraints[0]; else constraints = `(&${decorations.constraints.join("\n\t")})`; - const properties = {}; + const properties: Record = {}; decorations.properties.forEach((prop) => (properties[prop.key] = prop.value)); return { constraints, properties }; } - private parseConstraint(constraint): Constraint { + private parseConstraint(constraint: string): Constraint { for (const key in ComparisonOperator) { - const value = ComparisonOperator[key]; + const value = ComparisonOperator[key as keyof typeof ComparisonOperator]; const parsedConstraint = constraint.slice(1, -1).split(value); if (parsedConstraint.length === 2) { return { key: parsedConstraint[0], value: parsedConstraint[1], - comparisonOperator: ComparisonOperator[key], + comparisonOperator: value, }; } } diff --git a/src/market/demand.ts b/src/market/demand.ts index df6ecedbc..dbf5f323d 100644 --- a/src/market/demand.ts +++ b/src/market/demand.ts @@ -244,7 +244,7 @@ export class Demand extends EventTarget { * @hidden */ export class DemandEvent extends Event { - readonly proposal: Proposal; + readonly proposal?: Proposal; readonly error?: Error; /** @@ -253,7 +253,7 @@ export class DemandEvent extends Event { * @param data object with proposal data: * @param error optional error if occurred while subscription is active */ - constructor(type, data?, error?) { + constructor(type: string, data?: (Proposal & EventInit) | undefined, error?: GolemError | undefined) { super(type, data); this.proposal = data; this.error = error; diff --git a/src/market/proposal.ts b/src/market/proposal.ts index c761be658..41d678ec5 100644 --- a/src/market/proposal.ts +++ b/src/market/proposal.ts @@ -211,7 +211,7 @@ export class Proposal { } async respond(chosenPlatform: string) { - this.demandRequest.properties["golem.com.payment.chosen-platform"] = chosenPlatform; + (this.demandRequest.properties as ProposalProperties)["golem.com.payment.chosen-platform"] = chosenPlatform; const { data: counteringProposalId } = await this.api .counterProposalDemand(this.subscriptionId, this.id, this.demandRequest, { timeout: 20000 }) .catch((e) => { diff --git a/src/market/service.ts b/src/market/service.ts index 73183fe95..785cf3a61 100644 --- a/src/market/service.ts +++ b/src/market/service.ts @@ -76,7 +76,7 @@ export class MarketService { private demandEventListener(event: Event) { const proposal = (event as DemandEvent).proposal; const error = (event as DemandEvent).error; - if (error) { + if (error || !proposal) { this.logger?.error("Subscription failed. Trying to subscribe a new one..."); this.resubscribeDemand().catch((e) => this.logger?.warn(e)); return; @@ -98,7 +98,9 @@ export class MarketService { let attempt = 1; let success = false; while (!success && attempt <= this.maxResubscribeRetries) { - success = await this.createDemand().catch((e) => this.logger?.error(`Could not resubscribe demand. ${e}`)); + success = Boolean( + await this.createDemand().catch((e) => this.logger?.error(`Could not resubscribe demand. ${e}`)), + ); ++attempt; await sleep(20); } diff --git a/src/network/node.ts b/src/network/node.ts index 102377a3d..61ccec853 100644 --- a/src/network/node.ts +++ b/src/network/node.ts @@ -6,7 +6,7 @@ import { NetworkInfo } from "./network"; */ export class NetworkNode { constructor( - public readonly id, + public readonly id: string, public readonly ip: IPv4, private getNetworkInfo: () => NetworkInfo, private apiUrl: string, diff --git a/src/payment/payments.ts b/src/payment/payments.ts index e0ba001fb..7c1ca510a 100644 --- a/src/payment/payments.ts +++ b/src/payment/payments.ts @@ -63,11 +63,11 @@ export class Payments extends EventTarget { for (const event of invoiceEvents) { if (!this.isRunning) return; if (event.eventType !== "InvoiceReceivedEvent") continue; - const invoice = await Invoice.create(event["invoiceId"], this.yagnaApi, { ...this.options }).catch( - (e) => - this.logger?.error( - `Unable to create invoice ID: ${event["invoiceId"]}. ${e?.response?.data?.message || e}`, - ), + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore FIXME: ya-ts-client does not provide invoiceId in the event even though it is in the API response + const invoiceId = event["invoiceId"]; + const invoice = await Invoice.create(invoiceId, this.yagnaApi, { ...this.options }).catch( + (e) => this.logger?.error(`Unable to create invoice ID: ${invoiceId}. ${e?.response?.data?.message || e}`), ); if (!invoice) continue; this.dispatchEvent(new InvoiceEvent(PaymentEventType, invoice)); @@ -98,11 +98,12 @@ export class Payments extends EventTarget { for (const event of debitNotesEvents) { if (!this.isRunning) return; if (event.eventType !== "DebitNoteReceivedEvent") continue; - const debitNote = await DebitNote.create(event["debitNoteId"], this.yagnaApi, { ...this.options }).catch( + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore FIXME: ya-ts-client does not provide debitNoteId in the event even though it is in the API response + const debitNoteId = event["debitNoteId"]; + const debitNote = await DebitNote.create(debitNoteId, this.yagnaApi, { ...this.options }).catch( (e) => - this.logger?.error( - `Unable to create debit note ID: ${event["debitNoteId"]}. ${e?.response?.data?.message || e}`, - ), + this.logger?.error(`Unable to create debit note ID: ${debitNoteId}. ${e?.response?.data?.message || e}`), ); if (!debitNote) continue; this.dispatchEvent(new DebitNoteEvent(PaymentEventType, debitNote)); @@ -139,7 +140,7 @@ export class InvoiceEvent extends Event { * @param type A string with the name of the event: * @param data object with invoice data: */ - constructor(type, data) { + constructor(type: string, data: EventInit & Invoice) { super(type, data); this.invoice = data; } @@ -156,7 +157,7 @@ export class DebitNoteEvent extends Event { * @param type A string with the name of the event: * @param data object with debit note data: */ - constructor(type, data) { + constructor(type: string, data: EventInit & DebitNote) { super(type, data); this.debitNote = data; } diff --git a/src/payment/service.ts b/src/payment/service.ts index e08cd25e0..fa461394b 100644 --- a/src/payment/service.ts +++ b/src/payment/service.ts @@ -166,7 +166,7 @@ export class PaymentService { } } - private async subscribePayments(event) { + private async subscribePayments(event: Event) { if (event instanceof InvoiceEvent) this.processInvoice(event.invoice).then(); if (event instanceof DebitNoteEvent) this.processDebitNote(event.debitNote).then(); } diff --git a/src/script/command.ts b/src/script/command.ts index d1c048ad0..06b72859a 100644 --- a/src/script/command.ts +++ b/src/script/command.ts @@ -13,11 +13,11 @@ const EmptyErrorResult = new Result({ * @hidden */ export class Command { - protected args: object; + protected args: Record; constructor( private commandName: string, - args?: object, + args?: Record, ) { this.args = args || {}; } @@ -59,7 +59,7 @@ export class Command { * @hidden */ export class Deploy extends Command { - constructor(args?: object) { + constructor(args?: Record) { super("deploy", args); } } @@ -68,7 +68,7 @@ export class Deploy extends Command { * @hidden */ export class Start extends Command { - constructor(args?: object) { + constructor(args?: Record) { super("start", args); } } @@ -103,7 +103,7 @@ export class Run extends Command { } export class Terminate extends Command { - constructor(args?: object) { + constructor(args?: Record) { super("terminate", args); } } @@ -139,7 +139,7 @@ export class UploadFile extends Transfer { } async after(result: Result): Promise { - await this.storageProvider.release([this.args["from"]]); + await this.storageProvider.release([this.args["from"] as string]); return result; } } @@ -162,7 +162,7 @@ export class UploadData extends Transfer { } async after(result: Result): Promise { - await this.storageProvider.release([this.args["from"]]); + await this.storageProvider.release([this.args["from"] as string]); return result; } } @@ -185,7 +185,7 @@ export class DownloadFile extends Transfer { } async after(result: Result): Promise { - await this.storageProvider.release([this.args["to"]]); + await this.storageProvider.release([this.args["to"] as string]); return result; } } @@ -212,7 +212,7 @@ export class DownloadData extends Transfer { } async after(result: Result): Promise> { - await this.storageProvider.release([this.args["to"]]); + await this.storageProvider.release([this.args["to"] as string]); if (result.result === ResultState.Ok) { return new Result({ ...result, diff --git a/src/stats/abstract_aggregator.ts b/src/stats/abstract_aggregator.ts index 6b1882e2b..1aad263e6 100644 --- a/src/stats/abstract_aggregator.ts +++ b/src/stats/abstract_aggregator.ts @@ -17,7 +17,7 @@ export abstract class AbstractAggregator { protected getByField(field: string, value: string | number): Collection { return this.getAll().where(field, "==", value); } - protected updateItemInfo(id: string, data) { + protected updateItemInfo(id: string, data: Partial) { const item = this.items.get(id); if (!item) return; this.items?.set(id, { diff --git a/src/stats/activities.ts b/src/stats/activities.ts index c66d89cb0..c36a00e27 100644 --- a/src/stats/activities.ts +++ b/src/stats/activities.ts @@ -13,7 +13,7 @@ interface Payload { } export class Activities extends AbstractAggregator { - beforeAdd(payload): ActivityInfo { + beforeAdd(payload: ActivityInfo): ActivityInfo { return payload; } getByTaskId(taskId: string) { diff --git a/src/stats/agreements.ts b/src/stats/agreements.ts index bcaeee5c4..6d5c6d72c 100644 --- a/src/stats/agreements.ts +++ b/src/stats/agreements.ts @@ -20,7 +20,7 @@ interface Payload { } export class Agreements extends AbstractAggregator { - beforeAdd(payload): AgreementInfo { + beforeAdd(payload: AgreementInfo): AgreementInfo { return { ...payload, status: AgreementStatusEnum.Pending }; } confirm(id: string) { diff --git a/src/stats/allocations.ts b/src/stats/allocations.ts index 848188028..c5baea68a 100644 --- a/src/stats/allocations.ts +++ b/src/stats/allocations.ts @@ -13,7 +13,7 @@ interface Payload { } export class Allocations extends AbstractAggregator { - beforeAdd(payload): AllocationInfo { + beforeAdd(payload: Payload): AllocationInfo { return payload; } } diff --git a/src/stats/debit_notes.ts b/src/stats/debit_notes.ts index d92fd0f2b..b4faa9ee4 100644 --- a/src/stats/debit_notes.ts +++ b/src/stats/debit_notes.ts @@ -9,7 +9,7 @@ interface Payload { } export class DebitNotes extends AbstractAggregator { - beforeAdd(item): DebitNoteInfo { + beforeAdd(item: Payload): DebitNoteInfo { return item; } } diff --git a/src/stats/invoices.ts b/src/stats/invoices.ts index 16002ba7a..a327837dc 100644 --- a/src/stats/invoices.ts +++ b/src/stats/invoices.ts @@ -14,7 +14,7 @@ interface Payload { } export class Invoices extends AbstractAggregator { - beforeAdd(payload): InvoiceInfo { + beforeAdd(payload: Payload): InvoiceInfo { return { ...payload, amount: parseFloat(payload.amount), diff --git a/src/stats/payments.ts b/src/stats/payments.ts index 8b4bd7f11..d4ab0f891 100644 --- a/src/stats/payments.ts +++ b/src/stats/payments.ts @@ -14,7 +14,7 @@ interface Payload { } export class Payments extends AbstractAggregator { - beforeAdd(payload): PaymentInfo { + beforeAdd(payload: Payload): PaymentInfo { return { ...payload, amount: parseFloat(payload.amount), diff --git a/src/stats/proposals.ts b/src/stats/proposals.ts index cb6cd6bc9..9f3790b8c 100644 --- a/src/stats/proposals.ts +++ b/src/stats/proposals.ts @@ -10,7 +10,7 @@ interface Payload { } export class Proposals extends AbstractAggregator { - beforeAdd(payload): ProposalInfo { + beforeAdd(payload: Payload): ProposalInfo { return payload; } getByProviderId(providerId: string) { diff --git a/src/stats/providers.ts b/src/stats/providers.ts index 40234a6d4..6c43bbb61 100644 --- a/src/stats/providers.ts +++ b/src/stats/providers.ts @@ -10,9 +10,9 @@ interface Payload { } export class Providers extends AbstractAggregator { - beforeAdd(payload): ProviderInfo { + beforeAdd(payload: Payload): ProviderInfo { if (payload.providerName) { - return payload; + return payload as ProviderInfo; } const provider = this.getById(payload.id); diff --git a/src/stats/tasks.ts b/src/stats/tasks.ts index 71be86e6e..31e96245c 100644 --- a/src/stats/tasks.ts +++ b/src/stats/tasks.ts @@ -22,7 +22,7 @@ interface Payload { } export class Tasks extends AbstractAggregator { - beforeAdd(payload): TaskInfo { + beforeAdd(payload: Payload): TaskInfo { return { ...payload, stopTime: 0, diff --git a/src/stats/times.ts b/src/stats/times.ts index c9af31f51..511f6929a 100644 --- a/src/stats/times.ts +++ b/src/stats/times.ts @@ -17,7 +17,7 @@ export class Times extends AbstractAggregator { return { id, stopTime: stopTime || 0, startTime, duration: stopTime ? stopTime - startTime : 0 }; } - stop({ id, stopTime }) { + stop({ id, stopTime }: { id: string; stopTime: number }) { const item = this.items.get(id); this.updateItemInfo(id, { stopTime, duration: item?.startTime ? stopTime - item.startTime : 0 }); } diff --git a/src/task/work.ts b/src/task/work.ts index 1d9ee0aa4..03a9dc4f6 100644 --- a/src/task/work.ts +++ b/src/task/work.ts @@ -82,7 +82,7 @@ export class WorkContext { .catch((e) => { throw new GolemError(`Unable to deploy activity. ${e}`); }); - let timeoutId; + let timeoutId: NodeJS.Timeout; await Promise.race([ new Promise( (res, rej) => diff --git a/src/utils/logger/consoleLogger.ts b/src/utils/logger/consoleLogger.ts index 3c74dcd33..ccab715c6 100644 --- a/src/utils/logger/consoleLogger.ts +++ b/src/utils/logger/consoleLogger.ts @@ -4,7 +4,7 @@ import { Logger } from "./logger"; */ export function consoleLogger(): Logger { let level = "info"; - const print = (level, msg) => console.log(`${new Date().toISOString()} [${level}] ${msg}`); + const print = (level: string, msg: unknown) => console.log(`${new Date().toISOString()} [${level}] ${msg}`); return { debug: (msg) => print("debug", msg), error: (msg) => print("error", msg), diff --git a/src/utils/logger/logger.ts b/src/utils/logger/logger.ts index cdc0b6842..caf17ecf3 100644 --- a/src/utils/logger/logger.ts +++ b/src/utils/logger/logger.ts @@ -7,10 +7,10 @@ export enum LogLevel { } export interface Logger { level: string; - setLevel(level: string); - log(msg); - info(msg); - warn(msg); - error(msg); - debug(msg); + setLevel(level: string): void; + log(msg: unknown): void; + info(msg: unknown): void; + warn(msg: unknown): void; + error(msg: unknown): void; + debug(msg: unknown): void; } diff --git a/tests/tsconfig.json b/tests/tsconfig.json index 882c3e83d..78e771966 100644 --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -4,6 +4,7 @@ "exclude": ["./cypress"], "compilerOptions": { "types": ["jest"], - "resolveJsonModule": true + "resolveJsonModule": true, + "noImplicitAny": false } } diff --git a/tsconfig.json b/tsconfig.json index 743a58d5e..d536a3ea4 100755 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "esnext", - "noImplicitAny": false, + "noImplicitAny": true, "target": "es2018", "strict": true, "esModuleInterop": true, @@ -30,5 +30,5 @@ "excludeInternal": true }, "include": ["src"], - "exclude": ["**/*.spec.ts", "tmp/"] + "exclude": ["**/*.spec.ts", "**/*.test.ts", "tmp/"] } From 546dd0f5c1c6560e309739181ef2711d10c56638 Mon Sep 17 00:00:00 2001 From: Seweryn Kras Date: Fri, 15 Dec 2023 14:05:28 +0100 Subject: [PATCH 2/2] refactor: type guard provider name --- src/stats/providers.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/stats/providers.ts b/src/stats/providers.ts index 6c43bbb61..a95b60f4b 100644 --- a/src/stats/providers.ts +++ b/src/stats/providers.ts @@ -9,10 +9,14 @@ interface Payload { providerName?: string; } +function isProviderInfo(item: ProviderInfo | Payload): item is ProviderInfo { + return (item as ProviderInfo).providerName !== undefined; +} + export class Providers extends AbstractAggregator { beforeAdd(payload: Payload): ProviderInfo { - if (payload.providerName) { - return payload as ProviderInfo; + if (isProviderInfo(payload)) { + return payload; } const provider = this.getById(payload.id);