Generic, composable data layer abstractions for Swift with support for CoreData, Firestore, and custom sources.
Report Bug
·
Request Feature
LeezyData is a lightweight, extensible data layer framework for Swift.
It allows you to compose multiple sources of truth — local (CoreData) or remote (Firestore) — using a unified API built around generic Entity
, DataService
, and DataManager
abstractions.
- 📁 CoreData – for offline storage
- ☁️ Firestore – for real-time cloud sync
- 📦 RemoteCollection – for abstracting any REST or real-time backend
- 🧱 Common – contains the core interfaces:
Entity
,DataService
,DataManager
Add LeezyData
to your project using Swift Package Manager:
dependencies: [
.package(url: "https://github.com/matolah/LeezyData.git", .upToNextMajor(from: "1.0.0"))
]
.target(
name: "MyApp",
dependencies: [
.product(name: "LeezyData", package: "LeezyData"),
.product(name: "LeezyCoreData", package: "LeezyData"),
.product(name: "LeezyRemoteCollection", package: "LeezyData"),
.product(name: "LeezyFirestore", package: "LeezyData")
]
)
struct MySimpleEntity: Entity {
let id: String
}
class MyLocalEntity: CoreDataEntity {
@NSManaged var referenceID: String
var reference: MyRemoteEntity? {
if let reference = _reference, referenceID == reference.id {
return reference
} else {
let anyReference: AnyRemoteFirestoreEntity? = Self.referenceBuilder?.entity(with: referenceID)
_reference = anyReference?.value as? MyRemoteEntity
return _reference
}
}
private var _reference: MyRemoteEntity?
}
typealias AnyRemoteFirestoreEntity = AnyRemoteEntity<MyRemoteEntityIdentifier>
struct MyRemoteEntity: RemoteEntity {
static let collectionName = MyRemoteEntityIdentifier.collectionName
let id: String
}
enum MyRemoteEntityIdentifier: String, AnyRemoteEntityIdentifier {
case mock
static let collectionName = "my-remote-entity-collection"
var metatype: any RemoteEntity.Type {
switch self {
case .mock:
return MyRemoteEntity.self
}
}
}
lazy var dataManager: DataManager = {
let dataManager = DataManager(
dataServices: [
dataService,
coreDataDataService,
firestoreDataService
]
)
CoreDataEntity.coreDataEntityBuilder = dataManager
CoreDataEntity.referenceBuilder = dataManager
return dataManager
}()
let dataService = DataService<MySimpleEntity>()
let coreDataDataService = CoreDataDataService<MyLocalEntity>(
managedObjectContext: NSPersistentContainer(name: "my_model").viewContext
)
let firestoreDataService = RemoteCollectionDataService<AnyRemoteFirestoreEntity>(
database: Firestore.firestore()
)
Distributed under the MIT License. See LICENSE.txt
for more information.
Contributions are welcome! If you have suggestions for improvements, bug fixes, or new features, feel free to open an issue or submit a pull request.
Maintained by https://x.com/_matolah