// TRACES: FR-NC-12 //! The one place the interface names a backend. //! //! `dr-sync` defines [`RemoteBackend`] and a capability model the engine adapts //! to, so that a second backend can be added without touching the code that //! uses one (ARCH ยง8.1). Until this module existed that boundary was //! documentation: seven files in `dr-ui` constructed a `NextcloudBackend` //! directly and ten functions took one by concrete type, so the abstraction //! bought nothing it was designed for and a WebDAV or local-folder backend //! would have had nowhere to go. //! //! Everything above this module now works through `&dyn RemoteBackend`. Adding //! a backend is implementing the trait and changing [`connect`] โ€” not editing //! seven files. //! //! ## What is deliberately still Nextcloud-shaped //! //! Credentials. [`AppCredentials`] is an app password obtained through Login //! Flow v2, which is a Nextcloud protocol rather than a general notion of //! "how one authenticates to a remote". Abstracting it needs a decision about //! what an account *is* across backends โ€” an OAuth token, a bucket key pair //! and an app password have no useful common shape โ€” and inventing one before //! a second backend exists would produce a wrong answer confidently. That is //! the remaining half of this seam, and it is a design problem rather than a //! mechanical one. use dr_sync::{RemoteBackend, RemoteError}; use dr_sync_nextcloud::{AppCredentials, NextcloudBackend}; /// Open a connection to the configured remote. /// /// Returns the trait object every caller should hold. The error type is /// `dr-sync`'s rather than the connector's, so a caller handles a failure /// without learning which backend produced it. pub(crate) fn connect( creds: &AppCredentials, user_id: &str, ) -> Result, RemoteError> { Ok(Box::new(NextcloudBackend::new(creds, user_id)?)) }