feat: config portability with generic entity resolver framework

Full configuration export/import system for Homarr with excellent DX:
- Export/import boards, apps, integrations (with re-encrypted secrets),
  users (with bcrypt hashes), groups (with permissions and memberships),
  search engines, and server settings
- Homepage services.yaml import with widget-type mapping
- Generic resolveEntities() utility eliminates per-entity boilerplate
- Declarative entity-fields.ts: adding a new user preference requires
  only one line change (no export/import/schema edits needed)
- User schema uses .catchall(z.unknown()) for forward-compatible prefs
- groupByKey() utility replaces manual Map-building
- CONFIG_ENTITY_KEYS as single source of truth for entity metadata
- Reuse existing entities (apps by name+icon+href, integrations by
  kind+name+url, users by email, groups by name, boards by name)
- Skip duplicates with warnings rather than failing
- Onboarding flow skips user creation step when config includes users
- Reuse existing admin group during onboarding after config import
This commit is contained in:
Thomas Camlong committed 2026-06-06 16:22:59 +02:00
1 parent 1f7b7f0516
commit f6a598b774
48 files changed
+1869 -1435

No files matched your search

@@ -1,17 +0,0 @@
CREATE TABLE `docker_app_source` (
`host` text NOT NULL,
`container_id` text NOT NULL,
`external_id` text NOT NULL,
`app_id` text NOT NULL,
`board_id` text NOT NULL,
`item_id` text,
`integration_id` text,
`updated_at` integer NOT NULL,
PRIMARY KEY(`host`, `container_id`),
FOREIGN KEY (`app_id`) REFERENCES `app`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`board_id`) REFERENCES `board`(`id`) ON UPDATE no action ON DELETE cascade,
FOREIGN KEY (`item_id`) REFERENCES `item`(`id`) ON UPDATE no action ON DELETE set null,
FOREIGN KEY (`integration_id`) REFERENCES `integration`(`id`) ON UPDATE no action ON DELETE set null
);
--> statement-breakpoint
CREATE INDEX `docker_app_source__external_id_idx` ON `docker_app_source` (`host`,`external_id`);