Noções Básicas de Modularidade
7 exemplos para você começar com Modularidade em backends Node.js - 5 básicos e 2 intermediários.
Busque em todas as páginas da documentação
7 exemplos para você começar com Modularidade em backends Node.js - 5 básicos e 2 intermediários.
TypeScript 5.6+, Express 5 ou Fastify 5, e uma pasta src/ com pelo menos uma rota de API.
npm install express@5 zod
npm install -D typescript@5.6 tsxO manipulador analisa o HTTP e delega.
// infrastructure/http/orders-router.ts
import express from "express";
import { createOrder } from "../../application/create-order";
export const ordersRouter = express.Router();
ordersRouter.post("/", async (req, res, next) => {
try {
const order = await createOrder(req.body);
res.status(201).json({ data: order });
} catch (err) {
next(err);
}
});createOrder não tem importações do ExpressRelacionado: Casos de Uso e Serviços - camada de aplicação
// application/create-order.ts
import type { OrderRepository } from "../domain/ports/order-repository";
export type CreateOrderDeps = { orders: OrderRepository };
export async function createOrder(
deps: CreateOrderDeps,
input: { customerId: string; sku: string; qty: number }
) {
if (input.qty <= 0) throw new Error("INVALID_QTY");
const order = { id: crypto.randomUUID(), ...input, status: "pending" as const };
await deps.orders.save(order);
return order;
}OrderRepository em memória// domain/ports/order-repository.ts
export type Order = {
id: string;
customerId: string;
sku: string;
qty: number;
status: "pending" | "shipped";
};
export interface OrderRepository {
save(order: Order): Promise<void>;
findById(id: string): Promise<Order | null>;
}infrastructure/ implementa a portaRelacionado: Padrão Repository - duplos de teste
Permitido:
infrastructure/http -> application -> domain
Proibido:
domain -> express
domain -> infrastructure
application -> tipo Request do expressno-restricted-imports codifica a regra em CIRelacionado: Melhores Práticas de Modularidade - checklist de aplicação
// main.ts
import express from "express";
import { ordersRouter } from "./infrastructure/http/orders-router";
import { PostgresOrderRepository } from "./infrastructure/postgres-order-repository";
import { createOrderHandler } from "./infrastructure/http/create-order-handler";
const orders = new PostgresOrderRepository(pool);
const app = express();
app.use(express.json());
app.use("/orders", createOrderHandler({ orders }));
app.listen(3000);main.ts conhece classes concretasRelacionado: Padrões de Injeção de Dependência - manual vs Awilix vs Nest
src/
├── modules/orders/ # módulo de recurso - possui regras de pedido
├── modules/billing/
└── shared/
├── errors.ts # classe base AppError
└── logger.ts # instância pinoshared/ não tem regras de negócio como cálculo de impostosbilling a possui e expõe um serviçoshared/utils.tsimport { describe, it, expect } from "node:test";
import { createOrder } from "../application/create-order";
describe("createOrder", () => {
it("salva pedido válido", async () => {
const saved: unknown[] = [];
const orders = { save: async (o: unknown) => { saved.push(o); }, findById: async () => null };
const result = await createOrder({ orders }, { customerId: "c1", sku: "SKU1", qty: 2 });
expect(result.status).toBe("pending");
expect(saved).toHaveLength(1);
});
});node:test executa em milissegundossupertest, sem vinculação de portaVersões da Stack: Esta página foi escrita para Node.js 24.18.0 (LTS Ativo), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, e NestJS 11.
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026