Crate version_migrate

Crate version_migrate 

Source
Expand description

§version-migrate

A library for explicit, type-safe schema versioning and migration.

§Features

  • Type-safe migrations: Define migrations between versions using traits
  • Validation: Automatic validation of migration paths (circular path detection, version ordering)
  • Multi-format support: Load from JSON, TOML, YAML, or any serde-compatible format
  • Vec support: Migrate collections of versioned entities
  • Hierarchical structures: Support for nested versioned entities
  • Async migrations: Optional async support for I/O-heavy migrations

§Basic Example

use version_migrate::{Versioned, MigratesTo, IntoDomain, Migrator};
use serde::{Serialize, Deserialize};

// Version 1.0.0
#[derive(Serialize, Deserialize, Versioned)]
#[versioned(version = "1.0.0")]
struct TaskV1_0_0 {
    id: String,
    title: String,
}

// Version 1.1.0
#[derive(Serialize, Deserialize, Versioned)]
#[versioned(version = "1.1.0")]
struct TaskV1_1_0 {
    id: String,
    title: String,
    description: Option<String>,
}

// Domain model
struct TaskEntity {
    id: String,
    title: String,
    description: Option<String>,
}

impl MigratesTo<TaskV1_1_0> for TaskV1_0_0 {
    fn migrate(self) -> TaskV1_1_0 {
        TaskV1_1_0 {
            id: self.id,
            title: self.title,
            description: None,
        }
    }
}

impl IntoDomain<TaskEntity> for TaskV1_1_0 {
    fn into_domain(self) -> TaskEntity {
        TaskEntity {
            id: self.id,
            title: self.title,
            description: self.description,
        }
    }
}

§Working with Collections (Vec)

// Save multiple versioned entities
let tasks = vec![
    TaskV1_0_0 { id: "1".into(), title: "Task 1".into() },
    TaskV1_0_0 { id: "2".into(), title: "Task 2".into() },
];
let json = migrator.save_vec(tasks)?;

// Load and migrate multiple entities
let domains: Vec<TaskEntity> = migrator.load_vec("task", &json)?;

§Hierarchical Structures

For complex configurations with nested versioned entities:

#[derive(Serialize, Deserialize, Versioned)]
#[versioned(version = "1.0.0")]
struct ConfigV1 {
    setting: SettingV1,
    items: Vec<ItemV1>,
}

#[derive(Serialize, Deserialize, Versioned)]
#[versioned(version = "2.0.0")]
struct ConfigV2 {
    setting: SettingV2,
    items: Vec<ItemV2>,
}

impl MigratesTo<ConfigV2> for ConfigV1 {
    fn migrate(self) -> ConfigV2 {
        ConfigV2 {
            // Migrate nested entities
            setting: self.setting.migrate(),
            items: self.items.into_iter()
                .map(|item| item.migrate())
                .collect(),
        }
    }
}

§Design Philosophy

This library follows the explicit versioning approach:

  • Each version has its own type (V1, V2, V3, etc.)
  • Migration logic is explicit and testable
  • Version changes are tracked in code
  • Root-level versioning ensures consistency

This differs from ProtoBuf’s “append-only” approach but allows for:

  • Schema refactoring and cleanup
  • Type-safe migration paths
  • Clear version history in code

Re-exports§

pub use errors::IoOperationKind;
pub use errors::MigrationError;
pub use storage::AtomicWriteConfig;
pub use storage::FileStorage;
pub use storage::FileStorageStrategy;
pub use storage::FormatStrategy;
pub use storage::LoadBehavior;
pub use dir_storage::DirStorage;
pub use dir_storage::DirStorageStrategy;
pub use dir_storage::FilenameEncoding;
pub use paths::AppPaths;
pub use paths::PathStrategy;
pub use paths::PrefPath;

Modules§

dir_storage
Directory-based storage layer for managing multiple entity files.
errors
Error types for migration operations.
paths
Platform-agnostic path management for application configuration and data.
storage
File storage layer with ACID guarantees for versioned configuration.

Structs§

ConfigMigrator
A wrapper around JSON data that provides convenient query and update methods for partial updates with automatic migration.
MigrationPath
A complete migration path from versioned DTOs to a domain model.
Migrator
The migration manager that orchestrates all migrations.
VersionedWrapper
A wrapper for serialized data that includes explicit version information.

Traits§

FromDomain
Converts a domain model back into a versioned DTO.
IntoDomain
Converts a versioned DTO into the application’s domain model.
LatestVersioned
Associates a domain entity with its latest versioned representation.
MigratesTo
Defines explicit migration logic from one version to another.
Queryable
Marks a domain type as queryable, associating it with an entity name.
Versioned
A trait for versioned data schemas.

Derive Macros§

DeriveQueryable
Derives the Queryable trait for a struct.
VersionMigrate
Derives the LatestVersioned trait for a domain entity.
Versioned
Derives the Versioned trait for a struct.