Skip to main content

waypoint_core/
lib.rs

1//! Lightweight, Flyway-compatible PostgreSQL migration library.
2//!
3//! # Quick Start
4//!
5//! ```rust,no_run
6//! use waypoint_core::config::WaypointConfig;
7//! use waypoint_core::Waypoint;
8//!
9//! # async fn run() -> Result<(), Box<dyn std::error::Error>> {
10//! let config = WaypointConfig::load(None, None)?;
11//! let wp = Waypoint::new(config).await?;
12//! let report = wp.migrate(None).await?;
13//! println!("Applied {} migrations", report.migrations_applied);
14//! # Ok(())
15//! # }
16//! ```
17//!
18//! # Architecture
19//!
20//! - [`config`] — Configuration loading (TOML, env vars, CLI overrides)
21//! - [`migration`] — Migration file parsing and scanning
22//! - [`db`] — Database connections, TLS, advisory locks
23//! - [`history`] — Schema history table operations
24//! - [`commands`] — Individual command implementations (migrate, info, validate, repair, baseline, clean)
25//! - [`checksum`] — CRC32 checksums (Flyway-compatible)
26//! - [`placeholder`] — `${key}` placeholder replacement in SQL
27//! - [`hooks`] — SQL callback hooks (before/after migrate)
28//! - [`error`] — Error types
29
30pub mod checksum;
31pub mod commands;
32pub mod config;
33pub mod db;
34pub mod error;
35pub mod history;
36pub mod hooks;
37pub mod migration;
38pub mod placeholder;
39
40use config::WaypointConfig;
41use error::Result;
42use tokio_postgres::Client;
43
44pub use commands::info::{MigrationInfo, MigrationState};
45pub use commands::migrate::MigrateReport;
46pub use commands::repair::RepairReport;
47pub use commands::validate::ValidateReport;
48pub use config::CliOverrides;
49
50/// Main entry point for the Waypoint library.
51///
52/// Create a `Waypoint` instance with a config and use its methods to
53/// run migration commands programmatically.
54pub struct Waypoint {
55    pub config: WaypointConfig,
56    client: Client,
57}
58
59impl Waypoint {
60    /// Create a new Waypoint instance, connecting to the database.
61    ///
62    /// If `connect_retries` is configured, retries with exponential backoff.
63    pub async fn new(config: WaypointConfig) -> Result<Self> {
64        let conn_string = config.connection_string()?;
65        let client = db::connect_with_config(
66            &conn_string,
67            &config.database.ssl_mode,
68            config.database.connect_retries,
69            config.database.connect_timeout_secs,
70            config.database.statement_timeout_secs,
71        )
72        .await?;
73        Ok(Self { config, client })
74    }
75
76    /// Create a new Waypoint instance with an existing database client.
77    pub fn with_client(config: WaypointConfig, client: Client) -> Self {
78        Self { config, client }
79    }
80
81    /// Apply pending migrations.
82    pub async fn migrate(&self, target_version: Option<&str>) -> Result<MigrateReport> {
83        commands::migrate::execute(&self.client, &self.config, target_version).await
84    }
85
86    /// Show migration status information.
87    pub async fn info(&self) -> Result<Vec<MigrationInfo>> {
88        commands::info::execute(&self.client, &self.config).await
89    }
90
91    /// Validate applied migrations against local files.
92    pub async fn validate(&self) -> Result<ValidateReport> {
93        commands::validate::execute(&self.client, &self.config).await
94    }
95
96    /// Repair the schema history table.
97    pub async fn repair(&self) -> Result<RepairReport> {
98        commands::repair::execute(&self.client, &self.config).await
99    }
100
101    /// Baseline an existing database.
102    pub async fn baseline(&self, version: Option<&str>, description: Option<&str>) -> Result<()> {
103        commands::baseline::execute(&self.client, &self.config, version, description).await
104    }
105
106    /// Drop all objects in managed schemas.
107    pub async fn clean(&self, allow_clean: bool) -> Result<Vec<String>> {
108        commands::clean::execute(&self.client, &self.config, allow_clean).await
109    }
110}