Skip to content

Commit 1061283

Browse files
committed
loosen the grip entity had on Ids
1 parent 08949d0 commit 1061283

5 files changed

Lines changed: 47 additions & 62 deletions

File tree

Sources/JSONAPI/Resource/Entity.swift

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,8 @@ public struct Entity<Description: JSONAPI.EntityDescription, MetaType: JSONAPI.M
112112
}
113113
}
114114

115-
extension Entity: IdentifiableEntityType, Relatable, OptionalRelatable where EntityRawIdType: JSONAPI.RawIdType {
115+
extension Entity: Identifiable, IdentifiableEntityType, Relatable where EntityRawIdType: JSONAPI.RawIdType {
116116
public typealias Identifier = Entity.Id
117-
public typealias Wrapped = Entity
118-
public typealias WrappedId = Identifier
119117
}
120118

121119
extension Entity: CustomStringConvertible {
@@ -432,14 +430,14 @@ public extension EntityProxy {
432430
/// Access to an Id of a `ToOneRelationship`.
433431
/// This allows you to write `entity ~> \.other` instead
434432
/// of `entity.relationships.other.id`.
435-
public static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>>) -> OtherEntity.WrappedId {
433+
public static func ~><OtherEntity: Identifiable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>>) -> OtherEntity.Identifier {
436434
return entity.relationships[keyPath: path].id
437435
}
438436

439437
/// Access to an Id of an optional `ToOneRelationship`.
440438
/// This allows you to write `entity ~> \.other` instead
441439
/// of `entity.relationships.other?.id`.
442-
public static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.WrappedId where OtherEntity.WrappedId == OtherEntity.Wrapped.Identifier? {
440+
public static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier {
443441
// Implementation Note: This signature applies to `ToOneRelationship<E?, _, _>?`
444442
// whereas the one below applies to `ToOneRelationship<E, _, _>?`
445443
return entity.relationships[keyPath: path]?.id
@@ -448,7 +446,7 @@ public extension EntityProxy {
448446
/// Access to an Id of an optional `ToOneRelationship`.
449447
/// This allows you to write `entity ~> \.other` instead
450448
/// of `entity.relationships.other?.id`.
451-
public static func ~><OtherEntity: Relatable & OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier? where OtherEntity.WrappedId == OtherEntity.Identifier {
449+
public static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier? {
452450
// Implementation Note: This signature applies to `ToOneRelationship<E, _, _>?`
453451
// whereas the one above applies to `ToOneRelationship<E?, _, _>?`
454452
return entity.relationships[keyPath: path]?.id

Sources/JSONAPI/Resource/Id.swift

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public struct Unidentified: MaybeRawId, CustomStringConvertible {
3535
}
3636

3737
public protocol MaybeId: Codable {
38-
associatedtype EntityType: JSONAPI.EntityProxy
38+
associatedtype IdentifiableType: JSONAPI.JSONTyped
3939
associatedtype RawType: MaybeRawId
4040
}
4141

@@ -53,7 +53,7 @@ public protocol CreatableIdType: IdType {
5353

5454
/// An Entity ID. These IDs can be encoded to or decoded from
5555
/// JSON API IDs.
56-
public struct Id<RawType: MaybeRawId, EntityType: JSONAPI.EntityProxy>: Codable, Equatable, MaybeId {
56+
public struct Id<RawType: MaybeRawId, IdentifiableType: JSONAPI.JSONTyped>: Codable, Equatable, MaybeId {
5757

5858
public let rawValue: RawType
5959

@@ -74,10 +74,6 @@ public struct Id<RawType: MaybeRawId, EntityType: JSONAPI.EntityProxy>: Codable,
7474

7575
extension Id: Hashable, CustomStringConvertible, IdType where RawType: RawIdType {}
7676

77-
extension Id: WrappedIdType where RawType: RawIdType {
78-
public typealias Identifier = Id
79-
}
80-
8177
extension Id: CreatableIdType where RawType: CreatableRawIdType {
8278
public init() {
8379
rawValue = .unique()

Sources/JSONAPI/Resource/Relationship.swift

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -17,46 +17,46 @@ public protocol RelationshipType: Codable {
1717
/// a JSON API "Resource Linkage."
1818
/// See https://jsonapi.org/format/#document-resource-object-linkage
1919
/// A convenient typealias might make your code much more legible: `One<EntityDescription>`
20-
public struct ToOneRelationship<OptionalRelatable: JSONAPI.OptionalRelatable, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links>: RelationshipType, Equatable {
20+
public struct ToOneRelationship<Identifiable: JSONAPI.Identifiable, MetaType: JSONAPI.Meta, LinksType: JSONAPI.Links>: RelationshipType, Equatable {
2121

22-
public let id: OptionalRelatable.WrappedId
22+
public let id: Identifiable.Identifier
2323

2424
public let meta: MetaType
2525
public let links: LinksType
2626

27-
public init(id: OptionalRelatable.WrappedId, meta: MetaType, links: LinksType) {
27+
public init(id: Identifiable.Identifier, meta: MetaType, links: LinksType) {
2828
self.id = id
2929
self.meta = meta
3030
self.links = links
3131
}
3232
}
3333

3434
extension ToOneRelationship where MetaType == NoMetadata, LinksType == NoLinks {
35-
public init(id: OptionalRelatable.WrappedId) {
35+
public init(id: Identifiable.Identifier) {
3636
self.init(id: id, meta: .none, links: .none)
3737
}
3838
}
3939

4040
extension ToOneRelationship {
41-
public init<E: EntityType>(entity: E, meta: MetaType, links: LinksType) where E.Id == OptionalRelatable.WrappedId {
41+
public init<E: EntityType>(entity: E, meta: MetaType, links: LinksType) where E.Id == Identifiable.Identifier {
4242
self.init(id: entity.id, meta: meta, links: links)
4343
}
4444
}
4545

4646
extension ToOneRelationship where MetaType == NoMetadata, LinksType == NoLinks {
47-
public init<E: EntityType>(entity: E) where E.Id == OptionalRelatable.WrappedId {
47+
public init<E: EntityType>(entity: E) where E.Id == Identifiable.Identifier {
4848
self.init(id: entity.id, meta: .none, links: .none)
4949
}
5050
}
5151

52-
extension ToOneRelationship where OptionalRelatable.WrappedId == OptionalRelatable.Wrapped.Identifier? {
53-
public init<E: EntityType>(entity: E?, meta: MetaType, links: LinksType) where E.Id == OptionalRelatable.Wrapped.Identifier {
52+
extension ToOneRelationship where Identifiable: OptionalRelatable {
53+
public init<E: EntityType>(entity: E?, meta: MetaType, links: LinksType) where E.Id == Identifiable.Wrapped.Identifier {
5454
self.init(id: entity?.id, meta: meta, links: links)
5555
}
5656
}
5757

58-
extension ToOneRelationship where OptionalRelatable.WrappedId == OptionalRelatable.Wrapped.Identifier?, MetaType == NoMetadata, LinksType == NoLinks {
59-
public init<E: EntityType>(entity: E?) where E.Id == OptionalRelatable.Wrapped.Identifier {
58+
extension ToOneRelationship where Identifiable: OptionalRelatable, MetaType == NoMetadata, LinksType == NoLinks {
59+
public init<E: EntityType>(entity: E?) where E.Id == Identifiable.Wrapped.Identifier {
6060
self.init(id: entity?.id, meta: .none, links: .none)
6161
}
6262
}
@@ -78,7 +78,7 @@ public struct ToManyRelationship<Relatable: JSONAPI.Relatable, MetaType: JSONAPI
7878
self.links = links
7979
}
8080

81-
public init<T: JSONAPI.OptionalRelatable>(pointers: [ToOneRelationship<T, NoMetadata, NoLinks>], meta: MetaType, links: LinksType) where T.WrappedId == Relatable.Identifier {
81+
public init<T: JSONAPI.Identifiable>(pointers: [ToOneRelationship<T, NoMetadata, NoLinks>], meta: MetaType, links: LinksType) where T.Identifier == Relatable.Identifier {
8282
ids = pointers.map { $0.id }
8383
self.meta = meta
8484
self.links = links
@@ -103,7 +103,7 @@ extension ToManyRelationship where MetaType == NoMetadata, LinksType == NoLinks
103103
self.init(ids: ids, meta: .none, links: .none)
104104
}
105105

106-
public init<T: JSONAPI.OptionalRelatable>(pointers: [ToOneRelationship<T, NoMetadata, NoLinks>]) where T.WrappedId == Relatable.Identifier {
106+
public init<T: JSONAPI.Identifiable>(pointers: [ToOneRelationship<T, NoMetadata, NoLinks>]) where T.Identifier == Relatable.Identifier {
107107
self.init(pointers: pointers, meta: .none, links: .none)
108108
}
109109

@@ -116,29 +116,23 @@ extension ToManyRelationship where MetaType == NoMetadata, LinksType == NoLinks
116116
}
117117
}
118118

119+
public protocol Identifiable: JSONTyped {
120+
associatedtype Identifier: Equatable, Codable
121+
}
122+
119123
/// The Relatable protocol describes anything that
120124
/// has an IdType Identifier
121-
public protocol Relatable: JSONTyped {
122-
associatedtype Identifier: JSONAPI.IdType
125+
public protocol Relatable: Identifiable where Identifier: JSONAPI.IdType {
123126
}
124127

125128
/// OptionalRelatable just describes an Optional
126129
/// with a Reltable Wrapped type.
127-
public protocol OptionalRelatable: JSONTyped {
130+
public protocol OptionalRelatable: Identifiable where Identifier == Wrapped.Identifier? {
128131
associatedtype Wrapped: JSONAPI.Relatable
129-
associatedtype WrappedId: WrappedIdType where WrappedId.Identifier == Wrapped.Identifier
130-
}
131-
132-
public protocol WrappedIdType: Codable, Equatable {
133-
associatedtype Identifier: JSONAPI.IdType
134-
}
135-
136-
extension Optional: WrappedIdType where Wrapped: IdType {
137-
public typealias Identifier = Wrapped
138132
}
139133

140-
extension Optional: OptionalRelatable, JSONTyped where Wrapped: JSONAPI.Relatable {
141-
public typealias WrappedId = Wrapped.Identifier?
134+
extension Optional: Identifiable, OptionalRelatable, JSONTyped where Wrapped: JSONAPI.Relatable {
135+
public typealias Identifier = Wrapped.Identifier?
142136

143137
public static var type: String { return Wrapped.type }
144138
}
@@ -177,7 +171,7 @@ extension ToOneRelationship {
177171
// type at which point we can store nil in `id`.
178172
let anyNil: Any? = nil
179173
if try container.decodeNil(forKey: .data),
180-
let val = anyNil as? OptionalRelatable.WrappedId {
174+
let val = anyNil as? Identifiable.Identifier {
181175
id = val
182176
return
183177
}
@@ -186,11 +180,11 @@ extension ToOneRelationship {
186180

187181
let type = try identifier.decode(String.self, forKey: .entityType)
188182

189-
guard type == OptionalRelatable.type else {
190-
throw JSONAPIEncodingError.typeMismatch(expected: OptionalRelatable.type, found: type)
183+
guard type == Identifiable.type else {
184+
throw JSONAPIEncodingError.typeMismatch(expected: Identifiable.type, found: type)
191185
}
192186

193-
id = try identifier.decode(OptionalRelatable.WrappedId.self, forKey: .id)
187+
id = try identifier.decode(Identifiable.Identifier.self, forKey: .id)
194188
}
195189

196190
public func encode(to encoder: Encoder) throws {
@@ -211,7 +205,7 @@ extension ToOneRelationship {
211205
var identifier = container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data)
212206

213207
try identifier.encode(id, forKey: .id)
214-
try identifier.encode(OptionalRelatable.type, forKey: .entityType)
208+
try identifier.encode(Identifiable.type, forKey: .entityType)
215209
}
216210
}
217211

Sources/JSONAPITestLib/Relationship+Literal.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,34 @@
77

88
import JSONAPI
99

10-
extension ToOneRelationship: ExpressibleByNilLiteral where OptionalRelatable.WrappedId: ExpressibleByNilLiteral, MetaType == NoMetadata, LinksType == NoLinks {
10+
extension ToOneRelationship: ExpressibleByNilLiteral where Identifiable.Identifier: ExpressibleByNilLiteral, MetaType == NoMetadata, LinksType == NoLinks {
1111
public init(nilLiteral: ()) {
1212

13-
self.init(id: OptionalRelatable.WrappedId(nilLiteral: ()))
13+
self.init(id: Identifiable.Identifier(nilLiteral: ()))
1414
}
1515
}
1616

17-
extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where OptionalRelatable.WrappedId: ExpressibleByUnicodeScalarLiteral, MetaType == NoMetadata, LinksType == NoLinks {
18-
public typealias UnicodeScalarLiteralType = OptionalRelatable.WrappedId.UnicodeScalarLiteralType
17+
extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Identifiable.Identifier: ExpressibleByUnicodeScalarLiteral, MetaType == NoMetadata, LinksType == NoLinks {
18+
public typealias UnicodeScalarLiteralType = Identifiable.Identifier.UnicodeScalarLiteralType
1919

2020
public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) {
21-
self.init(id: OptionalRelatable.WrappedId(unicodeScalarLiteral: value))
21+
self.init(id: Identifiable.Identifier(unicodeScalarLiteral: value))
2222
}
2323
}
2424

25-
extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where OptionalRelatable.WrappedId: ExpressibleByExtendedGraphemeClusterLiteral, MetaType == NoMetadata, LinksType == NoLinks {
26-
public typealias ExtendedGraphemeClusterLiteralType = OptionalRelatable.WrappedId.ExtendedGraphemeClusterLiteralType
25+
extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where Identifiable.Identifier: ExpressibleByExtendedGraphemeClusterLiteral, MetaType == NoMetadata, LinksType == NoLinks {
26+
public typealias ExtendedGraphemeClusterLiteralType = Identifiable.Identifier.ExtendedGraphemeClusterLiteralType
2727

2828
public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) {
29-
self.init(id: OptionalRelatable.WrappedId(extendedGraphemeClusterLiteral: value))
29+
self.init(id: Identifiable.Identifier(extendedGraphemeClusterLiteral: value))
3030
}
3131
}
3232

33-
extension ToOneRelationship: ExpressibleByStringLiteral where OptionalRelatable.WrappedId: ExpressibleByStringLiteral, MetaType == NoMetadata, LinksType == NoLinks {
34-
public typealias StringLiteralType = OptionalRelatable.WrappedId.StringLiteralType
33+
extension ToOneRelationship: ExpressibleByStringLiteral where Identifiable.Identifier: ExpressibleByStringLiteral, MetaType == NoMetadata, LinksType == NoLinks {
34+
public typealias StringLiteralType = Identifiable.Identifier.StringLiteralType
3535

3636
public init(stringLiteral value: StringLiteralType) {
37-
self.init(id: OptionalRelatable.WrappedId(stringLiteral: value))
37+
self.init(id: Identifiable.Identifier(stringLiteral: value))
3838
}
3939
}
4040

Tests/JSONAPITests/NonJSONAPIRelatable/NonJSONAPIRelatableTests.swift

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ extension NonJSONAPIRelatableTests {
3232
// typealias Relationships = NoRelationships
3333
// }
3434

35-
// struct NonJSONAPIEntity: Relatable, OptionalRelatable {
36-
// typealias Description = NonJSONAPIEntityDescription
37-
// typealias EntityRawIdType = String
35+
// struct NonJSONAPIEntity: Relatable, OptionalRelatable, JSONTyped {
36+
// static var type: String { return "other" }
37+
//
3838
// typealias Identifier = NonJSONAPIEntity.Id
3939
// typealias WrappedIdentifier = NonJSONAPIEntity.Id
4040
//
@@ -44,13 +44,10 @@ extension NonJSONAPIRelatableTests {
4444
// let relationships: NoRelationships
4545
//
4646
// struct Id: IdType {
47-
// var rawValue: NonJSONAPIRelatableTests.NonJSONAPIEntity.Id.RawType
48-
//
49-
// typealias EntityType = <#type#>
47+
// var rawValue: String
5048
//
49+
// typealias IdentifiableType = NonJSONAPIEntity
5150
// typealias RawType = String
52-
//
53-
// let rawValue: String
5451
// }
5552
// }
5653
}

0 commit comments

Comments
 (0)