fase(16): integrations module
This commit is contained in:
111
dist/modules/integrations/infrastructure/http/IntegrationsController.js
vendored
Normal file
111
dist/modules/integrations/infrastructure/http/IntegrationsController.js
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createIntegrationsRouter = createIntegrationsRouter;
|
||||
const express_1 = require("express");
|
||||
const Integration_1 = require("../../domain/entities/Integration");
|
||||
const WebhookEndpoint_1 = require("../../domain/entities/WebhookEndpoint");
|
||||
const IntegrationType_1 = require("../../domain/value-objects/IntegrationType");
|
||||
function createIntegrationsRouter(deps) {
|
||||
const router = (0, express_1.Router)();
|
||||
const { integrationRepo, webhookRepo } = deps;
|
||||
// ─── Integrations CRUD ──────────────────────────────────────────────────────
|
||||
router.get('/', async (_req, res) => {
|
||||
const items = await integrationRepo.findAll();
|
||||
res.json(items.map(serializeIntegration));
|
||||
});
|
||||
router.post('/', async (req, res) => {
|
||||
const { name, type, config } = req.body;
|
||||
if (!name || !type) {
|
||||
res.status(400).json({ error: 'name and type are required' });
|
||||
return;
|
||||
}
|
||||
let intType;
|
||||
try {
|
||||
intType = IntegrationType_1.IntegrationType.fromString(type);
|
||||
}
|
||||
catch {
|
||||
res.status(400).json({ error: `Invalid integration type: ${type}` });
|
||||
return;
|
||||
}
|
||||
const integration = Integration_1.Integration.create({ name, type: intType, config: config ?? {} });
|
||||
await integrationRepo.save(integration);
|
||||
res.status(201).json(serializeIntegration(integration));
|
||||
});
|
||||
router.get('/:id', async (req, res) => {
|
||||
const item = await integrationRepo.findById(req.params['id']);
|
||||
if (!item) {
|
||||
res.status(404).json({ error: 'Integration not found' });
|
||||
return;
|
||||
}
|
||||
res.json(serializeIntegration(item));
|
||||
});
|
||||
router.patch('/:id', async (req, res) => {
|
||||
const item = await integrationRepo.findById(req.params['id']);
|
||||
if (!item) {
|
||||
res.status(404).json({ error: 'Integration not found' });
|
||||
return;
|
||||
}
|
||||
const { enabled, config } = req.body;
|
||||
if (enabled === true)
|
||||
item.enable();
|
||||
else if (enabled === false)
|
||||
item.disable();
|
||||
if (config)
|
||||
item.updateConfig(config);
|
||||
await integrationRepo.update(item);
|
||||
res.json(serializeIntegration(item));
|
||||
});
|
||||
router.delete('/:id', async (req, res) => {
|
||||
await integrationRepo.delete(req.params['id']);
|
||||
res.status(204).end();
|
||||
});
|
||||
// ─── Webhook Endpoints ───────────────────────────────────────────────────────
|
||||
router.get('/webhooks/endpoints', async (_req, res) => {
|
||||
const endpoints = await webhookRepo.findAll();
|
||||
res.json(endpoints.map(serializeWebhook));
|
||||
});
|
||||
router.post('/webhooks/endpoints', async (req, res) => {
|
||||
const { url } = req.body;
|
||||
if (!url) {
|
||||
res.status(400).json({ error: 'url is required' });
|
||||
return;
|
||||
}
|
||||
const endpoint = WebhookEndpoint_1.WebhookEndpoint.create({ url });
|
||||
await webhookRepo.save(endpoint);
|
||||
res.status(201).json(serializeWebhook(endpoint));
|
||||
});
|
||||
router.delete('/webhooks/endpoints/:id', async (req, res) => {
|
||||
await webhookRepo.delete(req.params['id']);
|
||||
res.status(204).end();
|
||||
});
|
||||
return router;
|
||||
}
|
||||
function serializeIntegration(i) {
|
||||
return {
|
||||
id: i.id.toString(),
|
||||
name: i.name,
|
||||
type: i.type.value,
|
||||
enabled: i.enabled,
|
||||
config: maskSecrets(i.config),
|
||||
createdAt: i.createdAt.toISOString(),
|
||||
};
|
||||
}
|
||||
function serializeWebhook(ep) {
|
||||
return {
|
||||
id: ep.id.toString(),
|
||||
url: ep.url,
|
||||
enabled: ep.enabled,
|
||||
createdAt: ep.createdAt.toISOString(),
|
||||
lastDeliveredAt: ep.lastDeliveredAt?.toISOString() ?? null,
|
||||
lastStatus: ep.lastStatus ?? null,
|
||||
// Return the secret only once at creation (caller can see it from the first POST)
|
||||
};
|
||||
}
|
||||
function maskSecrets(config) {
|
||||
const masked = { ...config };
|
||||
for (const key of ['token', 'secret', 'password', 'apiKey']) {
|
||||
if (masked[key])
|
||||
masked[key] = '***';
|
||||
}
|
||||
return masked;
|
||||
}
|
||||
Reference in New Issue
Block a user