Back to OSS
Swift Package 通信 / サーバー
swift-persistence
KeyValue / Secure / Document / Registry を束ねるプロトコル指向の永続化抽象レイヤー
Swift
persistencekeyvaluestorage
English | 日本語
SwiftPersistence
A protocol-oriented persistence abstraction layer for Swift
Features
- Protocol-Oriented - All persistence operations defined as abstract protocols for DI and testability
- KeyValueStore - Type-safe UserDefaults abstraction (Codable support)
- SecureStore - Safe Keychain wrapper (API key and credential protection)
- DocumentStore - File-based CRUD (individual JSON files, atomic writes)
- RegistryStore - Single JSON file registry pattern
- KeyResolver - Multi-source fallback resolution: Info.plist → Keychain → UserDefaults
- InMemory Test Doubles - Bundled InMemory implementations for all protocols
Installation
// Package.swift
dependencies: [
.package(url: "https://github.com/no-problem-dev/swift-persistence.git", .upToNextMajor(from: "1.0.0"))
]
Module Structure
Import only the modules you need:
| Module | Purpose |
|---|---|
PersistenceCore |
Protocols + error types (Foundation only, no external dependencies) |
PersistenceUserDefaults |
UserDefaults-backed KeyValueStore implementation |
PersistenceKeychain |
Keychain-backed SecureStore implementation |
PersistenceFileSystem |
File-backed DocumentStore / RegistryStore implementations |
PersistenceTesting |
5 InMemory implementations (test DI doubles) |
Quick Start
Key-Value Store (UserDefaults Abstraction)
import PersistenceUserDefaults
let store = UserDefaultsKeyValueStore()
// Save and retrieve Codable values
try await store.setValue("dark", forKey: "theme")
let theme: String? = try await store.string(forKey: "theme")
// Custom types supported
struct UserPrefs: Codable, Sendable {
var fontSize: Int
var language: String
}
try await store.setValue(UserPrefs(fontSize: 14, language: "en"), forKey: "prefs")
let prefs: UserPrefs? = try await store.value(forKey: "prefs", type: UserPrefs.self)
Secure Store (Keychain Abstraction)
import PersistenceKeychain
let secrets = KeychainSecureStore(service: "com.example.myapp")
// Securely store API keys
try await secrets.setString("sk-abc123...", forKey: "api_key")
let key = try await secrets.getString(forKey: "api_key")
Document Store (File-based CRUD)
import PersistenceFileSystem
struct Note: Codable, Identifiable, Sendable {
let id: UUID
var title: String
var body: String
}
let store = try FileSystemDocumentStore<Note>(
directory: documentsURL.appendingPathComponent("notes")
)
// CRUD operations
let note = Note(id: UUID(), title: "Memo", body: "Content")
try await store.save(note)
let all = try await store.loadAll()
try await store.delete(id: note.id)
Registry Store (Single JSON Registry)
import PersistenceFileSystem
struct CacheEntry: Codable, Sendable {
let version: String
let downloadedAt: Date
}
let registry = FileSystemRegistryStore<CacheEntry>(
directory: cacheURL,
filename: "registry.json"
)
var entries = await registry.load()
entries["model-v1"] = CacheEntry(version: "1.0", downloadedAt: Date())
try await registry.save(entries)
Multi-Source Fallback Resolution
import PersistenceCore
import PersistenceKeychain
import PersistenceUserDefaults
let resolver = ChainedKeyResolver(
secureStore: KeychainSecureStore(service: "com.example.myapp"),
keyValueStore: UserDefaultsKeyValueStore(),
keyMapping: [
"API_KEY": .init(secure: "api_key", keyValue: "api_key"),
]
)
// Searches in order: Info.plist → Keychain → UserDefaults
let apiKey = await resolver.resolve("API_KEY")
InMemory Test Doubles
import PersistenceTesting
// Inject via DI in tests
let mockStore = InMemoryKeyValueStore()
let mockSecrets = InMemorySecureStore()
let mockDocs = InMemoryDocumentStore<Note>()
let settings = AppSettings(
preferences: mockStore,
secrets: mockSecrets,
keyResolver: InMemoryKeyResolver(["API_KEY": "test-key"])
)
Architecture
2-layer architecture for separation of concerns:
Layer 0: PersistenceCore Protocols + error types (no external dependencies)
Layer 1: PersistenceUserDefaults UserDefaults concrete implementation
PersistenceKeychain Keychain concrete implementation
PersistenceFileSystem File system concrete implementation
PersistenceTesting InMemory test doubles
Requirements
- iOS 17.0+ / macOS 14.0+
- Swift 6.2+
- Xcode 16.0+
License
MIT License - See LICENSE for details
Links
同じカテゴリの OSS — 通信 / サーバー
swift-api-client
Swift Packageasync/await 対応の軽量 HTTP クライアント。型安全な API 通信を Swift で
Swift
· 通信 / サーバーhttp-clientasync-awaitnetworking
swift-api-contract
Swift PackageSwift マクロで型安全な API 契約を定義する
Swift
· 通信 / サーバーswift-macroapitype-safe
swift-api-server
Swift PackageVapor を抽象化し、アプリケーションコードをフレームワーク実装から独立させるサーバー層
Swift
· 通信 / サーバーservervaporbackend
swift-firebase-server
Swift Packageサーバーサイド Swift 向けの Firestore REST API クライアント
Swift
· 通信 / サーバーfirebasefirestoreserver
swift-http-transport
Swift PackageURLSession をプロトコル背後に隠し、リトライ / レート制限 / SSE を一元化する通信基盤
Swift
· 通信 / サーバーhttpurlsessionsse