Skip to content

Commit

Permalink
feat: add dependency injection (#257)
Browse files Browse the repository at this point in the history
  • Loading branch information
TimoGlastra authored May 7, 2021
1 parent 4dd950e commit 1965bfe
Show file tree
Hide file tree
Showing 44 changed files with 400 additions and 174 deletions.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@
"events": "^3.3.0",
"js-sha256": "^0.9.0",
"reflect-metadata": "^0.1.13",
"uuid": "^8.3.0",
"node-fetch": "^2.6.1"
"node-fetch": "^2.6.1",
"tsyringe": "^4.5.0",
"uuid": "^8.3.0"
},
"devDependencies": {
"@types/bn.js": "^5.1.0",
Expand Down
178 changes: 54 additions & 124 deletions src/agent/Agent.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,14 @@
import { EventEmitter } from 'events'
import { container as baseContainer, DependencyContainer } from 'tsyringe'

import { Logger } from '../logger'
import { InitConfig } from '../types'
import { IndyWallet } from '../wallet/IndyWallet'
import { MessageReceiver } from './MessageReceiver'
import { EnvelopeService } from './EnvelopeService'
import { ConnectionService, TrustPingService, ConnectionRecord } from '../modules/connections'
import { CredentialService, CredentialRecord } from '../modules/credentials'
import { ProofService, ProofRecord } from '../modules/proofs'
import {
ConsumerRoutingService,
ProviderRoutingService,
MessagePickupService,
ProvisioningService,
ProvisioningRecord,
} from '../modules/routing'
import { BasicMessageService, BasicMessageRecord } from '../modules/basic-messages'
import { LedgerService } from '../modules/ledger'
import { Dispatcher } from './Dispatcher'
import { MessageSender } from './MessageSender'
import { InboundTransporter } from '../transport/InboundTransporter'
import { OutboundTransporter } from '../transport/OutboundTransporter'
import { MessageRepository } from '../storage/MessageRepository'
import { Repository } from '../storage/Repository'
import { IndyStorageService } from '../storage/IndyStorageService'
import { AgentConfig } from './AgentConfig'
import { Wallet } from '../wallet/Wallet'
Expand All @@ -31,43 +18,50 @@ import { ProofsModule } from '../modules/proofs/ProofsModule'
import { RoutingModule } from '../modules/routing/RoutingModule'
import { BasicMessagesModule } from '../modules/basic-messages/BasicMessagesModule'
import { LedgerModule } from '../modules/ledger/LedgerModule'
import { InMemoryMessageRepository } from '../storage/InMemoryMessageRepository'
import { Symbols } from '../symbols'

export class Agent {
public readonly logger: Logger
public readonly agentConfig: AgentConfig
protected agentConfig: AgentConfig
protected logger: Logger
protected container: DependencyContainer
protected eventEmitter: EventEmitter
protected wallet: Wallet
protected messageReceiver: MessageReceiver
protected dispatcher: Dispatcher
protected messageSender: MessageSender
public inboundTransporter?: InboundTransporter

protected connectionService: ConnectionService
protected proofService: ProofService
protected basicMessageService: BasicMessageService
protected providerRoutingService: ProviderRoutingService
protected consumerRoutingService: ConsumerRoutingService
protected trustPingService: TrustPingService
protected messagePickupService: MessagePickupService
protected provisioningService: ProvisioningService
protected ledgerService: LedgerService
protected credentialService: CredentialService
protected basicMessageRepository: Repository<BasicMessageRecord>
protected connectionRepository: Repository<ConnectionRecord>
protected provisioningRepository: Repository<ProvisioningRecord>
protected credentialRepository: Repository<CredentialRecord>
protected proofRepository: Repository<ProofRecord>

public connections!: ConnectionsModule
public proofs!: ProofsModule
public routing!: RoutingModule
public basicMessages!: BasicMessagesModule
public ledger!: LedgerModule
public credentials!: CredentialsModule
public readonly connections!: ConnectionsModule
public readonly proofs!: ProofsModule
public readonly routing!: RoutingModule
public readonly basicMessages!: BasicMessagesModule
public readonly ledger!: LedgerModule
public readonly credentials!: CredentialsModule

public constructor(initialConfig: InitConfig, messageRepository?: MessageRepository) {
// Create child container so we don't interfere with anything outside of this agent
this.container = baseContainer.createChildContainer()

this.agentConfig = new AgentConfig(initialConfig)
this.logger = this.agentConfig.logger
this.eventEmitter = new EventEmitter()

// Bind class based instances
this.container.registerInstance(AgentConfig, this.agentConfig)
this.container.registerInstance(EventEmitter, this.eventEmitter)

// Based on interfaces. Need to register which class to use
this.container.registerInstance(Symbols.Logger, this.logger)
this.container.registerInstance(Symbols.Indy, this.agentConfig.indy)
this.container.registerSingleton(Symbols.Wallet, IndyWallet)
this.container.registerSingleton(Symbols.StorageService, IndyStorageService)

// TODO: do not make messageRepository input parameter
if (messageRepository) {
this.container.registerInstance(Symbols.MessageRepository, messageRepository)
} else {
this.container.registerSingleton(Symbols.MessageRepository, InMemoryMessageRepository)
}

this.logger.info('Creating agent with config', {
...initialConfig,
Expand All @@ -77,60 +71,27 @@ export class Agent {
logger: initialConfig.logger != undefined,
})

this.eventEmitter = new EventEmitter()
// Resolve instances after everything is registered
this.messageSender = this.container.resolve(MessageSender)
this.messageReceiver = this.container.resolve(MessageReceiver)
this.wallet = this.container.resolve(Symbols.Wallet)

// We set the modules in the constructor because that allows to set them as read-only
this.connections = this.container.resolve(ConnectionsModule)
this.credentials = this.container.resolve(CredentialsModule)
this.proofs = this.container.resolve(ProofsModule)
this.routing = this.container.resolve(RoutingModule)
this.basicMessages = this.container.resolve(BasicMessagesModule)
this.ledger = this.container.resolve(LedgerModule)

// Listen for new messages (either from transports or somewhere else in the framework / extensions)
this.listenForMessages()
}

private listenForMessages() {
this.eventEmitter.addListener('agentMessage', async (payload) => {
await this.receiveMessage(payload)
})

this.wallet = new IndyWallet(this.agentConfig)
const envelopeService = new EnvelopeService(this.wallet, this.agentConfig)

this.messageSender = new MessageSender(envelopeService)
this.dispatcher = new Dispatcher(this.messageSender)

const storageService = new IndyStorageService(this.wallet)
this.basicMessageRepository = new Repository<BasicMessageRecord>(
BasicMessageRecord,
storageService as IndyStorageService<BasicMessageRecord>
)
this.connectionRepository = new Repository<ConnectionRecord>(
ConnectionRecord,
storageService as IndyStorageService<ConnectionRecord>
)
this.provisioningRepository = new Repository<ProvisioningRecord>(
ProvisioningRecord,
storageService as IndyStorageService<ProvisioningRecord>
)
this.credentialRepository = new Repository<CredentialRecord>(
CredentialRecord,
storageService as IndyStorageService<CredentialRecord>
)
this.proofRepository = new Repository<ProofRecord>(ProofRecord, storageService as IndyStorageService<ProofRecord>)
this.provisioningService = new ProvisioningService(this.provisioningRepository, this.agentConfig)
this.connectionService = new ConnectionService(this.wallet, this.agentConfig, this.connectionRepository)
this.basicMessageService = new BasicMessageService(this.basicMessageRepository)
this.providerRoutingService = new ProviderRoutingService()
this.consumerRoutingService = new ConsumerRoutingService(this.messageSender, this.agentConfig)
this.trustPingService = new TrustPingService()
this.messagePickupService = new MessagePickupService(messageRepository)
this.ledgerService = new LedgerService(this.wallet, this.agentConfig)
this.credentialService = new CredentialService(
this.wallet,
this.credentialRepository,
this.connectionService,
this.ledgerService,
this.agentConfig
)
this.proofService = new ProofService(this.proofRepository, this.ledgerService, this.wallet, this.agentConfig)

this.messageReceiver = new MessageReceiver(
this.agentConfig,
envelopeService,
this.connectionService,
this.dispatcher
)

this.registerModules()
}

public setInboundTransporter(inboundTransporter: InboundTransporter) {
Expand Down Expand Up @@ -180,38 +141,7 @@ export class Agent {
await this.wallet.delete()
}

protected registerModules() {
this.connections = new ConnectionsModule(
this.dispatcher,
this.agentConfig,
this.connectionService,
this.trustPingService,
this.consumerRoutingService,
this.messageSender
)

this.credentials = new CredentialsModule(
this.dispatcher,
this.connectionService,
this.credentialService,
this.messageSender
)

this.proofs = new ProofsModule(this.dispatcher, this.proofService, this.connectionService, this.messageSender)

this.routing = new RoutingModule(
this.dispatcher,
this.agentConfig,
this.providerRoutingService,
this.provisioningService,
this.messagePickupService,
this.connectionService,
this.messageSender,
this.eventEmitter
)

this.basicMessages = new BasicMessagesModule(this.dispatcher, this.basicMessageService, this.messageSender)

this.ledger = new LedgerModule(this.wallet, this.ledgerService)
public get injectionContainer() {
return this.container
}
}
2 changes: 2 additions & 0 deletions src/agent/Dispatcher.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Lifecycle, scoped } from 'tsyringe'
import { OutboundMessage, OutboundPackage } from '../types'
import { Handler } from './Handler'
import { MessageSender } from './MessageSender'
import { AgentMessage } from './AgentMessage'
import { InboundMessageContext } from './models/InboundMessageContext'
import { ReturnRouteTypes } from '../decorators/transport/TransportDecorator'

@scoped(Lifecycle.ContainerScoped)
class Dispatcher {
private handlers: Handler[] = []
private messageSender: MessageSender
Expand Down
5 changes: 4 additions & 1 deletion src/agent/EnvelopeService.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { inject, scoped, Lifecycle } from 'tsyringe'
import { OutboundMessage, OutboundPackage, UnpackedMessageContext } from '../types'
import { Wallet } from '../wallet/Wallet'
import { ForwardMessage } from '../modules/routing/messages'
import { AgentConfig } from './AgentConfig'
import { Logger } from '../logger'
import { Symbols } from '../symbols'

@scoped(Lifecycle.ContainerScoped)
class EnvelopeService {
private wallet: Wallet
private logger: Logger

public constructor(wallet: Wallet, agentConfig: AgentConfig) {
public constructor(@inject(Symbols.Wallet) wallet: Wallet, agentConfig: AgentConfig) {
this.wallet = wallet
this.logger = agentConfig.logger
}
Expand Down
7 changes: 4 additions & 3 deletions src/agent/MessageReceiver.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Lifecycle, scoped } from 'tsyringe'

import { AgentConfig } from './AgentConfig'
import { Dispatcher } from './Dispatcher'
import { EnvelopeService } from './EnvelopeService'
Expand All @@ -10,7 +12,8 @@ import { JsonTransformer } from '../utils/JsonTransformer'
import { Logger } from '../logger'
import { replaceLegacyDidSovPrefixOnMessage } from '../utils/messageType'

class MessageReceiver {
@scoped(Lifecycle.ContainerScoped)
export class MessageReceiver {
private config: AgentConfig
private envelopeService: EnvelopeService
private connectionService: ConnectionService
Expand Down Expand Up @@ -148,5 +151,3 @@ class MessageReceiver {
return message
}
}

export { MessageReceiver }
7 changes: 4 additions & 3 deletions src/agent/MessageSender.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Lifecycle, scoped } from 'tsyringe'

import { OutboundMessage, OutboundPackage } from '../types'
import { OutboundTransporter } from '../transport/OutboundTransporter'
import { EnvelopeService } from './EnvelopeService'

class MessageSender {
@scoped(Lifecycle.ContainerScoped)
export class MessageSender {
private envelopeService: EnvelopeService
private outboundTransporter?: OutboundTransporter

Expand All @@ -26,5 +29,3 @@ class MessageSender {
await this.outboundTransporter.sendMessage(outboundPackage)
}
}

export { MessageSender }
Loading

0 comments on commit 1965bfe

Please sign in to comment.