Summary: - Sources: Migrations, Models, Protocols, Services, Utilities - Tests: AnyStorageKeyTests.swift, MigrationAdditionalTests.swift, MigrationIntegrationTests.swift, MigrationProtocolTests.swift, MigrationTests.swift (+1 more) - Docs: Migration, Migration_Refactor_Plan_Clean, Proposal, README - Added symbols: struct MyMigration, typealias DestinationKey, func shouldMigrate, func migrate, extension MyNewKey, protocol StorageMigration (+74 more) - Removed symbols: enum StorageDomain, func migrate, func validatePlatformAvailability, func deserialize, func applySecurity, func retrieve (+1 more) Stats: - 31 files changed, 2820 insertions(+), 80 deletions(-)
65 lines
2.0 KiB
Markdown
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())
|
|
}
|
|
}
|
|
```
|