@practica/create-node-app
Version:
Create Node.js app that is packed with best practices AND strive for simplicity
78 lines (70 loc) • 2.57 kB
text/typescript
import * as configurationProvider from '@practica/configuration-provider';
import cors from '@fastify/cors';
import fastifySwagger from '@fastify/swagger';
import fastifySwaggerUi from '@fastify/swagger-ui';
import Fastify, { FastifyInstance } from 'fastify';
import { Server } from 'http';
import { AddressInfo } from 'net';
import { fastifyErrorMiddleware } from '@practica/error-handling';
import { JWTVerifier, RequestContext } from '@practica/common-fastify-plugins';
import { logger } from '@practica/logger';
import { OpenAPIOptions, OpenAPIUIOptions } from './open-api-options';
import configurationSchema from '../../config';
import { routes } from './routes';
import { requestContextPlugin } from './request-context';
let httpServer: Server | undefined;
// ️️️✅ Best Practice: API exposes a start/stop function to allow testing control WHEN this should happen
export async function startWebServer(): Promise<AddressInfo> {
logger.info(`Starting the web server now`);
configurationProvider.initializeAndValidate(configurationSchema);
const app = Fastify({
logger: true,
});
app.setErrorHandler(fastifyErrorMiddleware);
await generateOpenAPI(app);
registerCommonPlugins(app);
registerAllRoutes(app);
const connectionAddress = await listenToRequests(app);
httpServer = app.server;
return connectionAddress;
}
export async function stopWebServer() {
if (httpServer) {
await httpServer.close();
httpServer = undefined;
}
}
async function generateOpenAPI(app: FastifyInstance) {
app.register(fastifySwagger, OpenAPIOptions);
app.register(fastifySwaggerUi, OpenAPIUIOptions);
}
async function registerAllRoutes(app: FastifyInstance) {
app.register(routes, { prefix: '/order' });
}
async function listenToRequests(app: FastifyInstance): Promise<AddressInfo> {
return new Promise((resolve, reject) => {
const portToListenTo = configurationProvider.getValue('port');
const webServerPort = portToListenTo
? parseInt(portToListenTo, 10)
: undefined;
app.listen({ host: '0.0.0.0', port: webServerPort }, (err) => {
if (err) {
reject(err);
// eslint-disable-next-line
process.exit(1);
}
resolve(app.server.address() as AddressInfo);
});
});
}
async function registerCommonPlugins(app: FastifyInstance) {
app.register(RequestContext);
app.register(JWTVerifier, {
secret: configurationProvider.getValue('jwtTokenSecret'),
});
app.register(requestContextPlugin);
app.register(cors, {
origin: '*',
methods: ['POST'],
});
}