feat: external importers + uptime monitors (merge plan M1)

Two tracks from the Beszel/Domain-Locker merge plan in ROADMAP.md:

- Importers: POST /api/import/external sniffs Homepage services.yml,
  Homarr JSON, and Dashy conf.yml into sections/items; SettingsDialog
  import now accepts all four formats.
- Monitors (M1): monitors + heartbeats schema, pure checkers for
  http/tcp/ping/dns/keyword/json-query/push, scheduler on app ctx,
  CRUD + check-now + push ingest API, /monitors + /monitors/:id pages
  (wouter), monitor board widget, ServiceDialog monitor opt-in.

Authored By: TDvorak <[email protected]>

Generated with Devin (https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-21 18:14:36 +02:00
1 parent f428e721fe
commit 1ff1b29ae7
29 files changed
+3050 -98

No files matched your search

+1 -1
View File
@@ -11,7 +11,7 @@ import (
// AdGuard Home REST API: GET /control/stats with HTTP basic auth.
type adguard struct{}
func init() { register(adguard{}) }
func init() { Register(adguard{}) }
func (adguard) Meta() Type {
return Type{
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// it and the add-widget dialog can offer it like any other type.
type clock struct{}
func init() { register(clock{}) }
func init() { Register(clock{}) }
func (clock) Meta() Type {
return Type{
+1 -1
View File
@@ -10,7 +10,7 @@ import (
// Immich REST API: GET /api/statistics with an x-api-key header.
type immich struct{}
func init() { register(immich{}) }
func init() { Register(immich{}) }
func (immich) Meta() Type {
return Type{
+1 -1
View File
@@ -11,7 +11,7 @@ import (
// jarvis: v5 only for now — v6 (/api/...) lands when someone runs it.
type pihole struct{}
func init() { register(pihole{}) }
func init() { Register(pihole{}) }
func (pihole) Meta() Type {
return Type{
+3 -1
View File
@@ -40,7 +40,9 @@ type Fetcher interface {
var registry = map[string]Fetcher{}
func register(f Fetcher) { registry[f.Meta().Type] = f }
// Register adds a fetcher — used by the api package for DB-backed widgets
// (monitor/domain/system) that can't live in this leaf package.
func Register(f Fetcher) { registry[f.Meta().Type] = f }
// Get resolves a config.type to its fetcher.
func Get(t string) (Fetcher, bool) {