generated from Dicken/dickendock
132 lines
4.9 KiB
TypeScript
132 lines
4.9 KiB
TypeScript
import { sqliteTable, text, integer, real } from "drizzle-orm/sqlite-core";
|
||
|
||
/**
|
||
* Ein physisches/logisches Gerät im Netzwerk (z. B. per FritzBox-Scan gefunden).
|
||
*/
|
||
export const devices = sqliteTable("devices", {
|
||
id: text("id").primaryKey(),
|
||
hostname: text("hostname").notNull(),
|
||
ip: text("ip").notNull(),
|
||
mac: text("mac"),
|
||
manufacturer: text("manufacturer"),
|
||
model: text("model"),
|
||
online: integer("online", { mode: "boolean" }).notNull().default(false),
|
||
source: text("source").notNull(), // fritzbox | dns | http | https | portscan | manual
|
||
lastScan: text("last_scan"), // ISO-8601
|
||
createdAt: text("created_at").notNull(),
|
||
updatedAt: text("updated_at").notNull(),
|
||
});
|
||
|
||
/**
|
||
* Ein Dienst, der auf einem Gerät läuft (z. B. Frigate, Portainer, Gitea ...).
|
||
* Benutzeränderungen (displayName, category, favorite, order, alias, icon,
|
||
* hostname, url, https, visible) dürfen von einem erneuten Scan eines bereits
|
||
* bekannten Dienstes NIEMALS überschrieben werden – siehe README/Spezifikation.
|
||
* Nur favicon/description werden bei jedem Scan aufgefrischt.
|
||
*/
|
||
export const services = sqliteTable("services", {
|
||
id: text("id").primaryKey(),
|
||
deviceId: text("device_id")
|
||
.notNull()
|
||
.references(() => devices.id, { onDelete: "cascade" }),
|
||
|
||
// vom Benutzer gepflegt bzw. nur beim erstmaligen Anlegen durch einen Scan gesetzt
|
||
displayName: text("display_name").notNull(),
|
||
category: text("category"),
|
||
favorite: integer("favorite", { mode: "boolean" }).notNull().default(false),
|
||
order: real("order").notNull().default(0),
|
||
alias: text("alias").notNull().default("[]"), // JSON-Array als String
|
||
icon: text("icon"),
|
||
hostname: text("hostname").notNull(),
|
||
url: text("url").notNull(),
|
||
https: integer("https", { mode: "boolean" }).notNull().default(false),
|
||
// Ausgeblendete Dienste erscheinen nicht in der Suche, bleiben aber im Adminbereich.
|
||
visible: integer("visible", { mode: "boolean" }).notNull().default(true),
|
||
|
||
// Bei jedem Scan aktualisierbar
|
||
port: integer("port").notNull(),
|
||
favicon: text("favicon"),
|
||
description: text("description"),
|
||
|
||
createdAt: text("created_at").notNull(),
|
||
updatedAt: text("updated_at").notNull(),
|
||
});
|
||
|
||
/**
|
||
* Frei definierbare Kategorien (Erstellen/Löschen/Umbenennen/Sortieren per Drag & Drop).
|
||
*/
|
||
export const categories = sqliteTable("categories", {
|
||
id: text("id").primaryKey(),
|
||
name: text("name").notNull(),
|
||
order: real("order").notNull().default(0),
|
||
color: text("color"),
|
||
createdAt: text("created_at").notNull(),
|
||
updatedAt: text("updated_at").notNull(),
|
||
});
|
||
|
||
/**
|
||
* Protokoll jedes Scan-Versuchs (Geräte-Netzwerk-Scan oder FritzBox-Scan),
|
||
* angezeigt im Adminbereich unter "Logs".
|
||
*/
|
||
export const scanLogs = sqliteTable("scan_logs", {
|
||
id: text("id").primaryKey(),
|
||
type: text("type").notNull(), // "device" | "fritzbox"
|
||
targetId: text("target_id"), // Geräte-ID bei type "device", sonst null
|
||
level: text("level").notNull(), // "info" | "error"
|
||
message: text("message").notNull(),
|
||
createdAt: text("created_at").notNull(),
|
||
});
|
||
|
||
/**
|
||
* Manuell angelegtes Lesezeichen – im Unterschied zu Diensten nicht an ein
|
||
* gescanntes Gerät gebunden, eigenständige Tabelle. Erscheint zusammen mit
|
||
* Diensten in der Suche (siehe packages/shared rankServices), wird aber
|
||
* separat verwaltet (Admin -> Lesezeichen).
|
||
*/
|
||
export const bookmarks = sqliteTable("bookmarks", {
|
||
id: text("id").primaryKey(),
|
||
url: text("url").notNull(),
|
||
displayName: text("display_name").notNull(),
|
||
hostname: text("hostname").notNull(), // aus der URL abgeleitet
|
||
description: text("description"),
|
||
category: text("category"),
|
||
icon: text("icon"),
|
||
favicon: text("favicon"),
|
||
favorite: integer("favorite", { mode: "boolean" }).notNull().default(false),
|
||
alias: text("alias").notNull().default("[]"),
|
||
order: real("order").notNull().default(0),
|
||
createdAt: text("created_at").notNull(),
|
||
updatedAt: text("updated_at").notNull(),
|
||
});
|
||
|
||
/**
|
||
* Zuletzt aus der Suche geöffnete Dienste/Lesezeichen, für die
|
||
* "Zuletzt besucht"-Leiste auf der Startseite.
|
||
*/
|
||
export const recentVisits = sqliteTable("recent_visits", {
|
||
id: text("id").primaryKey(),
|
||
itemType: text("item_type").notNull(), // "service" | "bookmark"
|
||
itemId: text("item_id").notNull(),
|
||
visitedAt: text("visited_at").notNull(),
|
||
});
|
||
|
||
/** Freie Schlüssel-Wert-Einstellungen, z. B. Anzahl "Zuletzt besucht". */
|
||
export const appSettings = sqliteTable("app_settings", {
|
||
key: text("key").primaryKey(),
|
||
value: text("value").notNull(),
|
||
});
|
||
|
||
/**
|
||
* "Später lesen": schnell von der Startseite abgelegte Links, unabhängig
|
||
* von Lesezeichen/Diensten. Können später zu einem Lesezeichen befördert
|
||
* oder gelöscht werden.
|
||
*/
|
||
export const readLater = sqliteTable("read_later", {
|
||
id: text("id").primaryKey(),
|
||
url: text("url").notNull(),
|
||
displayName: text("display_name").notNull(),
|
||
favicon: text("favicon"),
|
||
savedAt: text("saved_at").notNull(),
|
||
updatedAt: text("updated_at").notNull(),
|
||
});
|