@ff-admin/core-server (1.5.1)

Published 2026-05-30 11:18:29 +00:00 by jkeffects in FF-Admin/ff-admin-core-server

Installation

@ff-admin:registry=
npm install @ff-admin/core-server@1.5.1
"@ff-admin/core-server": "1.5.1"

About this package

ff-admin-core-server

Core-Funktionalität für ff-admin Server-Anwendungen als wiederverwendbares npm-Package.

Package Content

📋 Inhaltsverzeichnis

Übersicht

@ff-admin/core-server bietet eine vollständige Basis-Infrastruktur für FF-Admin Server-Anwendungen mit Fokus auf Benutzerverwaltung, Authentifizierung, Autorisierung und WebSocket-Kommunikation. Das Package ermöglicht die Verwendung und Entwicklung von Funktionen als Basis für mehrere Anwendungen und eine konsistente API-Struktur sicherzustellen.

Was übernimmt das Package?

🔐 Authentifizierung & Autorisierung

  • JWT-basierte Authentifizierung - Sichere Token-basierte Authentifizierung
  • Passkey-Unterstützung - Moderne WebAuthn/Passkey-Integration
  • Session-Management - Verwaltung von Benutzersitzungen
  • Refresh-Tokens - Automatische Token-Erneuerung
  • Reset-Funktionalität - Zugangs-Reset
  • WebAPI-Tokens - Authentifizierung für externe API-Zugriffe

👥 Benutzerverwaltung

  • User Entity - Vollständiges Benutzermodell mit TypeORM
  • Rollen & Berechtigungen - Flexibles rollenbasiertes Berechtigungssystem
  • Account-Management - Einheitlicher Zugriff auf Account-Funktionen
  • Benachrichtigungen - Benachrichtigungssystem für Benutzer
  • Device-Verwaltung - Tracking und Verwaltung von Geräten/Sessions
  • Push-Subscriptions - Web-Push-Benachrichtigungen pro Benutzer/Gerät

🛠️ Admin-Funktionalität

  • Einladungssystem - Verwaltung von Einladungen für neue Benutzer
  • Rollenverwaltung - CRUD-Operationen für Rollen
  • Berechtigungssystem - Granulare Berechtigungen auf User- und Rollenebene
  • WebAPI-Verwaltung - Verwaltung von API-Keys und Berechtigungen
  • Moduleinstellungen - Konfigurierbare Module und Einstellungen
  • Einstellungsverwaltung - Application- und Module-Settings

🌐 REST API Routes

Das Package stellt folgende fertige API-Endpunkte bereit:

  • /api/public - Öffentliche Endpunkte (Setup-Check, etc.)
  • /api/setup - Initiale Setup-Konfiguration
  • /api/reset - Passwort-Reset-Funktionalität
  • /api/invite - Einladungsverwaltung
  • /api/auth - Authentifizierung (Login, Logout, etc.)
  • /api/webapi - WebAPI-Token-Verwaltung
  • /api/admin - Admin-Funktionen (Benutzer, Rollen, etc.)
  • /api/account - Account-Management für eingeloggte Benutzer
  • /api/account/push - Push-Subscription-Verwaltung (Subscribe, Unsubscribe, Deaktivieren)
  • /api/server - Server-Verwaltung und Informationen

🔌 WebSocket-Unterstützung

  • Socket.IO Integration - Vollständige WebSocket-Unterstützung
  • Namespace-System - Erweiterbare Socket-Namespaces
  • Socket-Authentifizierung - JWT-basierte WebSocket-Authentifizierung
  • Admin UI - Socket.IO Admin Panel für Development

🧰 Helper-Funktionen

  • JWTHelper - Token-Generierung und -Validierung
  • PasskeyHelper - WebAuthn-Operationen
  • PermissionHelper - Berechtigungsprüfungen und Middlewares
  • MailHelper - E-Mail-Versand
  • BackupHelper - Automatische Datenbank-Backups
  • NotificationHelper - Benachrichtigungsverwaltung (inkl. Web Push)
  • WebPushHelper - VAPID-basierte Web-Push-Benachrichtigungen
  • SettingsHelper - Einstellungsverwaltung
  • DateHelper - Datums- und Zeitoperationen
  • FileSystemHelper - Dateisystem-Operationen
  • StringHelper - String-Manipulationen
  • und weitere...

