cfgmatic-files 2.2.0

Configuration file discovery and reading with multiple format support
Documentation
//! Configuration file discovery and reading with multiple format support.
//!
//! **DEPRECATED**: This crate is deprecated since version 2.0.1.
//! Use `cfgmatic-source` instead, which provides a more comprehensive
//! and unified API for configuration source management.
//!
//! # Migration Guide
//!
//! This crate has been superseded by `cfgmatic-source`. Below is a guide
//! for migrating your code to the new API.
//!
//! ## Crate Replacement
//!
//! Replace in `Cargo.toml`:
//! ```toml
//! // Old (deprecated)
//! [dependencies]
//! cfgmatic-files = "2.0"
//!
//! // New
//! [dependencies]
//! cfgmatic-source = "2.0"
//! ```
//!
//! ## Type Mappings
//!
//! | Old (cfgmatic-files) | New (cfgmatic-source) | Notes |
//! |----------------------|----------------------|-------|
//! | `ConfigFile` | `FileSource` | File-based configuration source |
//! | `ConfigFiles` | `CompositeSource` | Multiple sources with priority |
//! | `FileFinder` | `Loader` with `FileConfig` | Unified loading interface |
//! | `Mergeable` | `Merge` trait from `cfgmatic-merge` | Direct merge trait |
//! | `Format` | `cfgmatic_source::Format` | Same enum, new location |
//! | `FileError` | `SourceError` | Unified error type |
//!
//! ## API Examples
//!
//! ### Loading a Single File
//!
//! ```rust,ignore
//! // Old API (deprecated)
//! use cfgmatic_files::FileFinder;
//! let files = FileFinder::new("myapp").find()?;
//! let config: Config = files.first().unwrap().parse()?;
//!
//! // New API
//! use cfgmatic_source::prelude::*;
//! let config: Config = FileSource::new("config.toml").load()?.parse_as()?;
//! ```
//!
//! ### Loading with Multiple Sources
//!
//! ```rust,ignore
//! // Old API (deprecated)
//! use cfgmatic_files::load_merged;
//! let config: Config = load_merged("myapp")?;
//!
//! // New API
//! use cfgmatic_source::prelude::*;
//! let source = CompositeSource::new()
//!     .with_source(FileSource::new("config.toml"), SourcePriority::High)
//!     .with_source(EnvSource::new("APP"), SourcePriority::Low);
//! let config: Config = source.load()?.parse_as()?;
//! ```
//!
//! ### Finding Config Files
//!
//! ```rust,ignore
//! // Old API (deprecated)
//! use cfgmatic_files::{FileFinder, find_files};
//! let files = find_files("myapp")?;
//!
//! // New API
//! use cfgmatic_source::prelude::*;
//! let loader = Loader::new()
//!     .with_source(FileConfig::new().app_name("myapp"));
//! let result = loader.load()?;
//! ```
//!
//! # Features
//!
//! The new `cfgmatic-source` crate supports all features from this crate:
//!
//! - `toml` - TOML format support (default)
//! - `json` - JSON format support (default)
//! - `yaml` - YAML format support
//! - `env` - Environment variable sources
//! - `async` - Async loading support
//! - `remote` - Remote HTTP/HTTPS sources
//! - `watch` - File watching support
//!
//! # Transition Period
//!
//! During the transition period, this crate re-exports types from
//! `cfgmatic-source` for convenience. However, new code should use
//! `cfgmatic-source` directly.

#![deprecated(
    since = "2.0.1",
    note = "use cfgmatic-source crate instead, which provides a unified configuration source API"
)]
#![warn(missing_docs)]
// Deprecated crate - allow all pedantic lints and deprecated usage internally
#![allow(deprecated)]
#![allow(clippy::all)]
#![allow(clippy::pedantic)]
#![allow(clippy::cargo)]

// =============================================================================
// Re-exports from cfgmatic-source (new API)
// =============================================================================

/// Re-export of cfgmatic-source types for migration convenience.
pub use cfgmatic_source::{
    LoadResult, Loader, LoaderBuilder, Source, SourceError, SourceKind, SourceMetadata,
};

