Created
July 13, 2023 01:59
-
-
Save zastrozzi/24e83124d48a4a7debac52aa6a0ab80d to your computer and use it in GitHub Desktop.
This file contains hidden or 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 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