Commit 8: Plugin-System (Scanner erweitern, Geräte importieren, Icons)

This commit is contained in:
2026-07-19 10:14:43 +02:00
parent 6a7eb3dfe5
commit 986de50963
20 changed files with 517 additions and 20 deletions

View File

@@ -0,0 +1,61 @@
import type { FastifyInstance } from "fastify";
import * as deviceRepo from "../db/repositories/devices.js";
import * as logRepo from "../db/repositories/logs.js";
import { getLoadedPlugins, getPlugin } from "../plugins/loader.js";
export async function pluginRoutes(app: FastifyInstance): Promise<void> {
app.get("/api/plugins", async () => {
return getLoadedPlugins().map(({ plugin, capabilities }) => ({
name: plugin.name,
version: plugin.version,
description: plugin.description,
capabilities,
}));
});
// Manueller Geräte-Import über ein Plugin wie Scans nie automatisch,
// nur per Knopfdruck (Admin -> Plugins).
app.post("/api/plugins/:name/import", async (request, reply) => {
const { name } = request.params as { name: string };
const loaded = getPlugin(name);
if (!loaded) {
return reply.code(404).send({ error: "Plugin nicht gefunden" });
}
if (!loaded.plugin.importDevices) {
return reply.code(400).send({ error: "Dieses Plugin unterstützt keinen Geräte-Import" });
}
try {
const devices = await loaded.plugin.importDevices();
const imported = devices.map((d) =>
deviceRepo.upsertDeviceFromScan({
hostname: d.hostname,
ip: d.ip,
mac: d.mac,
manufacturer: d.manufacturer,
model: d.model,
online: d.online ?? false,
source: "plugin",
})
);
logRepo.logScan({
type: "device",
level: "info",
message: `Plugin "${name}": ${imported.length} Gerät(e) importiert`,
});
return { imported: imported.length, devices: imported };
} catch (err) {
const detail = err instanceof Error ? err.message : String(err);
logRepo.logScan({
type: "device",
level: "error",
message: `Plugin "${name}": Import fehlgeschlagen ${detail}`,
});
request.log.error(err);
return reply.code(500).send({ error: "Import fehlgeschlagen", detail });
}
});
}

View File

@@ -33,6 +33,7 @@ export async function scanRoutes(app: FastifyInstance): Promise<void> {
description: found.description,
suggestedDisplayName: found.suggestedDisplayName,
suggestedCategory: found.category,
suggestedIcon: found.icon,
})
);