Skip to content

Commit f0b4fce

Browse files
authored
Fix @RequiredTimestamp requiring conformance to Model instead of Fields (#15)
`@RequiredTimestamp` is valid for use in types conforming only to `Fields`; `Schema` or `Model` conformance is not required. The property declaring such a requirement was a bug.
1 parent 70fce0b commit f0b4fce

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

Sources/FluentKitExtras/RequiredTimestampProperty.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public import struct FoundationEssentials.Date
55
public import struct Foundation.Date
66
#endif
77

8-
extension Model {
8+
extension Fields {
99
public typealias RequiredTimestamp<Format> = RequiredTimestampProperty<Self, Format>
1010
where
1111
Format: TimestampFormat
@@ -16,7 +16,7 @@ extension Model {
1616
@propertyWrapper
1717
public final class RequiredTimestampProperty<Model, Format>: SendableMetatype
1818
where
19-
Model: FluentKit.Model,
19+
Model: FluentKit.Fields,
2020
Format: TimestampFormat
2121
{
2222
@FieldProperty<Model, Format.Value>

Tests/FluentKitExtrasTests/FluentKitExtrasTests.swift

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ struct FluentKitExtrasTests {
2525
#expect(model.group.blooey == "glooey")
2626
model.group.blooey = "flooey"
2727
#expect(model.blooey == "flooey")
28+
model.mooey = Date(timeIntervalSince1970: 0)
29+
#expect(model.mooey == Date(timeIntervalSince1970: 0))
30+
model.group.mooey = Date(timeIntervalSince1970: 1)
31+
#expect(model.mooey == Date(timeIntervalSince1970: 1))
2832
}
2933

3034
@Test
@@ -33,16 +37,17 @@ struct FluentKitExtrasTests {
3337
model.group = .init()
3438

3539
#expect(model.$group.description == "@BarModel.FlatGroup<BopFields>()")
36-
#expect(model.$group.keys == [.string("phooey"), .string("blooey")])
40+
#expect(model.$group.keys == [.string("phooey"), .string("blooey"), .string("mooey")])
3741

3842
model.group.phooey = "phooey"
3943
model.group.blooey = "blooey"
44+
model.group.mooey = Date(timeIntervalSince1970: 0)
4045

4146
let input = QuickInput()
4247
model.$group.input(to: input)
4348

4449
// The intent here is to test that @FlatGroup keeps its specified field keys intact, without @Group's prefixing.
45-
#expect(input.content == ["phooey": "phooey", "blooey": "blooey"])
50+
#expect(input.content == ["phooey": "phooey", "blooey": "blooey", "mooey": "1970-01-01 00:00:00 +0000"])
4651

4752
#expect(throws: Never.self) { try model.$group.output(from: ["phooey": "phooey", "blooey": "blooey"] as QuickOutput) }
4853

@@ -106,7 +111,7 @@ struct FluentKitExtrasTests {
106111
model.$bar.value = .init()
107112
#expect(model.bar.id == nil)
108113
#expect(model.$bar.description == model.$bar.name)
109-
await #expect(throws: Never.self) { try await model.$bar.get(reload: true, on: MockFluentDatabase([[["id": "1", "identifier": "b", "timestamp": fluentIso8601String(), "another": fluentIso8601String(), "recursive_baridentifier": "b", "blooey": "", "phooey": ""] as QuickOutput]])) }
114+
await #expect(throws: Never.self) { try await model.$bar.get(reload: true, on: MockFluentDatabase([[["id": "1", "identifier": "b", "timestamp": fluentIso8601String(), "another": fluentIso8601String(), "recursive_baridentifier": "b", "blooey": "", "phooey": "", "mooey": "1970-01-01T00:00:00Z"] as QuickOutput]])) }
110115
#expect(model.$bar.anyQueryableProperty === model.$bar.$ref)
111116
#expect(model.$bar.queryablePath == [.string("baridentifier")])
112117
#expect(model.$bar.queryableProperty === model.$bar.$ref)
@@ -187,6 +192,7 @@ struct FluentKitExtrasTests {
187192
model.another = .init()
188193
model.group.phooey = "phooey"
189194
model.group.blooey = "blooey"
195+
model.group.mooey = Date(timeIntervalSince1970: 0)
190196
#expect(throws: Never.self) { try JSONEncoder().encode(model) }
191197
await #expect(throws: Never.self) { try await model.$bazs.get(reload: true, on: MockFluentDatabase()) }
192198
await #expect(throws: Never.self) { try await model.$bazs.create(BazModel(), on: MockFluentDatabase([[["id": "1"] as QuickOutput]])).get() }
@@ -245,6 +251,9 @@ final class BarModel: FluentKit.Model, @unchecked Sendable {
245251
@Alias(of: \.$group.$blooey)
246252
var blooey
247253

254+
@Alias(of: \.$group.$mooey)
255+
var mooey
256+
248257
@OptionalField(key: "miscellaneous")
249258
var miscellaneous: String?
250259

@@ -303,6 +312,9 @@ final class BopFields: FluentKit.Fields, @unchecked Sendable {
303312
@Field(key: "blooey")
304313
var blooey: String
305314

315+
@RequiredTimestamp(key: "mooey")
316+
var mooey: Date
317+
306318
init() {}
307319
}
308320

@@ -394,11 +406,11 @@ final class QuickInput: DatabaseInput {
394406
}
395407

396408
func fluentIso8601Date(_ str: String) -> Date? {
397-
TimestampFormatFactory<ISO8601TimestampFormat>.iso8601.makeFormat().parse(str)
409+
try? Date(str, strategy: .iso8601)
398410
}
399411

400412
func fluentIso8601String(_ date: Date = .init()) -> String {
401-
TimestampFormatFactory<ISO8601TimestampFormat>.iso8601.makeFormat().serialize(date)!
413+
date.formatted(.iso8601)
402414
}
403415

404416
struct ModifiedStreamLogHandler: LogHandler {

0 commit comments

Comments
 (0)