RapidRepo
RapidRepo is a Vapor framework that provides structure to assist users setting up a modified version of the repository pattern within their own apps.
Installation
Architecture
A set of DataSource
s are established by the app owner that all models submitted to the repository must adapt to. For example, if the app owner wishes to use a Redis cache, a Postgres database, and and use mock data for testing, each model will have to set up adaptors for each of those data sources.
Usage
You can set up your models just like you would normally.
import Vapor
import FluentSQLite
struct Dog: SQLiteModel, Content {
var id: Int?
var name: String
var age: Int
}
You can then establish your data sources by setting up an AdapterSet
. The AdapterSet
represents the set of Adapters that all models will need to have.
This AdapterSet
establishes the requirement for database and mock adapters
struct AppAdapterSet<ModelType: SQLiteModel, DBAdapterType: SQLiteAdapter, MockAdapterType: MockAdapter>: AdapterSet {
let dbAdapater: DBAdapterType
let mockAdapter: MockAdapterType
}
You can set up a protocol with all the functionality you want all Dog
adapters to have.
protocol DogAdapterProtocol: ModelDataSourceAdapter where ModelType == Dog {
func get(id: ModelType.ID, on worker: Worker) throws -> Future<Dog?>
}
And then go ahead and set up your database and mock datasource adapters.
struct DogSQLiteAdapter: DogAdapterProtocol, SQLiteAdapter {
func get(id: Dog.ID, on worker: Worker) throws -> EventLoopFuture<Dog?> {
return try DataSourceType.DatabaseType().newConnection(on: worker).flatMap { (conn) in
return ModelType.find(id, on: conn)
}
}
}
struct DogMockAdapter: DogAdapterProtocol, MockAdapter {
func get(id: Dog.ID, on worker: Worker) throws -> EventLoopFuture<Dog?> {
return worker.future(Dog(id: id, name: "Rex", age: 5))
}
}
Now onto registering all that.
The AdapterSet
types get pretty long so it'll be good to have a typealias
typealias DogAdapterSet = AppAdapterSet<Dog, DogSQLiteAdapter, DogMockAdapter>
Then within configure.swift
let repo = Repository()
let dbDogAdapter = DogSQLiteAdapter()
let mockDogAdapter = DogMockAdapter()
let adapterSet = DogAdapterSet(dbAdapater: dbDogAdapter, mockAdapter: mockDogAdapter)
repo.register(adapterSet: adapterSet)
services.register(repo, as: Repository.self)
and finally you can use your repository.
Within routes.swift
:
router.get("repoTest") { req -> Future<Dog> in
let dogMocks = try req.make(Repository.self).make(DogAdapterSet.self).mockAdapter
return try dogMocks.get(id: 20, on: req).unwrap(or: Abort(.notFound))
}