homeos/app/Services/AddonRegistry.php

73 lines
2.6 KiB
PHP

<?php
namespace App\Services;
use App\Models\Addon;
/**
* Static catalogue of installable integrations. Each definition is UI-only metadata; runtime
* state (installed?, connected?, secrets) lives on the {@see Addon} row. Adding an integration
* later is a new entry here plus its normalizer under Support/Mqtt (H3).
*/
class AddonRegistry
{
/** @return array<string, array<string, mixed>> */
public static function all(): array
{
return [
'ring' => [
'key' => 'ring',
'name' => 'Ring',
'vendor' => 'Ring',
'icon' => 'doorbell',
// Ring has no local API — the established bridge is ring-mqtt (cloud, token auth).
'cloud' => true,
'summary_key' => 'addons.ring.summary',
'body_key' => 'addons.ring.body',
// The ring-mqtt sidecar generates a refresh token from an interactive Ring login
// (email + password + 2FA). We store that token; the sidecar does the rest.
'backend' => 'ring-mqtt',
'docs' => 'https://github.com/tsightler/ring-mqtt',
'fields' => [
['name' => 'email', 'type' => 'email', 'label_key' => 'addons.ring.email', 'secret' => false],
['name' => 'password', 'type' => 'password', 'label_key' => 'addons.ring.password', 'secret' => true],
['name' => 'code', 'type' => 'text', 'label_key' => 'addons.ring.code', 'secret' => false, 'optional' => true],
],
],
];
}
public static function get(string $key): ?array
{
return static::all()[$key] ?? null;
}
public static function has(string $key): bool
{
return isset(static::all()[$key]);
}
/**
* Merge each catalogue definition with its persisted state, creating rows lazily so the
* page can render before anything is installed.
*
* @return array<int, array<string, mixed>>
*/
public static function withState(): array
{
$rows = Addon::whereIn('key', array_keys(static::all()))->get()->keyBy('key');
return collect(static::all())->map(function (array $def) use ($rows) {
$state = $rows->get($def['key']);
return $def + [
'installed' => (bool) ($state?->installed ?? false),
'status' => $state?->status ?? 'disconnected',
'status_detail' => $state?->status_detail,
'connected_at' => $state?->connected_at,
'uuid' => $state?->uuid,
];
})->values()->all();
}
}