ferro_storage/lib.rs
1//! # Ferro Storage
2//!
3//! File storage abstraction for the Ferro framework.
4//!
5//! Provides a unified API for working with different storage backends:
6//! - Local filesystem
7//! - In-memory (for testing)
8//! - Amazon S3 (with `s3` feature)
9//!
10//! ## Example
11//!
12//! ```rust,ignore
13//! use ferro_storage::{Storage, DiskConfig};
14//!
15//! // Create storage with configuration
16//! let storage = Storage::with_config(
17//! "local",
18//! vec![
19//! ("local", DiskConfig::local("storage/app")),
20//! ("public", DiskConfig::local("storage/public").with_url("/storage")),
21//! ],
22//! );
23//!
24//! // Store a file
25//! storage.put("documents/report.pdf", file_contents).await?;
26//!
27//! // Get a file
28//! let contents = storage.get("documents/report.pdf").await?;
29//!
30//! // Get URL
31//! let url = storage.disk("public")?.url("images/logo.png").await?;
32//! ```
33//!
34//! ## Multiple Disks
35//!
36//! You can configure multiple disks and switch between them:
37//!
38//! ```rust,ignore
39//! use ferro_storage::Storage;
40//!
41//! // Use specific disk
42//! let disk = storage.disk("s3")?;
43//! disk.put("backups/data.json", data).await?;
44//!
45//! // Use default disk
46//! storage.put("temp/cache.txt", cache_data).await?;
47//! ```
48
49mod config;
50mod drivers;
51mod error;
52mod facade;
53mod storage;
54
55#[cfg(feature = "s3")]
56pub use drivers::S3Driver;
57pub use drivers::{LocalDriver, MemoryDriver};
58
59pub use config::StorageConfig;
60pub use error::Error;
61pub use facade::{Disk, DiskConfig, DiskDriver, Storage};
62pub use storage::{FileMetadata, PutOptions, StorageDriver, Visibility};
63
64/// Re-export bytes for convenience.
65pub use bytes::Bytes;
66
67/// Re-export async_trait for implementing StorageDriver.
68pub use async_trait::async_trait;
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[tokio::test]
75 async fn test_full_workflow() {
76 let storage = Storage::with_config(
77 "memory",
78 vec![(
79 "memory",
80 DiskConfig::memory().with_url("https://cdn.example.com"),
81 )],
82 );
83
84 // Put file
85 storage.put("test/file.txt", "test content").await.unwrap();
86
87 // Verify exists
88 assert!(storage.exists("test/file.txt").await.unwrap());
89
90 // Get file
91 let contents = storage.get_string("test/file.txt").await.unwrap();
92 assert_eq!(contents, "test content");
93
94 // Get URL
95 let url = storage.url("test/file.txt").await.unwrap();
96 assert_eq!(url, "https://cdn.example.com/test/file.txt");
97
98 // Delete file
99 storage.delete("test/file.txt").await.unwrap();
100 assert!(!storage.exists("test/file.txt").await.unwrap());
101 }
102}