2026-05-12 23:25:02 +08:00
package sqlite
import (
"context"
"fmt"
"strings"
)
type Host struct {
2026-05-15 19:26:25 +08:00
ID int64
2026-05-12 23:25:02 +08:00
HostID string
BaseURL string
HostVersion string
CapabilityProbeJSON string
2026-05-18 22:22:22 +08:00
AuthType string
AuthToken string
2026-05-12 23:25:02 +08:00
}
type HostsRepo struct {
db execQuerier
}
func newHostsRepo ( db execQuerier ) * HostsRepo {
return & HostsRepo { db : db }
}
2026-05-15 19:26:25 +08:00
func ( r * HostsRepo ) GetByID ( ctx context . Context , id int64 ) ( Host , error ) {
if id <= 0 {
return Host { } , fmt . Errorf ( "id is required" )
}
var host Host
2026-05-18 22:22:22 +08:00
if err := r . db . QueryRowContext ( ctx , ` SELECT id, host_id, base_url, host_version, capability_probe_json, auth_type, auth_token FROM hosts WHERE id = ? ` , id ) . Scan ( & host . ID , & host . HostID , & host . BaseURL , & host . HostVersion , & host . CapabilityProbeJSON , & host . AuthType , & host . AuthToken ) ; err != nil {
2026-05-15 19:26:25 +08:00
return Host { } , err
}
return host , nil
}
func ( r * HostsRepo ) GetByHostID ( ctx context . Context , hostID string ) ( Host , error ) {
hostID = strings . TrimSpace ( hostID )
if hostID == "" {
return Host { } , fmt . Errorf ( "host_id is required" )
}
var host Host
2026-05-18 22:22:22 +08:00
if err := r . db . QueryRowContext ( ctx , ` SELECT id, host_id, base_url, host_version, capability_probe_json, auth_type, auth_token FROM hosts WHERE host_id = ? ` , hostID ) . Scan ( & host . ID , & host . HostID , & host . BaseURL , & host . HostVersion , & host . CapabilityProbeJSON , & host . AuthType , & host . AuthToken ) ; err != nil {
return Host { } , err
}
return host , nil
}
func ( r * HostsRepo ) GetByBaseURL ( ctx context . Context , baseURL string ) ( Host , error ) {
baseURL = strings . TrimSpace ( baseURL )
if baseURL == "" {
return Host { } , fmt . Errorf ( "base_url is required" )
}
var host Host
if err := r . db . QueryRowContext ( ctx , ` SELECT id, host_id, base_url, host_version, capability_probe_json, auth_type, auth_token FROM hosts WHERE base_url = ? ` , baseURL ) . Scan ( & host . ID , & host . HostID , & host . BaseURL , & host . HostVersion , & host . CapabilityProbeJSON , & host . AuthType , & host . AuthToken ) ; err != nil {
2026-05-15 19:26:25 +08:00
return Host { } , err
}
return host , nil
}
2026-05-12 23:25:02 +08:00
func ( r * HostsRepo ) Create ( ctx context . Context , host Host ) ( int64 , error ) {
hostID := strings . TrimSpace ( host . HostID )
baseURL := strings . TrimSpace ( host . BaseURL )
hostVersion := strings . TrimSpace ( host . HostVersion )
capabilityProbeJSON := strings . TrimSpace ( host . CapabilityProbeJSON )
2026-05-18 22:22:22 +08:00
authType := firstNonEmptyTrimmed ( host . AuthType , "apikey" )
authToken := strings . TrimSpace ( host . AuthToken )
2026-05-12 23:25:02 +08:00
switch {
case hostID == "" :
return 0 , fmt . Errorf ( "host_id is required" )
case baseURL == "" :
return 0 , fmt . Errorf ( "base_url is required" )
case hostVersion == "" :
return 0 , fmt . Errorf ( "host_version is required" )
case capabilityProbeJSON == "" :
capabilityProbeJSON = "{}"
}
result , err := r . db . ExecContext (
ctx ,
2026-05-18 22:22:22 +08:00
` INSERT INTO hosts ( host_id , base_url , host_version , capability_probe_json , auth_type , auth_token )
VALUES ( ? , ? , ? , ? , ? , ? ) ` ,
2026-05-12 23:25:02 +08:00
hostID ,
baseURL ,
hostVersion ,
capabilityProbeJSON ,
2026-05-18 22:22:22 +08:00
authType ,
authToken ,
2026-05-12 23:25:02 +08:00
)
if err != nil {
return 0 , fmt . Errorf ( "insert host %q: %w" , hostID , err )
}
id , err := result . LastInsertId ( )
if err != nil {
return 0 , fmt . Errorf ( "read inserted host id for %q: %w" , hostID , err )
}
return id , nil
}
2026-05-18 22:22:22 +08:00
func ( r * HostsRepo ) UpdateConnectionByHostID ( ctx context . Context , hostID , baseURL , hostVersion , capabilityProbeJSON , authType , authToken string ) error {
hostID = strings . TrimSpace ( hostID )
baseURL = strings . TrimSpace ( baseURL )
hostVersion = strings . TrimSpace ( hostVersion )
capabilityProbeJSON = strings . TrimSpace ( capabilityProbeJSON )
authType = firstNonEmptyTrimmed ( authType , "apikey" )
authToken = strings . TrimSpace ( authToken )
if hostID == "" {
return fmt . Errorf ( "host_id is required" )
}
if baseURL == "" {
return fmt . Errorf ( "base_url is required" )
}
if hostVersion == "" {
return fmt . Errorf ( "host_version is required" )
}
if capabilityProbeJSON == "" {
capabilityProbeJSON = "{}"
}
result , err := r . db . ExecContext ( ctx , ` UPDATE hosts SET base_url = ?, host_version = ?, capability_probe_json = ?, auth_type = ?, auth_token = ? WHERE host_id = ? ` , baseURL , hostVersion , capabilityProbeJSON , authType , authToken , hostID )
if err != nil {
return fmt . Errorf ( "update host %q connection: %w" , hostID , err )
}
rows , err := result . RowsAffected ( )
if err != nil {
return err
}
if rows == 0 {
return fmt . Errorf ( "host %q not found" , hostID )
}
return nil
}
func ( r * HostsRepo ) ListAll ( ctx context . Context ) ( [ ] Host , error ) {
rows , err := r . db . QueryContext ( ctx , ` SELECT id, host_id, base_url, host_version, capability_probe_json, auth_type, auth_token FROM hosts ORDER BY id ` )
if err != nil {
return nil , fmt . Errorf ( "list hosts: %w" , err )
}
defer rows . Close ( )
var hosts [ ] Host
for rows . Next ( ) {
var host Host
if err := rows . Scan ( & host . ID , & host . HostID , & host . BaseURL , & host . HostVersion , & host . CapabilityProbeJSON , & host . AuthType , & host . AuthToken ) ; err != nil {
return nil , fmt . Errorf ( "scan host: %w" , err )
}
hosts = append ( hosts , host )
}
if err := rows . Err ( ) ; err != nil {
return nil , fmt . Errorf ( "iterate hosts: %w" , err )
}
return hosts , nil
}
func ( r * HostsRepo ) DeleteByHostID ( ctx context . Context , hostID string ) error {
hostID = strings . TrimSpace ( hostID )
if hostID == "" {
return fmt . Errorf ( "host_id is required" )
}
result , err := r . db . ExecContext ( ctx , ` DELETE FROM hosts WHERE host_id = ? ` , hostID )
if err != nil {
return fmt . Errorf ( "delete host %q: %w" , hostID , err )
}
rows , err := result . RowsAffected ( )
if err != nil {
return err
}
if rows == 0 {
return fmt . Errorf ( "host %q not found" , hostID )
}
return nil
}
func ( r * HostsRepo ) UpdateProbeByHostID ( ctx context . Context , hostID , hostVersion , capabilityProbeJSON string ) error {
hostID = strings . TrimSpace ( hostID )
hostVersion = strings . TrimSpace ( hostVersion )
capabilityProbeJSON = strings . TrimSpace ( capabilityProbeJSON )
if hostID == "" {
return fmt . Errorf ( "host_id is required" )
}
if hostVersion == "" {
return fmt . Errorf ( "host_version is required" )
}
if capabilityProbeJSON == "" {
capabilityProbeJSON = "{}"
}
result , err := r . db . ExecContext ( ctx , ` UPDATE hosts SET host_version = ?, capability_probe_json = ? WHERE host_id = ? ` , hostVersion , capabilityProbeJSON , hostID )
if err != nil {
return fmt . Errorf ( "update host %q probe: %w" , hostID , err )
}
rows , err := result . RowsAffected ( )
if err != nil {
return err
}
if rows == 0 {
return fmt . Errorf ( "host %q not found" , hostID )
}
return nil
}
func firstNonEmptyTrimmed ( values ... string ) string {
for _ , value := range values {
if trimmed := strings . TrimSpace ( value ) ; trimmed != "" {
return trimmed
}
}
return ""
}