@practica/create-node-app
Version:
Create Node.js app that is packed with best practices AND strive for simplicity
101 lines (93 loc) • 2.8 kB
text/typescript
import { IncomingMessage, Server, ServerResponse } from 'node:http';
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
import { Type } from '@sinclair/typebox';
import { FastifyBaseLogger, FastifyInstance } from 'fastify';
import { logger } from '@practica/logger';
import util from 'node:util';
import { orderSchema } from '../../domain/order-schema';
import * as newOrderUseCase from '../../domain/new-order-use-case';
export async function routes(app: FastifyWithTypeProvider) {
app.post('/', {
schema: {
body: orderSchema,
response: {
202: {
description:
'Successful acceptance of logs, but not necessarily processing',
type: 'null',
},
...commonHTTPResponses,
},
},
handler: async (request) => {
logger.info(
`Order API was called to add new Order ${util.inspect(request.body)}`
);
// ✅ Best Practice: Using the 3-tier architecture, routes/controller are kept thin, logic is encapsulated in a dedicated domain folder
const addOrderResponse = await newOrderUseCase.addOrder(request.body);
return addOrderResponse;
},
});
app.get('/:id', {
schema: {
response: {
200: orderSchema,
...commonHTTPResponses,
},
params: Type.Object({
id: Type.Number(),
}),
},
handler: async (request, response) => {
// Validation runs before the handler, request.params.id must be a number
logger.info(`Order API was called to get order by id`, {
orderId: request.params.id,
});
const result = await newOrderUseCase.getOrder(request.params.id);
if (!result) {
response.status(404);
return;
}
response.send(result);
},
});
app.delete('/:id', {
schema: {
response: {
204: orderSchema,
...commonHTTPResponses,
},
params: Type.Object({
id: Type.Number(),
}),
},
handler: async (request, response) => {
logger.info(`Order API was called to delete order`, {
orderId: request.params.id,
});
await newOrderUseCase.deleteOrder(request.params.id);
response.status(204).send();
},
});
}
const commonHTTPResponses = {
401: {
description: 'Unauthorized request, please provide a valid API key',
type: 'null',
},
400: {
description: 'Bad request, please check your request body',
type: 'null',
},
500: {
description: 'Internal server error, please try again later',
type: 'null',
},
};
export type FastifyWithTypeProvider = FastifyInstance<
Server<typeof IncomingMessage, typeof ServerResponse>,
IncomingMessage,
ServerResponse<IncomingMessage>,
FastifyBaseLogger,
TypeBoxTypeProvider
>;