Files
LaunchPad/apps/backend/src/index.ts

99 lines
3.4 KiB
TypeScript

import "./env.js";
import Fastify from "fastify";
import cors from "@fastify/cors";
import { ensureSchema } from "./db/client.js";
import { healthRoutes } from "./routes/health.js";
import { deviceRoutes } from "./routes/devices.js";
import { serviceRoutes } from "./routes/services.js";
import { categoryRoutes } from "./routes/categories.js";
import { scanRoutes } from "./routes/scan.js";
import { logRoutes } from "./routes/logs.js";
import { pluginRoutes } from "./routes/plugins.js";
import { resetRoutes } from "./routes/reset.js";
import { transferRoutes } from "./routes/transfer.js";
import { bookmarkRoutes } from "./routes/bookmarks.js";
import { recentVisitsRoutes } from "./routes/recentVisits.js";
import { settingsRoutes } from "./routes/settings.js";
import { readLaterRoutes } from "./routes/readLater.js";
import { faviconProxyRoutes } from "./routes/faviconProxy.js";
import { iconsRoutes } from "./routes/icons.js";
import { apiRoutes } from "./routes/apis.js";
import { loadPlugins } from "./plugins/loader.js";
import { startLiveStatusHeartbeat } from "./liveStatus.js";
import * as serviceRepo from "./db/repositories/services.js";
import * as bookmarkRepo from "./db/repositories/bookmarks.js";
import * as categoryRepo from "./db/repositories/categories.js";
const PORT = Number(process.env.PORT ?? 3001);
const HOST = process.env.HOST ?? "0.0.0.0";
async function main() {
const app = Fastify({
logger: {
level: process.env.LOG_LEVEL ?? "info",
transport:
process.env.NODE_ENV !== "production"
? { target: "pino-pretty", options: { colorize: true } }
: undefined,
},
});
await app.register(cors, {
origin: process.env.CORS_ORIGIN ?? true,
});
ensureSchema();
// Kategorien, die bereits auf Diensten stehen (z. B. aus Scans vor diesem
// Fix, oder von Plugins), aber noch nicht in der categories-Tabelle sind,
// hier nachtragen. Damit zeigt Admin -> Kategorien immer das, was auch in
// der Suche als Kategorie auftaucht.
const existingCategoryNames = Array.from(
new Set(
[
...serviceRepo.listServices().map((s) => s.category),
...bookmarkRepo.listBookmarks().map((b) => b.category),
].filter((c): c is string => !!c)
)
);
const syncedCount = categoryRepo.syncCategoriesFromServiceValues(existingCategoryNames);
if (syncedCount > 0) {
app.log.info(`${syncedCount} Kategorie(n) aus bestehenden Diensten nachgetragen`);
}
const plugins = await loadPlugins();
app.log.info(`${plugins.length} Plugin(s) geladen`);
await app.register(healthRoutes);
await app.register(deviceRoutes);
await app.register(serviceRoutes);
await app.register(categoryRoutes);
await app.register(scanRoutes);
await app.register(logRoutes);
await app.register(pluginRoutes);
await app.register(resetRoutes);
await app.register(transferRoutes);
await app.register(bookmarkRoutes);
await app.register(recentVisitsRoutes);
await app.register(settingsRoutes);
await app.register(readLaterRoutes);
await app.register(faviconProxyRoutes);
await app.register(iconsRoutes);
await app.register(apiRoutes);
app.get("/", async () => {
return { name: "LaunchPad API", status: "running" };
});
try {
await app.listen({ port: PORT, host: HOST });
app.log.info(`LaunchPad backend läuft auf http://${HOST}:${PORT}`);
startLiveStatusHeartbeat();
} catch (err) {
app.log.error(err);
process.exit(1);
}
}
main();