🛡️ Middlewares

  • Authentication - JWT- und WebAPI-Authentifizierung
  • Access Control - Permissions- und Role-basierter Zugriff
  • Rate Limiting - Schutz vor Brute-Force-Angriffen
  • Error Handling - Zentralisierte Fehlerbehandlung
  • File Upload - Multer-basierter File-Upload
  • Device Detection - Automatische Geräteerkennung
  • PWA Detection - Progressive Web App Erkennung

📦 TypeORM Integration

  • Entities - Vordefinierte Datenbank-Entities für alle Basis-Funktionen
  • CQRS Pattern - Commands und CommandHandlers für Datenbankoperationen
  • Factories - Factory-Pattern für Entitäten
  • Services - Geschäftslogik-Services
  • ViewModels - Optimierte Datenstrukturen für API-Responses

Cron Jobs

  • Tägliche Wartung - Automatische Bereinigung abgelaufener Tokens/Sessions
  • Backup-Automation - Automatische Backups zu konfigurierten Zeitpunkten
  • Geplante Benachrichtigungen - Benutzerkonfigurierbare Benachrichtigungen (Wochentage, Uhrzeit, Kanäle)
  • Erweiterbare Hooks - Eigene Cron-Jobs über registerDailyCronHook hinzufügen

🔧 Exception Handling

  • CustomRequestException - Basisklasse für API-Exceptions
  • BadRequestException - 400 Fehler
  • UnauthorizedRequestException - 401 Fehler
  • ForbiddenRequestException - 403 Fehler
  • InternalException - 500 Fehler
  • DatabaseActionException - Datenbank-spezifische Fehler

Installation

npm install @ff-admin/core-server

Peer Dependencies

Das Package benötigt folgende Peer Dependencies:

  • express >= 5.2.0
  • typeorm >= 0.3.0
  • reflect-metadata

Konfiguration

1. DataSource konfigurieren

Das Package benötigt eine TypeORM DataSource. Diese muss in der Anwendung konfiguriert und an das Package übergeben werden:

import { DataSource } from "typeorm";
import { DB_HOST, DB_PORT, DB_USER, DB_PASSWORD, DB_NAME, DB_SCHEMA, configureDataSource, baseTables } from "@ff-admin/core-server";

const AppDataSource = new DataSource({
  type: "postgres",
  host: DB_HOST,
  port: DB_PORT,
  username: DB_USER,
  password: DB_PASSWORD,
  database: DB_NAME,
  schema: DB_SCHEMA,
  entities: [...baseTables, ...applicationTables],
  migrations: [...applicationMigrations],
  synchronize: false,
});

// DataSource dem Package übergeben
configureDataSource(AppDataSource);

await AppDataSource.initialize();

Wichtig: Die Datenbank-Connection und Migrationen werden von der Anwendung verwaltet, nicht vom Package!

2. Umgebungsvariablen

Das Package erwartet folgende Umgebungsvariablen und veröffentlicht diese auch. Das Package prüft zudem den Inhalt der ENV-Variablen und setzt default Werte, sollte eine ENV nicht verwendet werden.

DB_PORT = 5432
DB_HOST = database_host
DB_NAME = database_name
DB_USERNAME = database_username
DB_PASSWORD = database_password

APPLICATION_SECRET = mysecret

SERVER_URL = myurl

VAPID_PUBLIC_KEY = <base64url-encoded public key>   # optional, wird generiert wenn leer
VAPID_PRIVATE_KEY = <base64url-encoded private key> # optional, wird generiert wenn leer
VAPID_SUBJECT = mailto:admin@example.com            # Kontakt-URI für Push-Dienste

