2023-07-23 16:04:49 -07:00

101 lines
2.2 KiB
TypeScript

import fastify, { FastifyInstance } from 'fastify';
import etags from '@fastify/etag';
import compress, { FastifyCompressOptions } from '@fastify/compress';
import formbody from '@fastify/formbody';
import { pino } from 'pino';
export type ServerStatus = 'unstarted' | 'starting' | 'ready' | 'closing' | 'closed';
export interface HttpConfig {
address: string;
port: number;
tls: false | {
key: string;
cert: string;
};
exposed_url?: string;
etag?: boolean;
compress?: false | FastifyCompressOptions['encodings'];
cache_control?: {
static_assets: string;
};
}
export interface BaseHttpDependencies {
logger: pino.Logger;
}
export interface RegisterHttpEndpoint<Deps extends BaseHttpDependencies> {
(server: FastifyInstance, conf: HttpConfig, deps: Deps): void;
}
export interface ContentParser {
(server: FastifyInstance, media_types: string[]): void;
}
export interface HttpParams<Deps extends BaseHttpDependencies> {
content_parsers: Record<string, ContentParser>;
endpoints: RegisterHttpEndpoint<Deps>[];
}
export function create_http_server<Deps extends BaseHttpDependencies>(conf: HttpConfig, deps: Deps, params: HttpParams<Deps>) {
const server = fastify({
logger: deps.logger
});
// Register error handlers
// todo: register error handlers...
// Register endpoints
for (const endpoint of params.endpoints) {
endpoint(server, conf, deps);
}
let resolve: () => void;
let status: ServerStatus = 'unstarted';
const ready = new Promise<void>((onResolve) => {
resolve = onResolve;
});
return {
server,
ready,
get status() {
return status;
},
//
async setup_plugins() {
await Promise.all([
server.register(formbody),
conf.etag ? server.register(etags) : null,
conf.compress ? server.register(compress, { encodings: conf.compress }) : null,
]);
},
async listen() {
status = 'starting';
try {
await server.listen({ port: conf.port, host: conf.address });
}
catch (error) {
server.log.error(error);
process.exit(1);
}
await server.ready();
status = 'ready';
resolve();
},
async close() {
status = 'closing';
await server.close();
status = 'closed';
},
};
}