A non-blocking I/O, asynchronous ODM. Written in Swift, inspired by Mongoose.
- Powered by Echo
- Reflective
- Asynchronous
- Non-blocking
- Beautiful Syntax
- SQLite via Orca-Sqlite
- MongoDB (experimental) via Orca-MongoDB
Orca is easy to set up, just add the following to your Package.swift
under dependencies
.Package(url: "https://github.com/elliottminns/orca.git", majorVersion: 0)
Saving a model is as simple as:
import Orca
let simba = Cat(name: "Simba", age: 7)
simba.king = true
simba.save() { error in
if error == nil {
print("Roar!")
}
}
That's it!
To create persistent models, you need to extend from the Orca Model
protocol.
Cat.swift
import Orca
class Cat: Model {
// Required
var identifier: String?
static var schema: [String: DataType.Type] {
return ["name": String.self,
"age": Int.self,
"claws": Double.self]
}
// User properties
var name: String
var age: Int
var king: Bool?
var claws: Double?
init(name: String, age: Int) {
self.name = name
self.age = age
}
// Required
required init?(serialized: [String: DataType]) {
self.identifier = serialized["identifier"] as? String
self.name = serialized["name"] as! String
self.age = serialized["age"] as! Int
self.claws = serialized["claws"] as? Double
}
}
Using reflection, Orca will automatically persist any properties that conform to the DataType protocol.
The current types are supported for automatic persistence:
String
Int
Double
Float
Bool
More will be added in the future.
To search for a saved model, all you need to do is:
let identifier = ""
Cat.find(identifier) { (model, error) in
if error == nil {
print(model?.name)
print(model?.identifier)
} else {
print(error)
}
}
or to retrieve all models of that class
Cat.findAll() { ([models], error) in
if error == nil {
for model in models {
print(model.name)
}
} else {
print(error)
}
}
To update a model, just change the properties you wish, and call save
simba.king = false
simba.save() { error in
if error == nil {
print("Simba is king? \(simba.king)")
// Simba is king? false
}
}
To delete a model, just call delete on it's instance.
simba.delete() { error in
Cat.find(simba.identifier!) { (model, error) in
print(model)
// nil
}
}
Any database can be supported, provided that a driver has been implemented for it. Orca defaults to a memory driver, which will only persist to the local memory, and will lose it's data once the process is killed.
To set a new driver, just initialize Orca like so:
Orca(driver: MyDatabaseDriver())
To create a database driver, you must extend the Driver
protocol and implement the required functions.
import Orca
extension MyDatabaseDriver: Driver {
public func generateUniqueIdentifier() -> String {
// Unique ID code
}
public func find(collection collection: String, filters: [Filter])
throws -> [[String: DataType]] {
// Find code...
}
public func findOne(collection collection: String,
filters: [Filter]) throws -> [String: DataType] {
// Find one code...
}
public func update(collection collection: String, filters: [Filter],
data: [String : DataType]) throws {
// Update code...
}
public func insert(collection collection: String,
data: [String: DataType], model: Model) throws {
// Insert code...
}
public func delete (collection collection: String,
filters: [Filter]) throws {
// Delete code...
}
}
For a more detailed example, see orca-sqlite for an Sqlite memory driver implementation.
This project is inspired by Fluent by Tanner Nelson, please go checkout and star his work.