124 lines
3 KiB
TypeScript
124 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();
|
||
|
|
}
|
||
|
|
);
|
||
|
|
});
|