use serde::{Deserialize, Serialize};
use version_migrate::{migrate_path, IntoDomain, MigratesTo, Migrator, Versioned};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct TaskV1 {
id: String,
title: String,
}
impl Versioned for TaskV1 {
const VERSION: &'static str = "1.0.0";
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct TaskV2 {
id: String,
title: String,
description: Option<String>,
}
impl Versioned for TaskV2 {
const VERSION: &'static str = "2.0.0";
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
struct TaskV3 {
id: String,
title: String,
description: Option<String>,
tags: Vec<String>,
}
impl Versioned for TaskV3 {
const VERSION: &'static str = "3.0.0";
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct TaskEntity {
id: String,
title: String,
description: Option<String>,
tags: Vec<String>,
}
impl MigratesTo<TaskV2> for TaskV1 {
fn migrate(self) -> TaskV2 {
TaskV2 {
id: self.id,
title: self.title,
description: None,
}
}
}
impl MigratesTo<TaskV3> for TaskV1 {
fn migrate(self) -> TaskV3 {
TaskV3 {
id: self.id,
title: self.title,
description: None,
tags: Vec::new(),
}
}
}
impl IntoDomain<TaskEntity> for TaskV1 {
fn into_domain(self) -> TaskEntity {
TaskEntity {
id: self.id,
title: self.title,
description: None,
tags: Vec::new(),
}
}
}
impl MigratesTo<TaskV3> for TaskV2 {
fn migrate(self) -> TaskV3 {
TaskV3 {
id: self.id,
title: self.title,
description: self.description,
tags: Vec::new(),
}
}
}
impl IntoDomain<TaskEntity> for TaskV2 {
fn into_domain(self) -> TaskEntity {
TaskEntity {
id: self.id,
title: self.title,
description: self.description,
tags: Vec::new(),
}
}
}
impl IntoDomain<TaskEntity> for TaskV3 {
fn into_domain(self) -> TaskEntity {
TaskEntity {
id: self.id,
title: self.title,
description: self.description,
tags: self.tags,
}
}
}
#[test]
fn test_migrator_basic() {
let path = migrate_path!("task", [TaskV1, TaskEntity]);
let mut migrator = Migrator::new();
migrator.register(path).unwrap();
let task_v1 = TaskV1 {
id: "1".to_string(),
title: "Test Task".to_string(),
};
let json = migrator.save(task_v1).unwrap();
let task_entity: TaskEntity = migrator.load("task", &json).unwrap();
assert_eq!(task_entity.id, "1");
assert_eq!(task_entity.title, "Test Task");
assert_eq!(task_entity.description, None);
assert_eq!(task_entity.tags, Vec::<String>::new());
}
#[test]
fn test_migrator_multi_step() {
let path = migrate_path!("task", [TaskV1, TaskV2, TaskEntity]);
let mut migrator = Migrator::new();
migrator.register(path).unwrap();
let task_v1 = TaskV1 {
id: "1".to_string(),
title: "Multi-step Task".to_string(),
};
let json = migrator.save(task_v1).unwrap();
let task_entity: TaskEntity = migrator.load("task", &json).unwrap();
assert_eq!(task_entity.id, "1");
assert_eq!(task_entity.title, "Multi-step Task");
assert_eq!(task_entity.description, None);
assert_eq!(task_entity.tags, Vec::<String>::new());
}
#[test]
fn test_migrator_with_custom_keys() {
let _path = migrate_path!(
"task",
[TaskV1, TaskEntity],
version_key = "schema_version",
data_key = "payload"
);
assert!(true);
}
#[test]
fn test_migrator_syntax_compilation() {
let _path1 = migrate_path!("task1", [TaskV1, TaskEntity]);
let _path2 = migrate_path!("task2", [TaskV1, TaskV2, TaskEntity]);
let _path3 = migrate_path!(
"task3",
[TaskV1, TaskEntity],
version_key = "v",
data_key = "d"
);
let _path4 = migrate_path!(
"task4",
[TaskV1, TaskV2, TaskEntity],
version_key = "v",
data_key = "d"
);
assert!(true);
}