LeezyData is a generic and agnostic entity-oriented data layer.
LeezyData
is a self-serve package, meaning you can choose to be completely agnostic from third-party libraries or Swift
frameworks and build your own services, or you can add LeezyData
's built-in integration with CoreData
(for your local database) and Firestore
(for you remote data).
If you are building an app with remote data collections and/or a local database layer, then the answer is yes, you should use this package.
This package contains the following libraries:
Common
: The foundations of your data layer. It contains theEntity
protocol, theDataService
blueprint for each of your entities CRUD operations and theDataManager
which is the class your app will use to communicate and perform data operations.CoreData
: A local database layer that uses CoreData to store and retrieve entities. By default, this library doesn't make use of CoreData's relationships, instead it fetches the entities in all the available services using anid
.RemoteCollection
: A remote collection layer that completely abstracts the database so you can choose the one that suits you best. This layer supports type-erased entities so you no longer have headaches when modelling your collections. All you need is anidentifier
for your custom types andAnyRemoteEntity
will do the rest.Firestore
: Contains protocol conformances to supportFirestore
as aRemoteCollection
source.
LeezyData
is available for installation via SPM:
dependencies: [
.package(name: "LeezyData", url: "https://github.com/matolah/LeezyData", .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")
]
),
Create your entities:
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
}
}
}
Create DataService
s for your entities and inject them in your DataManager
. Remember to initialize coreDataEntityBuilder
for initializing empty CoreData
objects and referenceBuilder
if you want to use LeezyData
relationship creation.
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.
Twitter: @_matolah