83 lines
2.6 KiB
Markdown
83 lines
2.6 KiB
Markdown
# LocalData Migration Guide
|
|
|
|
## Overview
|
|
`LocalData` provides protocol-based migration support to move data from legacy storage locations to modern `StorageKey` values.
|
|
|
|
## 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
|
|
extension StorageKey where Value == String {
|
|
static let legacyToken = StorageKey(
|
|
name: "old_key_name",
|
|
domain: .userDefaults(suite: nil),
|
|
security: .none,
|
|
serializer: .json,
|
|
owner: "MigrationDemo",
|
|
description: "Legacy token stored in UserDefaults."
|
|
)
|
|
|
|
static let modernToken = StorageKey(
|
|
name: "modern_token",
|
|
domain: .keychain(service: "com.myapp"),
|
|
owner: "MigrationDemo",
|
|
description: "Modern token stored in Keychain.",
|
|
migration: { key in
|
|
AnyStorageMigration(
|
|
SimpleLegacyMigration(
|
|
destinationKey: key,
|
|
sourceKey: .key(StorageKey.legacyToken)
|
|
)
|
|
)
|
|
}
|
|
)
|
|
}
|
|
```
|
|
|
|
### Protocol-Based Migration
|
|
For complex scenarios, attach an explicit migration:
|
|
```swift
|
|
struct MyMigration: StorageMigration {
|
|
typealias Value = String
|
|
|
|
let destinationKey = StorageKey.modernToken
|
|
|
|
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 StorageKey where Value == String {
|
|
static let modernToken = StorageKey(
|
|
name: "modern_token",
|
|
domain: .keychain(service: "com.myapp"),
|
|
owner: "MigrationDemo",
|
|
description: "Modern token stored in Keychain.",
|
|
migration: { _ in AnyStorageMigration(MyMigration()) }
|
|
)
|
|
}
|
|
```
|