LocalData/Documentation/Migration.md
Matt Bruce 281c9d5e91 migration
Signed-off-by: Matt Bruce <mbrucedogs@gmail.com>
2026-01-16 13:47:12 -06:00

2.0 KiB

LocalData Migration Guide

Overview

LocalData provides protocol-based migration support to move data from legacy storage locations to modern StorageKey definitions.

Automatic Migration

When calling get(_:) on a key, the StorageRouter automatically:

  1. Checks the primary location.
  2. If not found, evaluates migration defined on the key.
  3. If data is found in a source:
    • Unsecures it using the source's old policy.
    • Re-secures it using the destination key's policy.
    • Stores it in the new location.
    • Deletes the legacy data.
    • Returns the value.

Proactive Migration (Sweep)

You can trigger a sweep of all registered keys at app launch:

try await StorageRouter.shared.registerCatalog(MyCatalog(), migrateImmediately: true)

This iterates through all keys in the catalog and calls forceMigration(for:) on each, ensuring all legacy data is consolidated.

Defining Migration Sources

Simple Legacy Migration

For 1:1 migrations, attach a SimpleLegacyMigration:

struct MyNewKey: StorageKey {
    // ...
    var migration: AnyStorageMigration? {
        AnyStorageMigration(
            SimpleLegacyMigration(
                destinationKey: self,
                sourceKey: .key(LegacyKey(name: "old_key_name", domain: .userDefaults(suite: nil)))
            )
        )
    }
}

Protocol-Based Migration

For complex scenarios, attach an explicit migration:

struct MyMigration: StorageMigration {
    typealias DestinationKey = MyNewKey

    let destinationKey = MyNewKey()

    func shouldMigrate(using router: StorageRouter, context: MigrationContext) async throws -> Bool {
        try await router.exists(destinationKey)
    }

    func migrate(using router: StorageRouter, context: MigrationContext) async throws -> MigrationResult {
        // Custom migration logic
        MigrationResult(success: true)
    }
}

extension MyNewKey {
    var migration: AnyStorageMigration? {
        AnyStorageMigration(MyMigration())
    }
}