Skip to main content

html2pdf_api/
prelude.rs

1//! Convenient imports for common usage patterns.
2//!
3//! This module re-exports the most commonly used types from `html2pdf-api`,
4//! allowing you to quickly get started with a single import.
5//!
6//! # Quick Start
7//!
8//! ```rust,ignore
9//! use html2pdf_api::prelude::*;
10//! ```
11//!
12//! This single line gives you access to all the core types needed to create
13//! and use a browser pool for PDF generation.
14//!
15//! # What's Included
16//!
17//! ## Core Types (Always Available)
18//!
19//! | Type | Description |
20//! |------|-------------|
21//! | [`BrowserPool`] | Main pool for managing browser instances |
22//! | [`BrowserPoolBuilder`] | Builder for creating configured pools |
23//! | [`BrowserPoolConfig`] | Configuration settings for the pool |
24//! | [`BrowserPoolConfigBuilder`] | Builder for creating configurations |
25//! | [`BrowserPoolError`] | Error type for pool operations |
26//! | [`Result`] | Type alias for `Result<T, BrowserPoolError>` |
27//! | [`BrowserHandle`] | RAII handle for checked-out browsers |
28//! | [`PoolStats`] | Real-time pool statistics |
29//! | [`BrowserFactory`] | Trait for browser creation strategies |
30//! | [`ChromeBrowserFactory`] | Default Chrome/Chromium factory |
31//! | [`Healthcheck`] | Trait for browser health checking |
32//! | [`SharedBrowserPool`] | Type alias for `Arc<BrowserPool>` |
33//!
34//! ## Standard Library Re-exports
35//!
36//! For convenience, commonly needed types are re-exported:
37//!
38//! | Type | Description |
39//! |------|-------------|
40//! | [`Arc`] | Thread-safe reference counting |
41//! | [`Mutex`] | Mutual exclusion lock |
42//!
43//! ## Feature-Gated Exports
44//!
45//! Additional exports are available with feature flags:
46//!
47//! ### `env-config` Feature
48//!
49//! | Export | Description |
50//! |--------|-------------|
51//! | [`init_browser_pool`] | Initialize pool from environment variables |
52//! | [`from_env`] | Load configuration from environment |
53//! | [`chrome_path_from_env`] | Get Chrome path from `CHROME_PATH` env var |
54//!
55//! ### `actix-integration` Feature
56//!
57//! | Export | Description |
58//! |--------|-------------|
59//! | [`actix`] module | Actix-web handlers and helpers |
60//!
61//! ### `rocket-integration` Feature
62//!
63//! | Export | Description |
64//! |--------|-------------|
65//! | [`rocket`] module | Rocket handlers and helpers |
66//!
67//! ### `axum-integration` Feature
68//!
69//! | Export | Description |
70//! |--------|-------------|
71//! | [`axum`] module | Axum handlers and router |
72//!
73//! ### Any Integration Feature
74//!
75//! When any integration feature is enabled, service types are also available:
76//!
77//! | Type | Description |
78//! |------|-------------|
79//! | [`PdfFromUrlRequest`] | Request parameters for URL-to-PDF |
80//! | [`PdfFromHtmlRequest`] | Request parameters for HTML-to-PDF |
81//! | [`PdfResponse`] | Successful PDF generation result |
82//! | [`PdfServiceError`] | Service-level errors |
83//! | [`ErrorResponse`] | JSON error response format |
84//! | [`PoolStatsResponse`] | Pool statistics response |
85//! | [`HealthResponse`] | Health check response |
86//!
87//! # Usage Examples
88//!
89//! ## Basic Usage
90//!
91//! Create a pool with manual configuration:
92//!
93//! ```rust,ignore
94//! use html2pdf_api::prelude::*;
95//! use std::time::Duration;
96//!
97//! #[tokio::main]
98//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
99//!     // Build configuration
100//!     let config = BrowserPoolConfigBuilder::new()
101//!         .max_pool_size(5)
102//!         .warmup_count(3)
103//!         .browser_ttl(Duration::from_secs(3600))
104//!         .build()?;
105//!
106//!     // Create pool
107//!     let pool = BrowserPool::builder()
108//!         .config(config)
109//!         .factory(Box::new(ChromeBrowserFactory::with_defaults()))
110//!         .build()?;
111//!
112//!     // Warmup for production readiness
113//!     pool.warmup().await?;
114//!
115//!     // Use a browser (automatically returned to pool when dropped)
116//!     {
117//!         let browser = pool.get()?;
118//!         let tab = browser.new_tab()?;
119//!         tab.navigate_to("https://example.com")?;
120//!         tab.wait_until_navigated()?;
121//!         let pdf = tab.print_to_pdf(None)?;
122//!         std::fs::write("output.pdf", pdf)?;
123//!     }
124//!
125//!     // Graceful shutdown
126//!     pool.shutdown();
127//!
128//!     Ok(())
129//! }
130//! ```
131//!
132//! ## Using Environment Configuration
133//!
134//! With the `env-config` feature, initialization is simpler:
135//!
136//! ```rust,ignore
137//! use html2pdf_api::prelude::*;
138//!
139//! #[tokio::main]
140//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
141//!     // Reads BROWSER_POOL_SIZE, BROWSER_TTL_SECONDS, etc.
142//!     let pool = init_browser_pool().await?;
143//!
144//!     // Pool is Arc<BrowserPool>, ready for sharing
145//!     let browser = pool.get()?;
146//!     // ...
147//!
148//!     Ok(())
149//! }
150//! ```
151//!
152//! ## With Actix-web (Pre-built Routes)
153//!
154//! The fastest way to set up a PDF API:
155//!
156//! ```rust,ignore
157//! use actix_web::{App, HttpServer, web};
158//! use html2pdf_api::prelude::*;
159//! use html2pdf_api::integrations::actix::configure_routes;
160//!
161//! #[actix_web::main]
162//! async fn main() -> std::io::Result<()> {
163//!     let pool = init_browser_pool().await
164//!         .expect("Failed to initialize pool");
165//!
166//!     HttpServer::new(move || {
167//!         App::new()
168//!             .app_data(web::Data::new(pool.clone()))
169//!             .configure(configure_routes) // Adds /pdf, /pdf/html, /health, etc.
170//!     })
171//!     .bind("127.0.0.1:8080")?
172//!     .run()
173//!     .await
174//! }
175//! ```
176//!
177//! ## With Actix-web (Custom Handler)
178//!
179//! For more control, use service functions directly:
180//!
181//! ```rust,ignore
182//! use actix_web::{web, HttpResponse, Responder};
183//! use html2pdf_api::prelude::*;
184//! use html2pdf_api::service::{generate_pdf_from_url, PdfFromUrlRequest};
185//!
186//! async fn my_pdf_handler(
187//!     pool: web::Data<SharedBrowserPool>,
188//!     query: web::Query<PdfFromUrlRequest>,
189//! ) -> impl Responder {
190//!     let pool = pool.into_inner();
191//!     let request = query.into_inner();
192//!
193//!     let result = web::block(move || {
194//!         generate_pdf_from_url(&pool, &request)
195//!     }).await;
196//!
197//!     match result {
198//!         Ok(Ok(pdf)) => HttpResponse::Ok()
199//!             .content_type("application/pdf")
200//!             .body(pdf.data),
201//!         Ok(Err(e)) => HttpResponse::BadRequest().body(e.to_string()),
202//!         Err(e) => HttpResponse::InternalServerError().body(e.to_string()),
203//!     }
204//! }
205//! ```
206//!
207//! ## Checking Pool Statistics
208//!
209//! Monitor pool health in your application:
210//!
211//! ```rust,ignore
212//! use html2pdf_api::prelude::*;
213//!
214//! fn log_pool_status(pool: &SharedBrowserPool) {
215//!     let stats = pool.stats();
216//!     println!("Pool Status:");
217//!     println!("  Available: {}", stats.available);
218//!     println!("  Active: {}", stats.active);
219//!     println!("  Total: {}", stats.total);
220//!     
221//!     // Check capacity
222//!     if stats.available == 0 {
223//!         println!("  ⚠️ Warning: No idle browsers available");
224//!     }
225//! }
226//! ```
227//!
228//! ## Error Handling
229//!
230//! Handle pool errors appropriately:
231//!
232//! ```rust,ignore
233//! use html2pdf_api::prelude::*;
234//!
235//! fn generate_pdf(pool: &SharedBrowserPool, url: &str) -> Result<Vec<u8>> {
236//!     let browser = pool.get()?;  // Returns BrowserPoolError
237//!     let tab = browser.new_tab()
238//!         .map_err(|e| BrowserPoolError::BrowserCreation(e.to_string()))?;
239//!
240//!     tab.navigate_to(url)
241//!         .map_err(|e| BrowserPoolError::BrowserCreation(e.to_string()))?;
242//!     tab.wait_until_navigated()
243//!         .map_err(|e| BrowserPoolError::BrowserCreation(e.to_string()))?;
244//!
245//!     let pdf = tab.print_to_pdf(None)
246//!         .map_err(|e| BrowserPoolError::BrowserCreation(e.to_string()))?;
247//!
248//!     Ok(pdf)
249//! }
250//! ```
251//!
252//! # Feature Flag Reference
253//!
254//! | Feature | Adds to Prelude |
255//! |---------|-----------------|
256//! | (none) | Core types only |
257//! | `env-config` | `init_browser_pool`, `from_env`, `chrome_path_from_env` |
258//! | `actix-integration` | `actix` module + service types |
259//! | `rocket-integration` | `rocket` module + service types |
260//! | `axum-integration` | `axum` module + service types |
261//! | `test-utils` | `MockBrowserFactory` (in `factory::mock`) |
262//!
263//! # See Also
264//!
265//! - [`crate::pool`] - Browser pool implementation details
266//! - [`crate::config`] - Configuration options
267//! - [`crate::service`] - Core PDF generation service
268//! - [`crate::integrations`] - Web framework integrations
269
270// ============================================================================
271// Core Types (Always Available)
272// ============================================================================
273
274/// The main browser pool type for managing browser instances.
275///
276/// See [`crate::pool::BrowserPool`] for full documentation.
277pub use crate::pool::BrowserPool;
278
279/// Builder for creating configured [`BrowserPool`] instances.
280///
281/// See [`crate::pool::BrowserPoolBuilder`] for full documentation.
282pub use crate::pool::BrowserPoolBuilder;
283
284/// Configuration settings for the browser pool.
285///
286/// See [`crate::config::BrowserPoolConfig`] for full documentation.
287pub use crate::config::BrowserPoolConfig;
288
289/// Builder for creating [`BrowserPoolConfig`] instances.
290///
291/// See [`crate::config::BrowserPoolConfigBuilder`] for full documentation.
292pub use crate::config::BrowserPoolConfigBuilder;
293
294/// Error type for browser pool operations.
295///
296/// See [`crate::error::BrowserPoolError`] for full documentation.
297pub use crate::error::BrowserPoolError;
298
299/// Result type alias using [`BrowserPoolError`].
300///
301/// Equivalent to `std::result::Result<T, BrowserPoolError>`.
302pub use crate::error::Result;
303
304/// RAII handle for a browser checked out from the pool.
305///
306/// When dropped, the browser is automatically returned to the pool.
307/// See [`crate::handle::BrowserHandle`] for full documentation.
308pub use crate::handle::BrowserHandle;
309
310/// Real-time statistics about the browser pool.
311///
312/// See [`crate::stats::PoolStats`] for full documentation.
313pub use crate::stats::PoolStats;
314
315/// Trait for browser creation strategies.
316///
317/// Implement this trait to customize how browsers are created.
318/// See [`crate::factory::BrowserFactory`] for full documentation.
319pub use crate::factory::BrowserFactory;
320
321/// Default factory for creating Chrome/Chromium browsers.
322///
323/// See [`crate::factory::ChromeBrowserFactory`] for full documentation.
324pub use crate::factory::ChromeBrowserFactory;
325
326/// Trait for browser health checking.
327///
328/// See [`crate::traits::Healthcheck`] for full documentation.
329pub use crate::traits::Healthcheck;
330
331/// Type alias for a shared, thread-safe browser pool.
332///
333/// This is defined as `Arc<BrowserPool>` and is the standard
334/// way to share a pool across threads and async tasks.
335/// No outer `Mutex` is needed — the pool uses fine-grained internal locks.
336///
337/// # Example
338///
339/// ```rust,ignore
340/// use html2pdf_api::prelude::*;
341///
342/// let pool: SharedBrowserPool = BrowserPool::builder()
343///     .factory(Box::new(ChromeBrowserFactory::with_defaults()))
344///     .build()
345///     .unwrap()
346///     .into_shared();
347/// ```
348pub use crate::SharedBrowserPool;
349
350// ============================================================================
351// Standard Library Re-exports
352// ============================================================================
353
354/// Thread-safe reference counting pointer.
355///
356/// Re-exported for convenience when working with [`SharedBrowserPool`].
357///
358/// # Example
359///
360/// ```rust,ignore
361/// use html2pdf_api::prelude::*;
362///
363/// let pool = init_browser_pool().await?;
364/// let pool_clone = Arc::clone(&pool);  // Clone for another thread/task
365/// ```
366pub use std::sync::Arc;
367
368// (Mutex re-export removed — no longer needed for SharedBrowserPool)
369
370// ============================================================================
371// Environment Configuration (env-config feature)
372// ============================================================================
373
374/// Initialize a browser pool from environment variables.
375///
376/// This function reads configuration from environment variables and creates
377/// a ready-to-use shared pool. It's the recommended way to initialize the
378/// pool in production.
379///
380/// # Environment Variables
381///
382/// | Variable | Type | Default | Description |
383/// |----------|------|---------|-------------|
384/// | `BROWSER_POOL_SIZE` | usize | 5 | Maximum browsers in pool |
385/// | `BROWSER_WARMUP_COUNT` | usize | 3 | Browsers to pre-create |
386/// | `BROWSER_TTL_SECONDS` | u64 | 3600 | Browser lifetime |
387/// | `BROWSER_WARMUP_TIMEOUT_SECONDS` | u64 | 60 | Warmup timeout |
388/// | `BROWSER_PING_INTERVAL_SECONDS` | u64 | 15 | Health check interval |
389/// | `BROWSER_MAX_PING_FAILURES` | u32 | 3 | Max failures before removal |
390/// | `CHROME_PATH` | String | auto | Custom Chrome path |
391///
392/// # Example
393///
394/// ```rust,ignore
395/// use html2pdf_api::prelude::*;
396///
397/// #[tokio::main]
398/// async fn main() -> Result<(), Box<dyn std::error::Error>> {
399///     let pool = init_browser_pool().await?;
400///     // Pool is ready to use!
401///     Ok(())
402/// }
403/// ```
404///
405/// # Errors
406///
407/// Returns an error if:
408/// - Environment variables contain invalid values
409/// - Chrome/Chromium cannot be found or launched
410/// - Pool warmup fails
411#[cfg(feature = "env-config")]
412pub use crate::pool::init_browser_pool;
413
414/// Load pool configuration from environment variables.
415///
416/// Use this when you need to customize pool creation but still want
417/// environment-based configuration.
418///
419/// # Example
420///
421/// ```rust,ignore
422/// use html2pdf_api::prelude::*;
423///
424/// let config = from_env()?;
425/// let pool = BrowserPool::builder()
426///     .config(config)
427///     .factory(Box::new(ChromeBrowserFactory::with_defaults()))
428///     .enable_keep_alive(true)  // Custom option
429///     .build()?;
430/// ```
431#[cfg(feature = "env-config")]
432pub use crate::config::env::from_env;
433
434/// Get Chrome path from the `CHROME_PATH` environment variable.
435///
436/// Returns `Some(path)` if the variable is set, `None` otherwise.
437///
438/// # Example
439///
440/// ```rust,ignore
441/// use html2pdf_api::prelude::*;
442///
443/// let factory = match chrome_path_from_env() {
444///     Some(path) => ChromeBrowserFactory::with_path(path),
445///     None => ChromeBrowserFactory::with_defaults(),
446/// };
447/// ```
448#[cfg(feature = "env-config")]
449pub use crate::config::env::chrome_path_from_env;
450
451// ============================================================================
452// Service Types (Any Integration Feature)
453// ============================================================================
454
455/// Request parameters for URL-to-PDF conversion.
456///
457/// See [`crate::service::PdfFromUrlRequest`] for full documentation.
458#[cfg(any(
459    feature = "actix-integration",
460    feature = "rocket-integration",
461    feature = "axum-integration"
462))]
463pub use crate::service::PdfFromUrlRequest;
464
465/// Request parameters for HTML-to-PDF conversion.
466///
467/// See [`crate::service::PdfFromHtmlRequest`] for full documentation.
468#[cfg(any(
469    feature = "actix-integration",
470    feature = "rocket-integration",
471    feature = "axum-integration"
472))]
473pub use crate::service::PdfFromHtmlRequest;
474
475/// Successful PDF generation result.
476///
477/// Contains the PDF binary data and metadata.
478/// See [`crate::service::PdfResponse`] for full documentation.
479#[cfg(any(
480    feature = "actix-integration",
481    feature = "rocket-integration",
482    feature = "axum-integration"
483))]
484pub use crate::service::PdfResponse;
485
486/// Errors that can occur during PDF generation.
487///
488/// Includes HTTP status code mapping for easy response building.
489/// See [`crate::service::PdfServiceError`] for full documentation.
490#[cfg(any(
491    feature = "actix-integration",
492    feature = "rocket-integration",
493    feature = "axum-integration"
494))]
495pub use crate::service::PdfServiceError;
496
497/// JSON error response format.
498///
499/// See [`crate::service::ErrorResponse`] for full documentation.
500#[cfg(any(
501    feature = "actix-integration",
502    feature = "rocket-integration",
503    feature = "axum-integration"
504))]
505pub use crate::service::ErrorResponse;
506
507/// Pool statistics response for API endpoints.
508///
509/// See [`crate::service::PoolStatsResponse`] for full documentation.
510#[cfg(any(
511    feature = "actix-integration",
512    feature = "rocket-integration",
513    feature = "axum-integration"
514))]
515pub use crate::service::PoolStatsResponse;
516
517/// Health check response for API endpoints.
518///
519/// See [`crate::service::HealthResponse`] for full documentation.
520#[cfg(any(
521    feature = "actix-integration",
522    feature = "rocket-integration",
523    feature = "axum-integration"
524))]
525pub use crate::service::HealthResponse;
526
527// ============================================================================
528// Framework-Specific Modules
529// ============================================================================
530
531/// Actix-web integration module.
532///
533/// Provides pre-built handlers and helpers for Actix-web 4.x.
534///
535/// # Quick Start
536///
537/// ```rust,ignore
538/// use actix_web::{App, HttpServer, web};
539/// use html2pdf_api::prelude::*;
540/// use html2pdf_api::integrations::actix::configure_routes;
541///
542/// #[actix_web::main]
543/// async fn main() -> std::io::Result<()> {
544///     let pool = init_browser_pool().await.unwrap();
545///
546///     HttpServer::new(move || {
547///         App::new()
548///             .app_data(web::Data::new(pool.clone()))
549///             .configure(configure_routes)
550///     })
551///     .bind("127.0.0.1:8080")?
552///     .run()
553///     .await
554/// }
555/// ```
556///
557/// # Available Exports
558///
559/// | Export | Description |
560/// |--------|-------------|
561/// | `configure_routes` | Configure all pre-built routes |
562/// | `pdf_from_url` | Handler for URL-to-PDF |
563/// | `pdf_from_html` | Handler for HTML-to-PDF |
564/// | `pool_stats` | Handler for pool statistics |
565/// | `health_check` | Handler for health check |
566/// | `readiness_check` | Handler for readiness check |
567/// | `SharedPool` | Type alias for `Arc<BrowserPool>` |
568/// | `BrowserPoolData` | Type alias for `web::Data<SharedBrowserPool>` |
569/// | `BrowserPoolActixExt` | Extension trait for `BrowserPool` |
570///
571/// See [`crate::integrations::actix`] for full documentation.
572#[cfg(feature = "actix-integration")]
573pub mod actix {
574    pub use crate::integrations::actix::*;
575}
576
577/// Rocket integration module.
578///
579/// Provides pre-built handlers and helpers for Rocket 0.5.x.
580///
581/// # Quick Start
582///
583/// ```rust,ignore
584/// use html2pdf_api::prelude::*;
585/// use html2pdf_api::integrations::rocket::routes;
586///
587/// #[rocket::launch]
588/// async fn launch() -> _ {
589///     let pool = init_browser_pool().await.unwrap();
590///
591///     rocket::build()
592///         .manage(pool)
593///         .mount("/", routes())
594/// }
595/// ```
596///
597/// # Available Exports
598///
599/// | Export | Description |
600/// |--------|-------------|
601/// | `routes` | Get all pre-built routes |
602/// | `pdf_from_url` | Handler for URL-to-PDF |
603/// | `pdf_from_html` | Handler for HTML-to-PDF |
604/// | `pool_stats` | Handler for pool statistics |
605/// | `health_check` | Handler for health check |
606/// | `readiness_check` | Handler for readiness check |
607/// | `SharedPool` | Type alias for `Arc<BrowserPool>` |
608///
609/// See [`crate::integrations::rocket`] for full documentation.
610#[cfg(feature = "rocket-integration")]
611pub mod rocket {
612    pub use crate::integrations::rocket::*;
613}
614
615/// Axum integration module.
616///
617/// Provides pre-built handlers and router for Axum 0.7.x/0.8.x.
618///
619/// # Quick Start
620///
621/// ```rust,ignore
622/// use html2pdf_api::prelude::*;
623/// use html2pdf_api::integrations::axum::router;
624///
625/// #[tokio::main]
626/// async fn main() {
627///     let pool = init_browser_pool().await.unwrap();
628///
629///     let app = router().with_state(pool);
630///
631///     let listener = tokio::net::TcpListener::bind("127.0.0.1:8080")
632///         .await
633///         .unwrap();
634///     axum::serve(listener, app).await.unwrap();
635/// }
636/// ```
637///
638/// # Available Exports
639///
640/// | Export | Description |
641/// |--------|-------------|
642/// | `router` | Create router with all pre-built routes |
643/// | `pdf_from_url` | Handler for URL-to-PDF |
644/// | `pdf_from_html` | Handler for HTML-to-PDF |
645/// | `pool_stats` | Handler for pool statistics |
646/// | `health_check` | Handler for health check |
647/// | `readiness_check` | Handler for readiness check |
648/// | `SharedPool` | Type alias for `Arc<BrowserPool>` |
649///
650/// See [`crate::integrations::axum`] for full documentation.
651#[cfg(feature = "axum-integration")]
652pub mod axum {
653    pub use crate::integrations::axum::*;
654}
655
656// ============================================================================
657// Tests
658// ============================================================================
659
660#[cfg(test)]
661mod tests {
662    use super::*;
663
664    /// Verify all core types are accessible.
665    #[test]
666    fn test_core_types_exported() {
667        // These should all compile, proving the types are exported
668        fn _accepts_config(_: BrowserPoolConfig) {}
669        fn _accepts_error(_: BrowserPoolError) {}
670        fn _accepts_stats(_: PoolStats) {}
671        fn _returns_result() -> Result<()> {
672            Ok(())
673        }
674    }
675
676    /// Verify Arc is re-exported.
677    #[test]
678    fn test_std_reexports() {
679        let _: Arc<i32> = Arc::new(42);
680    }
681
682    /// Verify SharedBrowserPool type alias works.
683    #[test]
684    fn test_shared_browser_pool_type() {
685        fn _accepts_shared_pool(_: SharedBrowserPool) {}
686
687        // Verify it's Arc<BrowserPool>
688        fn _verify_type() {
689            let pool = BrowserPool::builder()
690                .factory(Box::new(crate::factory::mock::MockBrowserFactory::new()))
691                .build()
692                .unwrap();
693
694            let shared: SharedBrowserPool = Arc::new(pool);
695            _accepts_shared_pool(shared);
696        }
697    }
698
699    /// Verify env-config exports when feature is enabled.
700    #[cfg(feature = "env-config")]
701    #[test]
702    fn test_env_config_exports() {
703        // These should compile when env-config is enabled
704        let _: Option<String> = chrome_path_from_env();
705        fn _takes_from_env(_: fn() -> crate::error::Result<BrowserPoolConfig>) {}
706        _takes_from_env(from_env);
707    }
708
709    /// Verify service types when any integration is enabled.
710    #[cfg(any(
711        feature = "actix-integration",
712        feature = "rocket-integration",
713        feature = "axum-integration"
714    ))]
715    #[test]
716    fn test_service_types_exported() {
717        let _: PdfFromUrlRequest = PdfFromUrlRequest::default();
718        let _: PdfFromHtmlRequest = PdfFromHtmlRequest::default();
719        let _: HealthResponse = HealthResponse::default();
720    }
721}