From 85b6b605e86cee0fcb2c40cb63146635d19a995d Mon Sep 17 00:00:00 2001 From: Brian Faust Date: Mon, 19 Aug 2019 10:13:19 +0300 Subject: [PATCH] feat(core-kernel): application and service provider bootstrappers --- packages/core-api/src/service-provider.ts | 2 +- packages/core-blockchain/src/blockchain.ts | 10 +- .../core-blockchain/src/service-provider.ts | 10 +- packages/core-blockchain/src/state-machine.ts | 11 +- .../src/postgres-connection.ts | 2 +- .../src/service-provider.ts | 2 +- .../src/state-builder.ts | 2 +- .../core-database/src/database-service.ts | 2 +- packages/core-elasticsearch/src/index.ts | 2 +- .../core-elasticsearch/src/indices/base.ts | 2 +- .../core-error-tracker-airbrake/src/index.ts | 2 +- .../core-error-tracker-bugsnag/src/index.ts | 2 +- .../core-error-tracker-raygun/src/index.ts | 2 +- .../core-error-tracker-rollbar/src/index.ts | 2 +- .../core-error-tracker-sentry/src/index.ts | 2 +- packages/core-exchange-json-rpc/src/index.ts | 2 +- packages/core-explorer/src/index.ts | 2 +- packages/core-forger/src/service-provider.ts | 2 +- packages/core-kernel/src/application.ts | 269 +++--------------- .../core-kernel/src/bootstrap/app/index.ts | 14 + .../src/bootstrap/app/load-bindings.ts | 26 ++ .../src/bootstrap/app/load-configuration.ts | 22 ++ .../src/bootstrap/app/load-cryptography.ts | 30 ++ .../app/load-environment-variables.ts | 16 ++ .../src/bootstrap/app/load-error-handler.ts | 17 ++ .../src/bootstrap/app/load-factories.ts | 20 ++ .../src/bootstrap/app/load-namespace.ts | 24 ++ .../src/bootstrap/app/load-paths.ts | 37 +++ .../bootstrap/app/load-service-providers.ts | 22 ++ .../src/bootstrap/app/load-services.ts | 57 ++++ .../src/bootstrap/boot-providers.ts | 16 -- .../core-kernel/src/bootstrap/bootstrapper.ts | 16 ++ packages/core-kernel/src/bootstrap/index.ts | 9 +- .../src/bootstrap/load-configuration.ts | 16 -- .../src/bootstrap/load-cryptography.ts | 32 --- .../bootstrap/load-environment-variables.ts | 16 -- .../src/bootstrap/register-providers.ts | 60 ---- .../boot-service-providers.ts | 20 ++ .../src/bootstrap/service-providers/index.ts | 2 + .../register-service-providers.ts | 57 ++++ .../core-kernel/src/config/adapters/base.ts | 28 -- .../core-kernel/src/config/adapters/local.ts | 75 ++++- .../core-kernel/src/config/adapters/remote.ts | 12 +- packages/core-kernel/src/config/factory.ts | 18 +- packages/core-kernel/src/container.ts | 12 +- .../src/contracts/core-kernel/application.ts | 52 +--- .../src/contracts/core-kernel/config.ts | 9 + .../src/contracts/core-kernel/container.ts | 11 +- .../contracts/core-kernel/event-dispatcher.ts | 3 +- .../src/contracts/core-kernel/index.ts | 1 + packages/core-kernel/src/errors.ts | 74 ----- .../core-kernel/src/repositories/provider.ts | 117 ++++++-- .../src/services/events/dispatcher.ts | 3 +- .../src/support/service-provider.ts | 53 ++-- packages/core-kernel/src/types.ts | 5 + .../core-logger-pino/src/service-provider.ts | 2 +- .../src/service-provider.ts | 2 +- .../src/service-provider.ts | 2 +- packages/core-p2p/src/event-listener.ts | 2 +- packages/core-p2p/src/network-monitor.ts | 2 +- packages/core-p2p/src/peer-communicator.ts | 2 +- packages/core-p2p/src/peer-processor.ts | 2 +- packages/core-p2p/src/service-provider.ts | 2 +- .../src/socket-server/versions/internal.ts | 2 +- .../core-snapshots/src/service-provider.ts | 2 +- .../core-snapshots/src/transport/index.ts | 2 +- packages/core-state/src/service-provider.ts | 2 +- packages/core-state/src/stores/state.ts | 2 +- .../core-transaction-pool/src/connection.ts | 2 +- .../src/service-provider.ts | 2 +- packages/core-vote-report/src/index.ts | 2 +- .../core-wallet-api/src/service-provider.ts | 2 +- packages/core-webhooks/src/index.ts | 2 +- packages/core-webhooks/src/listener.ts | 2 +- packages/core/bin/config/testnet/config.js | 132 --------- .../core/bin/config/testnet/delegates.json | 55 ++++ packages/core/bin/config/testnet/peers.json | 8 + .../bin/config/testnet/service-providers.js | 67 +++++ packages/core/package.json | 2 +- packages/core/src/commands/command.ts | 2 +- .../core/src/commands/config/forger/bip39.ts | 2 +- .../core/src/commands/snapshot/restore.ts | 2 +- 82 files changed, 843 insertions(+), 797 deletions(-) create mode 100644 packages/core-kernel/src/bootstrap/app/index.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-bindings.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-configuration.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-cryptography.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-environment-variables.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-error-handler.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-factories.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-namespace.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-paths.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-service-providers.ts create mode 100644 packages/core-kernel/src/bootstrap/app/load-services.ts delete mode 100644 packages/core-kernel/src/bootstrap/boot-providers.ts create mode 100644 packages/core-kernel/src/bootstrap/bootstrapper.ts delete mode 100644 packages/core-kernel/src/bootstrap/load-configuration.ts delete mode 100644 packages/core-kernel/src/bootstrap/load-cryptography.ts delete mode 100644 packages/core-kernel/src/bootstrap/load-environment-variables.ts delete mode 100644 packages/core-kernel/src/bootstrap/register-providers.ts create mode 100644 packages/core-kernel/src/bootstrap/service-providers/boot-service-providers.ts create mode 100644 packages/core-kernel/src/bootstrap/service-providers/index.ts create mode 100644 packages/core-kernel/src/bootstrap/service-providers/register-service-providers.ts delete mode 100644 packages/core-kernel/src/config/adapters/base.ts create mode 100644 packages/core-kernel/src/contracts/core-kernel/config.ts delete mode 100644 packages/core/bin/config/testnet/config.js create mode 100644 packages/core/bin/config/testnet/delegates.json create mode 100644 packages/core/bin/config/testnet/peers.json create mode 100644 packages/core/bin/config/testnet/service-providers.js diff --git a/packages/core-api/src/service-provider.ts b/packages/core-api/src/service-provider.ts index 54790b2c2e..e14509358b 100644 --- a/packages/core-api/src/service-provider.ts +++ b/packages/core-api/src/service-provider.ts @@ -24,7 +24,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-blockchain/src/blockchain.ts b/packages/core-blockchain/src/blockchain.ts index 7427ad556e..cb4b03c8d3 100644 --- a/packages/core-blockchain/src/blockchain.ts +++ b/packages/core-blockchain/src/blockchain.ts @@ -10,7 +10,7 @@ import { BlockProcessor, BlockProcessorResult } from "./processor"; import { stateMachine } from "./state-machine"; const logger = app.resolve("logger"); -const emitter = app.resolve("event-dispatcher"); +const emitter = app.resolve("events"); const { BlockFactory } = Blocks; export class Blockchain implements Contracts.Blockchain.IBlockchain { @@ -19,7 +19,7 @@ export class Blockchain implements Contracts.Blockchain.IBlockchain { * @return {IStateStore} */ get state(): Contracts.State.IStateStore { - return stateMachine.state; + return app.resolve("state").getStore(); } /** @@ -27,7 +27,7 @@ export class Blockchain implements Contracts.Blockchain.IBlockchain { * @return {IPeerService} */ get p2p(): Contracts.P2P.IPeerService { - return app.resolve("p2p"); + return app.p2p; } /** @@ -35,7 +35,7 @@ export class Blockchain implements Contracts.Blockchain.IBlockchain { * @return {TransactionPool} */ get transactionPool(): Contracts.TransactionPool.IConnection { - return app.resolve("transaction-pool"); + return app.transactionPool; } /** @@ -43,7 +43,7 @@ export class Blockchain implements Contracts.Blockchain.IBlockchain { * @return {ConnectionInterface} */ get database(): Contracts.Database.IDatabaseService { - return app.resolve("database"); + return app.database; } public isStopped: boolean; diff --git a/packages/core-blockchain/src/service-provider.ts b/packages/core-blockchain/src/service-provider.ts index a1434384c1..5de3f7feb4 100644 --- a/packages/core-blockchain/src/service-provider.ts +++ b/packages/core-blockchain/src/service-provider.ts @@ -6,13 +6,7 @@ import { ReplayBlockchain } from "./replay"; export class ServiceProvider extends Support.AbstractServiceProvider { public async register(): Promise { - let blockchain: Blockchain; - - if (this.opts.replay) { - blockchain = new ReplayBlockchain(); - } else { - blockchain = new Blockchain(this.opts); - } + const blockchain: Blockchain = this.opts.replay ? new ReplayBlockchain() : new Blockchain(this.opts); this.app .resolve("state") @@ -31,7 +25,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { await this.app.resolve("blockchain").stop(); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-blockchain/src/state-machine.ts b/packages/core-blockchain/src/state-machine.ts index 493c17fdfc..914f3d2abc 100644 --- a/packages/core-blockchain/src/state-machine.ts +++ b/packages/core-blockchain/src/state-machine.ts @@ -11,14 +11,11 @@ import { blockchainMachine } from "./machines/blockchain"; import { Blockchain } from "./blockchain"; const { BlockFactory } = Blocks; -const emitter = app.resolve("event-dispatcher"); +const emitter = app.resolve("events"); const logger = app.resolve("logger"); -const stateStorage = app.resolve("state").getStore(); -/** - * @type {IStateStore} - */ -blockchainMachine.state = stateStorage; +// defer initialisation to "init" due to this being resolved before the container kicks in +let stateStorage; /** * The blockchain actions. @@ -120,6 +117,8 @@ blockchainMachine.actionMap = (blockchain: Blockchain) => ({ }, async init() { + stateStorage = app.resolve("state").getStore(); + try { const block: Interfaces.IBlock = await blockchain.database.getLastBlock(); diff --git a/packages/core-database-postgres/src/postgres-connection.ts b/packages/core-database-postgres/src/postgres-connection.ts index 5f10d2b2e3..9b9049146d 100644 --- a/packages/core-database-postgres/src/postgres-connection.ts +++ b/packages/core-database-postgres/src/postgres-connection.ts @@ -33,7 +33,7 @@ export class PostgresConnection implements Contracts.Database.IConnection { public pgp: IMain; private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); private migrationsRepository: MigrationsRepository; private cache: Map; diff --git a/packages/core-database-postgres/src/service-provider.ts b/packages/core-database-postgres/src/service-provider.ts index 00e2a15b0f..6d1b3018f1 100644 --- a/packages/core-database-postgres/src/service-provider.ts +++ b/packages/core-database-postgres/src/service-provider.ts @@ -22,7 +22,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { await this.app.resolve("database").connection.disconnect(); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-database-postgres/src/state-builder.ts b/packages/core-database-postgres/src/state-builder.ts index 0a0694a28e..912cee89b3 100644 --- a/packages/core-database-postgres/src/state-builder.ts +++ b/packages/core-database-postgres/src/state-builder.ts @@ -5,7 +5,7 @@ import { Interfaces, Managers, Utils } from "@arkecosystem/crypto"; export class StateBuilder { private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); constructor( diff --git a/packages/core-database/src/database-service.ts b/packages/core-database/src/database-service.ts index 04eb190628..90a1d16066 100644 --- a/packages/core-database/src/database-service.ts +++ b/packages/core-database/src/database-service.ts @@ -10,7 +10,7 @@ export class DatabaseService implements Contracts.Database.IDatabaseService { public connection: Contracts.Database.IConnection; public walletManager: Contracts.State.IWalletManager; public logger = app.resolve("logger"); - public emitter = app.resolve("event-dispatcher"); + public emitter = app.resolve("events"); public options: any; public wallets: Contracts.Database.IWalletsBusinessRepository; public delegates: Contracts.Database.IDelegatesBusinessRepository; diff --git a/packages/core-elasticsearch/src/index.ts b/packages/core-elasticsearch/src/index.ts index 5b2af898d0..39c24ed461 100644 --- a/packages/core-elasticsearch/src/index.ts +++ b/packages/core-elasticsearch/src/index.ts @@ -25,7 +25,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { await this.app.resolve("elasticsearch").stop(); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-elasticsearch/src/indices/base.ts b/packages/core-elasticsearch/src/indices/base.ts index f6ed7b6ff5..932b576d81 100644 --- a/packages/core-elasticsearch/src/indices/base.ts +++ b/packages/core-elasticsearch/src/indices/base.ts @@ -5,7 +5,7 @@ import { storage } from "../storage"; export abstract class Index { protected readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); protected readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); protected readonly database: Contracts.Database.IDatabaseService = app.resolve( diff --git a/packages/core-error-tracker-airbrake/src/index.ts b/packages/core-error-tracker-airbrake/src/index.ts index 4923d37357..b423f86786 100644 --- a/packages/core-error-tracker-airbrake/src/index.ts +++ b/packages/core-error-tracker-airbrake/src/index.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("error-tracker", new AirBrake(this.opts)); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-error-tracker-bugsnag/src/index.ts b/packages/core-error-tracker-bugsnag/src/index.ts index c17eb2215b..590aa6e35a 100644 --- a/packages/core-error-tracker-bugsnag/src/index.ts +++ b/packages/core-error-tracker-bugsnag/src/index.ts @@ -11,7 +11,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("error-tracker", bugsnag(this.opts as Bugsnag.IConfig)); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-error-tracker-raygun/src/index.ts b/packages/core-error-tracker-raygun/src/index.ts index db6d5bfed0..d1f935930b 100644 --- a/packages/core-error-tracker-raygun/src/index.ts +++ b/packages/core-error-tracker-raygun/src/index.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("error-tracker", new raygun.Client().init((this.opts as unknown) as raygun.raygun.RaygunOptions)); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-error-tracker-rollbar/src/index.ts b/packages/core-error-tracker-rollbar/src/index.ts index 3868284ae2..ddc6bed5cf 100644 --- a/packages/core-error-tracker-rollbar/src/index.ts +++ b/packages/core-error-tracker-rollbar/src/index.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("error-tracker", new Rollbar(this.opts)); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-error-tracker-sentry/src/index.ts b/packages/core-error-tracker-sentry/src/index.ts index 2319bff7aa..800f815080 100644 --- a/packages/core-error-tracker-sentry/src/index.ts +++ b/packages/core-error-tracker-sentry/src/index.ts @@ -9,7 +9,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("error-tracker", Sentry); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-exchange-json-rpc/src/index.ts b/packages/core-exchange-json-rpc/src/index.ts index 07a27a199f..941cafcbd7 100644 --- a/packages/core-exchange-json-rpc/src/index.ts +++ b/packages/core-exchange-json-rpc/src/index.ts @@ -30,7 +30,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-explorer/src/index.ts b/packages/core-explorer/src/index.ts index b03efc193b..57ffc78bfb 100644 --- a/packages/core-explorer/src/index.ts +++ b/packages/core-explorer/src/index.ts @@ -44,7 +44,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-forger/src/service-provider.ts b/packages/core-forger/src/service-provider.ts index 721140e569..a1b3743145 100644 --- a/packages/core-forger/src/service-provider.ts +++ b/packages/core-forger/src/service-provider.ts @@ -25,7 +25,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-kernel/src/application.ts b/packages/core-kernel/src/application.ts index 49330ee6da..5954e26891 100644 --- a/packages/core-kernel/src/application.ts +++ b/packages/core-kernel/src/application.ts @@ -1,24 +1,14 @@ -import { set } from "dottie"; -import envPaths from "env-paths"; -import expandHomeDir from "expand-home-dir"; import { existsSync, removeSync, writeFileSync } from "fs-extra"; -import camelCase from "lodash/camelCase"; -// import logProcessErrors from "log-process-errors"; -import { join, resolve } from "path"; +import { join } from "path"; import { JsonObject } from "type-fest"; +import { app } from "."; import * as Bootstrappers from "./bootstrap"; -import { ConfigFactory, ConfigRepository } from "./config"; +import { AbstractBootstrapper } from "./bootstrap/bootstrapper"; import { Container } from "./container"; import { Kernel } from "./contracts"; import * as Contracts from "./contracts"; -import { DirectoryNotFound, FailedNetworkDetection } from "./errors"; +import { DirectoryNotFound } from "./errors"; import { ProviderRepository } from "./repositories"; -import { CacheFactory } from "./services/cache"; -import { EventDispatcher } from "./services/events"; -import { LoggerFactory } from "./services/log"; -import { ConsoleLogger } from "./services/log/adapters/console"; -import { QueueFactory } from "./services/queue"; -import { AbstractServiceProvider } from "./support"; /** * @export @@ -27,26 +17,23 @@ import { AbstractServiceProvider } from "./support"; * @implements {Kernel.IApplication} */ export class Application extends Container implements Kernel.IApplication { - /** - * @private - * @type {ProviderRepository} - * @memberof Application - */ - private readonly providers: ProviderRepository = new ProviderRepository(this); - /** * @private * @type {boolean} * @memberof Application */ - private hasBeenBootstrapped: boolean = false; + private booted: boolean = false; /** - * @private - * @type {boolean} + * Creates an instance of Application. + * * @memberof Application */ - private booted: boolean = false; + public constructor() { + super(); + + this.bind("app", this); + } /** * @param {JsonObject} config @@ -54,19 +41,11 @@ export class Application extends Container implements Kernel.IApplication { * @memberof Application */ public async bootstrap(config: JsonObject): Promise { - this.registerErrorHandler(); - - await this.bindConfiguration(config); - - this.registerBindings(); + app.bind("config", config); - this.registerNamespace(); + app.singleton("providers", ProviderRepository); - this.registerPaths(); - - await this.registerFactories(); - - await this.registerServices(); + await this.runBootstrappers("app"); await this.boot(); } @@ -76,7 +55,7 @@ export class Application extends Container implements Kernel.IApplication { * @memberof Application */ public async boot(): Promise { - await this.registerServiceProviders(); + await this.runBootstrappers("serviceProviders"); this.booted = true; } @@ -88,70 +67,7 @@ export class Application extends Container implements Kernel.IApplication { public async reboot(): Promise { await this.terminate(); - await this.registerServiceProviders(); - } - - /** - * @returns {Set} - * @memberof Application - */ - public getProviders(): Set { - return this.providers; - } - - /** - * @param {AbstractServiceProvider} provider - * @returns {Promise} - * @memberof Application - */ - public async registerProvider(provider: AbstractServiceProvider): Promise { - await this.providers.register(provider); - } - - /** - * @param {AbstractServiceProvider} provider - * @returns {Promise} - * @memberof Application - */ - public async bootProvider(provider: AbstractServiceProvider): Promise { - await this.providers.boot(provider); - } - - /** - * @param {AbstractServiceProvider} provider - * @param {JsonObject} opts - * @returns {AbstractServiceProvider} - * @memberof Application - */ - public makeProvider(provider: AbstractServiceProvider, opts: JsonObject): AbstractServiceProvider { - return this.providers.make(provider, opts); - } - - /** - * @param {*} listener - * @returns {*} - * @memberof Application - */ - public afterLoadingEnvironment(listener: any): any { - return this.afterBootstrapping("LoadEnvironmentVariables", listener); - } - - /** - * @param {string} bootstrapper - * @param {*} listener - * @memberof Application - */ - public beforeBootstrapping(bootstrapper: string, listener: any): void { - this.events.listen(`bootstrapping: ${bootstrapper}`, listener); - } - - /** - * @param {string} bootstrapper - * @param {*} listener - * @memberof Application - */ - public afterBootstrapping(bootstrapper: string, listener: any): void { - this.events.listen(`bootstrapped: ${bootstrapper}`, listener); + await this.boot(); } /** @@ -358,14 +274,6 @@ export class Application extends Container implements Kernel.IApplication { return this.booted; } - /** - * @returns {boolean} - * @memberof Application - */ - public isBootstrapped(): boolean { - return this.hasBeenBootstrapped; - } - /** * @memberof Application */ @@ -403,11 +311,11 @@ export class Application extends Container implements Kernel.IApplication { * @memberof Application */ public async terminate(reason?: string, error?: Error): Promise { - this.hasBeenBootstrapped = false; + this.booted = false; - await this.disposeServiceProviders(); + this.log.notice(reason); - // @TODO: log the message + await this.disposeServiceProviders(); } /** @@ -421,115 +329,47 @@ export class Application extends Container implements Kernel.IApplication { /** * @readonly - * @type {Contracts.Blockchain.IBlockchain} + * @type {Contracts.Kernel.IEventDispatcher} * @memberof Application */ - public get blockchain(): Contracts.Blockchain.IBlockchain { - return this.resolve("blockchain"); + public get events(): Contracts.Kernel.IEventDispatcher { + return this.resolve("event"); } /** * @readonly - * @type {Contracts.P2P.IPeerService} + * @type {Contracts.Database.IDatabaseService} * @memberof Application */ - public get p2p(): Contracts.P2P.IPeerService { - return this.resolve("p2p"); + public get database(): Contracts.Database.IDatabaseService { + return this.resolve("database"); } /** * @readonly - * @type {Contracts.TransactionPool.IConnection} + * @type {Contracts.Blockchain.IBlockchain} * @memberof Application */ - public get transactionPool(): Contracts.TransactionPool.IConnection { - return this.resolve("transactionPool"); + public get blockchain(): Contracts.Blockchain.IBlockchain { + return this.resolve("blockchain"); } /** * @readonly - * @type {Contracts.Kernel.IEventDispatcher} - * @memberof Application - */ - public get events(): Contracts.Kernel.IEventDispatcher { - return this.resolve("event-dispatcher"); - } - - /** - * @private - * @memberof Application - */ - private registerErrorHandler(): void { - // @TODO: implement passing in of options and ensure handling of critical exceptions - // logProcessErrors({ exitOn: [] }); - } - - /** - * @private - * @param {JsonObject} config - * @memberof Application - */ - private async bindConfiguration(config: JsonObject): Promise { - // @TODO: pass in what config provider should be used - this.bind("configLoader", ConfigFactory.make(this, (config.configLoader || "local") as string)); - this.bind("config", new ConfigRepository(config)); - - this.resolve("config").set("options", config.options); - } - - /** - * @private - * @memberof Application - */ - private registerBindings(): void { - this.bind("app.env", this.config("env")); - this.bind("app.token", this.config("token")); - this.bind("app.network", this.config("network")); - this.bind("app.version", this.config("version")); - - // @TODO: implement a getter/setter that sets vars locally and in the process.env variables - process.env.CORE_ENV = this.config("env"); - process.env.NODE_ENV = process.env.CORE_ENV; - process.env.CORE_TOKEN = this.config("token"); - process.env.CORE_NETWORK_NAME = this.config("network"); - process.env.CORE_VERSION = this.config("version"); - } - - /** - * @private - * @memberof Application - */ - private registerNamespace(): void { - const token = this.token(); - const network = this.network(); - - if (!token || !network) { - throw new FailedNetworkDetection(); - } - - this.bind("app.namespace", `${token}-${network}`); - this.bind("app.dirPrefix", `${token}/${network}`); - } - - /** - * @private - * @returns {Promise} + * @type {Contracts.P2P.IPeerService} * @memberof Application */ - private async registerFactories(): Promise { - this.bind("factoryLogger", new LoggerFactory(this)); - this.bind("factoryCache", new CacheFactory(this)); - this.bind("factoryQueue", new QueueFactory(this)); + public get p2p(): Contracts.P2P.IPeerService { + return this.resolve("p2p"); } /** - * @private - * @returns {Promise} + * @readonly + * @type {Contracts.TransactionPool.IConnection} * @memberof Application */ - private async registerServices(): Promise { - this.bind("event-dispatcher", new EventDispatcher()); - this.bind("log", await this.resolve("factoryLogger").make(new ConsoleLogger())); + public get transactionPool(): Contracts.TransactionPool.IConnection { + return this.resolve("transaction-pool"); } /** @@ -537,15 +377,12 @@ export class Application extends Container implements Kernel.IApplication { * @returns {Promise} * @memberof Application */ - private async registerServiceProviders(): Promise { - this.hasBeenBootstrapped = true; - - for (const Bootstrapper of Object.values(Bootstrappers)) { - this.events.dispatch(`bootstrapping: ${Bootstrapper.name}`, this); - - await new Bootstrapper().bootstrap(this); + private async runBootstrappers(type: string): Promise { + const bootstrappers: AbstractBootstrapper[] = Object.values(Bootstrappers[type]); - this.events.dispatch(`bootstrapped: ${Bootstrapper.name}`, this); + for (const Bootstrapper of bootstrappers) { + // @ts-ignore + await new Bootstrapper(this).bootstrap(); } } @@ -555,33 +392,11 @@ export class Application extends Container implements Kernel.IApplication { * @memberof Application */ private async disposeServiceProviders(): Promise { - for (const provider of this.getProviders()) { + for (const provider of app.resolve("providers").allLoadedProviders()) { await provider.dispose(); } } - /** - * @private - * @memberof Application - */ - private registerPaths(): void { - const paths: Array<[string, string]> = Object.entries(envPaths(this.token(), { suffix: "core" })); - - for (let [type, path] of paths) { - const processPath: string | null = process.env[`CORE_PATH_${type.toUpperCase()}`]; - - if (processPath) { - path = resolve(expandHomeDir(processPath)); - } - - set(process.env, `CORE_PATH_${type.toUpperCase()}`, path); - - this[camelCase(`use_${type}_path`)](path); - - this.bind(`path.${type}`, path); - } - } - /** * @private * @param {string} type diff --git a/packages/core-kernel/src/bootstrap/app/index.ts b/packages/core-kernel/src/bootstrap/app/index.ts new file mode 100644 index 0000000000..22c8c19deb --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/index.ts @@ -0,0 +1,14 @@ +export * from "./load-error-handler"; + +export * from "./load-factories"; +export * from "./load-services"; + +export * from "./load-bindings"; +export * from "./load-namespace"; +export * from "./load-paths"; + +export * from "./load-environment-variables"; +export * from "./load-configuration"; +export * from "./load-cryptography"; + +export * from "./load-service-providers"; diff --git a/packages/core-kernel/src/bootstrap/app/load-bindings.ts b/packages/core-kernel/src/bootstrap/app/load-bindings.ts new file mode 100644 index 0000000000..45ad8d740b --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-bindings.ts @@ -0,0 +1,26 @@ +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadBindings + */ +export class LoadBindings extends AbstractBootstrapper { + /** + * @param {Kernel.IApplication} app + * @returns {Promise} + * @memberof LoadBindings + */ + public async bootstrap(): Promise { + this.app.bind("app.env", this.app.config("env")); + this.app.bind("app.token", this.app.config("token")); + this.app.bind("app.network", this.app.config("network")); + this.app.bind("app.version", this.app.config("version")); + + // @TODO: implement a getter/setter that sets vars locally and in the process.env variables + process.env.CORE_ENV = this.app.config("env"); + process.env.NODE_ENV = process.env.CORE_ENV; + process.env.CORE_TOKEN = this.app.config("token"); + process.env.CORE_NETWORK_NAME = this.app.config("network"); + process.env.CORE_VERSION = this.app.config("version"); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-configuration.ts b/packages/core-kernel/src/bootstrap/app/load-configuration.ts new file mode 100644 index 0000000000..95417e9c7e --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-configuration.ts @@ -0,0 +1,22 @@ +import { JsonObject } from "type-fest"; +import { ConfigRepository } from "../../config"; +import { IConfigAdapter } from "../../contracts/core-kernel"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadConfiguration + */ +export class LoadConfiguration extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadConfiguration + */ + public async bootstrap(): Promise { + const config: JsonObject = this.app.resolve("config"); + + this.app.resolve("config").set("options", config.options || {}); + + await this.app.resolve("configLoader").loadConfiguration(); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-cryptography.ts b/packages/core-kernel/src/bootstrap/app/load-cryptography.ts new file mode 100644 index 0000000000..ee19daec3d --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-cryptography.ts @@ -0,0 +1,30 @@ +import { Managers } from "@arkecosystem/crypto"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadCryptography + */ +export class LoadCryptography extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadCryptography + */ + public async bootstrap(): Promise { + this.configure(Managers.NetworkManager.findByName(this.app.network() as any)); + } + + /** + * @private + * @param {*} config + * @memberof LoadCryptography + */ + private configure(config: any): void { + Managers.configManager.setConfig(config); + + this.app.bind("crypto.network", Managers.configManager.all()); + this.app.bind("crypto.exceptions", Managers.configManager.get("exceptions")); + this.app.bind("crypto.milestones", Managers.configManager.get("milestones")); + this.app.bind("crypto.genesisBlock", Managers.configManager.get("genesisBlock")); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-environment-variables.ts b/packages/core-kernel/src/bootstrap/app/load-environment-variables.ts new file mode 100644 index 0000000000..c30099096f --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-environment-variables.ts @@ -0,0 +1,16 @@ +import { Kernel } from "../../contracts"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadEnvironmentVariables + */ +export class LoadEnvironmentVariables extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadEnvironmentVariables + */ + public async bootstrap(): Promise { + await this.app.resolve("configLoader").loadEnvironmentVariables(); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-error-handler.ts b/packages/core-kernel/src/bootstrap/app/load-error-handler.ts new file mode 100644 index 0000000000..968b03b171 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-error-handler.ts @@ -0,0 +1,17 @@ +// import logProcessErrors from "log-process-errors"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadErrorHandler + */ +export class LoadErrorHandler extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadErrorHandler + */ + public async bootstrap(): Promise { + // @TODO: implement passing in of options and ensure handling of critical exceptions + // logProcessErrors({ exitOn: [] }); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-factories.ts b/packages/core-kernel/src/bootstrap/app/load-factories.ts new file mode 100644 index 0000000000..d8fac78a24 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-factories.ts @@ -0,0 +1,20 @@ +import { CacheFactory } from "../../services/cache"; +import { LoggerFactory } from "../../services/log"; +import { QueueFactory } from "../../services/queue"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadFactories + */ +export class LoadFactories extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadFactories + */ + public async bootstrap(): Promise { + this.app.bind("factoryLogger", new LoggerFactory(this.app)); + this.app.bind("factoryCache", new CacheFactory(this.app)); + this.app.bind("factoryQueue", new QueueFactory(this.app)); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-namespace.ts b/packages/core-kernel/src/bootstrap/app/load-namespace.ts new file mode 100644 index 0000000000..d0ae48b8d1 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-namespace.ts @@ -0,0 +1,24 @@ +import { FailedNetworkDetection } from "../../errors"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadNamespace + */ +export class LoadNamespace extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadNamespace + */ + public async bootstrap(): Promise { + const token: string = this.app.token(); + const network: string = this.app.network(); + + if (!token || !network) { + throw new FailedNetworkDetection(); + } + + this.app.bind("app.namespace", `${token}-${network}`); + this.app.bind("app.dirPrefix", `${token}/${network}`); + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-paths.ts b/packages/core-kernel/src/bootstrap/app/load-paths.ts new file mode 100644 index 0000000000..5d9f46a249 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-paths.ts @@ -0,0 +1,37 @@ +import { set } from "dottie"; +import envPaths from "env-paths"; +import expandHomeDir from "expand-home-dir"; +import { ensureDirSync } from "fs-extra"; +import camelCase from "lodash/camelCase"; +import { resolve } from "path"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadPaths + */ +export class LoadPaths extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadPaths + */ + public async bootstrap(): Promise { + const paths: Array<[string, string]> = Object.entries(envPaths(this.app.token(), { suffix: "core" })); + + for (let [type, path] of paths) { + const processPath: string | null = process.env[`CORE_PATH_${type.toUpperCase()}`]; + + if (processPath) { + path = resolve(expandHomeDir(processPath)); + } + + ensureDirSync(path); + + set(process.env, `CORE_PATH_${type.toUpperCase()}`, path); + + this.app[camelCase(`use_${type}_path`)](path); + + this.app.bind(`path.${type}`, path); + } + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-service-providers.ts b/packages/core-kernel/src/bootstrap/app/load-service-providers.ts new file mode 100644 index 0000000000..088d67526b --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-service-providers.ts @@ -0,0 +1,22 @@ +import { ProviderRepository } from "../../repositories"; +import { AbstractServiceProvider } from "../../support"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadServiceProviders + * @extends {AbstractBootstrapper} + */ +export class LoadServiceProviders extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof RegisterProviders + */ + public async bootstrap(): Promise { + for (const [pkg, opts] of Object.entries(this.app.config("providers"))) { + const provider: AbstractServiceProvider = new (require(pkg)).ServiceProvider(this.app, opts); + + this.app.resolve("providers").set(pkg, provider); + } + } +} diff --git a/packages/core-kernel/src/bootstrap/app/load-services.ts b/packages/core-kernel/src/bootstrap/app/load-services.ts new file mode 100644 index 0000000000..15cfadc39a --- /dev/null +++ b/packages/core-kernel/src/bootstrap/app/load-services.ts @@ -0,0 +1,57 @@ +import { JsonObject } from "type-fest"; +import { ConfigFactory, ConfigRepository } from "../../config"; +import { IConfigAdapter } from "../../contracts/core-kernel"; +import { EventDispatcher } from "../../services/events"; +import { LoggerFactory } from "../../services/log"; +import { ConsoleLogger } from "../../services/log/adapters/console"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class LoadServices + */ +export class LoadServices extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof LoadServices + */ + public async bootstrap(): Promise { + this.registerEventDispatcher(); + + await this.registerLogger(); + + this.registerConfigLoader(); + } + + /** + * @private + * @memberof LoadServices + */ + private registerEventDispatcher(): void { + this.app.singleton("events", EventDispatcher); + } + + /** + * @private + * @returns {Promise} + * @memberof LoadServices + */ + private async registerLogger(): Promise { + this.app.bind("logger", await this.app.resolve("factoryLogger").make(new ConsoleLogger())); + } + + /** + * @private + * @memberof LoadServices + */ + private registerConfigLoader(): void { + const config: JsonObject = this.app.resolve("config"); + + this.app.bind( + "configLoader", + ConfigFactory.make(this.app, (config.configLoader || "local") as string), + ); + + this.app.bind("config", new ConfigRepository(config)); + } +} diff --git a/packages/core-kernel/src/bootstrap/boot-providers.ts b/packages/core-kernel/src/bootstrap/boot-providers.ts deleted file mode 100644 index 84c36382eb..0000000000 --- a/packages/core-kernel/src/bootstrap/boot-providers.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Kernel } from "../contracts"; - -/** - * @export - * @class RegisterProviders - */ -export class BootProviders { - /** - * @param {Kernel.IApplication} app - * @returns {Promise} - * @memberof RegisterProviders - */ - public async bootstrap(app: Kernel.IApplication): Promise { - console.log(app); - } -} diff --git a/packages/core-kernel/src/bootstrap/bootstrapper.ts b/packages/core-kernel/src/bootstrap/bootstrapper.ts new file mode 100644 index 0000000000..ca43d47fd5 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/bootstrapper.ts @@ -0,0 +1,16 @@ +import { Kernel } from "../contracts"; + +/** + * @export + * @abstract + * @class AbstractBootstrapper + */ +export abstract class AbstractBootstrapper { + /** + * Creates an instance of AbstractBootstrapper. + * + * @param {Kernel.IApplication} app + * @memberof AbstractBootstrapper + */ + public constructor(protected readonly app: Kernel.IApplication) {} +} diff --git a/packages/core-kernel/src/bootstrap/index.ts b/packages/core-kernel/src/bootstrap/index.ts index 883ff38242..50f71be0ea 100644 --- a/packages/core-kernel/src/bootstrap/index.ts +++ b/packages/core-kernel/src/bootstrap/index.ts @@ -1,5 +1,4 @@ -export * from "./load-environment-variables"; -export * from "./load-configuration"; -export * from "./load-cryptography"; -export * from "./register-providers"; -// export * from "./boot-providers"; +import * as app from "./app"; +import * as serviceProviders from "./service-providers"; + +export { app, serviceProviders }; diff --git a/packages/core-kernel/src/bootstrap/load-configuration.ts b/packages/core-kernel/src/bootstrap/load-configuration.ts deleted file mode 100644 index e43dd24418..0000000000 --- a/packages/core-kernel/src/bootstrap/load-configuration.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Kernel } from "../contracts"; - -/** - * @export - * @class LoadConfiguration - */ -export class LoadConfiguration { - /** - * @param {Kernel.IApplication} app - * @returns {Promise} - * @memberof LoadConfiguration - */ - public async bootstrap(app: Kernel.IApplication): Promise { - await app.resolve("configLoader").loadConfiguration(); - } -} diff --git a/packages/core-kernel/src/bootstrap/load-cryptography.ts b/packages/core-kernel/src/bootstrap/load-cryptography.ts deleted file mode 100644 index 2a8452d283..0000000000 --- a/packages/core-kernel/src/bootstrap/load-cryptography.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Managers } from "@arkecosystem/crypto"; -import { Kernel } from "../contracts"; - -/** - * @export - * @class LoadCryptography - */ -export class LoadCryptography { - /** - * @param {Kernel.IApplication} app - * @returns {Promise} - * @memberof LoadCryptography - */ - public async bootstrap(app: Kernel.IApplication): Promise { - this.configure(app, Managers.NetworkManager.findByName(app.network() as any)); - } - - /** - * @private - * @param {Kernel.IApplication} app - * @param {*} config - * @memberof LoadCryptography - */ - private configure(app: Kernel.IApplication, config: any): void { - Managers.configManager.setConfig(config); - - app.bind("crypto.network", Managers.configManager.all()); - app.bind("crypto.exceptions", Managers.configManager.get("exceptions")); - app.bind("crypto.milestones", Managers.configManager.get("milestones")); - app.bind("crypto.genesisBlock", Managers.configManager.get("genesisBlock")); - } -} diff --git a/packages/core-kernel/src/bootstrap/load-environment-variables.ts b/packages/core-kernel/src/bootstrap/load-environment-variables.ts deleted file mode 100644 index 5d5b1519f7..0000000000 --- a/packages/core-kernel/src/bootstrap/load-environment-variables.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Kernel } from "../contracts"; - -/** - * @export - * @class LoadEnvironmentVariables - */ -export class LoadEnvironmentVariables { - /** - * @param {Kernel.IApplication} app - * @returns {Promise} - * @memberof LoadEnvironmentVariables - */ - public async bootstrap(app: Kernel.IApplication): Promise { - await app.resolve("configLoader").loadEnvironmentVariables(); - } -} diff --git a/packages/core-kernel/src/bootstrap/register-providers.ts b/packages/core-kernel/src/bootstrap/register-providers.ts deleted file mode 100644 index e6bf8d33ce..0000000000 --- a/packages/core-kernel/src/bootstrap/register-providers.ts +++ /dev/null @@ -1,60 +0,0 @@ -import semver from "semver"; -import { JsonObject } from "type-fest"; -import { Kernel } from "../contracts"; -import { FailedDependencySatisfaction, FailedServiceProviderRegistration } from "../errors"; -import { AbstractServiceProvider } from "../support/service-provider"; - -/** - * @export - * @class RegisterProviders - */ -export class RegisterProviders { - /** - * @param {Kernel.IApplication} app - * @returns {Promise} - * @memberof RegisterProviders - */ - public async bootstrap(app: Kernel.IApplication): Promise { - const providers: JsonObject = app.config("providers"); - - for (const [pkg, opts] of Object.entries(providers)) { - const { ServiceProvider } = require(pkg); - - const serviceProvider: AbstractServiceProvider = app.makeProvider(ServiceProvider, opts as JsonObject); - - if (this.satisfiesDependencies(app, serviceProvider)) { - await app.registerProvider(serviceProvider); - } - } - } - - /** - * @private - * @param {Kernel.IApplication} app - * @param {AbstractServiceProvider} serviceProvider - * @returns {boolean} - * @memberof RegisterProviders - */ - private satisfiesDependencies(app: Kernel.IApplication, serviceProvider: AbstractServiceProvider): boolean { - const dependencies = serviceProvider.depends(); - - if (!dependencies) { - return true; - } - - for (const [dep, version] of Object.entries(dependencies)) { - if (!app.has(dep)) { - throw new FailedServiceProviderRegistration(serviceProvider.getName(), dep); - } - - // @ts-ignore - const constraint = app.resolve(dep).getVersion(); - - if (semver.satisfies(constraint, version)) { - throw new FailedDependencySatisfaction(dep, constraint, version); - } - } - - return true; - } -} diff --git a/packages/core-kernel/src/bootstrap/service-providers/boot-service-providers.ts b/packages/core-kernel/src/bootstrap/service-providers/boot-service-providers.ts new file mode 100644 index 0000000000..7d8b159f39 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/service-providers/boot-service-providers.ts @@ -0,0 +1,20 @@ +import { ProviderRepository } from "../../repositories"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class RegisterProviders + */ +export class BootServiceProviders extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof RegisterProviders + */ + public async bootstrap(): Promise { + const repository: ProviderRepository = this.app.resolve("providers"); + + for (const [name] of repository.all()) { + await repository.boot(name); + } + } +} diff --git a/packages/core-kernel/src/bootstrap/service-providers/index.ts b/packages/core-kernel/src/bootstrap/service-providers/index.ts new file mode 100644 index 0000000000..873eef6e72 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/service-providers/index.ts @@ -0,0 +1,2 @@ +export * from "./register-service-providers"; +export * from "./boot-service-providers"; diff --git a/packages/core-kernel/src/bootstrap/service-providers/register-service-providers.ts b/packages/core-kernel/src/bootstrap/service-providers/register-service-providers.ts new file mode 100644 index 0000000000..b2a19e3ab6 --- /dev/null +++ b/packages/core-kernel/src/bootstrap/service-providers/register-service-providers.ts @@ -0,0 +1,57 @@ +import semver from "semver"; +import { FailedDependencySatisfaction, FailedServiceProviderRegistration } from "../../errors"; +import { ProviderRepository } from "../../repositories"; +import { AbstractServiceProvider } from "../../support/service-provider"; +import { AbstractBootstrapper } from "../bootstrapper"; + +/** + * @export + * @class RegisterServiceProviders + * @extends {AbstractBootstrapper} + */ +export class RegisterServiceProviders extends AbstractBootstrapper { + /** + * @returns {Promise} + * @memberof RegisterProviders + */ + public async bootstrap(): Promise { + const providers: ProviderRepository = this.app.resolve("providers"); + + for (const [name, serviceProvider] of providers.all()) { + if (this.satisfiesDependencies(serviceProvider)) { + // @TODO: check conditional state and mark as either deferred or failed + // @TODO: check dependencies and either register or mark as failed + + await providers.register(name); + } + } + } + + /** + * @private + * @param {AbstractServiceProvider} serviceProvider + * @returns {boolean} + * @memberof RegisterProviders + */ + private satisfiesDependencies(serviceProvider: AbstractServiceProvider): boolean { + const dependencies: Record = serviceProvider.depends(); + + if (!dependencies) { + return true; + } + + for (const [dep, version] of Object.entries(dependencies)) { + if (!this.app.has(dep)) { + throw new FailedServiceProviderRegistration(serviceProvider.getName(), dep); + } + + const constraint = this.app.resolve(dep).getVersion(); + + if (semver.satisfies(constraint, version)) { + throw new FailedDependencySatisfaction(dep, constraint, version); + } + } + + return true; + } +} diff --git a/packages/core-kernel/src/config/adapters/base.ts b/packages/core-kernel/src/config/adapters/base.ts deleted file mode 100644 index c36cb504a7..0000000000 --- a/packages/core-kernel/src/config/adapters/base.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Kernel } from "../../contracts"; - -/** - * @export - * @abstract - * @class BaseAdapter - */ -export abstract class BaseAdapter { - /** - * @param {Kernel.IApplication} app - * @memberof BaseAdapter - */ - public constructor(protected readonly app: Kernel.IApplication) {} - - /** - * @abstract - * @returns {Promise} - * @memberof BaseAdapter - */ - public abstract async loadConfiguration(): Promise; - - /** - * @abstract - * @returns {Promise} - * @memberof BaseAdapter - */ - public abstract async loadEnvironmentVariables(): Promise; -} diff --git a/packages/core-kernel/src/config/adapters/local.ts b/packages/core-kernel/src/config/adapters/local.ts index c247c0d350..18b1bb0516 100644 --- a/packages/core-kernel/src/config/adapters/local.ts +++ b/packages/core-kernel/src/config/adapters/local.ts @@ -1,33 +1,34 @@ import cosmiconfig from "cosmiconfig"; import { set } from "dottie"; import { parseFileSync } from "envfile"; +import { JsonObject } from "type-fest"; +import { Kernel } from "../../contracts"; import { InvalidApplicationConfiguration, InvalidEnvironmentConfiguration } from "../../errors"; -import { BaseAdapter } from "./base"; /** * @export * @class LocalAdapter - * @extends {BaseAdapter} + * @implements {Kernel.IConfigAdapter} */ -export class LocalAdapter extends BaseAdapter { +export class LocalAdapter implements Kernel.IConfigAdapter { + /** + * @param {Kernel.IApplication} app + * @memberof BaseAdapter + */ + public constructor(protected readonly app: Kernel.IApplication) {} + /** * @returns {Promise} * @memberof LocalAdapter */ public async loadConfiguration(): Promise { - // @TODO: move this to run before `loadConfiguration` in a bootstraper - await this.loadEnvironmentVariables(); - try { - const explorer = cosmiconfig(this.app.namespace(), { - searchPlaces: [this.app.configPath("config.json"), this.app.configPath("config.js")], - stopDir: this.app.configPath(), - }); + await this.loadServiceProviders(); - for (const [key, value] of Object.entries(explorer.searchSync().config)) { - this.app.config(key, value); - } - } catch (error) { + await this.loadPeers(); + + await this.loadDelegates(); + } catch { throw new InvalidApplicationConfiguration(); } } @@ -52,4 +53,50 @@ export class LocalAdapter extends BaseAdapter { throw new InvalidEnvironmentConfiguration(); } } + + /** + * @private + * @returns {Promise} + * @memberof LocalAdapter + */ + private async loadServiceProviders(): Promise { + this.app.config( + "providers", + this.loadFromLocation([ + this.app.configPath("service-providers.json"), + this.app.configPath("service-providers.js"), + ]), + ); + } + + /** + * @private + * @returns {Promise} + * @memberof LocalAdapter + */ + private async loadPeers(): Promise { + this.app.config("peers", this.loadFromLocation([this.app.configPath("peers.json")])); + } + + /** + * @private + * @returns {Promise} + * @memberof LocalAdapter + */ + private async loadDelegates(): Promise { + this.app.config("delegates", this.loadFromLocation([this.app.configPath("delegates.json")])); + } + + /** + * @private + * @param {string[]} searchPlaces + * @returns {JsonObject} + * @memberof LocalAdapter + */ + private loadFromLocation(searchPlaces: string[]): JsonObject { + return cosmiconfig(this.app.namespace(), { + searchPlaces, + stopDir: this.app.configPath(), + }).searchSync().config; + } } diff --git a/packages/core-kernel/src/config/adapters/remote.ts b/packages/core-kernel/src/config/adapters/remote.ts index 5f9bc7c988..8d6b967165 100644 --- a/packages/core-kernel/src/config/adapters/remote.ts +++ b/packages/core-kernel/src/config/adapters/remote.ts @@ -1,11 +1,17 @@ -import { BaseAdapter } from "./base"; +import { Kernel } from "../../contracts"; /** * @export * @class RemoteAdapter - * @extends {BaseAdapter} + * @implements {Kernel.IConfigAdapter} */ -export class RemoteAdapter extends BaseAdapter { +export class RemoteAdapter implements Kernel.IConfigAdapter { + /** + * @param {Kernel.IApplication} app + * @memberof BaseAdapter + */ + public constructor(protected readonly app: Kernel.IApplication) {} + /** * @returns {Promise} * @memberof RemoteAdapter diff --git a/packages/core-kernel/src/config/factory.ts b/packages/core-kernel/src/config/factory.ts index 48905e5526..e613dadfd7 100644 --- a/packages/core-kernel/src/config/factory.ts +++ b/packages/core-kernel/src/config/factory.ts @@ -1,7 +1,5 @@ import { Kernel } from "../contracts"; -import { InvalidConfigurationAdapter } from "../errors"; import { LocalAdapter, RemoteAdapter } from "./adapters"; -import { BaseAdapter } from "./adapters/base"; /** * @export @@ -12,18 +10,14 @@ export class ConfigFactory { * @static * @param {Kernel.IApplication} app * @param {string} adapter - * @returns {Record} + * @returns {Record} * @memberof ConfigFactory */ - public static make(app: Kernel.IApplication, adapter: string): BaseAdapter { - try { - if (adapter === "remote") { - return new RemoteAdapter(app); - } - - return new LocalAdapter(app); - } catch (error) { - throw new InvalidConfigurationAdapter(); + public static make(app: Kernel.IApplication, adapter: string): Kernel.IConfigAdapter { + if (adapter === "remote") { + return new RemoteAdapter(app); } + + return new LocalAdapter(app); } } diff --git a/packages/core-kernel/src/container.ts b/packages/core-kernel/src/container.ts index 6ffd36d633..8e9b7dee48 100644 --- a/packages/core-kernel/src/container.ts +++ b/packages/core-kernel/src/container.ts @@ -14,7 +14,7 @@ import { Resolver, } from "awilix"; import { isClass, isFunction } from "typechecker"; -import { EntryDoesNotExist, InvalidType } from "./errors"; +import { InvalidType } from "./errors"; /** * @export @@ -39,10 +39,6 @@ export class Container { * @memberof Container */ public resolve(name: string): T { - if (!this.has(name)) { - throw new EntryDoesNotExist(name); - } - return this.container.resolve(name); } @@ -80,7 +76,7 @@ export class Container { * @param {ClassOrFunctionReturning} concrete * @memberof Container */ - public shared(name: string, concrete: ClassOrFunctionReturning): void { + public singleton(name: string, concrete: ClassOrFunctionReturning): void { let binding: BuildResolver & DisposableResolver; if (isClass(concrete)) { @@ -88,10 +84,10 @@ export class Container { } else if (isFunction(concrete)) { binding = asFunction(concrete as FunctionReturning); } else { - throw new InvalidType("shared", "concrete", "class or function", typeof concrete); + throw new InvalidType("singleton", "concrete", "class or function", typeof concrete); } - this.container.register(name, binding.singleton()); + this.container.register(name, binding.singleton()); } /** diff --git a/packages/core-kernel/src/contracts/core-kernel/application.ts b/packages/core-kernel/src/contracts/core-kernel/application.ts index 7f774c9e25..ad9f181c1a 100644 --- a/packages/core-kernel/src/contracts/core-kernel/application.ts +++ b/packages/core-kernel/src/contracts/core-kernel/application.ts @@ -1,6 +1,6 @@ import { JsonObject } from "type-fest"; -import { AbstractServiceProvider } from "../../support"; import { IBlockchain } from "../core-blockchain"; +import { IDatabaseService } from "../core-database"; import { IPeerService } from "../core-p2p"; import { IConnection } from "../core-transaction-pool"; import { IContainer } from "./container"; @@ -13,6 +13,16 @@ export interface IApplication extends IContainer { */ readonly log: ILogger; + /** + * Get an instance of the application event dispatcher. + */ + readonly events: IEventDispatcher; + + /** + * Get an instance of the application database. + */ + readonly database: IDatabaseService; + /** * Get an instance of the application blockchain. */ @@ -28,11 +38,6 @@ export interface IApplication extends IContainer { */ readonly transactionPool: IConnection; - /** - * Get an instance of the application event dispatcher. - */ - readonly events: IEventDispatcher; - /** * Bootstrap the application with the given configuration. */ @@ -48,36 +53,6 @@ export interface IApplication extends IContainer { */ reboot(): void; - /** - * Get the registered service provider instances if any exist. - */ - getProviders(): Set; - - /** - * Register the application service provider. - */ - registerProvider(provider: AbstractServiceProvider): Promise; - - /** - * Create a new provider instance. - */ - makeProvider(provider: AbstractServiceProvider, opts: JsonObject): AbstractServiceProvider; - - /** - * Register a listener to run after loading the environment. - */ - afterLoadingEnvironment(listener: any): any; - - /** - * Register a listener to run before a bootstrapper. - */ - beforeBootstrapping(bootstrapper: string, listener: any): void; - - /** - * Register a listener to run after a bootstrapper. - */ - afterBootstrapping(bootstrapper: string, listener: any): void; - /** * Get or set the specified configuration value. */ @@ -193,11 +168,6 @@ export interface IApplication extends IContainer { */ isBooted(): boolean; - /** - * Determine if the application has been bootstrapped. - */ - isBootstrapped(): boolean; - /** * Put the application into maintenance mode. */ diff --git a/packages/core-kernel/src/contracts/core-kernel/config.ts b/packages/core-kernel/src/contracts/core-kernel/config.ts new file mode 100644 index 0000000000..a23a812dd1 --- /dev/null +++ b/packages/core-kernel/src/contracts/core-kernel/config.ts @@ -0,0 +1,9 @@ +/** + * @export + * @interface IConfigAdapter + */ +export interface IConfigAdapter { + loadConfiguration(): Promise; + + loadEnvironmentVariables(): Promise; +} diff --git a/packages/core-kernel/src/contracts/core-kernel/container.ts b/packages/core-kernel/src/contracts/core-kernel/container.ts index 87518a4966..23e09050ad 100644 --- a/packages/core-kernel/src/contracts/core-kernel/container.ts +++ b/packages/core-kernel/src/contracts/core-kernel/container.ts @@ -1,4 +1,4 @@ -import { BuildResolverOptions, Constructor, FunctionReturning, Resolver } from "awilix"; +import { BuildResolverOptions, ClassOrFunctionReturning, Resolver } from "awilix"; export interface IContainer { /** @@ -9,12 +9,12 @@ export interface IContainer { /** * Register a class within the container. */ - bind(name: string, concrete: any): void; + bind(name: string, concrete: T | ClassOrFunctionReturning): void; /** * Register a class within the container. */ - shared(name: string, concrete: any): void; + singleton(name: string, concrete: ClassOrFunctionReturning): void; /** * Alias a registration to a different name. @@ -29,8 +29,5 @@ export interface IContainer { /** * Given a class or function, builds it up and returns it. */ - call( - targetOrResolver: FunctionReturning<{}> | Constructor<{}> | Resolver<{}>, - opts?: BuildResolverOptions<{}>, - ): any; + call(targetOrResolver: ClassOrFunctionReturning | Resolver, opts?: BuildResolverOptions<{}>): any; } diff --git a/packages/core-kernel/src/contracts/core-kernel/event-dispatcher.ts b/packages/core-kernel/src/contracts/core-kernel/event-dispatcher.ts index f2bcfa5b67..f0b3b375e6 100644 --- a/packages/core-kernel/src/contracts/core-kernel/event-dispatcher.ts +++ b/packages/core-kernel/src/contracts/core-kernel/event-dispatcher.ts @@ -1,5 +1,4 @@ -export type EventName = string | symbol; -export type EventListener = (name: EventName, data: any) => void; +import { EventListener, EventName } from "../../types"; export interface IEventDispatcher { /** diff --git a/packages/core-kernel/src/contracts/core-kernel/index.ts b/packages/core-kernel/src/contracts/core-kernel/index.ts index 24df62bfa6..f4f4108d75 100644 --- a/packages/core-kernel/src/contracts/core-kernel/index.ts +++ b/packages/core-kernel/src/contracts/core-kernel/index.ts @@ -1,5 +1,6 @@ export * from "./application"; export * from "./cache"; +export * from "./config"; export * from "./container"; export * from "./event-dispatcher"; export * from "./logger"; diff --git a/packages/core-kernel/src/errors.ts b/packages/core-kernel/src/errors.ts index 3c99f7e22e..0f381a8f1f 100644 --- a/packages/core-kernel/src/errors.ts +++ b/packages/core-kernel/src/errors.ts @@ -42,66 +42,6 @@ export class DirectoryNotFound extends KernelError { } } -/** - * @export - * @class EntryAlreadyExists - * @extends {KernelError} - */ -export class EntryAlreadyExists extends KernelError { - /** - * @param {string} value - * @memberof EntryAlreadyExists - */ - constructor(value: string) { - super(`[${value}] is not registered.`); - } -} - -/** - * @export - * @class EntryDoesNotExist - * @extends {KernelError} - */ -export class EntryDoesNotExist extends KernelError { - /** - * @param {string} value - * @memberof EntryDoesNotExist - */ - constructor(value: string) { - super(`[${value}] is not registered.`); - } -} - -/** - * @export - * @class FileNotFound - * @extends {KernelError} - */ -export class FileNotFound extends KernelError { - /** - * @param {string} value - * @memberof FileNotFound - */ - constructor(value: string) { - super(`File [${value}] could not be found.`); - } -} - -/** - * @export - * @class InvalidArgument - * @extends {KernelError} - */ -export class InvalidArgument extends KernelError { - /** - * @param {*} value - * @memberof InvalidArgument - */ - constructor(value: any) { - super(`[${value.toString()}] is an invalid argument.`); - } -} - /** * @export * @class InvalidType @@ -165,20 +105,6 @@ export class InvalidEnvironmentConfiguration extends KernelError { } } -/** - * @export - * @class InvalidConfigurationAdapter - * @extends {KernelError} - */ -export class InvalidConfigurationAdapter extends KernelError { - /** - * @memberof InvalidConfigurationAdapter - */ - constructor() { - super("Unable to load the environment file."); - } -} - /** * @export * @class FailedNetworkDetection diff --git a/packages/core-kernel/src/repositories/provider.ts b/packages/core-kernel/src/repositories/provider.ts index 226415e9f0..b045358068 100644 --- a/packages/core-kernel/src/repositories/provider.ts +++ b/packages/core-kernel/src/repositories/provider.ts @@ -1,48 +1,129 @@ -import { IApplication } from "../contracts/core-kernel"; import { AbstractServiceProvider } from "../support"; /** * @export * @class ProviderRepository - * @extends {Set} */ -export class ProviderRepository extends Set { +export class ProviderRepository { /** - * @param {IApplication} app + * All of the registered service providers. + * + * @private + * @type {Map} * @memberof ProviderRepository */ - public constructor(private readonly app: IApplication) { - super(); + private readonly serviceProviders: Map = new Map< + string, + AbstractServiceProvider + >(); + + /** + * The names of the loaded service providers. + * + * @private + * @type {Set} + * @memberof ProviderRepository + */ + private readonly loadedProviders: Set = new Set(); + + /** + * The names of the failed service providers. + * + * @private + * @type {Map} + * @memberof ProviderRepository + */ + private readonly failedProviders: Set = new Set(); + + /** + * The names of the deferred service providers. + * + * @private + * @type {Map} + * @memberof ProviderRepository + */ + private readonly deferredProviders: Set = new Set(); + + /** + * @returns {Array<[string, AbstractServiceProvider]>} + * @memberof ProviderRepository + */ + public all(): Array<[string, AbstractServiceProvider]> { + return Array.from(this.serviceProviders.entries()); } /** - * @param {AbstractServiceProvider} provider - * @returns {Promise} + * @returns {AbstractServiceProvider[]} * @memberof ProviderRepository */ - public async register(provider: AbstractServiceProvider): Promise { - await provider.register(); + public allServiceProviders(): AbstractServiceProvider[] { + return Array.from(this.serviceProviders.values()); + } - this.add(provider); + /** + * @returns {AbstractServiceProvider[]} + * @memberof ProviderRepository + */ + public allLoadedProviders(): AbstractServiceProvider[] { + return Array.from(this.loadedProviders.values()).map((name: string) => this.get(name)); } /** + * @returns {AbstractServiceProvider[]} + * @memberof ProviderRepository + */ + public allFailedProviders(): AbstractServiceProvider[] { + return Array.from(this.failedProviders.values()).map((name: string) => this.get(name)); + } + + /** + * @returns {AbstractServiceProvider[]} + * @memberof ProviderRepository + */ + public allDeferredProviders(): AbstractServiceProvider[] { + return Array.from(this.deferredProviders.values()).map((name: string) => this.get(name)); + } + + /** + * @param {string} name + * @returns {AbstractServiceProvider} + * @memberof ProviderRepository + */ + public get(name: string): AbstractServiceProvider { + return this.serviceProviders.get(name); + } + + /** + * + * @param {string} name + * @param {AbstractServiceProvider} provider + * @memberof ProviderRepository + */ + public set(name: string, provider: AbstractServiceProvider): void { + this.serviceProviders.set(name, provider); + } + + /** + * Register the given provider. + * * @param {AbstractServiceProvider} provider * @returns {Promise} * @memberof ProviderRepository */ - public async boot(provider: AbstractServiceProvider): Promise { - await provider.boot(); + public async register(name: string): Promise { + await this.serviceProviders.get(name).register(); } /** + * Boot the given provider. + * * @param {AbstractServiceProvider} provider - * @param {Record} opts - * @returns {AbstractServiceProvider} + * @returns {Promise} * @memberof ProviderRepository */ - public make(provider: AbstractServiceProvider, opts: Record): AbstractServiceProvider { - // @ts-ignore - return new provider(this.app, opts); + public async boot(name: string): Promise { + await this.serviceProviders.get(name).boot(); + + this.loadedProviders.add(name); } } diff --git a/packages/core-kernel/src/services/events/dispatcher.ts b/packages/core-kernel/src/services/events/dispatcher.ts index 74403e1d29..6214a4f205 100644 --- a/packages/core-kernel/src/services/events/dispatcher.ts +++ b/packages/core-kernel/src/services/events/dispatcher.ts @@ -1,5 +1,6 @@ import mm from "micromatch"; -import { EventListener, EventName, IEventDispatcher } from "../../contracts/core-kernel"; +import { IEventDispatcher } from "../../contracts/core-kernel"; +import { EventListener, EventName } from "../../types"; /** * @export diff --git a/packages/core-kernel/src/support/service-provider.ts b/packages/core-kernel/src/support/service-provider.ts index 58921493fb..f2273e98e6 100644 --- a/packages/core-kernel/src/support/service-provider.ts +++ b/packages/core-kernel/src/support/service-provider.ts @@ -1,35 +1,22 @@ -import { JsonObject, PackageJson } from "type-fest"; +import { PackageJson } from "type-fest"; import { Kernel } from "../contracts"; +import { ConfigObject } from "../types"; export abstract class AbstractServiceProvider { /** * @protected - * @type {Kernel.IApplication} + * @type {ConfigObject} * @memberof AbstractServiceProvider */ - protected app: Kernel.IApplication; - - /** - * @protected - * @type {Record} - * @memberof AbstractServiceProvider - */ - protected opts: Record; + protected opts: ConfigObject; /** * @param {Kernel.IApplication} app - * @param {Record} [opts={}] + * @param {ConfigObject} [opts={}] * @memberof AbstractServiceProvider */ - public constructor(app: Kernel.IApplication, opts: Record = {}) { - this.app = app; - this.opts = { ...opts, ...this.getDefaults() }; - - const globalOptions: JsonObject | undefined = app.config("options")[this.getName()]; - - if (globalOptions) { - this.opts = { ...this.opts, ...globalOptions }; - } + public constructor(protected readonly app: Kernel.IApplication, opts: ConfigObject = {}) { + this.opts = this.buildConfig(opts); } /** @@ -79,26 +66,36 @@ export abstract class AbstractServiceProvider { } /** - * @returns {Record} + * @returns {ConfigObject} * @memberof AbstractServiceProvider */ - public getDefaults(): Record { + public getDefaults(): ConfigObject { return {}; } /** - * @returns {string[]} + * @returns {Record} * @memberof AbstractServiceProvider */ - public provides(): string[] { - return []; + public depends(): Record { + return {}; } /** - * @returns {Record} + * @protected + * @param {ConfigObject} opts + * @returns {ConfigObject} * @memberof AbstractServiceProvider */ - public depends(): Record { - return {}; + protected buildConfig(opts: ConfigObject): ConfigObject { + opts = { ...opts, ...this.getDefaults() }; + + const globalOptions: ConfigObject | undefined = this.app.config("options")[this.getName()]; + + if (globalOptions) { + this.opts = { ...this.opts, ...globalOptions }; + } + + return opts; } } diff --git a/packages/core-kernel/src/types.ts b/packages/core-kernel/src/types.ts index f2a5bbaea2..ad36884934 100644 --- a/packages/core-kernel/src/types.ts +++ b/packages/core-kernel/src/types.ts @@ -1 +1,6 @@ export * from "type-fest"; + +export type ConfigObject = Record; + +export type EventName = string | symbol; +export type EventListener = (name: EventName, data: any) => void; diff --git a/packages/core-logger-pino/src/service-provider.ts b/packages/core-logger-pino/src/service-provider.ts index e3a52f5c13..b9ac4c38eb 100644 --- a/packages/core-logger-pino/src/service-provider.ts +++ b/packages/core-logger-pino/src/service-provider.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("logger", await this.app.resolve("factoryLogger").make(new PinoLogger(this.opts))); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-logger-signale/src/service-provider.ts b/packages/core-logger-signale/src/service-provider.ts index a5e590718d..68a0d7d751 100644 --- a/packages/core-logger-signale/src/service-provider.ts +++ b/packages/core-logger-signale/src/service-provider.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("logger", await this.app.resolve("factoryLogger").make(new SignaleLogger(this.opts))); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-logger-winston/src/service-provider.ts b/packages/core-logger-winston/src/service-provider.ts index d70104da52..97d5464ce6 100644 --- a/packages/core-logger-winston/src/service-provider.ts +++ b/packages/core-logger-winston/src/service-provider.ts @@ -7,7 +7,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("logger", await this.app.resolve("factoryLogger").make(new WinstonLogger(this.opts))); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-p2p/src/event-listener.ts b/packages/core-p2p/src/event-listener.ts index 679aeaf1e1..1fad88dbae 100644 --- a/packages/core-p2p/src/event-listener.ts +++ b/packages/core-p2p/src/event-listener.ts @@ -2,7 +2,7 @@ import { app, Contracts } from "@arkecosystem/core-kernel"; export class EventListener { private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); public constructor(service: Contracts.P2P.IPeerService) { diff --git a/packages/core-p2p/src/network-monitor.ts b/packages/core-p2p/src/network-monitor.ts index a06277e289..84c9900fcf 100644 --- a/packages/core-p2p/src/network-monitor.ts +++ b/packages/core-p2p/src/network-monitor.ts @@ -22,7 +22,7 @@ export class NetworkMonitor implements Contracts.P2P.INetworkMonitor { private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); private readonly communicator: Contracts.P2P.IPeerCommunicator; diff --git a/packages/core-p2p/src/peer-communicator.ts b/packages/core-p2p/src/peer-communicator.ts index 4e937c1e0a..ea896a6398 100644 --- a/packages/core-p2p/src/peer-communicator.ts +++ b/packages/core-p2p/src/peer-communicator.ts @@ -13,7 +13,7 @@ import { isValidVersion, socketEmit } from "./utils"; export class PeerCommunicator implements Contracts.P2P.IPeerCommunicator { private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); constructor(private readonly connector: Contracts.P2P.IPeerConnector) {} diff --git a/packages/core-p2p/src/peer-processor.ts b/packages/core-p2p/src/peer-processor.ts index aae5e923b3..a94ea524d8 100644 --- a/packages/core-p2p/src/peer-processor.ts +++ b/packages/core-p2p/src/peer-processor.ts @@ -10,7 +10,7 @@ export class PeerProcessor implements Contracts.P2P.IPeerProcessor { private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); private readonly communicator: Contracts.P2P.IPeerCommunicator; diff --git a/packages/core-p2p/src/service-provider.ts b/packages/core-p2p/src/service-provider.ts index f7c20e4af7..eea997a8c6 100644 --- a/packages/core-p2p/src/service-provider.ts +++ b/packages/core-p2p/src/service-provider.ts @@ -36,7 +36,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { .stopServer(); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-p2p/src/socket-server/versions/internal.ts b/packages/core-p2p/src/socket-server/versions/internal.ts index 83a4b50350..9a508bb563 100644 --- a/packages/core-p2p/src/socket-server/versions/internal.ts +++ b/packages/core-p2p/src/socket-server/versions/internal.ts @@ -7,7 +7,7 @@ export const acceptNewPeer = async ({ service, req }: { service: Contracts.P2P.I }; export const emitEvent = ({ req }): void => { - app.resolve("event-dispatcher").dispatch(req.data.event, req.data.body); + app.resolve("events").dispatch(req.data.event, req.data.body); }; export const getUnconfirmedTransactions = async (): Promise => { diff --git a/packages/core-snapshots/src/service-provider.ts b/packages/core-snapshots/src/service-provider.ts index 5fb5ca7ed9..070291b432 100644 --- a/packages/core-snapshots/src/service-provider.ts +++ b/packages/core-snapshots/src/service-provider.ts @@ -12,7 +12,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("snapshots", manager.make(databaseService.connection as PostgresConnection)); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-snapshots/src/transport/index.ts b/packages/core-snapshots/src/transport/index.ts index 586c7c32d2..4e13a80a55 100644 --- a/packages/core-snapshots/src/transport/index.ts +++ b/packages/core-snapshots/src/transport/index.ts @@ -13,7 +13,7 @@ import { Codec } from "./codec"; import { canImportRecord, verifyData } from "./verification"; const logger = app.resolve("logger"); -const emitter = app.resolve("event-dispatcher"); +const emitter = app.resolve("events"); const fixData = (table, data) => { if (table === "blocks" && data.height === 1) { diff --git a/packages/core-state/src/service-provider.ts b/packages/core-state/src/service-provider.ts index d03ea2ca3d..39f571afb3 100644 --- a/packages/core-state/src/service-provider.ts +++ b/packages/core-state/src/service-provider.ts @@ -19,7 +19,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { this.app.bind("state.options", this.opts); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-state/src/stores/state.ts b/packages/core-state/src/stores/state.ts index 3c953553f5..f2dab569b3 100644 --- a/packages/core-state/src/stores/state.ts +++ b/packages/core-state/src/stores/state.ts @@ -98,7 +98,7 @@ export class StateStore implements Contracts.State.IStateStore { Managers.configManager.setHeight(block.data.height); if (Managers.configManager.isNewMilestone()) { - app.resolve("event-dispatcher").dispatch( + app.resolve("events").dispatch( Enums.Event.Internal.MilestoneChanged, ); } diff --git a/packages/core-transaction-pool/src/connection.ts b/packages/core-transaction-pool/src/connection.ts index 4296d23035..a2946a8403 100644 --- a/packages/core-transaction-pool/src/connection.ts +++ b/packages/core-transaction-pool/src/connection.ts @@ -23,7 +23,7 @@ export class Connection implements Contracts.TransactionPool.IConnection { Contracts.Database.IDatabaseService >("database"); private readonly emitter: Contracts.Kernel.IEventDispatcher = app.resolve( - "event-dispatcher", + "events", ); private readonly logger: Contracts.Kernel.ILogger = app.resolve("logger"); diff --git a/packages/core-transaction-pool/src/service-provider.ts b/packages/core-transaction-pool/src/service-provider.ts index 53a8130852..03780273bc 100644 --- a/packages/core-transaction-pool/src/service-provider.ts +++ b/packages/core-transaction-pool/src/service-provider.ts @@ -33,7 +33,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-vote-report/src/index.ts b/packages/core-vote-report/src/index.ts index 5b0bbdb729..edad23b994 100644 --- a/packages/core-vote-report/src/index.ts +++ b/packages/core-vote-report/src/index.ts @@ -12,7 +12,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { await this.app.resolve("vote-report").stop(); } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-wallet-api/src/service-provider.ts b/packages/core-wallet-api/src/service-provider.ts index 7423ce5520..4292659b70 100644 --- a/packages/core-wallet-api/src/service-provider.ts +++ b/packages/core-wallet-api/src/service-provider.ts @@ -24,7 +24,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-webhooks/src/index.ts b/packages/core-webhooks/src/index.ts index c9a886e760..0eaa566cb7 100644 --- a/packages/core-webhooks/src/index.ts +++ b/packages/core-webhooks/src/index.ts @@ -27,7 +27,7 @@ export class ServiceProvider extends Support.AbstractServiceProvider { } } - public getDefaults(): Record { + public getDefaults(): Types.ConfigObject { return defaults; } diff --git a/packages/core-webhooks/src/listener.ts b/packages/core-webhooks/src/listener.ts index 0f000d4dbd..12f4c8a4da 100644 --- a/packages/core-webhooks/src/listener.ts +++ b/packages/core-webhooks/src/listener.ts @@ -6,7 +6,7 @@ import { IWebhook } from "./interfaces"; export const startListeners = (): void => { for (const event of Object.values(Enums.Event.State)) { - app.resolve("event-dispatcher").listen(event, async payload => { + app.resolve("events").listen(event, async payload => { const webhooks: IWebhook[] = database.findByEvent(event).filter((webhook: IWebhook) => { if (!webhook.enabled) { return false; diff --git a/packages/core/bin/config/testnet/config.js b/packages/core/bin/config/testnet/config.js deleted file mode 100644 index cfd9676891..0000000000 --- a/packages/core/bin/config/testnet/config.js +++ /dev/null @@ -1,132 +0,0 @@ -module.exports = { - providers: { - "@arkecosystem/core-logger-pino": {}, - "@arkecosystem/core-state": {}, - "@arkecosystem/core-database": {}, - "@arkecosystem/core-database-postgres": { - connection: { - host: process.env.CORE_DB_HOST || "localhost", - port: process.env.CORE_DB_PORT || 5432, - database: process.env.CORE_DB_DATABASE || `${process.env.CORE_TOKEN}_${process.env.CORE_NETWORK_NAME}`, - user: process.env.CORE_DB_USERNAME || process.env.CORE_TOKEN, - password: process.env.CORE_DB_PASSWORD || "password", - }, - }, - "@arkecosystem/core-transaction-pool": { - enabled: true, - maxTransactionsPerSender: process.env.CORE_TRANSACTION_POOL_MAX_PER_SENDER || 300, - allowedSenders: [], - dynamicFees: { - enabled: true, - minFeePool: 1000, - minFeeBroadcast: 1000, - addonBytes: { - transfer: 100, - secondSignature: 250, - delegateRegistration: 400000, - vote: 100, - multiSignature: 500, - ipfs: 250, - multiPayment: 500, - delegateResignation: 100, - htlcLock: 100, - htlcClaim: 0, - htlcRefund: 0, - }, - }, - }, - "@arkecosystem/core-p2p": { - server: { - port: process.env.CORE_P2P_PORT || 4000, - }, - minimumNetworkReach: 5, - }, - "@arkecosystem/core-blockchain": {}, - "@arkecosystem/core-api": { - enabled: !process.env.CORE_API_DISABLED, - host: process.env.CORE_API_HOST || "0.0.0.0", - port: process.env.CORE_API_PORT || 4003, - }, - "@arkecosystem/core-wallet-api": {}, - "@arkecosystem/core-webhooks": { - enabled: process.env.CORE_WEBHOOKS_ENABLED, - server: { - host: process.env.CORE_WEBHOOKS_HOST || "0.0.0.0", - port: process.env.CORE_WEBHOOKS_PORT || 4004, - whitelist: ["127.0.0.1", "::ffff:127.0.0.1"], - }, - }, - "@arkecosystem/core-forger": {}, - // "@arkecosystem/core-exchange-json-rpc": { - // enabled: process.env.CORE_EXCHANGE_JSON_RPC_ENABLED, - // host: process.env.CORE_EXCHANGE_JSON_RPC_HOST || "0.0.0.0", - // port: process.env.CORE_EXCHANGE_JSON_RPC_PORT || 8080, - // allowRemote: false, - // whitelist: ["127.0.0.1", "::ffff:127.0.0.1"], - // }, - // "@arkecosystem/core-snapshots": {}, - }, - delegates: { - secrets: [ - "clay harbor enemy utility margin pretty hub comic piece aerobic umbrella acquire", - "venue below waste gather spin cruise title still boost mother flash tuna", - "craft imitate step mixture patch forest volcano business charge around girl confirm", - "fatal hat sail asset chase barrel pluck bag approve coral slab bright", - "flash thank strike stove grain remove match reflect excess present beyond matrix", - "various present shine domain outdoor neck soup diesel limit express genuine tuna", - "hurdle pulse sheriff anchor two hope income pattern hazard bacon book night", - "glow boss party require silk interest pyramid marriage try wisdom snow grab", - "direct palace screen shuffle world fit produce rubber jelly gather river ordinary", - "wall ketchup shed word twist flip knock liar merge rural ill pond", - "measure blue volcano month orphan only cupboard found laugh peasant drama monitor", - "scissors sort pause medal target diesel reveal stock maze party gauge vacant", - "hand anchor hip pyramid taxi vote celery clap tribe damage shrimp brave", - "merge thunder detect stove else bottom favorite doll learn festival basic basic", - "educate attitude rely combine treat balcony west reopen coil west grab depth", - "advance silver advance squeeze load stone middle garden perfect invest field lounge", - "prison tobacco acquire stone dignity palace note decade they current lesson robot", - "team impact stadium year security steak harsh vacant fire pelican until olympic", - "walk intact ice prevent fit trial frog glory monkey once grunt gentle", - "same lens parrot suspect just sunset frown exercise lemon two mistake robust", - "skill insect issue crazy erase okay govern upgrade bounce dress motor athlete", - "peasant alert hard deposit naive follow page fiscal normal awful wedding history", - "resemble abandon same total oppose noise dune order fatal rhythm pink science", - "wide mesh ketchup acquire bright day mountain final below hamster scout drive", - "half weasel poet better rocket fan help left blade soda argue system", - "target sort neutral address language spike measure jaguar glance strong drop zone", - "race total stage trap wool believe twin pudding claim claim eternal miss", - "parade isolate wing vague magic husband acid skin skate path fence rib", - "neither fine dry priority example obtain bread reopen afford coyote milk minor", - "token atom lemon game charge area goose hotel excess endless spice oblige", - "pledge buffalo finish pipe mule popular bind clinic draft salon swamp purpose", - "west hat hold stand unique panther cable extend spell shaft injury reopen", - "van impulse pole install profit excuse give auction expire remain skate input", - "wrist maze potato april survey burden bamboo knee foot carry speak prison", - "three toddler copy owner pencil minimum doctor orange bottom ice detail design", - "ceiling warrior person thing whisper jeans black cricket drift ahead tornado typical", - "obvious mutual tone usual valve credit soccer mention also clown main box", - "valve slot soft green scale menu anxiety live drill legend upgrade chimney", - "twist comfort mule weather print oven cabin seek punch rival prepare sphere", - "say tumble glass argue aware service force caution until grocery hammer fetch", - "idea illegal empty frozen canvas arctic number poet rely track size obscure", - "chalk try large tower shed warfare blade clerk fame second charge tobacco", - "category nice verb fox start able brass climb boss luggage voice whale", - "favorite emotion trumpet visual welcome spend fine lock image review garage opera", - "waste axis humor auction next salmon much margin useful glimpse insect rotate", - "remember rose genuine police guard old flavor parent gain cross twelve first", - "coil tray elder mask circle crush anger electric harbor onion grab will", - "shove airport bus gather radio derive below horse canvas crime tribe adjust", - "retire lend burden cricket able sheriff output grocery empty scorpion flat inquiry", - "agree grain record shift fossil summer hunt mutual net vast behind pilot", - "decide rhythm oyster lady they merry betray jelly coyote solve episode then", - ], - }, - peers: { - list: [ - { - ip: "127.0.0.1", - port: 4000, - }, - ], - }, -}; diff --git a/packages/core/bin/config/testnet/delegates.json b/packages/core/bin/config/testnet/delegates.json new file mode 100644 index 0000000000..822250478e --- /dev/null +++ b/packages/core/bin/config/testnet/delegates.json @@ -0,0 +1,55 @@ +{ + "secrets": [ + "clay harbor enemy utility margin pretty hub comic piece aerobic umbrella acquire", + "venue below waste gather spin cruise title still boost mother flash tuna", + "craft imitate step mixture patch forest volcano business charge around girl confirm", + "fatal hat sail asset chase barrel pluck bag approve coral slab bright", + "flash thank strike stove grain remove match reflect excess present beyond matrix", + "various present shine domain outdoor neck soup diesel limit express genuine tuna", + "hurdle pulse sheriff anchor two hope income pattern hazard bacon book night", + "glow boss party require silk interest pyramid marriage try wisdom snow grab", + "direct palace screen shuffle world fit produce rubber jelly gather river ordinary", + "wall ketchup shed word twist flip knock liar merge rural ill pond", + "measure blue volcano month orphan only cupboard found laugh peasant drama monitor", + "scissors sort pause medal target diesel reveal stock maze party gauge vacant", + "hand anchor hip pyramid taxi vote celery clap tribe damage shrimp brave", + "merge thunder detect stove else bottom favorite doll learn festival basic basic", + "educate attitude rely combine treat balcony west reopen coil west grab depth", + "advance silver advance squeeze load stone middle garden perfect invest field lounge", + "prison tobacco acquire stone dignity palace note decade they current lesson robot", + "team impact stadium year security steak harsh vacant fire pelican until olympic", + "walk intact ice prevent fit trial frog glory monkey once grunt gentle", + "same lens parrot suspect just sunset frown exercise lemon two mistake robust", + "skill insect issue crazy erase okay govern upgrade bounce dress motor athlete", + "peasant alert hard deposit naive follow page fiscal normal awful wedding history", + "resemble abandon same total oppose noise dune order fatal rhythm pink science", + "wide mesh ketchup acquire bright day mountain final below hamster scout drive", + "half weasel poet better rocket fan help left blade soda argue system", + "target sort neutral address language spike measure jaguar glance strong drop zone", + "race total stage trap wool believe twin pudding claim claim eternal miss", + "parade isolate wing vague magic husband acid skin skate path fence rib", + "neither fine dry priority example obtain bread reopen afford coyote milk minor", + "token atom lemon game charge area goose hotel excess endless spice oblige", + "pledge buffalo finish pipe mule popular bind clinic draft salon swamp purpose", + "west hat hold stand unique panther cable extend spell shaft injury reopen", + "van impulse pole install profit excuse give auction expire remain skate input", + "wrist maze potato april survey burden bamboo knee foot carry speak prison", + "three toddler copy owner pencil minimum doctor orange bottom ice detail design", + "ceiling warrior person thing whisper jeans black cricket drift ahead tornado typical", + "obvious mutual tone usual valve credit soccer mention also clown main box", + "valve slot soft green scale menu anxiety live drill legend upgrade chimney", + "twist comfort mule weather print oven cabin seek punch rival prepare sphere", + "say tumble glass argue aware service force caution until grocery hammer fetch", + "idea illegal empty frozen canvas arctic number poet rely track size obscure", + "chalk try large tower shed warfare blade clerk fame second charge tobacco", + "category nice verb fox start able brass climb boss luggage voice whale", + "favorite emotion trumpet visual welcome spend fine lock image review garage opera", + "waste axis humor auction next salmon much margin useful glimpse insect rotate", + "remember rose genuine police guard old flavor parent gain cross twelve first", + "coil tray elder mask circle crush anger electric harbor onion grab will", + "shove airport bus gather radio derive below horse canvas crime tribe adjust", + "retire lend burden cricket able sheriff output grocery empty scorpion flat inquiry", + "agree grain record shift fossil summer hunt mutual net vast behind pilot", + "decide rhythm oyster lady they merry betray jelly coyote solve episode then" + ] +} diff --git a/packages/core/bin/config/testnet/peers.json b/packages/core/bin/config/testnet/peers.json new file mode 100644 index 0000000000..13faa40da6 --- /dev/null +++ b/packages/core/bin/config/testnet/peers.json @@ -0,0 +1,8 @@ +{ + "list": [ + { + "ip": "127.0.0.1", + "port": 4000 + } + ] +} diff --git a/packages/core/bin/config/testnet/service-providers.js b/packages/core/bin/config/testnet/service-providers.js new file mode 100644 index 0000000000..fe9c8b940d --- /dev/null +++ b/packages/core/bin/config/testnet/service-providers.js @@ -0,0 +1,67 @@ +module.exports = { + "@arkecosystem/core-logger-pino": {}, + "@arkecosystem/core-state": {}, + "@arkecosystem/core-database": {}, + "@arkecosystem/core-database-postgres": { + connection: { + host: process.env.CORE_DB_HOST || "localhost", + port: process.env.CORE_DB_PORT || 5432, + database: process.env.CORE_DB_DATABASE || `${process.env.CORE_TOKEN}_${process.env.CORE_NETWORK_NAME}`, + user: process.env.CORE_DB_USERNAME || process.env.CORE_TOKEN, + password: process.env.CORE_DB_PASSWORD || "password", + }, + }, + "@arkecosystem/core-transaction-pool": { + enabled: true, + maxTransactionsPerSender: process.env.CORE_TRANSACTION_POOL_MAX_PER_SENDER || 300, + allowedSenders: [], + dynamicFees: { + enabled: true, + minFeePool: 1000, + minFeeBroadcast: 1000, + addonBytes: { + transfer: 100, + secondSignature: 250, + delegateRegistration: 400000, + vote: 100, + multiSignature: 500, + ipfs: 250, + multiPayment: 500, + delegateResignation: 100, + htlcLock: 100, + htlcClaim: 0, + htlcRefund: 0, + }, + }, + }, + "@arkecosystem/core-p2p": { + server: { + port: process.env.CORE_P2P_PORT || 4000, + }, + minimumNetworkReach: 5, + }, + "@arkecosystem/core-blockchain": {}, + "@arkecosystem/core-api": { + enabled: !process.env.CORE_API_DISABLED, + host: process.env.CORE_API_HOST || "0.0.0.0", + port: process.env.CORE_API_PORT || 4003, + }, + "@arkecosystem/core-wallet-api": {}, + "@arkecosystem/core-webhooks": { + enabled: process.env.CORE_WEBHOOKS_ENABLED, + server: { + host: process.env.CORE_WEBHOOKS_HOST || "0.0.0.0", + port: process.env.CORE_WEBHOOKS_PORT || 4004, + whitelist: ["127.0.0.1", "::ffff:127.0.0.1"], + }, + }, + "@arkecosystem/core-forger": {}, + // "@arkecosystem/core-exchange-json-rpc": { + // enabled: process.env.CORE_EXCHANGE_JSON_RPC_ENABLED, + // host: process.env.CORE_EXCHANGE_JSON_RPC_HOST || "0.0.0.0", + // port: process.env.CORE_EXCHANGE_JSON_RPC_PORT || 8080, + // allowRemote: false, + // whitelist: ["127.0.0.1", "::ffff:127.0.0.1"], + // }, + // "@arkecosystem/core-snapshots": {}, +}; diff --git a/packages/core/package.json b/packages/core/package.json index 4fbe1a7b31..6309a30ca2 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -46,10 +46,10 @@ "dependencies": { "@arkecosystem/core-api": "^3.0.0-next.0", "@arkecosystem/core-blockchain": "^3.0.0-next.0", - "@arkecosystem/core-kernel": "^3.0.0-next.0", "@arkecosystem/core-database-postgres": "^3.0.0-next.0", "@arkecosystem/core-exchange-json-rpc": "^3.0.0-next.0", "@arkecosystem/core-forger": "^3.0.0-next.0", + "@arkecosystem/core-kernel": "^3.0.0-next.0", "@arkecosystem/core-logger-pino": "^3.0.0-next.0", "@arkecosystem/core-p2p": "^3.0.0-next.0", "@arkecosystem/core-snapshots": "^3.0.0-next.0", diff --git a/packages/core/src/commands/command.ts b/packages/core/src/commands/command.ts index 9ab6c5d8dd..b61c85dc63 100644 --- a/packages/core/src/commands/command.ts +++ b/packages/core/src/commands/command.ts @@ -246,7 +246,7 @@ export abstract class BaseCommand extends Command { const { config } = await this.getPaths(flags); // @TODO: update to follow new config convention - const configDelegates = join(config, "config.js"); + const configDelegates = join(config, "delegates.json"); if (!existsSync(configDelegates)) { this.error(`The ${configDelegates} file does not exist.`); diff --git a/packages/core/src/commands/config/forger/bip39.ts b/packages/core/src/commands/config/forger/bip39.ts index a5e3c522a9..b570994c8c 100644 --- a/packages/core/src/commands/config/forger/bip39.ts +++ b/packages/core/src/commands/config/forger/bip39.ts @@ -57,7 +57,7 @@ $ ark config:forger:bip39 --bip39="..." const { config } = await this.getPaths(flags); // @TODO: update to follow new config convention - const delegatesConfig = `${config}/config.js`; + const delegatesConfig = `${config}/delegates.json`; this.addTask("Prepare configuration", async () => { if (!fs.existsSync(delegatesConfig)) { diff --git a/packages/core/src/commands/snapshot/restore.ts b/packages/core/src/commands/snapshot/restore.ts index 5d837e6196..72e27b227a 100644 --- a/packages/core/src/commands/snapshot/restore.ts +++ b/packages/core/src/commands/snapshot/restore.ts @@ -42,7 +42,7 @@ export class RestoreCommand extends BaseCommand { } } - const emitter = app.resolve("event-dispatcher"); + const emitter = app.resolve("events"); const progressBar = new cliProgress.Bar( {