- docs/ARCHITECTURE.md: full system overview, technology stack, directory structure, component architecture, data flow, auth, polling/caching, download matching pipeline, API reference, frontend architecture, configuration, deployment guide - docs/diagrams/component.puml: system component diagram - docs/diagrams/seq-auth.puml: authentication sequence diagram - docs/diagrams/seq-dashboard.puml: dashboard request sequence diagram - docs/diagrams/seq-polling.puml: background polling cycle sequence - docs/diagrams/class-server.puml: server-side class/module diagram - docs/diagrams/class-data.puml: data model / entity diagram - docs/diagrams/state-ui.puml: frontend UI state diagram - docs/diagrams/state-poller.puml: poller state diagram - docs/diagrams/activity-matching.puml: download matching activity diagram
222 lines
4.6 KiB
Plaintext
222 lines
4.6 KiB
Plaintext
@startuml class-data
|
|
!theme plain
|
|
title sofarr — Data Model Diagram
|
|
|
|
skinparam classAttributeIconSize 0
|
|
|
|
package "External API Responses" {
|
|
class "SABnzbd Queue Slot" as sabq {
|
|
+ filename : string
|
|
+ nzbname : string
|
|
+ percentage : string
|
|
+ mb : string
|
|
+ mbmissing : string
|
|
+ size : string
|
|
+ timeleft : string
|
|
+ status : string
|
|
+ storage : string
|
|
}
|
|
|
|
class "SABnzbd History Slot" as sabh {
|
|
+ name : string
|
|
+ nzb_name : string
|
|
+ nzbname : string
|
|
+ status : string
|
|
+ size : string
|
|
+ completed_time : string
|
|
+ storage : string
|
|
}
|
|
|
|
class "Sonarr Queue Record" as sqr {
|
|
+ id : number
|
|
+ seriesId : number
|
|
+ series : SonarrSeries
|
|
+ title : string
|
|
+ sourceTitle : string
|
|
+ trackedDownloadStatus : string
|
|
+ trackedDownloadState : string
|
|
+ statusMessages : StatusMessage[]
|
|
+ errorMessage : string
|
|
}
|
|
|
|
class "Sonarr History Record" as shr {
|
|
+ id : number
|
|
+ seriesId : number
|
|
+ title : string
|
|
+ sourceTitle : string
|
|
+ eventType : string
|
|
}
|
|
|
|
class "SonarrSeries" as ss {
|
|
+ id : number
|
|
+ title : string
|
|
+ titleSlug : string
|
|
+ path : string
|
|
+ tags : number[]
|
|
+ images : Image[]
|
|
+ _instanceUrl : string
|
|
}
|
|
|
|
class "Radarr Queue Record" as rqr {
|
|
+ id : number
|
|
+ movieId : number
|
|
+ movie : RadarrMovie
|
|
+ title : string
|
|
+ sourceTitle : string
|
|
+ trackedDownloadStatus : string
|
|
+ trackedDownloadState : string
|
|
+ statusMessages : StatusMessage[]
|
|
+ errorMessage : string
|
|
}
|
|
|
|
class "Radarr History Record" as rhr {
|
|
+ id : number
|
|
+ movieId : number
|
|
+ title : string
|
|
+ sourceTitle : string
|
|
+ eventType : string
|
|
}
|
|
|
|
class "RadarrMovie" as rm {
|
|
+ id : number
|
|
+ title : string
|
|
+ titleSlug : string
|
|
+ path : string
|
|
+ tags : number[]
|
|
+ images : Image[]
|
|
+ _instanceUrl : string
|
|
}
|
|
|
|
class "Tag" as tag {
|
|
+ id : number
|
|
+ label : string
|
|
}
|
|
|
|
class "Image" as img {
|
|
+ coverType : string
|
|
+ remoteUrl : string
|
|
+ url : string
|
|
}
|
|
|
|
class "StatusMessage" as sm {
|
|
+ title : string
|
|
+ messages : string[]
|
|
}
|
|
|
|
class "qBittorrent Torrent" as qbt {
|
|
+ name : string
|
|
+ hash : string
|
|
+ size : number
|
|
+ completed : number
|
|
+ progress : number (0-1)
|
|
+ state : string
|
|
+ dlspeed : number
|
|
+ eta : number
|
|
+ num_seeds : number
|
|
+ num_leechs : number
|
|
+ availability : number
|
|
+ category : string
|
|
+ tags : string
|
|
+ save_path : string
|
|
+ content_path : string
|
|
+ instanceId : string
|
|
+ instanceName : string
|
|
}
|
|
|
|
class "Emby User" as eu {
|
|
+ Id : string
|
|
+ Name : string
|
|
+ Policy : { IsAdministrator: boolean }
|
|
}
|
|
|
|
sqr *-- ss : embedded\n(includeSeries)
|
|
rqr *-- rm : embedded\n(includeMovie)
|
|
sqr *-- sm
|
|
rqr *-- sm
|
|
ss *-- img
|
|
rm *-- img
|
|
}
|
|
|
|
package "sofarr Internal Models" {
|
|
class "Download Object" as dl {
|
|
+ type : 'series' | 'movie' | 'torrent'
|
|
+ title : string
|
|
+ coverArt : string | null
|
|
+ status : string
|
|
+ progress : string
|
|
+ mb : string
|
|
+ mbmissing : string
|
|
+ size : string
|
|
+ speed : string
|
|
+ eta : string
|
|
+ seriesName : string | null
|
|
+ movieName : string | null
|
|
+ episodeInfo : object | null
|
|
+ movieInfo : object | null
|
|
+ userTag : string
|
|
+ importIssues : string[] | null
|
|
+ downloadPath : string | null
|
|
+ targetPath : string | null
|
|
+ arrLink : string | null
|
|
+ qbittorrent : boolean
|
|
+ seeds : number
|
|
+ peers : number
|
|
+ availability : string
|
|
+ rawSize : number
|
|
+ rawSpeed : number
|
|
+ rawEta : number
|
|
+ hash : string
|
|
+ category : string
|
|
+ completedAt : string
|
|
}
|
|
|
|
class "API Response\n/user-downloads" as apir {
|
|
+ user : string
|
|
+ isAdmin : boolean
|
|
+ downloads : Download[]
|
|
}
|
|
|
|
class "Status Response\n/status" as statr {
|
|
+ server : ServerInfo
|
|
+ polling : PollingInfo
|
|
+ cache : CacheStats
|
|
+ clients : ClientInfo[]
|
|
}
|
|
|
|
class "ServerInfo" as si {
|
|
+ uptimeSeconds : number
|
|
+ nodeVersion : string
|
|
+ memoryUsageMB : number
|
|
+ heapUsedMB : number
|
|
+ heapTotalMB : number
|
|
}
|
|
|
|
class "PollingInfo" as pi {
|
|
+ enabled : boolean
|
|
+ intervalMs : number
|
|
+ lastPoll : PollTimings
|
|
}
|
|
|
|
class "Session Cookie\nemby_user" as cookie {
|
|
+ id : string
|
|
+ name : string
|
|
+ isAdmin : boolean
|
|
+ token : string
|
|
}
|
|
|
|
apir *-- dl
|
|
statr *-- si
|
|
statr *-- pi
|
|
}
|
|
|
|
' Data flow connections
|
|
sabq ..> dl : matched &\ntransformed
|
|
sabh ..> dl : matched &\ntransformed
|
|
qbt ..> dl : mapTorrentToDownload()
|
|
ss ..> dl : coverArt, seriesName,\npath, tags
|
|
rm ..> dl : coverArt, movieName,\npath, tags
|
|
tag ..> dl : userTag resolution
|
|
eu ..> cookie : login creates
|
|
|
|
@enduml
|