USE_SECURITY_STRICT_LIMIT = (true|false) # default ist true
SECURITY_STRICT_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 15m
SECURITY_STRICT_LIMIT_REQUEST_COUNT = strict_request_count # default ist 15
USE_SECURITY_LIMIT = (true|false) # default ist true
SECURITY_LIMIT_WINDOW = [0-9]*(y|d|h|m|s) # default ist 1m
SECURITY_LIMIT_REQUEST_COUNT = request_count # default ist 500

TRUST_PROXY = <boolean|number|ip|ip1,ip2,...> # wenn leer, wird dieser Wert nicht angewendet.

3. Package Config Vals

Setzen der anwendungsspezifischen Konfigurationswerte:

import { PackageConfigVals } from "@ff-admin/core-server";

PackageConfigVals.serverRSSFeedLink = "https://git.your-server.com/server/rss-feed";
PackageConfigVals.clientRSSFeedLink = "https://git.your-server.com/client/rss-feed";

4. Konfiguration bzw. Erweiterung der PackageTypen

Das Package stellt Basis-Typen bereit, welche in der Anwendung erweitert werden können. Eine Ausführliche Information gibt es weiter unten: [Erweiterungen](## Erweiterung)

Verwendung

Express App Setup

import express, { Express } from "express";
import cors from "cors";
import helmet from "helmet";
import morgan from "morgan";
import {
  // Routes
  auth,
  invite,
  reset,
  setup,
  publicAvailable,
  account,
  admin,
  applicationRouter,
  webapi,
  server,
  // Middlewares
  authenticate,
  authenticateAPI,
  preventWebapiAccess,
  allowSetup,
  detectPWA,
  extractDeviceInfo,
  httpApiAvailable,
  errorHandler,
  strictLimiter,
  generalLimiter,
  excludePaths,
  // Helpers
  PermissionHelper,
} from "@ff-admin/core-server";

export const setupApp = (app: Express) => {
  // Express-Konfiguration
  if (process.env.TRUST_PROXY) {
    app.set("trust proxy", process.env.TRUST_PROXY);
  }
  app.set("query parser", "extended");

  // Security & Logging
  app.use(cors());
  app.options("*", cors());
  app.use(helmet());
  app.use(morgan("combined"));

  // Body Parser
  app.use(express.json());
  app.use(express.urlencoded({ extended: true }));

  // API Verfügbarkeit
  app.use(httpApiAvailable);

  // Device Detection
  app.use(detectPWA);
  app.use(extractDeviceInfo);

  // Public Routes
  app.use("/api/public", publicAvailable);
  // Hinzufügen der anwendungsspezifischen Public Routes
  // app.use("/api/public", yourPublicRoutes);

  // Setup, Reset, Invite (mit Rate Limiting)
  app.use("/api/setup", strictLimiter, preventWebapiAccess, allowSetup, setup);
  app.use("/api/reset", strictLimiter, preventWebapiAccess, reset);
  app.use("/api/invite", strictLimiter, preventWebapiAccess, invite);

  // Authentication
  app.use("/api/auth", strictLimiter, preventWebapiAccess, auth);

  // WebAPI Routes
  app.use("/api/webapi", authenticateAPI, webapi);

  // Authentifizierung für alle folgenden Routes
  app.use(authenticate);

  // General Rate Limiting (mit Ausnahmen)
  app.use(excludePaths(generalLimiter, ["/synchronize"]));

  // Admin Routes
  app.use("/api/admin", admin);
  app.use("/api/admin", /* Anwendungs- Admin-Routes */);

  // Application routes
  app.use("/api/application", applicationRouter);

  // Account Routes
  app.use("/api/account", preventWebapiAccess, account);

  // Server Routes (nur für Admins)
  app.use("/api/server", preventWebapiAccess, PermissionHelper.isAdminMiddleware(), server);

  // Error Handler (muss am Ende sein!)
  app.use(errorHandler);
};

WebSocket Setup

import { createServer } from "http";
import { SocketServer } from "@ff-admin/core-server";

const httpServer = createServer(app);

// Socket.IO initialisieren
SocketServer.init(httpServer);

// Eigene Socket-Namespace-Hooks registrieren (optional)
SocketServer.registerSocketNamespaceHook((io) => {
  io.of("/my-namespace")
    .on("connection", (socket) => {
        console.log("socket connection: ", socket.id);
        socketBase(this.io, socket);
    });
});

// App-Namespace-Hooks registrieren (optional)
SocketServer.registerAppNamespaceHook((io, socket) => {
  socket.on("myCustomEvent", (data) => {
    // Handle custom events
  });
});

httpServer.listen(3000);

Eigene Routes erstellen

import { Router } from "express";
import { PermissionHelper, authenticate } from "@ff-admin/core-server";

const router = Router();

// Route mit Authentifizierung
router.get("/my-endpoint", authenticate, async (req, res) => {
  // req.userId, req.username, req.permissions sind verfügbar
  res.json({ message: "Hello " + req.username });
});

// Route mit Berechtigungsprüfung
router.post(
  "/admin-endpoint",
  authenticate,
  PermissionHelper.check("admin.write"),
  async (req, res) => {
    // Nur für Benutzer mit admin.write Berechtigung
    res.json({ success: true });
  }
);

export default router;

Commands verwenden

Das Package verwendet ein CQRS-Pattern. Das Package stellt CommandHandlers für Datenbankoperationen bereit:

import { UserCommandHandler, CreateUserCommand, UpdateUserCommand } from "@ff-admin/core-server";

// Benutzer erstellen
const createCommand: CreateUserCommand = {
  username: "john.doe",
  email: "john@example.com",
  firstname: "John",
  lastname: "Doe",
  password: "securePassword123",
};

const newUser = await UserCommandHandler.create(createCommand);

// Benutzer aktualisieren
const updateCommand: UpdateUserCommand = {
  id: newUser.id,
  firstname: "Jane",
};

await UserCommandHandler.update(updateCommand);

Helpers verwenden

import {
  JWTHelper,
  PermissionHelper,
  MailHelper,
  NotificationHelper,
} from "@ff-admin/core-server";

// JWT erstellen
const token = JWTHelper.sign({ userId: "123", username: "john" });

// JWT validieren
const payload = JWTHelper.verify(token);

// Berechtigungen prüfen
const hasPermission = PermissionHelper.check("admin.users.write");

// E-Mail senden
await MailHelper.send({
  to: "user@example.com",
  subject: "Welcome",
  html: "<h1>Welcome to our platform</h1>",
});

// Benachrichtigung erstellen
await NotificationHelper.create({
  userId: "123",
  title: "New Message",
  message: "You have a new message",
});

Cron Jobs erweitern

import { registerDailyCronHook } from "@ff-admin/core-server";

// Eigene tägliche Wartungsaufgabe registrieren
registerDailyCronHook(async () => {
  console.log("Running custom daily maintenance task");
  // Ihre Logik hier
  await cleanupOldData();
});

Geplante Benachrichtigungen (Scheduled Notifications)

Das Package bietet ein System für geplante Benachrichtigungen, bei dem Benutzer individuell konfigurieren können, wann und über welche Kanäle sie bestimmte Benachrichtigungen erhalten möchten.

Generator registrieren

In der konsumierenden Anwendung werden Notification-Generatoren registriert. Jeder Generator berechnet den Inhalt einer Benachrichtigung für einen bestimmten Benutzer:

import { registerScheduledNotificationGenerator } from "@ff-admin/core-server";

registerScheduledNotificationGenerator(
  "unit/inspection-remind",       // Eindeutiger Key
  "Geräteprüfung Erinnerung",    // Label (wird in der UI angezeigt)
  async (userId: string) => {
    // Logik: Prüfen ob es etwas zu melden gibt
    const dueInspections = await getDueInspections(userId);
    if (dueInspections.length === 0) return null; // nichts zu melden

    return {
      title: "Fällige Geräteprüfungen",
      message: `${dueInspections.length} Geräte müssen geprüft werden.`,
    };
  }
);

Tägliche Benachrichtigungen (daily-Flag)

Benachrichtigungen, deren Inhalt tagesaktuell ist (z.B. "heute fällige Prüfungen"), sollten mit { daily: true } registriert werden. Dadurch wird im Frontend die Wochentag-Auswahl ausgeblendet — der Benutzer kann nur noch die Uhrzeit und die Kanäle konfigurieren. Die Wochentage werden automatisch auf alle 7 Tage gesetzt.

registerScheduledNotificationGenerator(
  "unit/inspection-daily",
  "Geräteprüfung Tagesaktuell",
  async (userId: string) => {
    // Nur tagesaktuelle Inhalte (heute fällig, heute durch Intervall erinnert)
    const todaysInspections = await getTodaysInspections();
    if (todaysInspections.length === 0) return null;
    return { title: "Heutige Geräteprüfungen", message: "..." };
  },
  { daily: true } // Wochentag-Auswahl wird im Frontend ausgeblendet
);

Ablauf

  1. Registrierung: Beim Serverstart werden Generatoren via registerScheduledNotificationGenerator registriert
  2. Benutzer-Konfiguration: Benutzer konfigurieren über die API (/account/notification-schedule) ihre Wochentage, Uhrzeit und Kanäle
  3. Cron-Tick: Alle 5 Minuten prüft NotificationSchedulerHelper.tick() den In-Memory-Cache nach fälligen Schedules
  4. Generator-Aufruf: Für jedes fällige Schedule wird der zugehörige Generator mit der userId aufgerufen
  5. Versand: Bei Rückgabe von { title, message } wird über die konfigurierten Kanäle (inApp, email, webpush) versendet
  6. Deduplizierung: lastSentAt verhindert Doppelversand am selben Tag

Initialisierung

Der NotificationScheduleService muss beim Start der Anwendung initialisiert werden (lädt alle Schedules in den Cache):

import { NotificationScheduleService } from "@ff-admin/core-server";

await NotificationScheduleService.initialize();

API-Endpunkte

Methode Pfad Beschreibung
GET /account/notification-schedule Alle Schedules des Benutzers
GET /account/notification-schedule/available Verfügbare Notification-Typen
PUT /account/notification-schedule Schedule erstellen/aktualisieren
DELETE /account/notification-schedule/:reportKey Schedule löschen

Erweiterung

TypeScript Type Declarations erweitern

Das Package bietet mehrere Interfaces, die in der Anwendung erweitern werden können, um anwendungsspezifische Funktionalität hinzuzufügen.

SocketNamespaceMap

Erweitern der Socket.IO Namespaces:

declare module "@ff-admin/core-server" {
  interface SocketNamespaceMap {
    myCustomNamespace: "/custom";
    anotherNamespace: "/another";
  }
}

import { configureSocketNamespace, SocketNamespace } from "@ff-admin/core-server";

// Namespaces konfigurieren
configureSocketNamespace({
  myCustomNamespace: "/custom",
  anotherNamespace: "/another",
});

// Verwendung
console.log(SocketNamespace.myCustomNamespace); // "/custom"
const namespace: SocketNamespace = SocketNamespace.app; // Type-safe

PermissionSectionMap & PermissionModuleMap

Erweitern des Berechtigungssystem um eigene Sections und Module:

declare module "@ff-admin/core-server" {
  interface PermissionSectionMap {
    // Eigene Berechtiungs-Section hinzufügen
    mySection: void;
  }

  interface PermissionModuleMap {
    // Eigene Berechtigungs-Module hinzufügen
    myModule: void;
    anotherModule: void;
  }
}

// Verwendung im Code
import { PermissionHelper } from "@ff-admin/core-server";

// Nachfolgende Funktionen werden benötigt, um die Werte neben den Typen verfügbar zu machen.
extendPermissionSections(/** ... */)
extendPermissionModules(/** ... */)
configureSectionsAndModules(/** ... */)

ModuleSettingTopicMap & ModuleSettingValueMapping

Erweitern der Modul-Einstellungen um eigene Topics und Settings:

declare module "@ff-admin/core-server" {
  interface ModuleSettingTopicMap {
    myModule: void;
  }

  interface ModuleSettingValueMapping {
    "myModule.setting1": string;
    "myModule.setting2": number;
    "myModule.enabled": boolean;
  }
}

import { 
  configurModuleSettingsType, 
  ModuleSettingsSchema 
} from "@ff-admin/core-server";

// Schema für die neuen Settings definieren
configurModuleSettingsType({
  "myModule.setting1": { 
    type: "string", 
    default: "default value" 
  },
  "myModule.setting2": { 
    type: "number", 
    default: 42 
  },
  "myModule.enabled": { 
    type: "boolean", 
    default: false 
  },
});

// Verwendung
import { SettingsHelper } from "@ff-admin/core-server";

const setting = await SettingsHelper.getModuleSetting("myModule.setting1");
await SettingsHelper.setModuleSetting("myModule.enabled", true);

SettingTopicMap & SettingValueMapping

Erweitern der Application-Einstellungen um eigene Topics und Settings:

declare module "@ff-admin/core-server" {
  interface SettingTopicMap {
    myApp: void;
  }

  interface SettingValueMapping {
    "myApp.apiKey": string;
    "myApp.timeout": number;
    "myApp.baseUrl": string;
  }
}

import { 
  configurSettingsType, 
  SettingsSchema 
} from "@ff-admin/core-server";

// Schema für die neuen Settings definieren
configurSettingsType({
  "myApp.apiKey": { 
    type: "string", 
    optional: true 
  },
  "myApp.timeout": { 
    type: "number", 
    default: 5000 
  },
  "myApp.baseUrl": { 
    type: "url", 
    default: "https://api.example.com" 
  },
});

// Verwendung
import { SettingsHelper } from "@ff-admin/core-server";

const apiKey = await SettingsHelper.getSetting("myApp.apiKey");
await SettingsHelper.setSetting("myApp.timeout", 10000);

Eigene Entities

Erweitern der Package-Entities oder erstellen eigener:

import { Entity, Column, ManyToOne } from "typeorm";
import { User } from "@ff-admin/core-server";

@Entity()
export class CustomUserData {
  @Column()
  someCustomField: string;

  @ManyToOne(() => User)
  user: User;
}

Eigene Datenbanktabellen können direkt in der Anwendung angelegt werden. Soll eine bestehende Entität des packages erweitert werden, so kann eine eigene Entity von der Entität des Packages erben. Jedoch müssen dann auch alle Abhängigkeiten zu dieser Ursprungsentität ersetzt und in der Anwendung neue implementiert werden.

Routen überschreiben

Die vom Package bereitgestellten Routen können in der Anwendung jederzeit überschrieben werden. Express verwendet Pattern-Matching für Routes, wobei die zuerst definierte Route Vorrang hat.

import express from "express";
import { 
  auth,           // Package-Route
  authenticate 
} from "@ff-admin/core-server";

const app = express();

// Eigene Login-Route, die die Package-Route überschreibt
app.post("/api/auth/login", async (req, res) => {
  // Ihre angepasste Implementierung
  console.log("Custom login logic");
  // ...
  res.json({ success: true });
});

// Package-Route wird hinzugefügt, aber /api/auth/login ist bereits definiert
// Daher wird die obige Route für /login verwendet
app.use("/api/auth", auth);

// Alternativ: Nur bestimmte Endpunkte vom Package nutzen
app.post("/api/auth/login", customLoginHandler);      // Überschrieben
app.use("/api/auth", auth);                            // Andere Endpunkte vom Package

Wichtig: Definieren Sie Ihre benutzerdefinierten Routen vor den Package-Routen, um sicherzustellen, dass Ihre Implementierung verwendet wird.

Beispiel - Teilweises Überschreiben:

// Setup-Endpunkt mit zusätzlicher Validierung überschreiben
app.post("/api/setup/initial", 
  customValidationMiddleware, 
  customSetupHandler
);

// Restliche Setup-Routen vom Package verwenden
app.use("/api/setup", strictLimiter, preventWebapiAccess, allowSetup, setup);

API-Dokumentation

Express Request Extensions

Das Package erweitert das Express Request-Objekt um folgende Properties:

interface Request {
  userId: string;              // ID des authentifizierten Benutzers
  username: string;            // Username des Benutzers
  firstname: string;           // Vorname
  lastname: string;            // Nachname
  isOwner: boolean;           // Ist der Benutzer Owner?
  permissions: PermissionObject; // Berechtigungsobjekt
  isPWA: boolean;             // Zugriff über PWA?
  isWebApiRequest: boolean;   // Zugriff über WebAPI?
  deviceFingerprint: string;  // Geräte-Fingerprint
  deviceName: string;         // Gerätename
}

Wichtige Exports

Das Package exportiert folgende Hauptkomponenten:

  • Commands - CQRS Commands und CommandHandlers
  • Controllers - Controller für API-Endpunkte
  • Entities - TypeORM Entities
  • Enums - API-Status, Login-Routinen, Socket-Namespaces
  • Exceptions - Custom Exception-Klassen
  • Factories - Factory-Pattern Implementierungen
  • Helpers - Utility-Funktionen
  • Middlewares - Express-Middlewares
  • Routes - Fertige API-Routes
  • Services - Business-Logic Services
  • Types - TypeScript Type Definitions
  • ViewModels - API Response Models
  • WebSocket - Socket.IO Konfiguration

Lizenz

AGPL-3.0-only

Author

JK Effects

Repository

https://code.jk-effects.cloud/FF-Admin/ff-admin-core-server.git

Dependencies

Dependencies

ID Version
@simplewebauthn/server ^13.3.1
@socket.io/admin-ui ^0.5.1
cors ^2.8.6
crypto ^1.0.1
dotenv ^17.4.2
express ^5.2.1
express-rate-limit ^8.5.2
express-validator ^7.3.2
helmet ^8.2.0
ip-address ^10.2.0
jsonwebtoken ^9.0.3
lodash.clonedeep ^4.5.0
lodash.uniqby ^4.7.0
moment ^2.30.1
morgan ^1.10.1
ms ^2.1.3
multer ^2.1.1
node-schedule ^2.1.1
nodemailer ^8.0.10
qrcode ^1.5.4
reflect-metadata ^0.2.2
rss-parser ^3.13.0
sharp ^0.34.5
sharp-ico ^0.1.5
socket.io ^4.8.3
speakeasy ^2.0.0
typeorm ^1.0.0
ua-parser-js ^2.0.10
uuid ^14.0.0
validator ^13.15.35
web-push ^3.6.7
zod ^4.4.3

Development dependencies

ID Version
@types/cors ^2.8.19
@types/express ^5.0.6
@types/ip ^1.1.3
@types/jsonwebtoken ^9.0.10
@types/lodash.clonedeep ^4.5.9
@types/lodash.uniqby ^4.7.9
@types/morgan ^1.9.10
@types/ms ^2.1.0
@types/multer ^2.1.0
@types/node ^25.9.1
@types/node-schedule ^2.1.8
@types/nodemailer ^8.0.0
@types/qrcode ~1.5.6
@types/speakeasy ^2.0.10
@types/uuid ^11.0.0
@types/validator ^13.15.10
@types/web-push ^3.6.4
ts-node 10.9.2
tsc-alias ^1.8.17
typescript ^6.0.3

Keywords

Feuerwehr ff-admin
Details
npm
2026-05-30 11:18:29 +00:00
29
JK Effects
AGPL-3.0-only
194 KiB
Assets (1)
Versions (26) View all
1.6.2 2026-07-11
1.6.1 2026-07-06
1.6.0 2026-07-04
1.5.7 2026-06-24
1.5.6 2026-06-09