import * as Hapi from "@hapi/hapi"; import * as http from "http"; import type { HttpTerminator } from "http-terminator"; import * as Glue from "@hapi/glue"; import * as Promster from "@promster/hapi"; import figlet from "figlet"; import PinoPlugin from "hapi-pino"; import { createServer as createPrometheusServer } from "@promster/server"; import { createHttpTerminator } from "http-terminator"; import { getPrettyPrint } from "./logger"; import RequestIdPlugin from "./plugins/request-id"; import StatusPlugin from "./plugins/status"; import ConfigPlugin from "./plugins/config"; import { IMetamigoConfig } from "./config"; export interface Server { hapiServer: Hapi.Server; promServer?: http.Server; promTerminator?: HttpTerminator; } export const deployment = async ( manifest: Glue.Manifest, config: T, start = false ): Promise => { const hapiServer: Hapi.Server = await Glue.compose(manifest); await hapiServer.initialize(); if (!start) return { hapiServer }; await announce(config); await hapiServer.start(); const { port, address } = config.metrics; const promServer = await createPrometheusServer({ port, hostname: address, }); const promTerminator = createHttpTerminator({ server: promServer, }); console.log(` 🚀 Server listening on http://${hapiServer.info.address}:${hapiServer.info.port} Metrics listening on http://${address}:${port} `); return { hapiServer, promServer, promTerminator, }; }; export const stopDeployment = async (server: Server): Promise => { await server.hapiServer.stop(); if (server.promTerminator) await server.promTerminator.terminate(); }; export const defaultPlugins = ( config: T ): string[] | Glue.PluginObject[] | Array => { const { logRequestStart, logRequestComplete, logRequestPayload, logRequestQueryParams, level, redact, ignorePaths, ignoreTags, requestIdHeader, } = config.logging; const plugins = [ { plugin: ConfigPlugin, options: { config } }, { plugin: PinoPlugin, options: { prettyPrint: getPrettyPrint(config), level, logRequestStart, logRequestComplete, logPayload: logRequestPayload, logQueryParams: logRequestQueryParams, redact: { paths: redact, remove: true, }, ignorePaths, ignoreTags, }, }, { plugin: RequestIdPlugin, options: { header: requestIdHeader, }, }, { plugin: StatusPlugin }, { plugin: Promster.createPlugin() }, ]; // @ts-ignore return plugins; }; export const announce = async ( config: T ): Promise => new Promise((resolve, reject) => { // @ts-expect-error figlet.text( config.meta.name, { font: config.meta.figletFont }, (err, text) => { if (err) reject(err); console.log(`${text}`); resolve(); } ); });