Open Source Chakra Summer Re-Openning
#Puredux, #SwiftletModel, #Software Engineering, #iOS App Development
In recent months I revisited my GitHub account and had a lot of fun.
Vapor RestKit
I've updated VeporRestKit for Swift-Concurrency compatibility and released an update. The API has never been so smooth.
I think if I get a chance to use it this year more actively it will get a few more updates.
Puredux
I've made a significant refactoring of the internals that greatly improved Puredux performance and extendibility for future features.
The main thing that I'm planning is a redesign of the current architecture to a multiple-store tree of larger depths.
I also plan to update of side effects and syntax sugar for UIKit and SwiftUI.
Finally, there will be a redesign of internals to Swift-Concurrency and Actors, but it will likely involve breaking changes that I don't want to face at the moment.
Swiftlet Model
I've started a new project and called it SwiftletModel.
It will be an in-memory value-typed lightweight alternative to SwiftData with persistence capabilities.
It will perfectly fit the case when the app data model is rather complicated but the app is still a thin client and you have reasons to avoid CoreData/SwiftData/Realm.
I just imagined what could be the perfect CoreData and decided to implement it.
It's still in the early development stage, but
---SPOILER ALERT---
It's gonna be very sexy.
Here is how models will be defined:
struct Chat: EntityModel, Codable {
let id: String
@HasMany(\.users, inverse: \.chats)
var users: [User]?
@HasMany(\.messages, inverse: \.chat)
var messages: [Message]?
@HasMany(\.admins, inverse: \.adminOf)
var admins: [User]?
mutating func normalize() {
$users.normalize()
$messages.normalize()
$admins.normalize()
}
func save(to context: inout Context) throws {
context.insert(self)
try save(\.$users, inverse: \.$chats, to: &context)
try save(\.$messages, inverse: \.$chat, to: &context)
try save(\.$admins, inverse: \.$adminOf, to: &context)
}
func delete(from context: inout Context) throws {
try delete(\.$messages, inverse: \.$chat, from: &context)
context.remove(Chat.self, id: id)
detach(\.$users, inverse: \.$chats, in: &context)
detach(\.$admins, inverse: \.$adminOf, in: &context)
}
}
And this is how models will be queried:
let user = User
.query("1", in: context)
.with(\.$chats) {
$0.with(\.$messages) {
$0.with(\.$attachment)
.id(\.$author)
}
.with(\.$users)
.ids(\.$admins)
}
.resolve()
Planned Features
Currently I plan these features for the initial release:
- Strongly typed Relations with compile-time checks
- Handy model manipulation for data normalization and denormalization
- Incomplete data handling
- Fully Codable out-of-the-box
- Persistence to file in JSON format
The prorope is almost done. Now it requires outlining public API, cleaning up, adding unit tests, fixing bugs, writing docs, etc.
A huge pile of work, lol. Anyway, I'm already happy about it and now I just need some motivation to push it to the first release.
Comments