toasty_cli/migration/config.rs
1use serde::{Deserialize, Serialize};
2use std::path::PathBuf;
3
4/// Configuration for migration operations.
5///
6/// Controls where migration files, snapshot files, and the history file are
7/// stored, how migration file names are prefixed (sequential numbers or
8/// timestamps), and optional behaviors like checksum verification and
9/// statement breakpoint comments.
10///
11/// The default configuration uses a `toasty/` base path with sequential
12/// numbering, no checksums, and statement breakpoints enabled.
13///
14/// # Examples
15///
16/// ```
17/// use toasty_cli::{MigrationConfig, MigrationPrefixStyle};
18///
19/// let config = MigrationConfig::new()
20/// .path("my_app/db")
21/// .prefix_style(MigrationPrefixStyle::Timestamp);
22///
23/// assert_eq!(
24/// config.get_migrations_dir(),
25/// std::path::PathBuf::from("my_app/db/migrations"),
26/// );
27/// assert_eq!(
28/// config.get_snapshots_dir(),
29/// std::path::PathBuf::from("my_app/db/snapshots"),
30/// );
31/// assert_eq!(
32/// config.get_history_file_path(),
33/// std::path::PathBuf::from("my_app/db/history.toml"),
34/// );
35/// ```
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct MigrationConfig {
38 /// Path to the migrations folder
39 pub path: PathBuf,
40
41 /// Style of migration file prefixes
42 pub prefix_style: MigrationPrefixStyle,
43
44 /// Whether the history file should store and verify checksums of the migration files so that
45 /// they may not be changed.
46 pub checksums: bool,
47
48 /// Whether to add statement breakpoint comments to generated SQL migration files.
49 /// These comments mark boundaries where SQL statements should be split for execution.
50 /// This is needed because different databases have different batching capabilities:
51 /// some (like PostgreSQL) can execute multiple statements in one batch, while others
52 /// require each statement to be executed separately.
53 pub statement_breakpoints: bool,
54}
55
56/// Controls the prefix format used when naming generated migration files.
57///
58/// The prefix appears at the start of the migration file name and determines
59/// the ordering of migration files on disk.
60///
61/// # Examples
62///
63/// ```
64/// use toasty_cli::MigrationPrefixStyle;
65///
66/// // Default is sequential
67/// let style = MigrationPrefixStyle::Sequential;
68/// assert_eq!(style, MigrationPrefixStyle::Sequential);
69/// ```
70#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
71pub enum MigrationPrefixStyle {
72 /// Sequential numbering (e.g., 0001_, 0002_, 0003_)
73 Sequential,
74
75 /// Timestamp-based (e.g., 20240112_153045_)
76 Timestamp,
77}
78
79impl Default for MigrationConfig {
80 fn default() -> Self {
81 Self {
82 path: PathBuf::from("toasty"),
83 prefix_style: MigrationPrefixStyle::Sequential,
84 checksums: false,
85 statement_breakpoints: true,
86 }
87 }
88}
89
90impl MigrationConfig {
91 /// Create a new MigrationConfig with default values
92 pub fn new() -> Self {
93 Self::default()
94 }
95
96 /// Set the migrations path
97 pub fn path(mut self, path: impl Into<PathBuf>) -> Self {
98 self.path = path.into();
99 self
100 }
101
102 /// Set the migration prefix style
103 pub fn prefix_style(mut self, style: MigrationPrefixStyle) -> Self {
104 self.prefix_style = style;
105 self
106 }
107
108 /// Returns the directory of the migration files derived from `path`.
109 pub fn get_migrations_dir(&self) -> PathBuf {
110 self.path.join("migrations")
111 }
112
113 /// Returns the directory of the snapshot files derived from `path`.
114 pub fn get_snapshots_dir(&self) -> PathBuf {
115 self.path.join("snapshots")
116 }
117
118 /// Get the path to the history file
119 pub fn get_history_file_path(&self) -> PathBuf {
120 self.path.join("history.toml")
121 }
122}