link-stack/metamigo-common/hapi.ts
2023-02-13 12:41:30 +00:00

123 lines
3 KiB
TypeScript

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 <T extends IMetamigoConfig>(
manifest: Glue.Manifest,
config: T,
start = false
): Promise<Server> => {
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<void> => {
await server.hapiServer.stop();
if (server.promTerminator) await server.promTerminator.terminate();
};
export const defaultPlugins = <T extends IMetamigoConfig>(
config: T
): string[] | Glue.PluginObject[] | Array<string | Glue.PluginObject> => {
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 <T extends IMetamigoConfig>(
config: T
): Promise<void> =>
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();
}
);
});