Last active
May 30, 2020 14:25
-
-
Save maximkrouk/10126931f43694cf0950025032362bdf to your computer and use it in GitHub Desktop.
DEPRECATED
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Fluent | |
private struct _Migration<T>: Migration { | |
var preparation: (Database) -> EventLoopFuture<Void> | |
var revertion: (Database) -> EventLoopFuture<Void> | |
func prepare(on database: Database) -> EventLoopFuture<Void> { preparation(database) } | |
func revert(on database: Database) -> EventLoopFuture<Void> { revertion(database) } | |
} | |
public protocol MigrationProvider { | |
static func prepare(on database: Database) -> EventLoopFuture<Void> | |
static func revert(on database: Database) -> EventLoopFuture<Void> | |
} | |
extension MigrationProvider { | |
public static var migration: Migration { | |
_Migration<Self>(preparation: prepare, revertion: revert) | |
} | |
} | |
public protocol DatabaseModel: Model, MigrationProvider { | |
typealias SchemaBuilder = SchemaBuilderProxy<Self> | |
static func prepareSchema(using schemaBuilder: SchemaBuilder) -> EventLoopFuture<Void> | |
static func revertSchema(using schemaBuilder: SchemaBuilder) -> EventLoopFuture<Void> | |
} | |
extension DatabaseModel { | |
public static func prepare(on database: Database) -> EventLoopFuture<Void> { | |
prepareSchema(using: database.schema(for: Self.self)) | |
} | |
public static func revert(on database: Database) -> EventLoopFuture<Void> { | |
revertSchema(using: database.schema(for: Self.self)) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// SchemaBuilder+Extension.swift | |
// App | |
// | |
// Created by Maxim Krouk on 3/17/20. | |
// | |
import Fluent | |
// MARK: - Pass by reference | |
@propertyWrapper | |
private final class Ref<Object> { | |
public var wrappedValue: Object | |
public convenience init(_ object: Object) { | |
self.init(wrappedValue: object) | |
} | |
public init(wrappedValue: Object) { | |
self.wrappedValue = wrappedValue | |
} | |
} | |
@dynamicMemberLookup | |
public struct SchemaBuilderProxy<T: Fluent.Model> { | |
@Ref private var wrappedValue: SchemaBuilder | |
/// Empty model, used to access fields by keypath | |
private let model: T = .init() | |
// MARK: Initialization | |
internal init(wrappedValue: SchemaBuilder) { | |
self._wrappedValue = .init(wrappedValue) | |
} | |
// MARK: DynamicMember | |
public subscript<T>(dynamicMember keyPath: KeyPath<SchemaBuilder, T>) -> T { | |
get { wrappedValue[keyPath: keyPath] } | |
} | |
public subscript<T>(dynamicMember keyPath: WritableKeyPath<SchemaBuilder, T>) -> T { | |
get { wrappedValue[keyPath: keyPath] } | |
set { wrappedValue[keyPath: keyPath] = newValue } | |
} | |
// MARK: - FieldRepresentableSupport | |
public func field<V: FieldRepresentable>( | |
_ keyPath: KeyPath<T, V>, | |
_ dataType: DatabaseSchema.DataType, | |
_ constraints: DatabaseSchema.FieldConstraint... | |
) -> Self { | |
self.field(.definition( | |
name: .string(model[keyPath: keyPath].field.key), | |
dataType: dataType, | |
constraints: constraints | |
)) | |
} | |
public func unique<V: FieldRepresentable>(on keyPaths: KeyPath<T, V>...) -> Self { | |
wrappedValue.schema.constraints.append(.unique( | |
fields: keyPaths.map { .string(model[keyPath: $0].field.key) } | |
)) | |
return self | |
} | |
public func foreignKey<V: FieldRepresentable>( | |
_ keyPath: KeyPath<T, V>, | |
references foreignSchema: String, | |
_ foreignField: String, | |
onDelete: DatabaseSchema.Constraint.ForeignKeyAction = .noAction, | |
onUpdate: DatabaseSchema.Constraint.ForeignKeyAction = .noAction | |
) -> Self { | |
self.foreignKey( | |
model[keyPath: keyPath].field.key, | |
references: foreignSchema, | |
foreignField, | |
onDelete: onDelete, | |
onUpdate: onUpdate | |
) | |
} | |
public func deleteField<V: FieldRepresentable>(_ keyPath: KeyPath<T, V>) -> Self { | |
deleteField(model[keyPath: keyPath].field.key) | |
} | |
} | |
// MARK: - SchemaBuilderProxy.SchemeBuilderSupport | |
extension SchemaBuilderProxy { | |
public func field( | |
_ name: String, | |
_ dataType: DatabaseSchema.DataType, | |
_ constraints: DatabaseSchema.FieldConstraint... | |
) -> Self { | |
field(.definition( | |
name: .string(name), | |
dataType: dataType, | |
constraints: constraints | |
)) | |
} | |
public func field(_ field: DatabaseSchema.FieldDefinition) -> Self { | |
wrappedValue.schema.createFields.append(field) | |
return self | |
} | |
public func unique(on fields: String...) -> Self { | |
wrappedValue.schema.constraints.append(.unique( | |
fields: fields.map { .string($0) } | |
)) | |
return self | |
} | |
public func foreignKey( | |
_ field: String, | |
references foreignSchema: String, | |
_ foreignField: String, | |
onDelete: DatabaseSchema.Constraint.ForeignKeyAction = .noAction, | |
onUpdate: DatabaseSchema.Constraint.ForeignKeyAction = .noAction | |
) -> Self { | |
wrappedValue.schema.constraints.append(.foreignKey( | |
fields: [.string(field)], | |
foreignSchema: foreignSchema, | |
foreignFields: [.string(foreignField)], | |
onDelete: onDelete, | |
onUpdate: onUpdate | |
)) | |
return self | |
} | |
public func deleteField(_ name: String) -> Self { | |
deleteField(.string(name)) | |
} | |
public func deleteField(_ name: DatabaseSchema.FieldName) -> Self { | |
wrappedValue.schema.deleteFields.append(name) | |
return self | |
} | |
public func delete() -> EventLoopFuture<Void> { | |
wrappedValue.delete() | |
} | |
public func update() -> EventLoopFuture<Void> { | |
wrappedValue.update() | |
} | |
public func create() -> EventLoopFuture<Void> { | |
wrappedValue.create() | |
} | |
} | |
// MARK: - SchemaBuilder.Binding | |
extension SchemaBuilder { | |
public func bind<T: Model>(to type: T.Type) -> SchemaBuilderProxy<T> { | |
.init(wrappedValue: self) | |
} | |
} | |
// MARK: - Model.Schema | |
extension Model { | |
static var schema: String { String(describing: self) } | |
} | |
// MARK: - Database.Schema | |
extension Database { | |
public func schema<T: Model>(for type: T.Type) -> SchemaBuilderProxy<T> { | |
schema(T.schema).bind(to: type) | |
} | |
} |
Author
maximkrouk
commented
Mar 30, 2020
•
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment