Skip to content

Instantly share code, notes, and snippets.

@ksmandersen
Created January 10, 2019 10:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ksmandersen/d352a8831ca765d0875c0a786c6bac12 to your computer and use it in GitHub Desktop.
Save ksmandersen/d352a8831ca765d0875c0a786c6bac12 to your computer and use it in GitHub Desktop.
struct ValidateErrors: ValidationError {
/// the errors thrown
var errors: [ValidationError]
/// See ValidationError.keyPath
var path: [String]
/// See ValidationError.reason
var reason: String {
return errors.map { error in
var mutableError = error
mutableError.path = path + error.path
return mutableError.reason
}.joined(separator: ", ")
}
/// creates a new validatable error
init(_ errors: [ValidationError]) {
self.errors = errors
self.path = []
}
}
struct AsyncValidator<T> {
private let closure: (T, Request) throws -> Future<T>
init(_ closure: @escaping (T, Request) throws -> Future<T>) {
self.closure = closure
}
func validate(_ data: T, on req: Request) throws -> Future<T> {
return try closure(data, req)
}
}
struct AsyncValidations<M> where M: AsyncValidatable {
private var storage: [AsyncValidator<M>]
init(_ model: M.Type) {
self.storage = []
}
mutating func add(_ message: String, _ closure: @escaping (M, Request) throws -> Future<M>) {
storage.append(AsyncValidator<M>(closure))
}
func run(model: M, on req: Request) throws -> Future<M> {
return try storage.map({ validator in
return try validator.validate(model, on: req)
}).flatten(on: req).map { _ in return model }
}
}
protocol AsyncValidatable {
static func asyncValidations() throws -> AsyncValidations<Self>
}
extension AsyncValidatable {
func validate(on req: Request) throws -> Future<Self> {
return try Self.asyncValidations().run(model: self, on: req)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment