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

65 lines
2.0 KiB
Markdown

# 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:
```swift
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`:
```swift
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:
```swift
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())
}
}
```