Skip to content

Instantly share code, notes, and snippets.

@zastrozzi
Created July 13, 2023 01:59
Show Gist options
  • Select an option

  • Save zastrozzi/24e83124d48a4a7debac52aa6a0ab80d to your computer and use it in GitHub Desktop.

Select an option

Save zastrozzi/24e83124d48a4a7debac52aa6a0ab80d to your computer and use it in GitHub Desktop.
import Foundation
import Fluent
extension Fields {
public typealias AsyncTransformableField<Value, TransformedValue> = AsyncTransformableFieldProperty<Self, Value, TransformedValue> where Value: Codable
}
@propertyWrapper
public final class AsyncTransformableFieldProperty<Model, Value, TransformedValue> where Model: FluentKit.Fields, Value: Codable {
@FieldProperty<Model, Value>
public var field: Value
public let transformer: (_ wrappedValue: Value) async throws -> (TransformedValue?)
public func asyncTransformed() async throws -> TransformedValue? {
try await self.transformer(self.wrappedValue)
}
public var projectedValue: AsyncTransformableFieldProperty<Model, Value, TransformedValue> { self }
public var wrappedValue: Value {
get {
guard let value = self.value else {
fatalError("Cannot access field before it is initialized or fetched: \(self.$field.key)")
}
return value
}
set {
self.value = newValue
}
}
public init(key: FieldKey, transformer: @escaping (_ wrappedValue: Value) async throws -> (TransformedValue?)) {
self._field = .init(key: key)
self.transformer = transformer
}
}
extension AsyncTransformableFieldProperty: Property {
public var value: Value? {
get { self.$field.value }
set { self.$field.value = newValue }
}
}
extension AsyncTransformableFieldProperty: AnyProperty {}
extension AsyncTransformableFieldProperty: AnyQueryableProperty {
public var path: [FieldKey] { self.$field.path }
}
extension AsyncTransformableFieldProperty: QueryableProperty {}
extension AsyncTransformableFieldProperty: AnyQueryAddressableProperty {
public var anyQueryableProperty: AnyQueryableProperty { self }
public var queryablePath: [FieldKey] { self.path }
}
extension AsyncTransformableFieldProperty: QueryAddressableProperty {
public var queryableProperty: AsyncTransformableFieldProperty<Model, Value, TransformedValue> { self }
}
extension AsyncTransformableFieldProperty: AnyDatabaseProperty {
public var keys: [FieldKey] { self.$field.keys }
public func input(to input: DatabaseInput) { self.$field.input(to: input) }
public func output(from output: DatabaseOutput) throws { try self.$field.output(from: output) }
}
extension AsyncTransformableFieldProperty: AnyCodableProperty {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.wrappedValue)
}
public func decode(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.value = try container.decode(Value.self)
}
}
// EXAMPLE FIELD IMPLEMENTATION
extension Fields {
public typealias DynamicTypedDataField = DynamicTypedDataFieldProperty<Self>
}
@propertyWrapper
public final class DynamicTypedDataFieldProperty<Model> where Model: FluentKit.Fields {
@AsyncTransformableFieldProperty<Model, Int32, any DynamicDataTypeable>
public var field: Int32
// public func asyncTransformed() async throws -> TransformedValue? {
// try await self.transformer(self.wrappedValue)
// }
public var projectedValue: DynamicTypedDataFieldProperty<Model> { self }
public var wrappedValue: Int32 {
get {
guard let value = self.value else {
fatalError("Cannot access field before it is initialized or fetched: \(self.$field.$field.key)")
}
return value
}
set {
self.value = newValue
}
}
public init(key: FieldKey, dataType: Application.DynamicTypeCacheService.DataType) {
self._field = .init(key: key, transformer: { val in
Application.DynamicDataCacheService.getCachedValue(for: dataType)(val )
})
// self.transformer = transformer
}
}
extension DynamicTypedDataFieldProperty: Property {
public var value: Int32? {
get { self.$field.value }
set { self.$field.value = newValue }
}
}
extension DynamicTypedDataFieldProperty: AnyProperty {}
extension DynamicTypedDataFieldProperty: AnyQueryableProperty {
public var path: [FieldKey] { self.$field.path }
}
extension DynamicTypedDataFieldProperty: QueryableProperty {}
extension DynamicTypedDataFieldProperty: AnyQueryAddressableProperty {
public var anyQueryableProperty: AnyQueryableProperty { self }
public var queryablePath: [FieldKey] { self.path }
}
extension DynamicTypedDataFieldProperty: QueryAddressableProperty {
public var queryableProperty: DynamicTypedDataFieldProperty<Model> { self }
}
extension DynamicTypedDataFieldProperty: AnyDatabaseProperty {
public var keys: [FieldKey] { self.$field.keys }
public func input(to input: DatabaseInput) { self.$field.input(to: input) }
public func output(from output: DatabaseOutput) throws { try self.$field.output(from: output) }
}
extension DynamicTypedDataFieldProperty: AnyCodableProperty {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.wrappedValue)
}
public func decode(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
self.value = try container.decode(Value.self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment