metis-desk/modules/companies/src/api/infrastructure/http/mail-configuration.routes.ts
David e099b8c507 feat(mail): implement mail configuration management with persistence and UI components
- Added migration scripts for mail configurations and revisions.
- Created persistence mapper for mail configurations and revisions.
- Developed Sequelize repository for mail configuration management.
- Introduced common schemas and types for mail configurations.
- Implemented API for fetching and saving mail configurations.
- Built React components for mail configuration forms and pages.
- Added internationalization support for mail-related texts in English and Spanish.
- Implemented feedback mechanism for API errors in mail components.
- Created tests for mail configuration components and functionality.
2026-10-04 23:06:07 +02:00

82 lines
2.7 KiB
TypeScript

import { type Application, type RequestHandler, type Response, Router } from "express";
import { z } from "zod/v4";
import {
MailItemParamsSchema,
MailParamsSchema,
SaveMailRequestSchema,
} from "../../../common/mail-configurations";
import type { MailConfigurationUseCases } from "../../application/mail-configuration.use-cases";
import { buildMailResponse } from "../../application/mail-configuration-response.builder";
function fail(response: Response, code: string) {
response
.status(code === "INVALID_REQUEST" ? 400 : code.endsWith("NOT_FOUND") ? 404 : 409)
.json({ code, requestId: response.getHeader("x-request-id") });
}
export function registerMailRoutes(
app: Application,
useCases: MailConfigurationUseCases,
authenticate: RequestHandler
) {
const router = Router();
router.get("/:companyId", (request, response, next) => {
const params = MailParamsSchema.safeParse(request.params);
if (!(params.success && z.strictObject({}).safeParse(request.query).success)) {
fail(response, "INVALID_REQUEST");
return;
}
useCases
.get(params.data.companyId)
.then((result) => {
if (!result.isSuccess) {
fail(response, result.error.code);
return;
}
response.json({
configurations: result.data.configurations.map((item) =>
buildMailResponse(item, result.data)
),
});
})
.catch(next);
});
for (const path of ["/:companyId", "/:companyId/:id/update"]) {
router.post(path, (request, response, next) => {
const params = (path.endsWith("update") ? MailItemParamsSchema : MailParamsSchema).safeParse(
request.params
);
const body = SaveMailRequestSchema.safeParse(request.body);
const actor = z
.object({ userId: z.uuid() })
.safeParse("session" in request ? request.session : undefined);
if (
!(
params.success &&
body.success &&
actor.success &&
z.strictObject({}).safeParse(request.query).success
)
) {
fail(response, "INVALID_REQUEST");
return;
}
const id =
"id" in params.data && typeof params.data.id === "string" ? params.data.id : undefined;
useCases
.save(params.data.companyId, id, body.data.values, actor.data.userId)
.then((result) => {
if (!result.isSuccess) {
fail(response, result.error.code);
return;
}
response.status(id ? 200 : 201).json({
configuration: buildMailResponse(result.data.configuration, result.data.context),
});
})
.catch(next);
});
}
app.use("/api/mail-configurations", authenticate, router);
}