// Feature-gated re-exports from cfgmatic-source
#[cfg(feature = "toml")]
pub use cfgmatic_source::FileSource;

// =============================================================================
// Legacy types (deprecated but kept for backwards compatibility)
// =============================================================================

// Legacy module
mod legacy;

pub use error::{FileError, Result};
pub use file::{ConfigFile, ConfigFiles, Mergeable};
pub use finder::{FileFinder, FileFinderState, find_files, find_first_file, load_first};
pub use format::Format;
pub use loader::{RuleBasedLoader, load_with_rules};
pub use merge::{ArrayMergeStrategy, MergeBehavior, MergeOptions};

// Re-export from cfgmatic-paths for convenience (legacy)
pub use cfgmatic_paths::{
    ConfigCandidate, ConfigFileRule, ConfigRuleSet, ConfigTier, FragmentRule, RuleBasedDiscovery,
    TierSearchMode,
};

mod error;
mod file;
mod finder;
mod format;
mod loader;
mod merge;

/// Convenience functions for common operations.
///
/// **Deprecated**: Use `cfgmatic_source::prelude` instead.
pub mod prelude {
    /// Common imports for working with configuration files.
    ///
    /// **Deprecated**: Use `cfgmatic_source::prelude` instead.
    #[deprecated(since = "2.0.1", note = "use cfgmatic_source::prelude instead")]
    pub use crate::{
        ArrayMergeStrategy, ConfigFile, ConfigFiles, ConfigTier, FileFinder, FileFinderState,
        Format, MergeBehavior, MergeOptions, Mergeable, Result, find_files, find_first_file,
        load_first,
    };

    // Re-export new types for migration
    pub use cfgmatic_source::{
        Format as SourceFormat, LoadResult, Loader, LoaderBuilder, Source, SourceError, SourceKind,
        SourceMetadata,
    };

    #[cfg(feature = "toml")]
    pub use cfgmatic_source::FileSource;
}

/// Load and merge configuration from all found files.
///
/// **Deprecated**: Use `cfgmatic_source::Loader` instead.
///
/// # Example
///
/// ```
/// use cfgmatic_files::load_merged;
///
/// match load_merged::<serde_json::Value>("myapp") {
///     Ok(config) => println!("Loaded: {:?}", config),
///     Err(e) => eprintln!("Failed to load config: {}", e),
/// }
/// ```
///
/// # Errors
///
/// Returns an error if directories cannot be accessed or files cannot be parsed.
#[deprecated(since = "2.0.1", note = "use cfgmatic_source::Loader instead")]
pub fn load_merged<T: serde::de::DeserializeOwned + Mergeable + Default>(
    app_name: impl Into<String>,
) -> Result<T> {
    let mut files = FileFinder::new(app_name).find()?;
    files.merge()
}

/// Find configuration files with a specific format.
///
/// **Deprecated**: Use `cfgmatic_source::Loader` with `FileConfig` instead.
///
/// # Example
///
/// ```
/// use cfgmatic_files::find_with_format;
///
/// let files = find_with_format("myapp", cfgmatic_files::Format::Toml)
///     .expect("find toml files");
/// ```
///
/// # Errors
///
/// Returns an error if directories cannot be accessed.
#[deprecated(
    since = "2.0.1",
    note = "use cfgmatic_source::Loader with FileConfig instead"
)]
pub fn find_with_format(app_name: impl Into<String>, format: Format) -> Result<ConfigFiles> {
    FileFinder::new(app_name).formats(&[format]).find()
}

/// Check if a configuration exists for the application.
///
/// Returns `true` if at least one configuration file is found.
#[deprecated(since = "2.0.1", note = "use cfgmatic_source::Loader instead")]
pub fn config_exists(app_name: impl Into<String>) -> bool {
    find_first_file(app_name)
        .map(|f| f.is_some())
        .unwrap_or(false)
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    #[allow(deprecated)]
    fn test_module_exports() {
        // Just verify all public types are accessible
        let _: FileFinder = FileFinder::new("test");
        let _: Format = Format::Toml;
    }

    #[test]
    #[allow(deprecated)]
    fn test_config_exists_nonexistent() {
        assert!(!config_exists("nonexistent_app_12345"));
    }
}