mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-03-30 11:18:38 -07:00
Prepping for ToOneRelationships that have optional related types for use in situations where null is an acceptable relationship value.
This commit is contained in:
@@ -21,6 +21,12 @@ public struct Includes<I: IncludeDecoder>: Decodable {
|
||||
public init(from decoder: Decoder) throws {
|
||||
var container = try decoder.unkeyedContainer()
|
||||
|
||||
// If not parsing includes, no need to loop over them.
|
||||
guard I.self != NoIncludes.self else {
|
||||
values = []
|
||||
return
|
||||
}
|
||||
|
||||
var valueAggregator = [I]()
|
||||
while !container.isAtEnd {
|
||||
valueAggregator.append(try container.decode(I.self))
|
||||
|
||||
@@ -129,7 +129,7 @@ extension Entity where EntityType.Attributes == NoAttributes, EntityType.Relatio
|
||||
public extension Entity where EntityType.Identifier: IdType {
|
||||
/// Get a pointer to this entity that can be used as a
|
||||
/// relationship to another entity.
|
||||
public var pointer: ToOneRelationship<EntityType> {
|
||||
public var pointer: ToOneRelationship<Entity> {
|
||||
return ToOneRelationship(entity: self)
|
||||
}
|
||||
}
|
||||
@@ -163,14 +163,14 @@ public extension Entity {
|
||||
/// Access to an Id of a `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other.id`.
|
||||
public static func ~><OtherEntityType: JSONAPI.EntityDescription>(entity: Entity<EntityType>, path: KeyPath<EntityType.Relationships, ToOneRelationship<OtherEntityType>>) -> OtherEntityType.Identifier {
|
||||
public static func ~><OtherEntity: Relatable>(entity: Entity<EntityType>, path: KeyPath<EntityType.Relationships, ToOneRelationship<OtherEntity>>) -> OtherEntity.Description.Identifier {
|
||||
return entity.relationships[keyPath: path].id
|
||||
}
|
||||
|
||||
|
||||
/// Access to all Ids of a `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others.ids`.
|
||||
public static func ~><OtherEntityType: JSONAPI.EntityDescription>(entity: Entity<EntityType>, path: KeyPath<EntityType.Relationships, ToManyRelationship<OtherEntityType>>) -> [OtherEntityType.Identifier] {
|
||||
public static func ~><OtherEntity: Relatable>(entity: Entity<EntityType>, path: KeyPath<EntityType.Relationships, ToManyRelationship<OtherEntity>>) -> [OtherEntity.Description.Identifier] {
|
||||
return entity.relationships[keyPath: path].ids
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,23 @@ extension String: RawIdType {}
|
||||
|
||||
public protocol Identifier: Codable, Equatable {}
|
||||
|
||||
public struct Unidentified: Identifier {
|
||||
public struct Unidentified: Identifier, CustomStringConvertible {
|
||||
public init() {}
|
||||
|
||||
public var description: String { return "Id(Unidentified)" }
|
||||
}
|
||||
|
||||
public protocol IdType: Identifier {
|
||||
public protocol IdType: Identifier, CustomStringConvertible {
|
||||
associatedtype EntityType: JSONAPI.EntityDescription
|
||||
associatedtype RawType: RawIdType
|
||||
|
||||
var rawValue: RawType { get }
|
||||
}
|
||||
|
||||
public extension IdType {
|
||||
var description: String { return "Id(\(String(describing: rawValue)))" }
|
||||
}
|
||||
|
||||
public protocol CreatableIdType: IdType {
|
||||
init()
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/// You should use the `ToOneRelationship` and `ToManyRelationship`
|
||||
/// concrete types.
|
||||
/// See https://jsonapi.org/format/#document-resource-object-linkage
|
||||
public protocol Relationship: Equatable, Encodable {
|
||||
public protocol Relationship: Equatable, Encodable, CustomStringConvertible {
|
||||
associatedtype EntityType: JSONAPI.EntityDescription where EntityType.Identifier: IdType
|
||||
var ids: [EntityType.Identifier] { get }
|
||||
}
|
||||
@@ -19,7 +19,9 @@ public protocol Relationship: Equatable, Encodable {
|
||||
/// a JSON API "Resource Linkage."
|
||||
/// See https://jsonapi.org/format/#document-resource-object-linkage
|
||||
/// A convenient typealias might make your code much more legible: `One<EntityDescription>`
|
||||
public struct ToOneRelationship<EntityType: JSONAPI.EntityDescription>: Equatable, Relationship, Decodable where EntityType.Identifier: IdType {
|
||||
public struct ToOneRelationship<Relatable: JSONAPI.OptionalRelatable>: Equatable, Relationship, Decodable {
|
||||
public typealias EntityType = Relatable.Description
|
||||
|
||||
public let id: EntityType.Identifier
|
||||
|
||||
public init(entity: Entity<EntityType>) {
|
||||
@@ -35,7 +37,9 @@ public struct ToOneRelationship<EntityType: JSONAPI.EntityDescription>: Equatabl
|
||||
/// a JSON API "Resource Linkage."
|
||||
/// See https://jsonapi.org/format/#document-resource-object-linkage
|
||||
/// A convenient typealias might make your code much more legible: `Many<EntityDescription>`
|
||||
public struct ToManyRelationship<EntityType: JSONAPI.EntityDescription>: Equatable, Relationship, Decodable where EntityType.Identifier: IdType {
|
||||
public struct ToManyRelationship<Relatable: JSONAPI.Relatable>: Equatable, Relationship, Decodable {
|
||||
public typealias EntityType = Relatable.Description
|
||||
|
||||
public let ids: [EntityType.Identifier]
|
||||
|
||||
public init(entities: [Entity<EntityType>]) {
|
||||
@@ -51,6 +55,24 @@ public struct ToManyRelationship<EntityType: JSONAPI.EntityDescription>: Equatab
|
||||
}
|
||||
}
|
||||
|
||||
/// The OptionalRelatable protocol ONLY describes
|
||||
/// Optional<T: Relatable> types.
|
||||
public protocol OptionalRelatable {
|
||||
associatedtype Description: EntityDescription where Description.Identifier: IdType
|
||||
}
|
||||
|
||||
/// The Relatable protocol describes anything that
|
||||
/// has an EntityDescription
|
||||
public protocol Relatable: OptionalRelatable {}
|
||||
|
||||
extension Entity: Relatable, OptionalRelatable where EntityType.Identifier: IdType {
|
||||
public typealias Description = EntityType
|
||||
}
|
||||
|
||||
extension Optional: OptionalRelatable where Wrapped: Relatable {
|
||||
public typealias Description = Wrapped.Description
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
private enum ResourceLinkageCodingKeys: String, CodingKey {
|
||||
case data = "data"
|
||||
@@ -120,3 +142,12 @@ extension ToManyRelationship {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: CustomStringDescribable
|
||||
public extension ToOneRelationship {
|
||||
var description: String { return "Relationship(\(String(describing: id)))" }
|
||||
}
|
||||
|
||||
public extension ToManyRelationship {
|
||||
var description: String { return "Relationship(\(String(describing: ids)))" }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user