vespertide_core/
migration.rs1#[derive(Debug, Clone)]
23#[non_exhaustive]
24pub struct MigrationOptions {
25 pub version_table: String,
30}
31
32impl MigrationOptions {
33 #[must_use]
44 pub fn new(version_table: impl Into<String>) -> Self {
45 Self {
46 version_table: version_table.into(),
47 }
48 }
49}
50
51impl Default for MigrationOptions {
52 fn default() -> Self {
53 Self {
54 version_table: "vespertide_migrations".to_string(),
55 }
56 }
57}
58
59#[derive(thiserror::Error, Debug)]
60pub enum MigrationError {
61 #[error("migration execution is not yet implemented")]
62 NotImplemented,
63 #[error("database error: {0}")]
64 #[deprecated(
65 since = "0.1.62",
66 note = "Use Database { message, source } for proper error source chains"
67 )]
68 DatabaseError(String),
69 #[error("database error: {message}")]
70 Database {
71 message: String,
72 #[source]
73 source: Option<Box<dyn std::error::Error + Send + Sync>>,
74 },
75 #[error(
76 "migration id mismatch for version {version}: expected '{expected}', found '{found}' in database"
77 )]
78 IdMismatch {
79 version: u32,
80 expected: String,
81 found: String,
82 },
83}
84
85impl From<sea_orm::DbErr> for MigrationError {
86 fn from(err: sea_orm::DbErr) -> Self {
87 Self::Database {
88 message: err.to_string(),
89 source: Some(Box::new(err)),
90 }
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
99
100 #[test]
101 fn new_constructs_with_override_table_name() {
102 let opts = MigrationOptions::new("tenant_migrations");
104 assert_eq!(opts.version_table, "tenant_migrations");
105 }
106
107 #[test]
108 fn new_accepts_owned_string_via_into() {
109 let owned: String = String::from("audit_migrations");
111 let opts = MigrationOptions::new(owned);
112 assert_eq!(opts.version_table, "audit_migrations");
113 }
114
115 #[test]
116 fn default_uses_canonical_version_table() {
117 let opts = MigrationOptions::default();
119 assert_eq!(opts.version_table, "vespertide_migrations");
120 }
121
122 #[test]
123 fn migration_error_not_implemented_display() {
124 let err = MigrationError::NotImplemented;
125 assert_eq!(
126 err.to_string(),
127 "migration execution is not yet implemented"
128 );
129 }
130
131 #[test]
132 fn migration_error_database_struct_display() {
133 let err = MigrationError::Database {
134 message: "connection refused".to_string(),
135 source: None,
136 };
137 assert_eq!(err.to_string(), "database error: connection refused");
138 }
139
140 #[test]
141 fn migration_error_id_mismatch_display() {
142 let err = MigrationError::IdMismatch {
143 version: 7,
144 expected: "abc".to_string(),
145 found: "def".to_string(),
146 };
147 assert!(err.to_string().contains("version 7"));
148 assert!(err.to_string().contains("'abc'"));
149 assert!(err.to_string().contains("'def'"));
150 }
151}