diff --git a/packages/core-api/src/defaults.ts b/packages/core-api/src/defaults.ts index d03d84b63b..3207d70a68 100644 --- a/packages/core-api/src/defaults.ts +++ b/packages/core-api/src/defaults.ts @@ -1,65 +1,72 @@ export const defaults = { - enabled: !process.env.CORE_API_DISABLED, - host: process.env.CORE_API_HOST || "0.0.0.0", - port: process.env.CORE_API_PORT || 4003, - cache: { - enabled: true, - /** - * How many seconds the server will try to complete the request and cache the result. - * - * Defaults to 8 seconds, set it to false if you do not care about the timeout. - * - * Setting it to false can result in requests never being completed, which is usually - * caused by low-spec servers that are unable to handle the heavy load that results - * out of SQL queries on the blocks and transactions tables. - * - * If you experience issues with the cache timeout, which is indicated by a 503 status codes, - * you should consider upgrading your hardware or tweak your PostgreSQL settings. - */ - generateTimeout: process.env.CORE_API_CACHE_TIMEOUT || 8000, - }, - // @see https://hapijs.com/api#-serveroptionstls - ssl: { - enabled: process.env.CORE_API_SSL, - host: process.env.CORE_API_SSL_HOST || "0.0.0.0", - port: process.env.CORE_API_SSL_PORT || 8443, - key: process.env.CORE_API_SSL_KEY, - cert: process.env.CORE_API_SSL_CERT, - }, - // @see https://github.com/wraithgar/hapi-rate-limit - rateLimit: { - enabled: !process.env.CORE_API_RATE_LIMIT, - pathLimit: false, - userLimit: process.env.CORE_API_RATE_LIMIT_USER_LIMIT || 300, - userCache: { - expiresIn: process.env.CORE_API_RATE_LIMIT_USER_EXPIRES || 60000, + server: { + http: { + enabled: !process.env.CORE_API_DISABLED, + host: process.env.CORE_API_HOST || "0.0.0.0", + port: process.env.CORE_API_PORT || 4003, + }, + // @see https://hapijs.com/api#-serveroptionstls + https: { + enabled: process.env.CORE_API_SSL, + host: process.env.CORE_API_SSL_HOST || "0.0.0.0", + port: process.env.CORE_API_SSL_PORT || 8443, + tls: { + key: process.env.CORE_API_SSL_KEY, + cert: process.env.CORE_API_SSL_CERT, + }, }, }, - // @see https://github.com/fknop/hapi-pagination - pagination: { - limit: 100, - include: [ - "/api/blocks", - "/api/blocks/{id}/transactions", - "/api/blocks/search", - "/api/delegates", - "/api/delegates/{id}/blocks", - "/api/delegates/{id}/voters", - "/api/delegates/search", - "/api/peers", - "/api/transactions", - "/api/transactions/search", - "/api/transactions/unconfirmed", - "/api/votes", - "/api/wallets", - "/api/wallets/top", - "/api/wallets/{id}/transactions", - "/api/wallets/{id}/transactions/received", - "/api/wallets/{id}/transactions/sent", - "/api/wallets/{id}/votes", - "/api/wallets/search", - ], + plugins: { + cache: { + enabled: true, + /** + * How many seconds the server will try to complete the request and cache the result. + * + * Defaults to 8 seconds, set it to false if you do not care about the timeout. + * + * Setting it to false can result in requests never being completed, which is usually + * caused by low-spec servers that are unable to handle the heavy load that results + * out of SQL queries on the blocks and transactions tables. + * + * If you experience issues with the cache timeout, which is indicated by a 503 status codes, + * you should consider upgrading your hardware or tweak your PostgreSQL settings. + */ + generateTimeout: process.env.CORE_API_CACHE_TIMEOUT || 8000, + }, + // @see https://github.com/wraithgar/hapi-rate-limit + rateLimit: { + enabled: !process.env.CORE_API_RATE_LIMIT, + pathLimit: false, + userLimit: process.env.CORE_API_RATE_LIMIT_USER_LIMIT || 300, + userCache: { + expiresIn: process.env.CORE_API_RATE_LIMIT_USER_EXPIRES || 60000, + }, + }, + // @see https://github.com/fknop/hapi-pagination + pagination: { + limit: 100, + include: [ + "/api/blocks", + "/api/blocks/{id}/transactions", + "/api/blocks/search", + "/api/delegates", + "/api/delegates/{id}/blocks", + "/api/delegates/{id}/voters", + "/api/delegates/search", + "/api/peers", + "/api/transactions", + "/api/transactions/search", + "/api/transactions/unconfirmed", + "/api/votes", + "/api/wallets", + "/api/wallets/top", + "/api/wallets/{id}/transactions", + "/api/wallets/{id}/transactions/received", + "/api/wallets/{id}/transactions/sent", + "/api/wallets/{id}/votes", + "/api/wallets/search", + ], + }, + whitelist: ["*"], }, - whitelist: ["*"], - plugins: [], }; diff --git a/packages/core-api/src/handlers/blocks/methods.ts b/packages/core-api/src/handlers/blocks/methods.ts index 1ea598025c..19bb182a97 100644 --- a/packages/core-api/src/handlers/blocks/methods.ts +++ b/packages/core-api/src/handlers/blocks/methods.ts @@ -4,21 +4,21 @@ import Boom from "@hapi/boom"; import { ServerCache } from "../../services"; import { paginate, respondWithResource, toPagination } from "../utils"; -const databaseService = app.get(Container.Identifiers.DatabaseService); -const blocksRepository = databaseService.blocksBusinessRepository; -const transactionsRepository = databaseService.transactionsBusinessRepository; - const index = async request => { - const blocks = await blocksRepository.search({ - ...request.query, - ...paginate(request), - }); + const blocks = await app + .get(Container.Identifiers.DatabaseService) + .blocksBusinessRepository.search({ + ...request.query, + ...paginate(request), + }); return toPagination(blocks, "block", request.query.transform); }; const show = async request => { - const block = await blocksRepository.findByIdOrHeight(request.params.id); + const block = await app + .get(Container.Identifiers.DatabaseService) + .blocksBusinessRepository.findByIdOrHeight(request.params.id); if (!block) { return Boom.notFound("Block not found"); @@ -28,26 +28,32 @@ const show = async request => { }; const transactions = async request => { - const block = await blocksRepository.findByIdOrHeight(request.params.id); + const block = await app + .get(Container.Identifiers.DatabaseService) + .blocksBusinessRepository.findByIdOrHeight(request.params.id); if (!block) { return Boom.notFound("Block not found"); } - const rows = await transactionsRepository.findAllByBlock(block.id, { - ...request.query, - ...paginate(request), - }); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findAllByBlock(block.id, { + ...request.query, + ...paginate(request), + }); return toPagination(rows, "transaction", request.query.transform); }; const search = async request => { - const blocks = await blocksRepository.search({ - ...request.payload, - ...request.query, - ...paginate(request), - }); + const blocks = await app + .get(Container.Identifiers.DatabaseService) + .blocksBusinessRepository.search({ + ...request.payload, + ...request.query, + ...paginate(request), + }); return toPagination(blocks, "block", request.query.transform); }; diff --git a/packages/core-api/src/handlers/delegates/methods.ts b/packages/core-api/src/handlers/delegates/methods.ts index a010f6e238..3e66a0f862 100644 --- a/packages/core-api/src/handlers/delegates/methods.ts +++ b/packages/core-api/src/handlers/delegates/methods.ts @@ -4,20 +4,21 @@ import Boom from "@hapi/boom"; import { ServerCache } from "../../services"; import { paginate, respondWithResource, toPagination } from "../utils"; -const databaseService = app.get(Container.Identifiers.DatabaseService); -const blocksRepository = databaseService.blocksBusinessRepository; - const index = async request => { - const delegates = databaseService.delegates.search({ - ...request.query, - ...paginate(request), - }); + const delegates = app + .get(Container.Identifiers.DatabaseService) + .delegates.search({ + ...request.query, + ...paginate(request), + }); return toPagination(delegates, "delegate"); }; const show = async request => { - const delegate = databaseService.delegates.findById(request.params.id); + const delegate = app + .get(Container.Identifiers.DatabaseService) + .delegates.findById(request.params.id); if (!delegate) { return Boom.notFound("Delegate not found"); @@ -27,38 +28,48 @@ const show = async request => { }; const search = async request => { - const delegates = databaseService.delegates.search({ - ...request.payload, - ...request.query, - ...paginate(request), - }); + const delegates = app + .get(Container.Identifiers.DatabaseService) + .delegates.search({ + ...request.payload, + ...request.query, + ...paginate(request), + }); return toPagination(delegates, "delegate"); }; const blocks = async request => { - const delegate = databaseService.delegates.findById(request.params.id); + const delegate = app + .get(Container.Identifiers.DatabaseService) + .delegates.findById(request.params.id); if (!delegate) { return Boom.notFound("Delegate not found"); } - const rows = await blocksRepository.findAllByGenerator(delegate.publicKey, paginate(request)); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .blocksBusinessRepository.findAllByGenerator(delegate.publicKey, paginate(request)); return toPagination(rows, "block", request.query.transform); }; const voters = async request => { - const delegate = databaseService.delegates.findById(request.params.id); + const delegate = app + .get(Container.Identifiers.DatabaseService) + .delegates.findById(request.params.id); if (!delegate) { return Boom.notFound("Delegate not found"); } - const wallets = databaseService.wallets.findAllByVote(delegate.publicKey, { - ...request.query, - ...paginate(request), - }); + const wallets = app + .get(Container.Identifiers.DatabaseService) + .wallets.findAllByVote(delegate.publicKey, { + ...request.query, + ...paginate(request), + }); return toPagination(wallets, "wallet"); }; diff --git a/packages/core-api/src/handlers/rounds/methods.ts b/packages/core-api/src/handlers/rounds/methods.ts index f9653edc91..56f56bc258 100644 --- a/packages/core-api/src/handlers/rounds/methods.ts +++ b/packages/core-api/src/handlers/rounds/methods.ts @@ -6,10 +6,9 @@ import { ServerCache } from "../../services"; import { respondWithCollection } from "../utils"; const delegates = async request => { - const databaseService = app.get(Container.Identifiers.DatabaseService); - const roundsRepository = databaseService.connection.roundsRepository; - - const delegates = await roundsRepository.findById(request.params.id); + const delegates = await app + .get(Container.Identifiers.DatabaseService) + .connection.roundsRepository.findById(request.params.id); if (!delegates || !delegates.length) { return Boom.notFound("Round not found"); diff --git a/packages/core-api/src/handlers/shared/schemas/pagination.ts b/packages/core-api/src/handlers/shared/schemas/pagination.ts index 03529bd402..96b1c10ccd 100644 --- a/packages/core-api/src/handlers/shared/schemas/pagination.ts +++ b/packages/core-api/src/handlers/shared/schemas/pagination.ts @@ -1,4 +1,4 @@ -import { app } from "@arkecosystem/core-kernel"; +// import { app } from "@arkecosystem/core-kernel"; import Joi from "@hapi/joi"; export const pagination = { @@ -10,6 +10,7 @@ export const pagination = { .min(0), limit: Joi.number() .integer() - .min(1) - .max(app.get("api.options").pagination.limit), + .min(1), + // @fixme: the container is not available at the time this file is loaded + // .max(app.get("api.options").get("plugins.pagination.limit")), }; diff --git a/packages/core-api/src/handlers/transactions/methods.ts b/packages/core-api/src/handlers/transactions/methods.ts index bc992b3ea9..3536fac030 100644 --- a/packages/core-api/src/handlers/transactions/methods.ts +++ b/packages/core-api/src/handlers/transactions/methods.ts @@ -4,20 +4,21 @@ import Boom from "@hapi/boom"; import { ServerCache } from "../../services"; import { paginate, respondWithResource, toPagination } from "../utils"; -const transactionsRepository = app.get(Container.Identifiers.DatabaseService) - .transactionsBusinessRepository; - const index = async request => { - const transactions = await transactionsRepository.search({ - ...request.query, - ...paginate(request), - }); + const transactions = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.search({ + ...request.query, + ...paginate(request), + }); return toPagination(transactions, "transaction", (request.query.transform as unknown) as boolean); }; const show = async request => { - const transaction = await transactionsRepository.findById(request.params.id); + const transaction = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findById(request.params.id); if (!transaction) { return Boom.notFound("Transaction not found"); @@ -27,11 +28,13 @@ const show = async request => { }; const search = async request => { - const transactions = await transactionsRepository.search({ - ...request.query, - ...request.payload, - ...paginate(request), - }); + const transactions = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.search({ + ...request.query, + ...request.payload, + ...paginate(request), + }); return toPagination(transactions, "transaction", (request.query.transform as unknown) as boolean); }; diff --git a/packages/core-api/src/handlers/transactions/schema.ts b/packages/core-api/src/handlers/transactions/schema.ts index f972aee92a..a9829d9019 100644 --- a/packages/core-api/src/handlers/transactions/schema.ts +++ b/packages/core-api/src/handlers/transactions/schema.ts @@ -1,4 +1,4 @@ -import { app } from "@arkecosystem/core-kernel"; +// import { app } from "@arkecosystem/core-kernel"; import Joi from "@hapi/joi"; import { blockId } from "../shared/schemas/block-id"; @@ -55,7 +55,9 @@ export const store: object = { transactions: { $ref: "transactions", minItems: 1, - maxItems: app.get("transactionPool.options").maxTransactionsPerRequest, + maxItems: 40, + // @fixme: the container is not available at the time this file is loaded + // maxItems: app.get("transactionPool.options").maxTransactionsPerRequest, }, }, }; diff --git a/packages/core-api/src/handlers/utils.ts b/packages/core-api/src/handlers/utils.ts index 2ec7c12d23..dadb3ead92 100644 --- a/packages/core-api/src/handlers/utils.ts +++ b/packages/core-api/src/handlers/utils.ts @@ -32,7 +32,7 @@ export const respondWithCollection = (data, transformer, transform = true): obje }; export const respondWithCache = (data, h): any => { - if (!app.get("api.options").cache.enabled) { + if (!app.get("api.options").get("plugins.cache.enabled")) { return data; } diff --git a/packages/core-api/src/handlers/votes/methods.ts b/packages/core-api/src/handlers/votes/methods.ts index 88a9d2ddd8..e8de2304c8 100644 --- a/packages/core-api/src/handlers/votes/methods.ts +++ b/packages/core-api/src/handlers/votes/methods.ts @@ -7,20 +7,21 @@ import { paginate, respondWithResource, toPagination } from "../utils"; const { TransactionType } = Enums; -const databaseService = app.get(Container.Identifiers.DatabaseService); -const transactionsRepository = databaseService.transactionsBusinessRepository; - const index = async request => { - const transactions = await transactionsRepository.findAllByType(TransactionType.Vote, { - ...request.query, - ...paginate(request), - }); + const transactions = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findAllByType(TransactionType.Vote, { + ...request.query, + ...paginate(request), + }); return toPagination(transactions, "transaction", (request.query.transform as unknown) as boolean); }; const show = async request => { - const transaction = await transactionsRepository.findByTypeAndId(TransactionType.Vote, request.params.id); + const transaction = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findByTypeAndId(TransactionType.Vote, request.params.id); if (!transaction) { return Boom.notFound("Vote not found"); diff --git a/packages/core-api/src/handlers/wallets/methods.ts b/packages/core-api/src/handlers/wallets/methods.ts index b758613183..623afba96f 100644 --- a/packages/core-api/src/handlers/wallets/methods.ts +++ b/packages/core-api/src/handlers/wallets/methods.ts @@ -4,11 +4,8 @@ import Boom from "@hapi/boom"; import { ServerCache } from "../../services"; import { paginate, respondWithResource, toPagination } from "../utils"; -const databaseService = app.get(Container.Identifiers.DatabaseService); -const transactionsRepository = databaseService.transactionsBusinessRepository; - const index = async request => { - const wallets = databaseService.wallets.search({ + const wallets = app.get(Container.Identifiers.DatabaseService).wallets.search({ ...request.query, ...paginate(request), }); @@ -17,13 +14,17 @@ const index = async request => { }; const top = async request => { - const wallets = databaseService.wallets.top(paginate(request)); + const wallets = app + .get(Container.Identifiers.DatabaseService) + .wallets.top(paginate(request)); return toPagination(wallets, "wallet"); }; const show = async request => { - const wallet = databaseService.wallets.findById(request.params.id); + const wallet = app + .get(Container.Identifiers.DatabaseService) + .wallets.findById(request.params.id); if (!wallet) { return Boom.notFound("Wallet not found"); @@ -33,23 +34,29 @@ const show = async request => { }; const transactions = async request => { - const wallet = databaseService.wallets.findById(request.params.id); + const wallet = app + .get(Container.Identifiers.DatabaseService) + .wallets.findById(request.params.id); if (!wallet) { return Boom.notFound("Wallet not found"); } - const rows = await transactionsRepository.findAllByWallet(wallet, { - ...request.query, - ...request.params, - ...paginate(request), - }); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findAllByWallet(wallet, { + ...request.query, + ...request.params, + ...paginate(request), + }); return toPagination(rows, "transaction", (request.query.transform as unknown) as boolean); }; const transactionsSent = async request => { - const wallet = databaseService.wallets.findById(request.params.id); + const wallet = app + .get(Container.Identifiers.DatabaseService) + .wallets.findById(request.params.id); if (!wallet) { return Boom.notFound("Wallet not found"); @@ -58,17 +65,21 @@ const transactionsSent = async request => { // NOTE: We unset this value because it otherwise will produce a faulty SQL query delete request.params.id; - const rows = await transactionsRepository.findAllBySender(wallet.publicKey, { - ...request.query, - ...request.params, - ...paginate(request), - }); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findAllBySender(wallet.publicKey, { + ...request.query, + ...request.params, + ...paginate(request), + }); return toPagination(rows, "transaction", (request.query.transform as unknown) as boolean); }; const transactionsReceived = async request => { - const wallet = databaseService.wallets.findById(request.params.id); + const wallet = app + .get(Container.Identifiers.DatabaseService) + .wallets.findById(request.params.id); if (!wallet) { return Boom.notFound("Wallet not found"); @@ -77,17 +88,21 @@ const transactionsReceived = async request => { // NOTE: We unset this value because it otherwise will produce a faulty SQL query delete request.params.id; - const rows = await transactionsRepository.findAllByRecipient(wallet.address, { - ...request.query, - ...request.params, - ...paginate(request), - }); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.findAllByRecipient(wallet.address, { + ...request.query, + ...request.params, + ...paginate(request), + }); return toPagination(rows, "transaction", (request.query.transform as unknown) as boolean); }; const votes = async request => { - const wallet = databaseService.wallets.findById(request.params.id); + const wallet = app + .get(Container.Identifiers.DatabaseService) + .wallets.findById(request.params.id); if (!wallet) { return Boom.notFound("Wallet not found"); @@ -96,16 +111,18 @@ const votes = async request => { // NOTE: We unset this value because it otherwise will produce a faulty SQL query delete request.params.id; - const rows = await transactionsRepository.allVotesBySender(wallet.publicKey, { - ...request.params, - ...paginate(request), - }); + const rows = await app + .get(Container.Identifiers.DatabaseService) + .transactionsBusinessRepository.allVotesBySender(wallet.publicKey, { + ...request.params, + ...paginate(request), + }); return toPagination(rows, "transaction", (request.query.transform as unknown) as boolean); }; const search = async request => { - const wallets = databaseService.wallets.search({ + const wallets = app.get(Container.Identifiers.DatabaseService).wallets.search({ ...request.payload, ...request.query, ...paginate(request), diff --git a/packages/core-api/src/index.ts b/packages/core-api/src/index.ts index b180e4e4e2..5d8cdd8def 100644 --- a/packages/core-api/src/index.ts +++ b/packages/core-api/src/index.ts @@ -1,4 +1 @@ -export * from "./defaults"; -export * from "./server"; -export * from "./interfaces"; export * from "./service-provider"; diff --git a/packages/core-api/src/plugins/index.ts b/packages/core-api/src/plugins/index.ts new file mode 100644 index 0000000000..768ef99233 --- /dev/null +++ b/packages/core-api/src/plugins/index.ts @@ -0,0 +1,42 @@ +import { plugins } from "@arkecosystem/core-http-utils"; + +export const preparePlugins = config => [ + { plugin: plugins.contentType }, + { + plugin: plugins.corsHeaders, + }, + { + plugin: plugins.whitelist, + options: { + whitelist: config.whitelist, + }, + }, + { + plugin: require("./set-headers"), + }, + { plugin: plugins.hapiAjv }, + { + plugin: require("hapi-rate-limit"), + options: config.rateLimit, + }, + { + plugin: require("hapi-pagination"), + options: { + meta: { + baseUri: "", + }, + query: { + limit: { + default: config.pagination.limit, + }, + }, + results: { + name: "data", + }, + routes: { + include: config.pagination.include, + exclude: ["*"], + }, + }, + }, +]; diff --git a/packages/core-api/src/server.ts b/packages/core-api/src/server.ts index 6614c49c46..5df89c8ed8 100644 --- a/packages/core-api/src/server.ts +++ b/packages/core-api/src/server.ts @@ -1,163 +1,69 @@ -import { createServer, mountServer, plugins } from "@arkecosystem/core-http-utils"; -import { Contracts } from "@arkecosystem/core-kernel"; -import Hapi from "@hapi/hapi"; +import { Container, Contracts, Types } from "@arkecosystem/core-kernel"; +import { Server as HapiServer } from "@hapi/hapi"; +import Handlers from "./handlers"; +import { preparePlugins } from "./plugins"; + +@Container.injectable() export class Server { /** - * The application instance. - * - * @protected + * @private * @type {Contracts.Kernel.Application} - * @memberof AbstractManager + * @memberof Server */ + @Container.inject(Container.Identifiers.Application) private readonly app: Contracts.Kernel.Application; - private readonly config: any; - - private http: any; - private https: any; - /** - * Creates an instance of AbstractBootstrapper. - * - * @param {{ app: Contracts.Kernel.Application }} { app } - * @memberof AbstractBootstrapper + * @private + * @type {HapiServer} + * @memberof Server */ - public constructor({ app }: { app: Contracts.Kernel.Application }) { - this.app = app; - this.config = app.get("api.options"); - } - - public async start(): Promise { - const options = { - host: this.config.host, - port: this.config.port, - }; - - if (this.config.enabled) { - this.http = await createServer(options); - this.http.app.config = this.config; - - this.registerPlugins("HTTP", this.http); - } - - if (this.config.ssl.enabled) { - this.https = await createServer({ - ...options, - ...{ host: this.config.ssl.host, port: this.config.ssl.port }, - ...{ tls: { key: this.config.ssl.key, cert: this.config.ssl.cert } }, - }); - this.https.app.config = this.config; - - this.registerPlugins("HTTPS", this.https); - } - } - - public async stop(): Promise { - if (this.http) { - this.app.log.info(`Stopping Public HTTP API`); - await this.http.stop(); - } - - if (this.https) { - this.app.log.info(`Stopping Public HTTPS API`); - await this.https.stop(); - } - } - - public async restart(): Promise { - if (this.http) { - await this.http.stop(); - await this.http.start(); - } - - if (this.https) { - await this.https.stop(); - await this.https.start(); - } - } - - public instance(type: string): Hapi.Server { - return this[type]; - } - - private async registerPlugins(name: string, server: Hapi.Server): Promise { - await server.register({ plugin: plugins.contentType }); - - await server.register({ - plugin: plugins.corsHeaders, - }); - - await server.register({ - plugin: plugins.whitelist, - options: { - whitelist: this.config.whitelist, - }, - }); + private server: HapiServer; - await server.register({ - plugin: require("./plugins/set-headers"), - }); + /** + * @param {Options} options + * @returns {Promise} + * @memberof Server + */ + public async init(optionsServer: Types.JsonObject, optionsPlugins: Types.JsonObject): Promise { + this.server = new HapiServer(optionsServer); - await server.register(plugins.hapiAjv); + await this.server.register(preparePlugins(optionsPlugins)); - await server.register({ - plugin: require("hapi-rate-limit"), - options: this.config.rateLimit, - }); - - await server.register({ - plugin: require("hapi-pagination"), - options: { - meta: { - baseUri: "", - }, - query: { - limit: { - default: this.config.pagination.limit, - }, - }, - results: { - name: "data", - }, - routes: { - include: this.config.pagination.include, - exclude: ["*"], - }, + this.server.route({ + method: "GET", + path: "/", + handler() { + return { data: "Hello World!" }; }, }); - await server.register({ - plugin: require("./handlers"), + await this.server.register({ + plugin: Handlers, routes: { prefix: "/api" }, }); + } - for (const plugin of this.config.plugins) { - if (typeof plugin.plugin === "string") { - plugin.plugin = require(plugin.plugin); - } - - await server.register(plugin); - } + /** + * @returns {Promise} + * @memberof Server + */ + public async start(): Promise { + await this.server.start(); - server.route({ - method: "GET", - path: "/", - handler() { - return { data: "Hello World!" }; - }, - }); + this.app.log.info(`Server started at ${this.server.info.uri}`); + } - // @todo: remove this with the release of 3.0 - adds support for /api and /api/v2 - server.ext("onRequest", (request: Hapi.Request, h: Hapi.ResponseToolkit) => { - if (request.url) { - const path: string = request.url.pathname.replace("/v2", ""); - request.setUrl(request.url.search ? `${path}${request.url.search}` : path); - } + /** + * @returns {Promise} + * @memberof Server + */ + public async stop(): Promise { + console.log(this.server); - return h.continue; - }); + await this.server.stop(); - await mountServer(`Public ${name.toUpperCase()} API`, server); + this.app.log.info(`Server stopped at ${this.server.info.uri}`); } } diff --git a/packages/core-api/src/service-provider.ts b/packages/core-api/src/service-provider.ts index f5672ec420..d8f33382b3 100644 --- a/packages/core-api/src/service-provider.ts +++ b/packages/core-api/src/service-provider.ts @@ -1,31 +1,72 @@ import { Providers } from "@arkecosystem/core-kernel"; +import expandHomeDir from "expand-home-dir"; +import { readFileSync } from "fs"; import { Server } from "./server"; export class ServiceProvider extends Providers.ServiceProvider { public async register(): Promise { - if (!this.config().get("enabled")) { - this.app.log.info("Public API is disabled"); - return; + this.app.bind("api.options").toConstantValue(this.config()); + + if (this.config().get("server.http.enabled")) { + this.app + .bind("api.http") + .to(Server) + .inSingletonScope(); + + const options: { + enabled: boolean; + host: string; + port: number; + } = { ...this.config().get("server.http") }; + + delete options.enabled; + + await this.app.get("api.http").init(options, this.config().get("plugins")); } - this.app.bind("api.options").toConstantValue(this.config().all()); + if (this.config().get("server.https.enabled")) { + this.app + .bind("api.https") + .to(Server) + .inSingletonScope(); + + const options: { + enabled: boolean; + host: string; + port: number; + tls: { + key: string; + cert: string; + }; + } = { ...this.config().get("server.https") }; + + delete options.enabled; - this.app - .bind("api") - .to(Server) - .inSingletonScope(); + options.tls.key = readFileSync(expandHomeDir(options.tls.key)).toString(); + options.tls.cert = readFileSync(expandHomeDir(options.tls.cert)).toString(); + + await this.app.get("api.https").init(options, this.config().get("plugins")); + } } public async boot(): Promise { - await this.app.get("api").start(); + if (this.config().get("server.http.enabled")) { + await this.app.get("api.http").start(); + } + + if (this.config().get("server.https.enabled")) { + await this.app.get("api.https").start(); + } } public async dispose(): Promise { - if (this.config().get("enabled")) { - this.app.log.info(`Stopping Public API`); + if (this.config().get("server.http.enabled")) { + await this.app.get("api.http").stop(); + } - await this.app.get("api").stop(); + if (this.config().get("server.https.enabled")) { + await this.app.get("api.https").stop(); } } } diff --git a/packages/core-api/src/services/cache.ts b/packages/core-api/src/services/cache.ts index d674fdbdc5..a6260f2df9 100644 --- a/packages/core-api/src/services/cache.ts +++ b/packages/core-api/src/services/cache.ts @@ -12,8 +12,7 @@ export class ServerCache { public method(name: string, method: ServerMethod, expiresIn: number, argsCallback?: any): this { let options = {}; - // @ts-ignore - if (this.server.app.config.cache.enabled) { + if (app.get("api.options").get("plugins.cache.enabled")) { options = { cache: { expiresIn: expiresIn * 1000, @@ -34,7 +33,7 @@ export class ServerCache { } private getCacheTimeout(): number | boolean { - const { generateTimeout } = app.get("api.options").cache; + const { generateTimeout } = app.get("api.options").get("plugins.cache"); return JSON.parse(generateTimeout); } diff --git a/packages/core-kernel/src/bootstrap/app/index.ts b/packages/core-kernel/src/bootstrap/app/index.ts index 66ae558834..a79033604f 100644 --- a/packages/core-kernel/src/bootstrap/app/index.ts +++ b/packages/core-kernel/src/bootstrap/app/index.ts @@ -1,5 +1,5 @@ // Foundation -export * from "./register-error-handler"; +// export * from "./register-error-handler"; export * from "./register-base-configuration"; export * from "./register-base-service-providers"; export * from "./register-base-bindings"; @@ -10,7 +10,7 @@ export * from "./register-base-paths"; export * from "./load-environment-variables"; export * from "./load-configuration"; export * from "./load-cryptography"; -export * from "./watch-configuration"; +// export * from "./watch-configuration"; // Service Providers export * from "./load-service-providers"; diff --git a/packages/core-kernel/src/contracts/kernel/application.ts b/packages/core-kernel/src/contracts/kernel/application.ts index 034f290b5c..2913590f2a 100644 --- a/packages/core-kernel/src/contracts/kernel/application.ts +++ b/packages/core-kernel/src/contracts/kernel/application.ts @@ -5,6 +5,11 @@ import { EventDispatcher } from "./events"; import { Logger } from "./log"; export interface Application { + /** + * Get an instance of the application container. + */ + readonly container: Container.Container; + /** * Get an instance of the application logger. */ diff --git a/packages/core/bin/config/testnet/packages.js b/packages/core/bin/config/testnet/packages.js index 2832ff0a97..d2c5497c33 100644 --- a/packages/core/bin/config/testnet/packages.js +++ b/packages/core/bin/config/testnet/packages.js @@ -65,30 +65,34 @@ module.exports = [{ port: process.env.CORE_API_PORT || 4003, } }, - { - package: "@arkecosystem/core-wallet-api", - }, { - package: "@arkecosystem/core-webhooks", - options: { - 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"], - }, - }, - }, { - package: "@arkecosystem/core-forger", - }, { - package: "@arkecosystem/core-exchange-json-rpc", - options: { - 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"], - }, - }, { - package: "@arkecosystem/core-snapshots", - } + // { + // package: "@arkecosystem/core-wallet-api", + // }, + // { + // package: "@arkecosystem/core-webhooks", + // options: { + // 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"], + // }, + // }, + // }, + // { + // package: "@arkecosystem/core-forger", + // }, + // { + // package: "@arkecosystem/core-exchange-json-rpc", + // options: { + // 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"], + // }, + // }, + // { + // package: "@arkecosystem/core-snapshots", + // } ]; diff --git a/yarn.lock b/yarn.lock index e9a96d1aae..03e1ca26e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -702,30 +702,6 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@bugsnag/browser@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@bugsnag/browser/-/browser-6.4.0.tgz#96211bd3fcff48c91f91fdc270c02d2665585189" - integrity sha512-f6KUTIQ4hvJ35MxU35ORsyWwbLPxQ/vFOJdmYwvqrpH1FJSMJjTEmjW4pZbXY0iFkyJ0utYdMVek4ezY7xLtJg== - -"@bugsnag/js@^6.3.2": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@bugsnag/js/-/js-6.4.0.tgz#1690cc0de987198819c4cea4446f2a8119a034dc" - integrity sha512-4wcNz3fY4Cos3JPWxHz0IADRqFVIIPclX5peihQmSRJgPqpKuZlnwNVzIpp3VPw00cHjEAXKKID7CCv9NuQObA== - dependencies: - "@bugsnag/browser" "^6.4.0" - "@bugsnag/node" "^6.4.0" - -"@bugsnag/node@^6.4.0": - version "6.4.0" - resolved "https://registry.yarnpkg.com/@bugsnag/node/-/node-6.4.0.tgz#946af87eb2dd284901ac3c05faf979d8664198a2" - integrity sha512-vr/1u59oQ0batGfPGzlk9Mhg2n7TV/pwEpbaYBA8nsdMF3wiEsJkvpkq1tvixOSClzdVfI1h85v1IrHOFOgXaQ== - dependencies: - byline "^5.0.0" - error-stack-parser "^2.0.2" - iserror "^0.0.2" - pump "^3.0.0" - stack-generator "^2.0.3" - "@cnakazawa/watch@^1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" @@ -2266,62 +2242,6 @@ dependencies: any-observable "^0.3.0" -"@sentry/core@5.6.2": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.6.2.tgz#8c5477654a83ebe41a72e86a79215deb5025e418" - integrity sha512-grbjvNmyxP5WSPR6UobN2q+Nss7Hvz+BClBT8QTr7VTEG5q89TwNddn6Ej3bGkaUVbct/GpVlI3XflWYDsnU6Q== - dependencies: - "@sentry/hub" "5.6.1" - "@sentry/minimal" "5.6.1" - "@sentry/types" "5.6.1" - "@sentry/utils" "5.6.1" - tslib "^1.9.3" - -"@sentry/hub@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.6.1.tgz#9f355c0abcc92327fbd10b9b939608aa4967bece" - integrity sha512-m+OhkIV5yTAL3R1+XfCwzUQka0UF/xG4py8sEfPXyYIcoOJ2ZTX+1kQJLy8QQJ4RzOBwZA+DzRKP0cgzPJ3+oQ== - dependencies: - "@sentry/types" "5.6.1" - "@sentry/utils" "5.6.1" - tslib "^1.9.3" - -"@sentry/minimal@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.6.1.tgz#09d92b26de0b24555cd50c3c33ba4c3e566009a1" - integrity sha512-ercCKuBWHog6aS6SsJRuKhJwNdJ2oRQVWT2UAx1zqvsbHT9mSa8ZRjdPHYOtqY3DoXKk/pLUFW/fkmAnpdMqRw== - dependencies: - "@sentry/hub" "5.6.1" - "@sentry/types" "5.6.1" - tslib "^1.9.3" - -"@sentry/node@^5.5.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@sentry/node/-/node-5.6.2.tgz#4b62f056031da65cad78220d48c546b8bfbfaed7" - integrity sha512-A9CELco6SjF4zt8iS1pO3KdUVI2WVhtTGhSH6X04OVf2en1fimPR+Vs8YVY/04udwd7o+3mI6byT+rS9+/Qzow== - dependencies: - "@sentry/core" "5.6.2" - "@sentry/hub" "5.6.1" - "@sentry/types" "5.6.1" - "@sentry/utils" "5.6.1" - cookie "0.3.1" - https-proxy-agent "2.2.1" - lru_map "0.3.3" - tslib "^1.9.3" - -"@sentry/types@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.6.1.tgz#5915e1ee4b7a678da3ac260c356b1cb91139a299" - integrity sha512-Kub8TETefHpdhvtnDj3kKfhCj0u/xn3Zi2zIC7PB11NJHvvPXENx97tciz4roJGp7cLRCJsFqCg4tHXniqDSnQ== - -"@sentry/utils@5.6.1": - version "5.6.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.6.1.tgz#69d9e151e50415bc91f2428e3bcca8beb9bc2815" - integrity sha512-rfgha+UsHW816GqlSRPlniKqAZylOmQWML2JsujoUP03nPu80zdN43DK9Poy/d9OxBxv0gd5K2n+bFdM2kqLQQ== - dependencies: - "@sentry/types" "5.6.1" - tslib "^1.9.3" - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3193,11 +3113,6 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== -"@types/raygun@^0.10.1": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@types/raygun/-/raygun-0.10.2.tgz#798538491f1821a4e6f5c83184e798c6b92e397f" - integrity sha512-vdBRrp/Z4U0904H9Zr1SSFT1Ib5xZIaAm+I7/BK3lgXnaOiaCB5NJvIMWB3BZC84abuwuO8fgGRV5BNpzEbWtA== - "@types/readable-stream@^2.3.2": version "2.3.4" resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-2.3.4.tgz#993d7cab73f392766716c5f18376d078ccbe2cbe" @@ -3564,7 +3479,7 @@ acorn@^7.0.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.0.0.tgz#26b8d1cd9a9b700350b71c0905546f64d1284e7a" integrity sha512-PaF/MduxijYYt7unVGRuds1vBC9bFxbNf+VWqhOClfdgy7RlVkQqt610ig1/yxTgsDIfW1cWDel5EBbOy3jdtQ== -agent-base@4, agent-base@^4.1.0, agent-base@^4.2.0, agent-base@^4.3.0: +agent-base@4, agent-base@^4.2.0, agent-base@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== @@ -3593,11 +3508,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^3.2.0" -airbrake-js@^1.6.8: - version "1.6.8" - resolved "https://registry.yarnpkg.com/airbrake-js/-/airbrake-js-1.6.8.tgz#a2b7e7587ebd8b578bce8cb5214b060b385c66fc" - integrity sha512-ru2A1lyXv1cqAPbN3T27cUT4HphH0eFQzp0xDVzXpiaUy3pMEBU6i06cGueHavK4CyEEhL6mKQrIshcNsIqwlg== - ajv-keywords@^3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" @@ -3920,11 +3830,6 @@ async@^3.1.0: resolved "https://registry.yarnpkg.com/async/-/async-3.1.0.tgz#42b3b12ae1b74927b5217d8c0016baaf62463772" integrity sha512-4vx/aaY6j/j3Lw3fbCHNWP0pPaTCew3F6F3hYyl/tHs/ndmV1q7NW9T5yuJ2XAGwdQrP+6Wu20x06U4APo/iQQ== -async@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/async/-/async-1.2.1.tgz#a4816a17cd5ff516dfa2c7698a453369b9790de0" - integrity sha1-pIFqF81f9RbfosdpikUzabl5DeA= - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -4369,7 +4274,7 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= -buffer-from@1.x, buffer-from@>=1.1, buffer-from@^1.0.0: +buffer-from@1.x, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -5100,11 +5005,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -console-polyfill@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/console-polyfill/-/console-polyfill-0.3.0.tgz#84900902a18c47a5eba932be75fa44d23e8af861" - integrity sha512-w+JSDZS7XML43Xnwo2x5O5vxB0ID7T5BdqDtyqT6uiCAX2kZAgcWxNaGqT97tZfSHzfOcvrfsDAodKcJ3UvnXQ== - content-disposition@0.5.3: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" @@ -5219,11 +5119,6 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" - integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= - cookie@0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" @@ -5487,13 +5382,6 @@ debuglog@^1.0.1: resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= -decache@^3.0.5: - version "3.1.0" - resolved "https://registry.yarnpkg.com/decache/-/decache-3.1.0.tgz#4f5036fbd6581fcc97237ac3954a244b9536c2da" - integrity sha1-T1A2+9ZYH8yXI3rDlUokS5U2wto= - dependencies: - find "^0.2.4" - decamelize-keys@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" @@ -5551,18 +5439,6 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.0.tgz#3103cdf8ab6d32cf4a8df7865458f2b8d33f3745" - integrity sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw== - dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" @@ -6012,20 +5888,6 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -error-stack-parser@1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-1.3.3.tgz#fada6e3a9cd2b0e080e6d6fc751418649734f35c" - integrity sha1-+tpuOpzSsOCA5tb8dRQYZJc081w= - dependencies: - stackframe "^0.3.1" - -error-stack-parser@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/error-stack-parser/-/error-stack-parser-2.0.3.tgz#9d3c000fb9f5c461f7c4e63c1aa75373ac7aaa36" - integrity sha512-vRC4rKv87twMZy92X4+TmUdv3iYMsmePbpG/YguHsfzmZ8bYJZYYep7yrXH09yFUaCEPKgNK5X79+Yq7hwLVOA== - dependencies: - stackframe "^1.0.4" - es-abstract@^1.5.1: version "1.13.0" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" @@ -6664,13 +6526,6 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find@^0.2.4: - version "0.2.9" - resolved "https://registry.yarnpkg.com/find/-/find-0.2.9.tgz#4b73f1ff9e56ad91b76e716407fe5ffe6554bb8c" - integrity sha1-S3Px/55WrZG3bnFkB/5f/mVUu4w= - dependencies: - traverse-chain "~0.1.0" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -7465,14 +7320,6 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -https-proxy-agent@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz#51552970fa04d723e04c56d04178c3f92592bbc0" - integrity sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ== - dependencies: - agent-base "^4.1.0" - debug "^3.1.0" - https-proxy-agent@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.2.tgz#271ea8e90f836ac9f119daccd39c19ff7dfb0793" @@ -7777,11 +7624,6 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" -is-arguments@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" - integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" @@ -8132,11 +7974,6 @@ is-yarn-global@^0.3.0: resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw== -is_js@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/is_js/-/is_js-0.9.0.tgz#0ab94540502ba7afa24c856aa985561669e9c52d" - integrity sha1-CrlFQFArp6+iTIVqqYVWFmnpxS0= - isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" @@ -8154,11 +7991,6 @@ isemail@3.x.x: dependencies: punycode "2.x.x" -iserror@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/iserror/-/iserror-0.0.2.tgz#bd53451fe2f668b9f2402c1966787aaa2c7c0bf5" - integrity sha1-vVNFH+L2aLnyQCwZZnh6qix8C/U= - isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -8748,7 +8580,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stringify-safe@5.x.x, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.0, json-stringify-safe@~5.0.1: +json-stringify-safe@5.x.x, json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= @@ -9451,16 +9283,6 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@~2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" - integrity sha1-bGWGGb7PFAMdDQtZSxYELOTcBj0= - -lru_map@0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/lru_map/-/lru_map-0.3.3.tgz#b5c8351b9464cbd750335a79650a0ec0e56118dd" - integrity sha1-tcg1G5Rky9dQM1p5ZQoOwOVhGN0= - lunr@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.6.tgz#f278beee7ffd56ad86e6e478ce02ab2b98c78dd5" @@ -10080,21 +9902,6 @@ nock@^11.0.0-beta.17: mkdirp "^0.5.0" propagate "^2.0.0" -nock@~9: - version "9.6.1" - resolved "https://registry.yarnpkg.com/nock/-/nock-9.6.1.tgz#d96e099be9bc1d0189a77f4490bbbb265c381b49" - integrity sha512-EDgl/WgNQ0C1BZZlASOQkQdE6tAWXJi8QQlugqzN64JJkvZ7ILijZuG24r4vCC7yOfnm6HKpne5AGExLGCeBWg== - dependencies: - chai "^4.1.2" - debug "^3.1.0" - deep-equal "^1.0.0" - json-stringify-safe "^5.0.1" - lodash "^4.17.5" - mkdirp "^0.5.0" - propagate "^1.0.0" - qs "^6.5.1" - semver "^5.5.0" - node-alias@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/node-alias/-/node-alias-1.0.4.tgz#1f1b916b56b9ea241c0135f97ced6940f556f292" @@ -10403,21 +10210,11 @@ object-hash@^1.3.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-1.3.1.tgz#fde452098a951cb145f039bb7d455449ddc126df" integrity sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA== -object-is@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" - integrity sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY= - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object-to-human-string@0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/object-to-human-string/-/object-to-human-string-0.0.3.tgz#7feb121a79496248ef8daa160da23862c09e89f2" - integrity sha1-f+sSGnlJYkjvjaoWDaI4YsCeifI= - object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" @@ -11355,11 +11152,6 @@ promzard@^0.3.0: dependencies: read "1" -propagate@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-1.0.0.tgz#00c2daeedda20e87e3782b344adba1cddd6ad709" - integrity sha1-AMLa7t2iDofjeCs0Stuhzd1q1wk= - propagate@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" @@ -11483,11 +11275,6 @@ qs@6.7.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== -qs@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.8.0.tgz#87b763f0d37ca54200334cd57bb2ef8f68a1d081" - integrity sha512-tPSkj8y92PfZVbinY1n84i1Qdx75lZjMQYx9WZhnkofyxzw2r7Ho39G3/aEvSUdebxpnnM4LZJCtvE/Aq3+s9w== - qs@~6.5.2: version "6.5.2" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" @@ -11564,15 +11351,6 @@ raw-body@^2.2.0: iconv-lite "0.4.24" unpipe "1.0.0" -raygun@^0.10.1: - version "0.10.1" - resolved "https://registry.yarnpkg.com/raygun/-/raygun-0.10.1.tgz#093b26765f5d42114673c082e6216c7e472418fe" - integrity sha512-wXZJ/898b8CCGTsAhIiZ/I4fnTna5W1l3aXv+H675G9jV7PueZ98X214OZ0Ou2kLcaGpsjPnOpypfJU9YvmEDg== - dependencies: - nock "~9" - object-to-human-string "0.0.3" - stack-trace "0.0.6" - rc-config-loader@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/rc-config-loader/-/rc-config-loader-2.0.4.tgz#fe23e26a87e2ec07541b29e7f37bfd75807a4c36" @@ -11820,13 +11598,6 @@ regexp-tree@^0.1.6: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.12.tgz#28eaaa6e66eeb3527c15108a3ff740d9e574e420" integrity sha512-TsXZ8+cv2uxMEkLfgwO0E068gsNMLfuYwMMhiUxf0Kw2Vcgzq93vgl6wIlIYuPmfMqMjfQ9zAporiozqCnwLuQ== -regexp.prototype.flags@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz#6b30724e306a27833eeb171b66ac8890ba37e41c" - integrity sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA== - dependencies: - define-properties "^1.1.2" - regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -11908,13 +11679,6 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request-ip@~2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/request-ip/-/request-ip-2.0.2.tgz#deeae6d4af21768497db8cd05fa37143f8f1257e" - integrity sha1-3urm1K8hdoSX24zQX6NxQ/jxJX4= - dependencies: - is_js "^0.9.0" - request-promise-core@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.2.tgz#339f6aababcafdb31c799ff158700336301d3346" @@ -12096,24 +11860,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rollbar@^2.8.1: - version "2.12.3" - resolved "https://registry.yarnpkg.com/rollbar/-/rollbar-2.12.3.tgz#ae0e4c5ba58528ea4483a9b6590045c324d22d25" - integrity sha512-r+d3YiRr8U5ucpI19YzO081UIN7vXRTRsRMtSnLwgfoOUmCMHJPklYMbV0bhfGYyGpq7LAej7N89O6aI3zMGtw== - dependencies: - async "~1.2.1" - buffer-from ">=1.1" - console-polyfill "0.3.0" - debug "2.6.9" - error-stack-parser "1.3.3" - json-stringify-safe "~5.0.0" - lru-cache "~2.2.1" - request-ip "~2.0.1" - source-map ">=0.5.0" - uuid "3.0.x" - optionalDependencies: - decache "^3.0.5" - rollup-plugin-commonjs@^10.0.1: version "10.1.0" resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz#417af3b54503878e084d127adf4d1caf8beb86fb" @@ -12952,11 +12698,6 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= -source-map@>=0.5.0: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - source-map@^0.5.0, source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -13071,33 +12812,11 @@ ssri@^6.0.0, ssri@^6.0.1: dependencies: figgy-pudding "^3.5.1" -stack-generator@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/stack-generator/-/stack-generator-2.0.3.tgz#bb74385c67ffc4ccf3c4dee5831832d4e509c8a0" - integrity sha512-kdzGoqrnqsMxOEuXsXyQTmvWXZmG0f3Ql2GDx5NtmZs59sT2Bt9Vdyq0XdtxUi58q/+nxtbF9KOQ9HkV1QznGg== - dependencies: - stackframe "^1.0.4" - -stack-trace@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.6.tgz#1e719bd6a2629ff09c189e17a9ef902a94fc5db0" - integrity sha1-HnGb1qJin/CcGJ4Xqe+QKpT8XbA= - stack-utils@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== -stackframe@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-0.3.1.tgz#33aa84f1177a5548c8935533cbfeb3420975f5a4" - integrity sha1-M6qE8Rd6VUjIk1Uzy/6zQgl19aQ= - -stackframe@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/stackframe/-/stackframe-1.0.4.tgz#357b24a992f9427cba6b545d96a14ed2cbca187b" - integrity sha512-to7oADIniaYwS3MhtCa/sQhrxidCCQiF/qp4/m5iN3ipf0Y7Xlri0f6eG29r08aL7JYl8n32AF3Q5GYBZ7K8vw== - statehood@6.x.x: version "6.0.9" resolved "https://registry.yarnpkg.com/statehood/-/statehood-6.0.9.tgz#b347ae19818aec7fc26645fe1ec6a61928a57a3c" @@ -13675,11 +13394,6 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -traverse-chain@~0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" - integrity sha1-YdvC1Ttp/2CRoSoWj9fUMxB+QPE= - "traverse@>=0.3.0 <0.4": version "0.3.9" resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" @@ -14126,11 +13840,6 @@ uuid-parse@^1.0.0: resolved "https://registry.yarnpkg.com/uuid-parse/-/uuid-parse-1.1.0.tgz#7061c5a1384ae0e1f943c538094597e1b5f3a65b" integrity sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A== -uuid@3.0.x: - version "3.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.0.1.tgz#6544bba2dfda8c1cf17e629a3a305e2bb1fee6c1" - integrity sha1-ZUS7ot/ajBzxfmKaOjBeK7H+5sE= - uuid@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04"