From d6f01d6c1d13315d5314307fc813b4fc4383238e Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Tue, 5 Nov 2019 22:27:59 -0800 Subject: [PATCH 1/2] indentation --- Sources/JSONAPI/Document/Document.swift | 282 ++++++++++++------------ 1 file changed, 141 insertions(+), 141 deletions(-) diff --git a/Sources/JSONAPI/Document/Document.swift b/Sources/JSONAPI/Document/Document.swift index 98b4445..60030c3 100644 --- a/Sources/JSONAPI/Document/Document.swift +++ b/Sources/JSONAPI/Document/Document.swift @@ -106,34 +106,34 @@ public protocol CodableJSONAPIDocument: EncodableJSONAPIDocument, Decodable wher /// a conversion such as the one offerred by the /// Foundation JSONEncoder/Decoder: `KeyDecodingStrategy` public struct Document: EncodableJSONAPIDocument { - public typealias Include = IncludeType + public typealias Include = IncludeType public typealias BodyData = Body.Data - /// The JSON API Spec calls this the JSON:API Object. It contains version - /// and metadata information about the API itself. - public let apiDescription: APIDescription + /// The JSON API Spec calls this the JSON:API Object. It contains version + /// and metadata information about the API itself. + public let apiDescription: APIDescription - /// The Body of the Document. This body is either one or more errors - /// with links and metadata attempted to parse but not guaranteed or - /// it is a successful data struct containing all the primary and - /// included resources, the metadata, and the links that this - /// document type specifies. - public let body: Body + /// The Body of the Document. This body is either one or more errors + /// with links and metadata attempted to parse but not guaranteed or + /// it is a successful data struct containing all the primary and + /// included resources, the metadata, and the links that this + /// document type specifies. + public let body: Body - public init(apiDescription: APIDescription, + public init(apiDescription: APIDescription, errors: [Error], meta: MetaType? = nil, links: LinksType? = nil) { - body = .errors(errors, meta: meta, links: links) - self.apiDescription = apiDescription - } - - public init(apiDescription: APIDescription, - body: PrimaryResourceBody, - includes: Includes, - meta: MetaType, - links: LinksType) { - self.body = .data( + body = .errors(errors, meta: meta, links: links) + self.apiDescription = apiDescription + } + + public init(apiDescription: APIDescription, + body: PrimaryResourceBody, + includes: Includes, + meta: MetaType, + links: LinksType) { + self.body = .data( .init( primary: body, includes: includes, @@ -141,8 +141,8 @@ public struct Document MetaType, - combiningLinksWith linksMerge: (LinksType, LinksType) -> LinksType) -> Document.Body.Data { - return Document.Body.Data(primary: primary.appending(other.primary), - includes: includes.appending(other.includes), - meta: metaMerge(meta, other.meta), - links: linksMerge(links, other.links)) - } + public func merging(_ other: Document.Body.Data, + combiningMetaWith metaMerge: (MetaType, MetaType) -> MetaType, + combiningLinksWith linksMerge: (LinksType, LinksType) -> LinksType) -> Document.Body.Data { + return Document.Body.Data(primary: primary.appending(other.primary), + includes: includes.appending(other.includes), + meta: metaMerge(meta, other.meta), + links: linksMerge(links, other.links)) + } } extension Document.Body.Data where PrimaryResourceBody: ResourceBodyAppendable, MetaType == NoMetadata, LinksType == NoLinks { - public func merging(_ other: Document.Body.Data) -> Document.Body.Data { - return merging(other, - combiningMetaWith: { _, _ in .none }, - combiningLinksWith: { _, _ in .none }) - } + public func merging(_ other: Document.Body.Data) -> Document.Body.Data { + return merging(other, + combiningMetaWith: { _, _ in .none }, + combiningLinksWith: { _, _ in .none }) + } } extension Document where IncludeType == NoIncludes { - /// Create a new Document with the given includes. - public func including(_ includes: Includes) -> Document { - // Note that if IncludeType is NoIncludes, then we allow anything - // to be included, but if IncludeType already specifies a type - // of thing to be expected then we lock that down. - // See: Document.including() where IncludeType: _Poly1 - switch body { - case .data(let data): - return .init(apiDescription: apiDescription, - body: data.primary, - includes: includes, - meta: data.meta, - links: data.links) - case .errors(let errors, meta: let meta, links: let links): - return .init(apiDescription: apiDescription, - errors: errors, - meta: meta, - links: links) - } - } + /// Create a new Document with the given includes. + public func including(_ includes: Includes) -> Document { + // Note that if IncludeType is NoIncludes, then we allow anything + // to be included, but if IncludeType already specifies a type + // of thing to be expected then we lock that down. + // See: Document.including() where IncludeType: _Poly1 + switch body { + case .data(let data): + return .init(apiDescription: apiDescription, + body: data.primary, + includes: includes, + meta: data.meta, + links: data.links) + case .errors(let errors, meta: let meta, links: let links): + return .init(apiDescription: apiDescription, + errors: errors, + meta: meta, + links: links) + } + } } // extending where _Poly1 means all non-zero _Poly arities are included extension Document where IncludeType: _Poly1 { - /// Create a new Document adding the given includes. This does not - /// remove existing includes; it is additive. - public func including(_ includes: Includes) -> Document { - // Note that if IncludeType is NoIncludes, then we allow anything - // to be included, but if IncludeType already specifies a type - // of thing to be expected then we lock that down. - // See: Document.including() where IncludeType == NoIncludes - switch body { - case .data(let data): - return .init(apiDescription: apiDescription, - body: data.primary, - includes: data.includes + includes, - meta: data.meta, - links: data.links) - case .errors(let errors, meta: let meta, links: let links): - return .init(apiDescription: apiDescription, - errors: errors, - meta: meta, - links: links) - } - } + /// Create a new Document adding the given includes. This does not + /// remove existing includes; it is additive. + public func including(_ includes: Includes) -> Document { + // Note that if IncludeType is NoIncludes, then we allow anything + // to be included, but if IncludeType already specifies a type + // of thing to be expected then we lock that down. + // See: Document.including() where IncludeType == NoIncludes + switch body { + case .data(let data): + return .init(apiDescription: apiDescription, + body: data.primary, + includes: data.includes + includes, + meta: data.meta, + links: data.links) + case .errors(let errors, meta: let meta, links: let links): + return .init(apiDescription: apiDescription, + errors: errors, + meta: meta, + links: links) + } + } } // MARK: - Codable extension Document { - private enum RootCodingKeys: String, CodingKey { - case data - case errors - case included - case meta - case links - case jsonapi - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: RootCodingKeys.self) - - switch body { - case .errors(let errors, meta: let meta, links: let links): - var errContainer = container.nestedUnkeyedContainer(forKey: .errors) - - for error in errors { - try errContainer.encode(error) - } - - if MetaType.self != NoMetadata.self, - let metaVal = meta { - try container.encode(metaVal, forKey: .meta) - } - - if LinksType.self != NoLinks.self, - let linksVal = links { - try container.encode(linksVal, forKey: .links) - } - - case .data(let data): - try container.encode(data.primary, forKey: .data) - - if Include.self != NoIncludes.self { - try container.encode(data.includes, forKey: .included) - } - - if MetaType.self != NoMetadata.self { - try container.encode(data.meta, forKey: .meta) - } - - if LinksType.self != NoLinks.self { - try container.encode(data.links, forKey: .links) - } - } - - if APIDescription.self != NoAPIDescription.self { - try container.encode(apiDescription, forKey: .jsonapi) - } - } + private enum RootCodingKeys: String, CodingKey { + case data + case errors + case included + case meta + case links + case jsonapi + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: RootCodingKeys.self) + + switch body { + case .errors(let errors, meta: let meta, links: let links): + var errContainer = container.nestedUnkeyedContainer(forKey: .errors) + + for error in errors { + try errContainer.encode(error) + } + + if MetaType.self != NoMetadata.self, + let metaVal = meta { + try container.encode(metaVal, forKey: .meta) + } + + if LinksType.self != NoLinks.self, + let linksVal = links { + try container.encode(linksVal, forKey: .links) + } + + case .data(let data): + try container.encode(data.primary, forKey: .data) + + if Include.self != NoIncludes.self { + try container.encode(data.includes, forKey: .included) + } + + if MetaType.self != NoMetadata.self { + try container.encode(data.meta, forKey: .meta) + } + + if LinksType.self != NoLinks.self { + try container.encode(data.links, forKey: .links) + } + } + + if APIDescription.self != NoAPIDescription.self { + try container.encode(apiDescription, forKey: .jsonapi) + } + } } extension Document: Decodable, CodableJSONAPIDocument where PrimaryResourceBody: ResourceBody, IncludeType: Decodable { @@ -405,26 +405,26 @@ extension Document: Decodable, CodableJSONAPIDocument where PrimaryResourceBody: // MARK: - CustomStringConvertible extension Document: CustomStringConvertible { - public var description: String { - return "Document(\(String(describing: body)))" - } + public var description: String { + return "Document(\(String(describing: body)))" + } } extension Document.Body: CustomStringConvertible { - public var description: String { - switch self { - case .errors(let errors, meta: let meta, links: let links): - return "errors: \(String(describing: errors)), meta: \(String(describing: meta)), links: \(String(describing: links))" - case .data(let data): - return String(describing: data) - } - } + public var description: String { + switch self { + case .errors(let errors, meta: let meta, links: let links): + return "errors: \(String(describing: errors)), meta: \(String(describing: meta)), links: \(String(describing: links))" + case .data(let data): + return String(describing: data) + } + } } extension Document.Body.Data: CustomStringConvertible { - public var description: String { - return "primary: \(String(describing: primary)), includes: \(String(describing: includes)), meta: \(String(describing: meta)), links: \(String(describing: links))" - } + public var description: String { + return "primary: \(String(describing: primary)), includes: \(String(describing: includes)), meta: \(String(describing: meta)), links: \(String(describing: links))" + } } // MARK: - Error and Success Document Types From e6f82c6052e6d156bc95ad491c8857d26facd0b3 Mon Sep 17 00:00:00 2001 From: Mathew Polzin Date: Tue, 5 Nov 2019 22:37:48 -0800 Subject: [PATCH 2/2] indentation --- Sources/JSONAPI/Document/APIDescription.swift | 64 +- Sources/JSONAPI/Document/Includes.swift | 120 +-- Sources/JSONAPI/Document/ResourceBody.swift | 60 +- Sources/JSONAPI/EncodingError.swift | 10 +- Sources/JSONAPI/Error/BasicJSONAPIError.swift | 7 +- Sources/JSONAPI/Error/JSONAPIError.swift | 28 +- Sources/JSONAPI/Meta/Links.swift | 86 +- Sources/JSONAPI/Meta/Meta.swift | 6 +- .../JSONAPI/Resource/Attribute+Functor.swift | 48 +- Sources/JSONAPI/Resource/Attribute.swift | 175 ++-- Sources/JSONAPI/Resource/Id.swift | 92 +- .../Resource/Poly+PrimaryResource.swift | 144 ++- Sources/JSONAPI/Resource/Relationship.swift | 374 ++++---- .../Resource Object/ResourceObject.swift | 828 +++++++++--------- .../JSONAPITesting/Attribute+Literal.swift | 126 +-- Sources/JSONAPITesting/Id+Literal.swift | 40 +- Sources/JSONAPITesting/Optional+Literal.swift | 24 +- .../JSONAPITesting/Relationship+Literal.swift | 38 +- .../JSONAPITesting/ResourceObjectCheck.swift | 104 +-- 19 files changed, 1228 insertions(+), 1146 deletions(-) diff --git a/Sources/JSONAPI/Document/APIDescription.swift b/Sources/JSONAPI/Document/APIDescription.swift index a0ba2ff..cb417a6 100644 --- a/Sources/JSONAPI/Document/APIDescription.swift +++ b/Sources/JSONAPI/Document/APIDescription.swift @@ -7,58 +7,58 @@ /// This is what the JSON API Spec calls the "JSON:API Object" public protocol APIDescriptionType: Codable, Equatable { - associatedtype Meta + associatedtype Meta } /// This is what the JSON API Spec calls the "JSON:API Object" public struct APIDescription: APIDescriptionType { - public let version: String - public let meta: Meta + public let version: String + public let meta: Meta - public init(version: String, meta: Meta) { - self.version = version - self.meta = meta - } + public init(version: String, meta: Meta) { + self.version = version + self.meta = meta + } } /// Can be used as `APIDescriptionType` for Documents that do not /// have any API Description (a.k.a. "JSON:API Object"). public struct NoAPIDescription: APIDescriptionType, CustomStringConvertible { - public typealias Meta = NoMetadata + public typealias Meta = NoMetadata - public init() {} + public init() {} - public static var none: NoAPIDescription { return .init() } + public static var none: NoAPIDescription { return .init() } - public var description: String { return "No JSON:API Object" } + public var description: String { return "No JSON:API Object" } } extension APIDescription { - private enum CodingKeys: String, CodingKey { - case version - case meta - } + private enum CodingKeys: String, CodingKey { + case version + case meta + } - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) - // The spec says that if a version is not specified, it should be assumed to be at least 1.0 - version = (try? container.decode(String.self, forKey: .version)) ?? "1.0" + // The spec says that if a version is not specified, it should be assumed to be at least 1.0 + version = (try? container.decode(String.self, forKey: .version)) ?? "1.0" - if let metaVal = NoMetadata() as? Meta { - meta = metaVal - } else { - meta = try container.decode(Meta.self, forKey: .meta) - } - } + if let metaVal = NoMetadata() as? Meta { + meta = metaVal + } else { + meta = try container.decode(Meta.self, forKey: .meta) + } + } - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: CodingKeys.self) + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(version, forKey: .version) + try container.encode(version, forKey: .version) - if Meta.self != NoMetadata.self { - try container.encode(meta, forKey: .meta) - } - } + if Meta.self != NoMetadata.self { + try container.encode(meta, forKey: .meta) + } + } } diff --git a/Sources/JSONAPI/Document/Includes.swift b/Sources/JSONAPI/Document/Includes.swift index b6d93e0..087b2b5 100644 --- a/Sources/JSONAPI/Document/Includes.swift +++ b/Sources/JSONAPI/Document/Includes.swift @@ -20,29 +20,29 @@ public typealias Include = EncodableJSONPoly /// /// `let includedThings = includes[Thing1.self]` public struct Includes: Encodable, Equatable { - public static var none: Includes { return .init(values: []) } - - let values: [I] - - public init(values: [I]) { - self.values = values - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() - - guard I.self != NoIncludes.self else { - throw JSONAPIEncodingError.illegalEncoding("Attempting to encode Include0, which should be represented by the absense of an 'included' entry altogether.") - } - - for value in values { - try container.encode(value) - } - } - - public var count: Int { - return values.count - } + public static var none: Includes { return .init(values: []) } + + let values: [I] + + public init(values: [I]) { + self.values = values + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.unkeyedContainer() + + guard I.self != NoIncludes.self else { + throw JSONAPIEncodingError.illegalEncoding("Attempting to encode Include0, which should be represented by the absense of an 'included' entry altogether.") + } + + for value in values { + try container.encode(value) + } + } + + public var count: Int { + return values.count + } } extension Includes: Decodable where I: Decodable { @@ -65,25 +65,25 @@ extension Includes: Decodable where I: Decodable { } extension Includes { - public func appending(_ other: Includes) -> Includes { - return Includes(values: values + other.values) - } + public func appending(_ other: Includes) -> Includes { + return Includes(values: values + other.values) + } } public func +(_ left: Includes, _ right: Includes) -> Includes { - return left.appending(right) + return left.appending(right) } extension Includes: CustomStringConvertible { - public var description: String { - return "Includes(\(String(describing: values))" - } + public var description: String { + return "Includes(\(String(describing: values))" + } } extension Includes where I == NoIncludes { - public init() { - values = [] - } + public init() { + values = [] + } } // MARK: - 0 includes @@ -93,73 +93,73 @@ public typealias NoIncludes = Include0 // MARK: - 1 include public typealias Include1 = Poly1 extension Includes where I: _Poly1 { - public subscript(_ lookup: I.A.Type) -> [I.A] { - return values.compactMap { $0.a } - } + public subscript(_ lookup: I.A.Type) -> [I.A] { + return values.compactMap { $0.a } + } } // MARK: - 2 includes public typealias Include2 = Poly2 extension Includes where I: _Poly2 { - public subscript(_ lookup: I.B.Type) -> [I.B] { - return values.compactMap { $0.b } - } + public subscript(_ lookup: I.B.Type) -> [I.B] { + return values.compactMap { $0.b } + } } // MARK: - 3 includes public typealias Include3 = Poly3 extension Includes where I: _Poly3 { - public subscript(_ lookup: I.C.Type) -> [I.C] { - return values.compactMap { $0.c } - } + public subscript(_ lookup: I.C.Type) -> [I.C] { + return values.compactMap { $0.c } + } } // MARK: - 4 includes public typealias Include4 = Poly4 extension Includes where I: _Poly4 { - public subscript(_ lookup: I.D.Type) -> [I.D] { - return values.compactMap { $0.d } - } + public subscript(_ lookup: I.D.Type) -> [I.D] { + return values.compactMap { $0.d } + } } // MARK: - 5 includes public typealias Include5 = Poly5 extension Includes where I: _Poly5 { - public subscript(_ lookup: I.E.Type) -> [I.E] { - return values.compactMap { $0.e } - } + public subscript(_ lookup: I.E.Type) -> [I.E] { + return values.compactMap { $0.e } + } } // MARK: - 6 includes public typealias Include6 = Poly6 extension Includes where I: _Poly6 { - public subscript(_ lookup: I.F.Type) -> [I.F] { - return values.compactMap { $0.f } - } + public subscript(_ lookup: I.F.Type) -> [I.F] { + return values.compactMap { $0.f } + } } // MARK: - 7 includes public typealias Include7 = Poly7 extension Includes where I: _Poly7 { - public subscript(_ lookup: I.G.Type) -> [I.G] { - return values.compactMap { $0.g } - } + public subscript(_ lookup: I.G.Type) -> [I.G] { + return values.compactMap { $0.g } + } } // MARK: - 8 includes public typealias Include8 = Poly8 extension Includes where I: _Poly8 { - public subscript(_ lookup: I.H.Type) -> [I.H] { - return values.compactMap { $0.h } - } + public subscript(_ lookup: I.H.Type) -> [I.H] { + return values.compactMap { $0.h } + } } // MARK: - 9 includes public typealias Include9 = Poly9 extension Includes where I: _Poly9 { - public subscript(_ lookup: I.I.Type) -> [I.I] { - return values.compactMap { $0.i } - } + public subscript(_ lookup: I.I.Type) -> [I.I] { + return values.compactMap { $0.i } + } } // MARK: - 10 includes diff --git a/Sources/JSONAPI/Document/ResourceBody.swift b/Sources/JSONAPI/Document/ResourceBody.swift index 7d8b9e2..8fd20d6 100644 --- a/Sources/JSONAPI/Document/ResourceBody.swift +++ b/Sources/JSONAPI/Document/ResourceBody.swift @@ -41,47 +41,47 @@ public protocol ResourceBody: Decodable, EncodableResourceBody {} /// A `ResourceBody` that has the ability to take on more primary /// resources by appending another similarly typed `ResourceBody`. public protocol ResourceBodyAppendable { - func appending(_ other: Self) -> Self + func appending(_ other: Self) -> Self } public func +(_ left: R, right: R) -> R { - return left.appending(right) + return left.appending(right) } /// A type allowing for a document body containing 1 primary resource. /// If the `Entity` specialization is an `Optional` type, the body can contain /// 0 or 1 primary resources. public struct SingleResourceBody: EncodableResourceBody { - public let value: Entity + public let value: Entity - public init(resourceObject: Entity) { - self.value = resourceObject - } + public init(resourceObject: Entity) { + self.value = resourceObject + } } /// A type allowing for a document body containing 0 or more primary resources. public struct ManyResourceBody: EncodableResourceBody, ResourceBodyAppendable { - public let values: [Entity] + public let values: [Entity] - public init(resourceObjects: [Entity]) { - values = resourceObjects - } + public init(resourceObjects: [Entity]) { + values = resourceObjects + } - public func appending(_ other: ManyResourceBody) -> ManyResourceBody { - return ManyResourceBody(resourceObjects: values + other.values) - } + public func appending(_ other: ManyResourceBody) -> ManyResourceBody { + return ManyResourceBody(resourceObjects: values + other.values) + } } /// Use NoResourceBody to indicate you expect a JSON API document to not /// contain a "data" top-level key. public struct NoResourceBody: ResourceBody { - public static var none: NoResourceBody { return NoResourceBody() } + public static var none: NoResourceBody { return NoResourceBody() } } // MARK: Codable extension SingleResourceBody { - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() let anyNil: Any? = nil let nilValue = anyNil as? Entity @@ -90,8 +90,8 @@ extension SingleResourceBody { return } - try container.encode(value) - } + try container.encode(value) + } } extension SingleResourceBody: Decodable, ResourceBody where Entity: OptionalPrimaryResource { @@ -110,13 +110,13 @@ extension SingleResourceBody: Decodable, ResourceBody where Entity: OptionalPrim } extension ManyResourceBody { - public func encode(to encoder: Encoder) throws { - var container = encoder.unkeyedContainer() + public func encode(to encoder: Encoder) throws { + var container = encoder.unkeyedContainer() - for value in values { - try container.encode(value) - } - } + for value in values { + try container.encode(value) + } + } } extension ManyResourceBody: Decodable, ResourceBody where Entity: PrimaryResource { @@ -133,13 +133,13 @@ extension ManyResourceBody: Decodable, ResourceBody where Entity: PrimaryResourc // MARK: CustomStringConvertible extension SingleResourceBody: CustomStringConvertible { - public var description: String { - return "PrimaryResourceBody(\(String(describing: value)))" - } + public var description: String { + return "PrimaryResourceBody(\(String(describing: value)))" + } } extension ManyResourceBody: CustomStringConvertible { - public var description: String { - return "PrimaryResourceBody(\(String(describing: values)))" - } + public var description: String { + return "PrimaryResourceBody(\(String(describing: values)))" + } } diff --git a/Sources/JSONAPI/EncodingError.swift b/Sources/JSONAPI/EncodingError.swift index 1d8145f..8b461cd 100644 --- a/Sources/JSONAPI/EncodingError.swift +++ b/Sources/JSONAPI/EncodingError.swift @@ -6,9 +6,9 @@ // public enum JSONAPIEncodingError: Swift.Error { - case typeMismatch(expected: String, found: String) - case illegalEncoding(String) - case illegalDecoding(String) - case missingOrMalformedMetadata - case missingOrMalformedLinks + case typeMismatch(expected: String, found: String) + case illegalEncoding(String) + case illegalDecoding(String) + case missingOrMalformedMetadata + case missingOrMalformedLinks } diff --git a/Sources/JSONAPI/Error/BasicJSONAPIError.swift b/Sources/JSONAPI/Error/BasicJSONAPIError.swift index 28795b9..88ed95e 100644 --- a/Sources/JSONAPI/Error/BasicJSONAPIError.swift +++ b/Sources/JSONAPI/Error/BasicJSONAPIError.swift @@ -9,7 +9,9 @@ public struct BasicJSONAPIErrorPayload: Codable, Equatable, ErrorDictType { /// a unique identifier for this particular occurrence of the problem public let id: IdType? -// public let links: Links? // we skip this for now to avoid adding complexity to using this basic type. + + // public let links: Links? // we skip this for now to avoid adding complexity to using this basic type. + /// the HTTP status code applicable to this problem public let status: String? /// an application-specific error code @@ -20,7 +22,8 @@ public struct BasicJSONAPIErrorPayload: Codable, Eq public let detail: String? /// an object containing references to the source of the error public let source: Source? -// public let meta: Meta? // we skip this for now to avoid adding complexity to using this basic type + + // public let meta: Meta? // we skip this for now to avoid adding complexity to using this basic type public init(id: IdType? = nil, status: String? = nil, diff --git a/Sources/JSONAPI/Error/JSONAPIError.swift b/Sources/JSONAPI/Error/JSONAPIError.swift index b997a69..6f19105 100644 --- a/Sources/JSONAPI/Error/JSONAPIError.swift +++ b/Sources/JSONAPI/Error/JSONAPIError.swift @@ -6,7 +6,7 @@ // public protocol JSONAPIError: Swift.Error, Equatable, Codable { - static var unknown: Self { get } + static var unknown: Self { get } } /// `UnknownJSONAPIError` can actually be used in any sitaution @@ -16,18 +16,18 @@ public protocol JSONAPIError: Swift.Error, Equatable, Codable { /// information the server might be providing in the error payload, /// use `BasicJSONAPIError` instead. public enum UnknownJSONAPIError: JSONAPIError { - case unknownError - - public init(from decoder: Decoder) throws { - self = .unknown - } + case unknownError - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode("unknown") - } - - public static var unknown: Self { - return .unknownError - } + public init(from decoder: Decoder) throws { + self = .unknown + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode("unknown") + } + + public static var unknown: Self { + return .unknownError + } } diff --git a/Sources/JSONAPI/Meta/Links.swift b/Sources/JSONAPI/Meta/Links.swift index 00658cb..876995f 100644 --- a/Sources/JSONAPI/Meta/Links.swift +++ b/Sources/JSONAPI/Meta/Links.swift @@ -10,58 +10,58 @@ public protocol Links: Codable, Equatable {} /// Use NoLinks where no links should belong to a JSON API component public struct NoLinks: Links, CustomStringConvertible { - public static var none: NoLinks { return NoLinks() } - public init() {} - - public var description: String { return "No Links" } + public static var none: NoLinks { return NoLinks() } + public init() {} + + public var description: String { return "No Links" } } public protocol JSONAPIURL: Codable, Equatable {} public struct Link: Equatable, Codable { - public let url: URL - public let meta: Meta - - public init(url: URL, meta: Meta) { - self.url = url - self.meta = meta - } + public let url: URL + public let meta: Meta + + public init(url: URL, meta: Meta) { + self.url = url + self.meta = meta + } } extension Link where Meta == NoMetadata { - public init(url: URL) { - self.init(url: url, meta: .none) - } + public init(url: URL) { + self.init(url: url, meta: .none) + } } public extension Link { - private enum CodingKeys: String, CodingKey { - case href - case meta - } - - init(from decoder: Decoder) throws { - guard Meta.self == NoMetadata.self, - let noMeta = NoMetadata() as? Meta else { - let container = try decoder.container(keyedBy: CodingKeys.self) - meta = try container.decode(Meta.self, forKey: .meta) - url = try container.decode(URL.self, forKey: .href) - return - } - let container = try decoder.singleValueContainer() - url = try container.decode(URL.self) - meta = noMeta - } - - func encode(to encoder: Encoder) throws { - guard Meta.self == NoMetadata.self else { - var container = encoder.container(keyedBy: CodingKeys.self) - try container.encode(url, forKey: .href) - try container.encode(meta, forKey: .meta) - return - } - var container = encoder.singleValueContainer() - - try container.encode(url) - } + private enum CodingKeys: String, CodingKey { + case href + case meta + } + + init(from decoder: Decoder) throws { + guard Meta.self == NoMetadata.self, + let noMeta = NoMetadata() as? Meta else { + let container = try decoder.container(keyedBy: CodingKeys.self) + meta = try container.decode(Meta.self, forKey: .meta) + url = try container.decode(URL.self, forKey: .href) + return + } + let container = try decoder.singleValueContainer() + url = try container.decode(URL.self) + meta = noMeta + } + + func encode(to encoder: Encoder) throws { + guard Meta.self == NoMetadata.self else { + var container = encoder.container(keyedBy: CodingKeys.self) + try container.encode(url, forKey: .href) + try container.encode(meta, forKey: .meta) + return + } + var container = encoder.singleValueContainer() + + try container.encode(url) + } } diff --git a/Sources/JSONAPI/Meta/Meta.swift b/Sources/JSONAPI/Meta/Meta.swift index 68b2c94..b49149f 100644 --- a/Sources/JSONAPI/Meta/Meta.swift +++ b/Sources/JSONAPI/Meta/Meta.swift @@ -22,9 +22,9 @@ extension Optional: Meta where Wrapped: Meta {} /// Use this type when you want to specify not to encode or decode any metadata /// for a type. public struct NoMetadata: Meta, CustomStringConvertible { - public static var none: NoMetadata { return NoMetadata() } + public static var none: NoMetadata { return NoMetadata() } - public init() { } + public init() { } - public var description: String { return "No Metadata" } + public var description: String { return "No Metadata" } } diff --git a/Sources/JSONAPI/Resource/Attribute+Functor.swift b/Sources/JSONAPI/Resource/Attribute+Functor.swift index 1da6ff0..6f4b4dc 100644 --- a/Sources/JSONAPI/Resource/Attribute+Functor.swift +++ b/Sources/JSONAPI/Resource/Attribute+Functor.swift @@ -6,31 +6,31 @@ // public extension TransformedAttribute { - /// Map an Attribute to a new wrapped type. - /// Note that the resulting Attribute will have no transformer, even if the - /// source Attribute has a transformer. - /// You are mapping the output of the source transform into - /// the RawValue of a new transformerless Attribute. - /// - /// Generally, this is the most useful operation. The transformer gives you - /// control over the decoding of the Attribute, but once the Attribute exists, - /// mapping on it is most useful for creating computed Attribute properties. - func map(_ transform: (Transformer.To) throws -> T) rethrows -> Attribute { - return Attribute(value: try transform(value)) - } + /// Map an Attribute to a new wrapped type. + /// Note that the resulting Attribute will have no transformer, even if the + /// source Attribute has a transformer. + /// You are mapping the output of the source transform into + /// the RawValue of a new transformerless Attribute. + /// + /// Generally, this is the most useful operation. The transformer gives you + /// control over the decoding of the Attribute, but once the Attribute exists, + /// mapping on it is most useful for creating computed Attribute properties. + func map(_ transform: (Transformer.To) throws -> T) rethrows -> Attribute { + return Attribute(value: try transform(value)) + } } public extension Attribute { - /// Map an Attribute to a new wrapped type. - /// Note that the resulting Attribute will have no transformer, even if the - /// source Attribute has a transformer. - /// You are mapping the output of the source transform into - /// the RawValue of a new transformerless Attribute. - /// - /// Generally, this is the most useful operation. The transformer gives you - /// control over the decoding of the Attribute, but once the Attribute exists, - /// mapping on it is most useful for creating computed Attribute properties. - func map(_ transform: (ValueType) throws -> T) rethrows -> Attribute { - return Attribute(value: try transform(value)) - } + /// Map an Attribute to a new wrapped type. + /// Note that the resulting Attribute will have no transformer, even if the + /// source Attribute has a transformer. + /// You are mapping the output of the source transform into + /// the RawValue of a new transformerless Attribute. + /// + /// Generally, this is the most useful operation. The transformer gives you + /// control over the decoding of the Attribute, but once the Attribute exists, + /// mapping on it is most useful for creating computed Attribute properties. + func map(_ transform: (ValueType) throws -> T) rethrows -> Attribute { + return Attribute(value: try transform(value)) + } } diff --git a/Sources/JSONAPI/Resource/Attribute.swift b/Sources/JSONAPI/Resource/Attribute.swift index c05983d..f73d672 100644 --- a/Sources/JSONAPI/Resource/Attribute.swift +++ b/Sources/JSONAPI/Resource/Attribute.swift @@ -6,49 +6,49 @@ // public protocol AttributeType: Codable { - associatedtype RawValue: Codable - associatedtype ValueType + associatedtype RawValue: Codable + associatedtype ValueType - var value: ValueType { get } + var value: ValueType { get } } // MARK: TransformedAttribute /// A TransformedAttribute takes a Codable type and attempts to turn it into another type. public struct TransformedAttribute: AttributeType where Transformer.From == RawValue { - public let rawValue: RawValue + public let rawValue: RawValue - public let value: Transformer.To + public let value: Transformer.To - public init(rawValue: RawValue) throws { - self.rawValue = rawValue - value = try Transformer.transform(rawValue) - } + public init(rawValue: RawValue) throws { + self.rawValue = rawValue + value = try Transformer.transform(rawValue) + } } extension TransformedAttribute where Transformer == IdentityTransformer { - // If we are using the identity transform, we can skip the transform and guarantee no - // error is thrown. - public init(value: RawValue) { - rawValue = value - self.value = value - } + // If we are using the identity transform, we can skip the transform and guarantee no + // error is thrown. + public init(value: RawValue) { + rawValue = value + self.value = value + } } extension TransformedAttribute where Transformer: ReversibleTransformer { - /// Initialize a TransformedAttribute from its transformed value. The - /// RawValue, which is what gets encoded/decoded, is determined using - /// The Transformer's reverse function. - public init(transformedValue: Transformer.To) throws { - self.value = transformedValue - rawValue = try Transformer.reverse(value) - } + /// Initialize a TransformedAttribute from its transformed value. The + /// RawValue, which is what gets encoded/decoded, is determined using + /// The Transformer's reverse function. + public init(transformedValue: Transformer.To) throws { + self.value = transformedValue + rawValue = try Transformer.reverse(value) + } } extension TransformedAttribute: CustomStringConvertible { - public var description: String { - return "Attribute<\(String(describing: Transformer.From.self)) -> \(String(describing: Transformer.To.self))>(\(String(describing: value)))" - } + public var description: String { + return "Attribute<\(String(describing: Transformer.From.self)) -> \(String(describing: Transformer.To.self))>(\(String(describing: value)))" + } } extension TransformedAttribute: Equatable where Transformer.From: Equatable, Transformer.To: Equatable {} @@ -63,85 +63,86 @@ public typealias ValidatedAttribute: AttributeType { - let attribute: TransformedAttribute> + let attribute: TransformedAttribute> - public var value: RawValue { - return attribute.value - } + public var value: RawValue { + return attribute.value + } - public init(value: RawValue) { - attribute = .init(value: value) - } + public init(value: RawValue) { + attribute = .init(value: value) + } } extension Attribute: CustomStringConvertible { - public var description: String { - return "Attribute<\(String(describing: RawValue.self))>(\(String(describing: value)))" - } + public var description: String { + return "Attribute<\(String(describing: RawValue.self))>(\(String(describing: value)))" + } } extension Attribute: Equatable where RawValue: Equatable {} // MARK: - Codable extension TransformedAttribute { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - let rawVal: RawValue - - // A little trickery follows. If the value is nil, the - // container.decode(Value.self) will fail even if Value - // is Optional. However, we can check if decoding nil - // succeeds and then attempt to coerce nil to a Value - // type at which point we can store nil in `value`. - let anyNil: Any? = nil - if container.decodeNil(), - let val = anyNil as? Transformer.From { - rawVal = val - } else { - rawVal = try container.decode(Transformer.From.self) - } - - rawValue = rawVal - value = try Transformer.transform(rawVal) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - - try container.encode(rawValue) - } + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + + let rawVal: RawValue + + // A little trickery follows. If the value is nil, the + // container.decode(Value.self) will fail even if Value + // is Optional. However, we can check if decoding nil + // succeeds and then attempt to coerce nil to a Value + // type at which point we can store nil in `value`. + let anyNil: Any? = nil + if container.decodeNil(), + let val = anyNil as? Transformer.From { + rawVal = val + } else { + rawVal = try container.decode(Transformer.From.self) + } + + rawValue = rawVal + value = try Transformer.transform(rawVal) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode(rawValue) + } } extension Attribute { - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - - // A little trickery follows. If the value is nil, the - // container.decode(Value.self) will fail even if Value - // is Optional. However, we can check if decoding nil - // succeeds and then attempt to coerce nil to a Value - // type at which point we can store nil in `value`. - let anyNil: Any? = nil - if container.decodeNil(), - let val = anyNil as? RawValue { - attribute = .init(value: val) - } else { - attribute = try container.decode(TransformedAttribute>.self) - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - - try container.encode(attribute) - } + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + + // A little trickery follows. If the value is nil, the + // container.decode(Value.self) will fail even if Value + // is Optional. However, we can check if decoding nil + // succeeds and then attempt to coerce nil to a Value + // type at which point we can store nil in `value`. + let anyNil: Any? = nil + if container.decodeNil(), + let val = anyNil as? RawValue { + attribute = .init(value: val) + } else { + attribute = try container.decode(TransformedAttribute>.self) + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + + try container.encode(attribute) + } } // MARK: Attribute decoding and encoding defaults extension AttributeType { - public static func defaultDecoding(from container: Container, forKey key: Container.Key) throws -> Self { - return try container.decode(Self.self, forKey: key) - } + public static func defaultDecoding(from container: Container, + forKey key: Container.Key) throws -> Self { + return try container.decode(Self.self, forKey: key) + } } diff --git a/Sources/JSONAPI/Resource/Id.swift b/Sources/JSONAPI/Resource/Id.swift index a375c08..d66e3d9 100644 --- a/Sources/JSONAPI/Resource/Id.swift +++ b/Sources/JSONAPI/Resource/Id.swift @@ -23,7 +23,7 @@ public protocol RawIdType: MaybeRawId, Hashable {} /// Conformances for `String` and `UUID` /// are given in the README for this library. public protocol CreatableRawIdType: RawIdType { - static func unique() -> Self + static func unique() -> Self } extension String: RawIdType {} @@ -32,80 +32,80 @@ extension String: RawIdType {} /// have an Id (most likely because it was created by a client and the server will be responsible /// for assigning it an Id). public struct Unidentified: MaybeRawId, CustomStringConvertible { - public init() {} - - public var description: String { return "Unidentified" } + public init() {} + + public var description: String { return "Unidentified" } } public protocol OptionalId: Codable { - associatedtype IdentifiableType: JSONAPI.JSONTyped - associatedtype RawType: MaybeRawId + associatedtype IdentifiableType: JSONAPI.JSONTyped + associatedtype RawType: MaybeRawId - var rawValue: RawType { get } - init(rawValue: RawType) + var rawValue: RawType { get } + init(rawValue: RawType) } public protocol IdType: OptionalId, CustomStringConvertible, Hashable where RawType: RawIdType {} extension Optional: MaybeRawId where Wrapped: Codable & Equatable {} extension Optional: OptionalId where Wrapped: IdType { - public typealias IdentifiableType = Wrapped.IdentifiableType - public typealias RawType = Wrapped.RawType? - - public var rawValue: Wrapped.RawType? { - guard case .some(let value) = self else { - return nil - } - return value.rawValue - } - - public init(rawValue: Wrapped.RawType?) { - self = rawValue.map { Wrapped(rawValue: $0) } - } + public typealias IdentifiableType = Wrapped.IdentifiableType + public typealias RawType = Wrapped.RawType? + + public var rawValue: Wrapped.RawType? { + guard case .some(let value) = self else { + return nil + } + return value.rawValue + } + + public init(rawValue: Wrapped.RawType?) { + self = rawValue.map { Wrapped(rawValue: $0) } + } } public extension IdType { - var description: String { return "Id(\(String(describing: rawValue)))" } + var description: String { return "Id(\(String(describing: rawValue)))" } } public protocol CreatableIdType: IdType { - init() + init() } /// An ResourceObject ID. These IDs can be encoded to or decoded from /// JSON API IDs. public struct Id: Equatable, OptionalId { - public let rawValue: RawType - - public init(rawValue: RawType) { - self.rawValue = rawValue - } - - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let rawValue = try container.decode(RawType.self) - self.init(rawValue: rawValue) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encode(rawValue) - } + public let rawValue: RawType + + public init(rawValue: RawType) { + self.rawValue = rawValue + } + + public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + let rawValue = try container.decode(RawType.self) + self.init(rawValue: rawValue) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encode(rawValue) + } } extension Id: Hashable, CustomStringConvertible, IdType where RawType: RawIdType { - public static func id(from rawValue: RawType) -> Id { - return Id(rawValue: rawValue) - } + public static func id(from rawValue: RawType) -> Id { + return Id(rawValue: rawValue) + } } extension Id: CreatableIdType where RawType: CreatableRawIdType { - public init() { - rawValue = .unique() - } + public init() { + rawValue = .unique() + } } extension Id where RawType == Unidentified { - public static var unidentified: Id { return .init(rawValue: Unidentified()) } + public static var unidentified: Id { return .init(rawValue: Unidentified()) } } diff --git a/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift b/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift index 284e10a..3ee23a1 100644 --- a/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift +++ b/Sources/JSONAPI/Resource/Poly+PrimaryResource.swift @@ -21,66 +21,144 @@ public typealias EncodablePolyWrapped = Encodable & Equatable public typealias PolyWrapped = EncodablePolyWrapped & Decodable extension Poly0: PrimaryResource { - public init(from decoder: Decoder) throws { - throw JSONAPIEncodingError.illegalDecoding("Attempted to decode Poly0, which should represent a thing that is not expected to be found in a document.") - } + public init(from decoder: Decoder) throws { + throw JSONAPIEncodingError.illegalDecoding("Attempted to decode Poly0, which should represent a thing that is not expected to be found in a document.") + } - public func encode(to encoder: Encoder) throws { - throw JSONAPIEncodingError.illegalEncoding("Attempted to encode Poly0, which should represent a thing that is not expected to be found in a document.") - } + public func encode(to encoder: Encoder) throws { + throw JSONAPIEncodingError.illegalEncoding("Attempted to encode Poly0, which should represent a thing that is not expected to be found in a document.") + } } // MARK: - 1 type -extension Poly1: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped {} +extension Poly1: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped {} -extension Poly1: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped {} +extension Poly1: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped {} // MARK: - 2 types -extension Poly2: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped {} +extension Poly2: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped, B: EncodablePolyWrapped {} -extension Poly2: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped {} +extension Poly2: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped {} // MARK: - 3 types -extension Poly3: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped {} +extension Poly3: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped {} -extension Poly3: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {} +extension Poly3: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {} // MARK: - 4 types -extension Poly4: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped {} +extension Poly4: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped {} -extension Poly4: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {} +extension Poly4: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {} // MARK: - 5 types -extension Poly5: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped {} +extension Poly5: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped {} -extension Poly5: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {} +extension Poly5: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {} // MARK: - 6 types -extension Poly6: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped {} +extension Poly6: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped {} -extension Poly6: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {} +extension Poly6: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {} // MARK: - 7 types -extension Poly7: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped {} - -extension Poly7: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {} +extension Poly7: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where + A: EncodablePolyWrapped, + B: EncodablePolyWrapped, + C: EncodablePolyWrapped, + D: EncodablePolyWrapped, + E: EncodablePolyWrapped, + F: EncodablePolyWrapped, + G: EncodablePolyWrapped {} + +extension Poly7: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {} // MARK: - 8 types -extension Poly8: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped {} - -extension Poly8: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {} +extension Poly8: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where + A: EncodablePolyWrapped, + B: EncodablePolyWrapped, + C: EncodablePolyWrapped, + D: EncodablePolyWrapped, + E: EncodablePolyWrapped, + F: EncodablePolyWrapped, + G: EncodablePolyWrapped, + H: EncodablePolyWrapped {} + +extension Poly8: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {} // MARK: - 9 types -extension Poly9: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped {} - -extension Poly9: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {} +extension Poly9: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where + A: EncodablePolyWrapped, + B: EncodablePolyWrapped, + C: EncodablePolyWrapped, + D: EncodablePolyWrapped, + E: EncodablePolyWrapped, + F: EncodablePolyWrapped, + G: EncodablePolyWrapped, + H: EncodablePolyWrapped, + I: EncodablePolyWrapped {} + +extension Poly9: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {} // MARK: - 10 types -extension Poly10: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped, J: EncodablePolyWrapped {} - -extension Poly10: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped {} +extension Poly10: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where + A: EncodablePolyWrapped, + B: EncodablePolyWrapped, + C: EncodablePolyWrapped, + D: EncodablePolyWrapped, + E: EncodablePolyWrapped, + F: EncodablePolyWrapped, + G: EncodablePolyWrapped, + H: EncodablePolyWrapped, + I: EncodablePolyWrapped, + J: EncodablePolyWrapped {} + +extension Poly10: PrimaryResource, OptionalPrimaryResource + where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped {} // MARK: - 11 types -extension Poly11: EncodablePrimaryResource, OptionalEncodablePrimaryResource where A: EncodablePolyWrapped, B: EncodablePolyWrapped, C: EncodablePolyWrapped, D: EncodablePolyWrapped, E: EncodablePolyWrapped, F: EncodablePolyWrapped, G: EncodablePolyWrapped, H: EncodablePolyWrapped, I: EncodablePolyWrapped, J: EncodablePolyWrapped, K: EncodablePolyWrapped {} - -extension Poly11: PrimaryResource, OptionalPrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped, J: PolyWrapped, K: PolyWrapped {} +extension Poly11: EncodablePrimaryResource, OptionalEncodablePrimaryResource + where + A: EncodablePolyWrapped, + B: EncodablePolyWrapped, + C: EncodablePolyWrapped, + D: EncodablePolyWrapped, + E: EncodablePolyWrapped, + F: EncodablePolyWrapped, + G: EncodablePolyWrapped, + H: EncodablePolyWrapped, + I: EncodablePolyWrapped, + J: EncodablePolyWrapped, + K: EncodablePolyWrapped {} + +extension Poly11: PrimaryResource, OptionalPrimaryResource + where + A: PolyWrapped, + B: PolyWrapped, + C: PolyWrapped, + D: PolyWrapped, + E: PolyWrapped, + F: PolyWrapped, + G: PolyWrapped, + H: PolyWrapped, + I: PolyWrapped, + J: PolyWrapped, + K: PolyWrapped {} diff --git a/Sources/JSONAPI/Resource/Relationship.swift b/Sources/JSONAPI/Resource/Relationship.swift index 43f5457..69fabd9 100644 --- a/Sources/JSONAPI/Resource/Relationship.swift +++ b/Sources/JSONAPI/Resource/Relationship.swift @@ -6,11 +6,11 @@ // public protocol RelationshipType { - associatedtype LinksType - associatedtype MetaType + associatedtype LinksType + associatedtype MetaType - var links: LinksType { get } - var meta: MetaType { get } + var links: LinksType { get } + var meta: MetaType { get } } /// An ResourceObject relationship that can be encoded to or decoded from @@ -19,46 +19,46 @@ public protocol RelationshipType { /// A convenient typealias might make your code much more legible: `One` public struct ToOneRelationship: RelationshipType, Equatable { - public let id: Identifiable.Identifier + public let id: Identifiable.Identifier - public let meta: MetaType - public let links: LinksType + public let meta: MetaType + public let links: LinksType - public init(id: Identifiable.Identifier, meta: MetaType, links: LinksType) { - self.id = id - self.meta = meta - self.links = links - } + public init(id: Identifiable.Identifier, meta: MetaType, links: LinksType) { + self.id = id + self.meta = meta + self.links = links + } } extension ToOneRelationship where MetaType == NoMetadata, LinksType == NoLinks { - public init(id: Identifiable.Identifier) { - self.init(id: id, meta: .none, links: .none) - } + public init(id: Identifiable.Identifier) { + self.init(id: id, meta: .none, links: .none) + } } extension ToOneRelationship { - public init(resourceObject: T, meta: MetaType, links: LinksType) where T.Id == Identifiable.Identifier { - self.init(id: resourceObject.id, meta: meta, links: links) - } + public init(resourceObject: T, meta: MetaType, links: LinksType) where T.Id == Identifiable.Identifier { + self.init(id: resourceObject.id, meta: meta, links: links) + } } extension ToOneRelationship where MetaType == NoMetadata, LinksType == NoLinks { - public init(resourceObject: T) where T.Id == Identifiable.Identifier { - self.init(id: resourceObject.id, meta: .none, links: .none) - } + public init(resourceObject: T) where T.Id == Identifiable.Identifier { + self.init(id: resourceObject.id, meta: .none, links: .none) + } } extension ToOneRelationship where Identifiable: OptionalRelatable { - public init(resourceObject: T?, meta: MetaType, links: LinksType) where T.Id == Identifiable.Wrapped.Identifier { - self.init(id: resourceObject?.id, meta: meta, links: links) - } + public init(resourceObject: T?, meta: MetaType, links: LinksType) where T.Id == Identifiable.Wrapped.Identifier { + self.init(id: resourceObject?.id, meta: meta, links: links) + } } extension ToOneRelationship where Identifiable: OptionalRelatable, MetaType == NoMetadata, LinksType == NoLinks { - public init(resourceObject: T?) where T.Id == Identifiable.Wrapped.Identifier { - self.init(id: resourceObject?.id, meta: .none, links: .none) - } + public init(resourceObject: T?) where T.Id == Identifiable.Wrapped.Identifier { + self.init(id: resourceObject?.id, meta: .none, links: .none) + } } /// An ResourceObject relationship that can be encoded to or decoded from @@ -67,57 +67,57 @@ extension ToOneRelationship where Identifiable: OptionalRelatable, MetaType == N /// A convenient typealias might make your code much more legible: `Many` public struct ToManyRelationship: RelationshipType, Equatable { - public let ids: [Relatable.Identifier] + public let ids: [Relatable.Identifier] - public let meta: MetaType - public let links: LinksType + public let meta: MetaType + public let links: LinksType - public init(ids: [Relatable.Identifier], meta: MetaType, links: LinksType) { - self.ids = ids - self.meta = meta - self.links = links - } + public init(ids: [Relatable.Identifier], meta: MetaType, links: LinksType) { + self.ids = ids + self.meta = meta + self.links = links + } - public init(pointers: [ToOneRelationship], meta: MetaType, links: LinksType) where T.Identifier == Relatable.Identifier { - ids = pointers.map { $0.id } - self.meta = meta - self.links = links - } + public init(pointers: [ToOneRelationship], meta: MetaType, links: LinksType) where T.Identifier == Relatable.Identifier { + ids = pointers.map { $0.id } + self.meta = meta + self.links = links + } - public init(resourceObjects: [T], meta: MetaType, links: LinksType) where T.Id == Relatable.Identifier { - self.init(ids: resourceObjects.map { $0.id }, meta: meta, links: links) - } + public init(resourceObjects: [T], meta: MetaType, links: LinksType) where T.Id == Relatable.Identifier { + self.init(ids: resourceObjects.map { $0.id }, meta: meta, links: links) + } - private init(meta: MetaType, links: LinksType) { - self.init(ids: [], meta: meta, links: links) - } + private init(meta: MetaType, links: LinksType) { + self.init(ids: [], meta: meta, links: links) + } - public static func none(withMeta meta: MetaType, links: LinksType) -> ToManyRelationship { - return ToManyRelationship(meta: meta, links: links) - } + public static func none(withMeta meta: MetaType, links: LinksType) -> ToManyRelationship { + return ToManyRelationship(meta: meta, links: links) + } } extension ToManyRelationship where MetaType == NoMetadata, LinksType == NoLinks { - public init(ids: [Relatable.Identifier]) { - self.init(ids: ids, meta: .none, links: .none) - } + public init(ids: [Relatable.Identifier]) { + self.init(ids: ids, meta: .none, links: .none) + } - public init(pointers: [ToOneRelationship]) where T.Identifier == Relatable.Identifier { - self.init(pointers: pointers, meta: .none, links: .none) - } + public init(pointers: [ToOneRelationship]) where T.Identifier == Relatable.Identifier { + self.init(pointers: pointers, meta: .none, links: .none) + } - public static var none: ToManyRelationship { - return .none(withMeta: .none, links: .none) - } + public static var none: ToManyRelationship { + return .none(withMeta: .none, links: .none) + } - public init(resourceObjects: [T]) where T.Id == Relatable.Identifier { - self.init(resourceObjects: resourceObjects, meta: .none, links: .none) - } + public init(resourceObjects: [T]) where T.Id == Relatable.Identifier { + self.init(resourceObjects: resourceObjects, meta: .none, links: .none) + } } public protocol Identifiable: JSONTyped { - associatedtype Identifier: Equatable + associatedtype Identifier: Equatable } /// The Relatable protocol describes anything that @@ -128,152 +128,152 @@ public protocol Relatable: Identifiable where Identifier: JSONAPI.IdType { /// OptionalRelatable just describes an Optional /// with a Reltable Wrapped type. public protocol OptionalRelatable: Identifiable where Identifier == Wrapped.Identifier? { - associatedtype Wrapped: JSONAPI.Relatable + associatedtype Wrapped: JSONAPI.Relatable } extension Optional: Identifiable, OptionalRelatable, JSONTyped where Wrapped: JSONAPI.Relatable { - public typealias Identifier = Wrapped.Identifier? + public typealias Identifier = Wrapped.Identifier? - public static var jsonType: String { return Wrapped.jsonType } + public static var jsonType: String { return Wrapped.jsonType } } // MARK: Codable private enum ResourceLinkageCodingKeys: String, CodingKey { - case data = "data" - case meta = "meta" - case links = "links" + case data = "data" + case meta = "meta" + case links = "links" } private enum ResourceIdentifierCodingKeys: String, CodingKey { - case id = "id" - case entityType = "type" + case id = "id" + case entityType = "type" } extension ToOneRelationship: Codable where Identifiable.Identifier: OptionalId { - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self) - - if let noMeta = NoMetadata() as? MetaType { - meta = noMeta - } else { - meta = try container.decode(MetaType.self, forKey: .meta) - } - - if let noLinks = NoLinks() as? LinksType { - links = noLinks - } else { - links = try container.decode(LinksType.self, forKey: .links) - } - - // A little trickery follows. If the id is nil, the - // container.decode(Identifier.self) will fail even if Identifier - // is Optional. However, we can check if decoding nil - // succeeds and then attempt to coerce nil to a Identifier - // type at which point we can store nil in `id`. - let anyNil: Any? = nil - if try container.decodeNil(forKey: .data), - let val = anyNil as? Identifiable.Identifier { - id = val - return - } - - let identifier = try container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data) - - let type = try identifier.decode(String.self, forKey: .entityType) - - guard type == Identifiable.jsonType else { - throw JSONAPIEncodingError.typeMismatch(expected: Identifiable.jsonType, found: type) - } - - id = Identifiable.Identifier(rawValue: try identifier.decode(Identifiable.Identifier.RawType.self, forKey: .id)) - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: ResourceLinkageCodingKeys.self) - - if MetaType.self != NoMetadata.self { - try container.encode(meta, forKey: .meta) - } - - if LinksType.self != NoLinks.self { - try container.encode(links, forKey: .links) - } - - // If id is nil, instead of {id: , type: } we will just - // encode `null` - let anyNil: Any? = nil - let nilId = anyNil as? Identifiable.Identifier - guard id != nilId else { - try container.encodeNil(forKey: .data) - return - } - - var identifier = container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data) - - try identifier.encode(id.rawValue, forKey: .id) - try identifier.encode(Identifiable.jsonType, forKey: .entityType) - } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self) + + if let noMeta = NoMetadata() as? MetaType { + meta = noMeta + } else { + meta = try container.decode(MetaType.self, forKey: .meta) + } + + if let noLinks = NoLinks() as? LinksType { + links = noLinks + } else { + links = try container.decode(LinksType.self, forKey: .links) + } + + // A little trickery follows. If the id is nil, the + // container.decode(Identifier.self) will fail even if Identifier + // is Optional. However, we can check if decoding nil + // succeeds and then attempt to coerce nil to a Identifier + // type at which point we can store nil in `id`. + let anyNil: Any? = nil + if try container.decodeNil(forKey: .data), + let val = anyNil as? Identifiable.Identifier { + id = val + return + } + + let identifier = try container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data) + + let type = try identifier.decode(String.self, forKey: .entityType) + + guard type == Identifiable.jsonType else { + throw JSONAPIEncodingError.typeMismatch(expected: Identifiable.jsonType, found: type) + } + + id = Identifiable.Identifier(rawValue: try identifier.decode(Identifiable.Identifier.RawType.self, forKey: .id)) + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: ResourceLinkageCodingKeys.self) + + if MetaType.self != NoMetadata.self { + try container.encode(meta, forKey: .meta) + } + + if LinksType.self != NoLinks.self { + try container.encode(links, forKey: .links) + } + + // If id is nil, instead of {id: , type: } we will just + // encode `null` + let anyNil: Any? = nil + let nilId = anyNil as? Identifiable.Identifier + guard id != nilId else { + try container.encodeNil(forKey: .data) + return + } + + var identifier = container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data) + + try identifier.encode(id.rawValue, forKey: .id) + try identifier.encode(Identifiable.jsonType, forKey: .entityType) + } } extension ToManyRelationship: Codable { - public init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self) - - if let noMeta = NoMetadata() as? MetaType { - meta = noMeta - } else { - meta = try container.decode(MetaType.self, forKey: .meta) - } - - if let noLinks = NoLinks() as? LinksType { - links = noLinks - } else { - links = try container.decode(LinksType.self, forKey: .links) - } - - var identifiers = try container.nestedUnkeyedContainer(forKey: .data) - - var newIds = [Relatable.Identifier]() - while !identifiers.isAtEnd { - let identifier = try identifiers.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self) - - let type = try identifier.decode(String.self, forKey: .entityType) - - guard type == Relatable.jsonType else { - throw JSONAPIEncodingError.typeMismatch(expected: Relatable.jsonType, found: type) - } - - newIds.append(Relatable.Identifier(rawValue: try identifier.decode(Relatable.Identifier.RawType.self, forKey: .id))) - } - ids = newIds - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.container(keyedBy: ResourceLinkageCodingKeys.self) - - if MetaType.self != NoMetadata.self { - try container.encode(meta, forKey: .meta) - } - - if LinksType.self != NoLinks.self { - try container.encode(links, forKey: .links) - } - - var identifiers = container.nestedUnkeyedContainer(forKey: .data) - - for id in ids { - var identifier = identifiers.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self) - - try identifier.encode(id.rawValue, forKey: .id) - try identifier.encode(Relatable.jsonType, forKey: .entityType) - } - } + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: ResourceLinkageCodingKeys.self) + + if let noMeta = NoMetadata() as? MetaType { + meta = noMeta + } else { + meta = try container.decode(MetaType.self, forKey: .meta) + } + + if let noLinks = NoLinks() as? LinksType { + links = noLinks + } else { + links = try container.decode(LinksType.self, forKey: .links) + } + + var identifiers = try container.nestedUnkeyedContainer(forKey: .data) + + var newIds = [Relatable.Identifier]() + while !identifiers.isAtEnd { + let identifier = try identifiers.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self) + + let type = try identifier.decode(String.self, forKey: .entityType) + + guard type == Relatable.jsonType else { + throw JSONAPIEncodingError.typeMismatch(expected: Relatable.jsonType, found: type) + } + + newIds.append(Relatable.Identifier(rawValue: try identifier.decode(Relatable.Identifier.RawType.self, forKey: .id))) + } + ids = newIds + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: ResourceLinkageCodingKeys.self) + + if MetaType.self != NoMetadata.self { + try container.encode(meta, forKey: .meta) + } + + if LinksType.self != NoLinks.self { + try container.encode(links, forKey: .links) + } + + var identifiers = container.nestedUnkeyedContainer(forKey: .data) + + for id in ids { + var identifier = identifiers.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self) + + try identifier.encode(id.rawValue, forKey: .id) + try identifier.encode(Relatable.jsonType, forKey: .entityType) + } + } } // MARK: CustomStringDescribable extension ToOneRelationship: CustomStringConvertible { - public var description: String { return "Relationship(\(String(describing: id)))" } + public var description: String { return "Relationship(\(String(describing: id)))" } } extension ToManyRelationship: CustomStringConvertible { - public var description: String { return "Relationship([\(ids.map(String.init(describing:)).joined(separator: ", "))])" } + public var description: String { return "Relationship([\(ids.map(String.init(describing:)).joined(separator: ", "))])" } } diff --git a/Sources/JSONAPI/Resource/Resource Object/ResourceObject.swift b/Sources/JSONAPI/Resource/Resource Object/ResourceObject.swift index a62d271..b242778 100644 --- a/Sources/JSONAPI/Resource/Resource Object/ResourceObject.swift +++ b/Sources/JSONAPI/Resource/Resource Object/ResourceObject.swift @@ -28,34 +28,34 @@ public protocol SparsableAttributes: Attributes { /// Can be used as `Relationships` Type for Entities that do not /// have any Relationships. public struct NoRelationships: Relationships { - public static var none: NoRelationships { return .init() } + public static var none: NoRelationships { return .init() } } extension NoRelationships: CustomStringConvertible { - public var description: String { return "No Relationships" } + public var description: String { return "No Relationships" } } /// Can be used as `Attributes` Type for Entities that do not /// have any Attributes. public struct NoAttributes: Attributes { - public static var none: NoAttributes { return .init() } + public static var none: NoAttributes { return .init() } } extension NoAttributes: CustomStringConvertible { - public var description: String { return "No Attributes" } + public var description: String { return "No Attributes" } } /// Something that is JSONTyped provides a String representation /// of its type. public protocol JSONTyped { - static var jsonType: String { get } + static var jsonType: String { get } } /// A `ResourceObjectProxyDescription` is an `ResourceObjectDescription` /// without Codable conformance. public protocol ResourceObjectProxyDescription: JSONTyped { - associatedtype Attributes: Equatable - associatedtype Relationships: Equatable + associatedtype Attributes: Equatable + associatedtype Relationships: Equatable } /// A `ResourceObjectDescription` describes a JSON API @@ -70,38 +70,38 @@ public protocol ResourceObjectDescription: ResourceObjectProxyDescription where /// or decoded as ResourceObjects. @dynamicMemberLookup public protocol ResourceObjectProxy: Equatable, JSONTyped { - associatedtype Description: ResourceObjectProxyDescription - associatedtype EntityRawIdType: JSONAPI.MaybeRawId + associatedtype Description: ResourceObjectProxyDescription + associatedtype EntityRawIdType: JSONAPI.MaybeRawId - typealias Id = JSONAPI.Id + typealias Id = JSONAPI.Id - typealias Attributes = Description.Attributes - typealias Relationships = Description.Relationships + typealias Attributes = Description.Attributes + typealias Relationships = Description.Relationships - /// The `Entity`'s Id. This can be of type `Unidentified` if - /// the entity is being created clientside and the - /// server is being asked to create a unique Id. Otherwise, - /// this should be of a type conforming to `IdType`. - var id: Id { get } + /// The `Entity`'s Id. This can be of type `Unidentified` if + /// the entity is being created clientside and the + /// server is being asked to create a unique Id. Otherwise, + /// this should be of a type conforming to `IdType`. + var id: Id { get } - /// The JSON API compliant attributes of this `Entity`. - var attributes: Attributes { get } + /// The JSON API compliant attributes of this `Entity`. + var attributes: Attributes { get } - /// The JSON API compliant relationships of this `Entity`. - var relationships: Relationships { get } + /// The JSON API compliant relationships of this `Entity`. + var relationships: Relationships { get } } extension ResourceObjectProxy { - /// The JSON API compliant "type" of this `ResourceObject`. - public static var jsonType: String { return Description.jsonType } + /// The JSON API compliant "type" of this `ResourceObject`. + public static var jsonType: String { return Description.jsonType } } /// ResourceObjectType is the protocol that ResourceObject conforms to. This /// protocol lets other types accept any ResourceObject as a generic /// specialization. public protocol ResourceObjectType: ResourceObjectProxy, PrimaryResource where Description: ResourceObjectDescription { - associatedtype Meta: JSONAPI.Meta - associatedtype Links: JSONAPI.Links + associatedtype Meta: JSONAPI.Meta + associatedtype Links: JSONAPI.Links } public protocol IdentifiableResourceObjectType: ResourceObjectType, Relatable where EntityRawIdType: JSONAPI.RawIdType {} @@ -112,369 +112,369 @@ public protocol IdentifiableResourceObjectType: ResourceObjectType, Relatable wh /// See https://jsonapi.org/format/#document-resource-objects public struct ResourceObject: ResourceObjectType { - public typealias Meta = MetaType - public typealias Links = LinksType - - /// The `ResourceObject`'s Id. This can be of type `Unidentified` if - /// the entity is being created clientside and the - /// server is being asked to create a unique Id. Otherwise, - /// this should be of a type conforming to `IdType`. - public let id: ResourceObject.Id - - /// The JSON API compliant attributes of this `ResourceObject`. - public let attributes: Description.Attributes - - /// The JSON API compliant relationships of this `ResourceObject`. - public let relationships: Description.Relationships - - /// Any additional metadata packaged with the entity. - public let meta: MetaType - - /// Links related to the entity. - public let links: LinksType - - public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.id = id - self.attributes = attributes - self.relationships = relationships - self.meta = meta - self.links = links - } -} - -extension ResourceObject: Identifiable, IdentifiableResourceObjectType, Relatable where EntityRawIdType: JSONAPI.RawIdType { - public typealias Identifier = ResourceObject.Id -} - -extension ResourceObject: CustomStringConvertible { - public var description: String { - return "ResourceObject<\(ResourceObject.jsonType)>(id: \(String(describing: id)), attributes: \(String(describing: attributes)), relationships: \(String(describing: relationships)))" - } -} - -// MARK: - Convenience initializers -extension ResourceObject where EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.id = ResourceObject.Id() - self.attributes = attributes - self.relationships = relationships - self.meta = meta - self.links = links - } -} - -extension ResourceObject where EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.id = .unidentified - self.attributes = attributes - self.relationships = relationships - self.meta = meta - self.links = links - } -} - -/* -extension ResourceObject where Description.Attributes == NoAttributes { - public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.init(id: id, attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata { - public init(id: ResourceObject.Id, relationships: Description.Relationships, links: LinksType) { - self.init(id: id, relationships: relationships, meta: .none, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks { - public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType) { - self.init(id: id, relationships: relationships, meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks { - public init(id: ResourceObject.Id, relationships: Description.Relationships) { - self.init(id: id, relationships: relationships, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType: CreatableRawIdType { - public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { - public init(relationships: Description.Relationships, links: LinksType) { - self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: links) - } -} + public typealias Meta = MetaType + public typealias Links = LinksType -extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(relationships: Description.Relationships, meta: MetaType) { - self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: .none) - } -} + /// The `ResourceObject`'s Id. This can be of type `Unidentified` if + /// the entity is being created clientside and the + /// server is being asked to create a unique Id. Otherwise, + /// this should be of a type conforming to `IdType`. + public let id: ResourceObject.Id -extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(relationships: Description.Relationships) { - self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: .none) - } -} + /// The JSON API compliant attributes of this `ResourceObject`. + public let attributes: Description.Attributes -extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType == Unidentified { - public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) { - self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) - } -} + /// The JSON API compliant relationships of this `ResourceObject`. + public let relationships: Description.Relationships -extension ResourceObject where Description.Relationships == NoRelationships { - public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType, links: LinksType) { - self.init(id: id, attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) - } -} + /// Any additional metadata packaged with the entity. + public let meta: MetaType -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata { - public init(id: ResourceObject.Id, attributes: Description.Attributes, links: LinksType) { - self.init(id: id, attributes: attributes, meta: .none, links: links) - } -} + /// Links related to the entity. + public let links: LinksType -extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks { - public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType) { - self.init(id: id, attributes: attributes, meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks { - public init(id: ResourceObject.Id, attributes: Description.Attributes) { - self.init(id: id, attributes: attributes, meta: .none, links: .none) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, links: LinksType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, meta: MetaType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, links: LinksType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, meta: MetaType) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes) { - self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships { - public init(id: ResourceObject.Id, meta: MetaType, links: LinksType) { - self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata { - public init(id: ResourceObject.Id, links: LinksType) { - self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks { - public init(id: ResourceObject.Id, meta: MetaType) { - self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks { - public init(id: ResourceObject.Id) { - self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { - public init(meta: MetaType, links: LinksType) { - self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { - public init(links: LinksType) { - self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(meta: MetaType) { - self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none) - } -} - -extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init() { - self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none) - } -} - -extension ResourceObject where MetaType == NoMetadata { - public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { - self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: links) - } -} - -extension ResourceObject where MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { - self.init(attributes: attributes, relationships: relationships, meta: .none, links: links) - } -} - -extension ResourceObject where MetaType == NoMetadata, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { - self.init(attributes: attributes, relationships: relationships, meta: .none, links: links) - } -} - -extension ResourceObject where LinksType == NoLinks { - public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { - self.init(id: id, attributes: attributes, relationships: relationships, meta: meta, links: .none) - } + public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.id = id + self.attributes = attributes + self.relationships = relationships + self.meta = meta + self.links = links + } } -extension ResourceObject where LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { - self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none) - } +extension ResourceObject: Identifiable, IdentifiableResourceObjectType, Relatable where EntityRawIdType: JSONAPI.RawIdType { + public typealias Identifier = ResourceObject.Id } -extension ResourceObject where LinksType == NoLinks, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { - self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none) - } +extension ResourceObject: CustomStringConvertible { + public var description: String { + return "ResourceObject<\(ResourceObject.jsonType)>(id: \(String(describing: id)), attributes: \(String(describing: attributes)), relationships: \(String(describing: relationships)))" + } } -extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks { - public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships) { - self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: .none) - } +// MARK: - Convenience initializers +extension ResourceObject where EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.id = ResourceObject.Id() + self.attributes = attributes + self.relationships = relationships + self.meta = meta + self.links = links + } } -extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { - public init(attributes: Description.Attributes, relationships: Description.Relationships) { - self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none) - } +extension ResourceObject where EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.id = .unidentified + self.attributes = attributes + self.relationships = relationships + self.meta = meta + self.links = links + } } -extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified { - public init(attributes: Description.Attributes, relationships: Description.Relationships) { - self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none) - } -} -*/ +/* + extension ResourceObject where Description.Attributes == NoAttributes { + public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.init(id: id, attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata { + public init(id: ResourceObject.Id, relationships: Description.Relationships, links: LinksType) { + self.init(id: id, relationships: relationships, meta: .none, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks { + public init(id: ResourceObject.Id, relationships: Description.Relationships, meta: MetaType) { + self.init(id: id, relationships: relationships, meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks { + public init(id: ResourceObject.Id, relationships: Description.Relationships) { + self.init(id: id, relationships: relationships, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType: CreatableRawIdType { + public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { + public init(relationships: Description.Relationships, links: LinksType) { + self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(relationships: Description.Relationships, meta: MetaType) { + self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(relationships: Description.Relationships) { + self.init(attributes: NoAttributes(), relationships: relationships, meta: .none, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, EntityRawIdType == Unidentified { + public init(relationships: Description.Relationships, meta: MetaType, links: LinksType) { + self.init(attributes: NoAttributes(), relationships: relationships, meta: meta, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships { + public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType, links: LinksType) { + self.init(id: id, attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata { + public init(id: ResourceObject.Id, attributes: Description.Attributes, links: LinksType) { + self.init(id: id, attributes: attributes, meta: .none, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks { + public init(id: ResourceObject.Id, attributes: Description.Attributes, meta: MetaType) { + self.init(id: id, attributes: attributes, meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks { + public init(id: ResourceObject.Id, attributes: Description.Attributes) { + self.init(id: id, attributes: attributes, meta: .none, links: .none) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, links: LinksType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, meta: MetaType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, meta: MetaType, links: LinksType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, links: LinksType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: links) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, meta: MetaType) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes) { + self.init(attributes: attributes, relationships: NoRelationships(), meta: .none, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships { + public init(id: ResourceObject.Id, meta: MetaType, links: LinksType) { + self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata { + public init(id: ResourceObject.Id, links: LinksType) { + self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks { + public init(id: ResourceObject.Id, meta: MetaType) { + self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks { + public init(id: ResourceObject.Id) { + self.init(id: id, attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, EntityRawIdType: CreatableRawIdType { + public init(meta: MetaType, links: LinksType) { + self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { + public init(links: LinksType) { + self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: links) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(meta: MetaType) { + self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: meta, links: .none) + } + } + + extension ResourceObject where Description.Attributes == NoAttributes, Description.Relationships == NoRelationships, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init() { + self.init(attributes: NoAttributes(), relationships: NoRelationships(), meta: .none, links: .none) + } + } + + extension ResourceObject where MetaType == NoMetadata { + public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { + self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: links) + } + } + + extension ResourceObject where MetaType == NoMetadata, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { + self.init(attributes: attributes, relationships: relationships, meta: .none, links: links) + } + } + + extension ResourceObject where MetaType == NoMetadata, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, relationships: Description.Relationships, links: LinksType) { + self.init(attributes: attributes, relationships: relationships, meta: .none, links: links) + } + } + + extension ResourceObject where LinksType == NoLinks { + public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { + self.init(id: id, attributes: attributes, relationships: relationships, meta: meta, links: .none) + } + } + + extension ResourceObject where LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { + self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none) + } + } + + extension ResourceObject where LinksType == NoLinks, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, relationships: Description.Relationships, meta: MetaType) { + self.init(attributes: attributes, relationships: relationships, meta: meta, links: .none) + } + } + + extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks { + public init(id: ResourceObject.Id, attributes: Description.Attributes, relationships: Description.Relationships) { + self.init(id: id, attributes: attributes, relationships: relationships, meta: .none, links: .none) + } + } + + extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType: CreatableRawIdType { + public init(attributes: Description.Attributes, relationships: Description.Relationships) { + self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none) + } + } + + extension ResourceObject where MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == Unidentified { + public init(attributes: Description.Attributes, relationships: Description.Relationships) { + self.init(attributes: attributes, relationships: relationships, meta: .none, links: .none) + } + } + */ // MARK: - Pointer for Relationships use public extension ResourceObject where EntityRawIdType: JSONAPI.RawIdType { - /// A `ResourceObject.Pointer` is a `ToOneRelationship` with no metadata or links. - /// This is just a convenient way to reference a `ResourceObject` so that - /// other ResourceObjects' Relationships can be built up from it. - typealias Pointer = ToOneRelationship + /// A `ResourceObject.Pointer` is a `ToOneRelationship` with no metadata or links. + /// This is just a convenient way to reference a `ResourceObject` so that + /// other ResourceObjects' Relationships can be built up from it. + typealias Pointer = ToOneRelationship - /// `ResourceObject.Pointers` is a `ToManyRelationship` with no metadata or links. - /// This is just a convenient way to reference a bunch of ResourceObjects so - /// that other ResourceObjects' Relationships can be built up from them. - typealias Pointers = ToManyRelationship + /// `ResourceObject.Pointers` is a `ToManyRelationship` with no metadata or links. + /// This is just a convenient way to reference a bunch of ResourceObjects so + /// that other ResourceObjects' Relationships can be built up from them. + typealias Pointers = ToManyRelationship - /// Get a pointer to this resource object that can be used as a - /// relationship to another resource object. - var pointer: Pointer { - return Pointer(resourceObject: self) - } + /// Get a pointer to this resource object that can be used as a + /// relationship to another resource object. + var pointer: Pointer { + return Pointer(resourceObject: self) + } /// Get a pointer (i.e. `ToOneRelationship`) to this resource /// object with the given metadata and links attached. - func pointer(withMeta meta: MType, links: LType) -> ToOneRelationship { - return ToOneRelationship(resourceObject: self, meta: meta, links: links) - } + func pointer(withMeta meta: MType, links: LType) -> ToOneRelationship { + return ToOneRelationship(resourceObject: self, meta: meta, links: links) + } } // MARK: - Identifying Unidentified Entities public extension ResourceObject where EntityRawIdType == Unidentified { - /// Create a new `ResourceObject` from this one with a newly created - /// unique Id of the given type. - func identified(byType: RawIdType.Type) -> ResourceObject { - return .init(attributes: attributes, relationships: relationships, meta: meta, links: links) - } - - /// Create a new `ResourceObject` from this one with the given Id. - func identified(by id: RawIdType) -> ResourceObject { - return .init(id: ResourceObject.Identifier(rawValue: id), attributes: attributes, relationships: relationships, meta: meta, links: links) - } + /// Create a new `ResourceObject` from this one with a newly created + /// unique Id of the given type. + func identified(byType: RawIdType.Type) -> ResourceObject { + return .init(attributes: attributes, relationships: relationships, meta: meta, links: links) + } + + /// Create a new `ResourceObject` from this one with the given Id. + func identified(by id: RawIdType) -> ResourceObject { + return .init(id: ResourceObject.Identifier(rawValue: id), attributes: attributes, relationships: relationships, meta: meta, links: links) + } } public extension ResourceObject where EntityRawIdType: CreatableRawIdType { - /// Create a copy of this `ResourceObject` with a new unique Id. - func withNewIdentifier() -> ResourceObject { - return ResourceObject(attributes: attributes, relationships: relationships, meta: meta, links: links) - } + /// Create a copy of this `ResourceObject` with a new unique Id. + func withNewIdentifier() -> ResourceObject { + return ResourceObject(attributes: attributes, relationships: relationships, meta: meta, links: links) + } } // MARK: - Attribute Access public extension ResourceObjectProxy { // MARK: Keypath Subscript Lookup - /// Access the attribute at the given keypath. This just - /// allows you to write `resourceObject[\.propertyName]` instead - /// of `resourceObject.attributes.propertyName.value`. - subscript(_ path: KeyPath) -> T.ValueType { - return attributes[keyPath: path].value - } - - /// Access the attribute at the given keypath. This just - /// allows you to write `resourceObject[\.propertyName]` instead - /// of `resourceObject.attributes.propertyName.value`. - subscript(_ path: KeyPath) -> T.ValueType? { - return attributes[keyPath: path]?.value - } - - /// Access the attribute at the given keypath. This just - /// allows you to write `resourceObject[\.propertyName]` instead - /// of `resourceObject.attributes.propertyName.value`. - subscript(_ path: KeyPath) -> U? where T.ValueType == U? { - // Implementation Note: Handles Transform that returns optional - // type. - return attributes[keyPath: path].flatMap { $0.value } - } + /// Access the attribute at the given keypath. This just + /// allows you to write `resourceObject[\.propertyName]` instead + /// of `resourceObject.attributes.propertyName.value`. + subscript(_ path: KeyPath) -> T.ValueType { + return attributes[keyPath: path].value + } + + /// Access the attribute at the given keypath. This just + /// allows you to write `resourceObject[\.propertyName]` instead + /// of `resourceObject.attributes.propertyName.value`. + subscript(_ path: KeyPath) -> T.ValueType? { + return attributes[keyPath: path]?.value + } + + /// Access the attribute at the given keypath. This just + /// allows you to write `resourceObject[\.propertyName]` instead + /// of `resourceObject.attributes.propertyName.value`. + subscript(_ path: KeyPath) -> U? where T.ValueType == U? { + // Implementation Note: Handles Transform that returns optional + // type. + return attributes[keyPath: path].flatMap { $0.value } + } // MARK: Dynaminc Member Keypath Lookup /// Access the attribute at the given keypath. This just @@ -499,27 +499,27 @@ public extension ResourceObjectProxy { } // MARK: Direct Keypath Subscript Lookup - /// Access the storage of the attribute at the given keypath. This just + /// Access the storage of the attribute at the given keypath. This just /// allows you to write `resourceObject[direct: \.propertyName]` instead - /// of `resourceObject.attributes.propertyName`. + /// of `resourceObject.attributes.propertyName`. /// Most of the subscripts dig into an `AttributeType`. This subscript /// returns the `AttributeType` (or another type, if you are accessing /// an attribute that is not stored in an `AttributeType`). - subscript(direct path: KeyPath) -> T { - // Implementation Note: Handles attributes that are not - // AttributeType. These should only exist as computed properties. - return attributes[keyPath: path] - } + subscript(direct path: KeyPath) -> T { + // Implementation Note: Handles attributes that are not + // AttributeType. These should only exist as computed properties. + return attributes[keyPath: path] + } } // MARK: - Meta-Attribute Access public extension ResourceObjectProxy { // MARK: Keypath Subscript Lookup - /// Access an attribute requiring a transformation on the RawValue _and_ - /// a secondary transformation on this entity (self). - subscript(_ path: KeyPath T>) -> T { - return attributes[keyPath: path](self) - } + /// Access an attribute requiring a transformation on the RawValue _and_ + /// a secondary transformation on this entity (self). + subscript(_ path: KeyPath T>) -> T { + return attributes[keyPath: path](self) + } // MARK: Dynamic Member Keypath Lookup /// Access an attribute requiring a transformation on the RawValue _and_ @@ -531,61 +531,61 @@ public extension ResourceObjectProxy { // MARK: - Relationship Access public extension ResourceObjectProxy { - /// Access to an Id of a `ToOneRelationship`. - /// This allows you to write `resourceObject ~> \.other` instead - /// of `resourceObject.relationships.other.id`. - static func ~>(entity: Self, path: KeyPath>) -> OtherEntity.Identifier { - return entity.relationships[keyPath: path].id - } - - /// Access to an Id of an optional `ToOneRelationship`. - /// This allows you to write `resourceObject ~> \.other` instead - /// of `resourceObject.relationships.other?.id`. - static func ~>(entity: Self, path: KeyPath?>) -> OtherEntity.Identifier { - // Implementation Note: This signature applies to `ToOneRelationship?` - // whereas the one below applies to `ToOneRelationship?` - return entity.relationships[keyPath: path]?.id - } - - /// Access to an Id of an optional `ToOneRelationship`. - /// This allows you to write `resourceObject ~> \.other` instead - /// of `resourceObject.relationships.other?.id`. - static func ~>(entity: Self, path: KeyPath?>) -> OtherEntity.Identifier? { - // Implementation Note: This signature applies to `ToOneRelationship?` - // whereas the one above applies to `ToOneRelationship?` - return entity.relationships[keyPath: path]?.id - } - - /// Access to all Ids of a `ToManyRelationship`. - /// This allows you to write `resourceObject ~> \.others` instead - /// of `resourceObject.relationships.others.ids`. - static func ~>(entity: Self, path: KeyPath>) -> [OtherEntity.Identifier] { - return entity.relationships[keyPath: path].ids - } - - /// Access to all Ids of an optional `ToManyRelationship`. - /// This allows you to write `resourceObject ~> \.others` instead - /// of `resourceObject.relationships.others?.ids`. - static func ~>(entity: Self, path: KeyPath?>) -> [OtherEntity.Identifier]? { - return entity.relationships[keyPath: path]?.ids - } + /// Access to an Id of a `ToOneRelationship`. + /// This allows you to write `resourceObject ~> \.other` instead + /// of `resourceObject.relationships.other.id`. + static func ~>(entity: Self, path: KeyPath>) -> OtherEntity.Identifier { + return entity.relationships[keyPath: path].id + } + + /// Access to an Id of an optional `ToOneRelationship`. + /// This allows you to write `resourceObject ~> \.other` instead + /// of `resourceObject.relationships.other?.id`. + static func ~>(entity: Self, path: KeyPath?>) -> OtherEntity.Identifier { + // Implementation Note: This signature applies to `ToOneRelationship?` + // whereas the one below applies to `ToOneRelationship?` + return entity.relationships[keyPath: path]?.id + } + + /// Access to an Id of an optional `ToOneRelationship`. + /// This allows you to write `resourceObject ~> \.other` instead + /// of `resourceObject.relationships.other?.id`. + static func ~>(entity: Self, path: KeyPath?>) -> OtherEntity.Identifier? { + // Implementation Note: This signature applies to `ToOneRelationship?` + // whereas the one above applies to `ToOneRelationship?` + return entity.relationships[keyPath: path]?.id + } + + /// Access to all Ids of a `ToManyRelationship`. + /// This allows you to write `resourceObject ~> \.others` instead + /// of `resourceObject.relationships.others.ids`. + static func ~>(entity: Self, path: KeyPath>) -> [OtherEntity.Identifier] { + return entity.relationships[keyPath: path].ids + } + + /// Access to all Ids of an optional `ToManyRelationship`. + /// This allows you to write `resourceObject ~> \.others` instead + /// of `resourceObject.relationships.others?.ids`. + static func ~>(entity: Self, path: KeyPath?>) -> [OtherEntity.Identifier]? { + return entity.relationships[keyPath: path]?.ids + } } // MARK: - Meta-Relationship Access public extension ResourceObjectProxy { - /// Access to an Id of a `ToOneRelationship`. - /// This allows you to write `resourceObject ~> \.other` instead - /// of `resourceObject.relationships.other.id`. - static func ~>(entity: Self, path: KeyPath Identifier>) -> Identifier { - return entity.relationships[keyPath: path](entity) - } - - /// Access to all Ids of a `ToManyRelationship`. - /// This allows you to write `resourceObject ~> \.others` instead - /// of `resourceObject.relationships.others.ids`. - static func ~>(entity: Self, path: KeyPath [Identifier]>) -> [Identifier] { - return entity.relationships[keyPath: path](entity) - } + /// Access to an Id of a `ToOneRelationship`. + /// This allows you to write `resourceObject ~> \.other` instead + /// of `resourceObject.relationships.other.id`. + static func ~>(entity: Self, path: KeyPath Identifier>) -> Identifier { + return entity.relationships[keyPath: path](entity) + } + + /// Access to all Ids of a `ToManyRelationship`. + /// This allows you to write `resourceObject ~> \.others` instead + /// of `resourceObject.relationships.others.ids`. + static func ~>(entity: Self, path: KeyPath [Identifier]>) -> [Identifier] { + return entity.relationships[keyPath: path](entity) + } } infix operator ~> diff --git a/Sources/JSONAPITesting/Attribute+Literal.swift b/Sources/JSONAPITesting/Attribute+Literal.swift index 706b6e4..b631bab 100644 --- a/Sources/JSONAPITesting/Attribute+Literal.swift +++ b/Sources/JSONAPITesting/Attribute+Literal.swift @@ -2,81 +2,81 @@ import JSONAPI extension Attribute: ExpressibleByUnicodeScalarLiteral where RawValue: ExpressibleByUnicodeScalarLiteral { - public typealias UnicodeScalarLiteralType = RawValue.UnicodeScalarLiteralType + public typealias UnicodeScalarLiteralType = RawValue.UnicodeScalarLiteralType - public init(unicodeScalarLiteral value: RawValue.UnicodeScalarLiteralType) { - self.init(value: RawValue(unicodeScalarLiteral: value)) - } + public init(unicodeScalarLiteral value: RawValue.UnicodeScalarLiteralType) { + self.init(value: RawValue(unicodeScalarLiteral: value)) + } } extension Attribute: ExpressibleByExtendedGraphemeClusterLiteral where RawValue: ExpressibleByExtendedGraphemeClusterLiteral { - public typealias ExtendedGraphemeClusterLiteralType = RawValue.ExtendedGraphemeClusterLiteralType + public typealias ExtendedGraphemeClusterLiteralType = RawValue.ExtendedGraphemeClusterLiteralType - public init(extendedGraphemeClusterLiteral value: RawValue.ExtendedGraphemeClusterLiteralType) { - self.init(value: RawValue(extendedGraphemeClusterLiteral: value)) - } + public init(extendedGraphemeClusterLiteral value: RawValue.ExtendedGraphemeClusterLiteralType) { + self.init(value: RawValue(extendedGraphemeClusterLiteral: value)) + } } extension Attribute: ExpressibleByStringLiteral where RawValue: ExpressibleByStringLiteral { - public typealias StringLiteralType = RawValue.StringLiteralType + public typealias StringLiteralType = RawValue.StringLiteralType - public init(stringLiteral value: RawValue.StringLiteralType) { - self.init(value: RawValue(stringLiteral: value)) - } + public init(stringLiteral value: RawValue.StringLiteralType) { + self.init(value: RawValue(stringLiteral: value)) + } } extension Attribute: ExpressibleByNilLiteral where RawValue: ExpressibleByNilLiteral { - public init(nilLiteral: ()) { - self.init(value: RawValue(nilLiteral: ())) - } + public init(nilLiteral: ()) { + self.init(value: RawValue(nilLiteral: ())) + } } extension Attribute: ExpressibleByFloatLiteral where RawValue: ExpressibleByFloatLiteral { - public typealias FloatLiteralType = RawValue.FloatLiteralType + public typealias FloatLiteralType = RawValue.FloatLiteralType - public init(floatLiteral value: RawValue.FloatLiteralType) { - self.init(value: RawValue(floatLiteral: value)) - } + public init(floatLiteral value: RawValue.FloatLiteralType) { + self.init(value: RawValue(floatLiteral: value)) + } } extension Optional: ExpressibleByFloatLiteral where Wrapped: ExpressibleByFloatLiteral { - public typealias FloatLiteralType = Wrapped.FloatLiteralType + public typealias FloatLiteralType = Wrapped.FloatLiteralType - public init(floatLiteral value: FloatLiteralType) { - self = .some(Wrapped(floatLiteral: value)) - } + public init(floatLiteral value: FloatLiteralType) { + self = .some(Wrapped(floatLiteral: value)) + } } extension Attribute: ExpressibleByBooleanLiteral where RawValue: ExpressibleByBooleanLiteral { - public typealias BooleanLiteralType = RawValue.BooleanLiteralType + public typealias BooleanLiteralType = RawValue.BooleanLiteralType - public init(booleanLiteral value: BooleanLiteralType) { - self.init(value: RawValue(booleanLiteral: value)) - } + public init(booleanLiteral value: BooleanLiteralType) { + self.init(value: RawValue(booleanLiteral: value)) + } } extension Optional: ExpressibleByBooleanLiteral where Wrapped: ExpressibleByBooleanLiteral { - public typealias BooleanLiteralType = Wrapped.BooleanLiteralType + public typealias BooleanLiteralType = Wrapped.BooleanLiteralType - public init(booleanLiteral value: BooleanLiteralType) { - self = .some(Wrapped(booleanLiteral: value)) - } + public init(booleanLiteral value: BooleanLiteralType) { + self = .some(Wrapped(booleanLiteral: value)) + } } extension Attribute: ExpressibleByIntegerLiteral where RawValue: ExpressibleByIntegerLiteral { - public typealias IntegerLiteralType = RawValue.IntegerLiteralType + public typealias IntegerLiteralType = RawValue.IntegerLiteralType - public init(integerLiteral value: IntegerLiteralType) { - self.init(value: RawValue(integerLiteral: value)) - } + public init(integerLiteral value: IntegerLiteralType) { + self.init(value: RawValue(integerLiteral: value)) + } } extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByIntegerLiteral { - public typealias IntegerLiteralType = Wrapped.IntegerLiteralType + public typealias IntegerLiteralType = Wrapped.IntegerLiteralType - public init(integerLiteral value: IntegerLiteralType) { - self = .some(Wrapped(integerLiteral: value)) - } + public init(integerLiteral value: IntegerLiteralType) { + self = .some(Wrapped(integerLiteral: value)) + } } // regretably, array and dictionary literals are not so easy because Dictionaries and Arrays @@ -84,55 +84,55 @@ extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByInte // we can still provide a case for the Array and Dictionary types, though. public protocol DictionaryType { - associatedtype Key: Hashable - associatedtype Value + associatedtype Key: Hashable + associatedtype Value - init(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary.Value, Dictionary.Value) throws -> Dictionary.Value) rethrows where S : Sequence, S.Element == (Key, Value) + init(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary.Value, Dictionary.Value) throws -> Dictionary.Value) rethrows where S : Sequence, S.Element == (Key, Value) } extension Dictionary: DictionaryType {} extension Attribute: ExpressibleByDictionaryLiteral where RawValue: DictionaryType { - public typealias Key = RawValue.Key + public typealias Key = RawValue.Key - public typealias Value = RawValue.Value + public typealias Value = RawValue.Value - public init(dictionaryLiteral elements: (RawValue.Key, RawValue.Value)...) { + public init(dictionaryLiteral elements: (RawValue.Key, RawValue.Value)...) { - // we arbitrarily keep the first value if two values are assigned to the same key - self.init(value: RawValue(elements, uniquingKeysWith: { val, _ in val })) - } + // we arbitrarily keep the first value if two values are assigned to the same key + self.init(value: RawValue(elements, uniquingKeysWith: { val, _ in val })) + } } extension Optional: DictionaryType where Wrapped: DictionaryType { - public typealias Key = Wrapped.Key + public typealias Key = Wrapped.Key - public typealias Value = Wrapped.Value + public typealias Value = Wrapped.Value - public init(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary.Value, Dictionary.Value) throws -> Dictionary.Value) rethrows where S : Sequence, S.Element == (Key, Value) { - self = try .some(Wrapped(keysAndValues, uniquingKeysWith: combine)) - } + public init(_ keysAndValues: S, uniquingKeysWith combine: (Dictionary.Value, Dictionary.Value) throws -> Dictionary.Value) rethrows where S : Sequence, S.Element == (Key, Value) { + self = try .some(Wrapped(keysAndValues, uniquingKeysWith: combine)) + } } public protocol ArrayType { - associatedtype Element + associatedtype Element - init(_ s: S) where Element == S.Element, S : Sequence + init(_ s: S) where Element == S.Element, S : Sequence } extension Array: ArrayType {} extension ArraySlice: ArrayType {} extension Attribute: ExpressibleByArrayLiteral where RawValue: ArrayType { - public typealias ArrayLiteralElement = RawValue.Element + public typealias ArrayLiteralElement = RawValue.Element - public init(arrayLiteral elements: ArrayLiteralElement...) { - self.init(value: RawValue(elements)) - } + public init(arrayLiteral elements: ArrayLiteralElement...) { + self.init(value: RawValue(elements)) + } } extension Optional: ArrayType where Wrapped: ArrayType { - public typealias Element = Wrapped.Element + public typealias Element = Wrapped.Element - public init(_ s: S) where Element == S.Element, S : Sequence { - self = .some(Wrapped(s)) - } + public init(_ s: S) where Element == S.Element, S : Sequence { + self = .some(Wrapped(s)) + } } diff --git a/Sources/JSONAPITesting/Id+Literal.swift b/Sources/JSONAPITesting/Id+Literal.swift index b05b8b1..92121f9 100644 --- a/Sources/JSONAPITesting/Id+Literal.swift +++ b/Sources/JSONAPITesting/Id+Literal.swift @@ -8,33 +8,33 @@ import JSONAPI extension Id: ExpressibleByUnicodeScalarLiteral where RawType: ExpressibleByUnicodeScalarLiteral { - public typealias UnicodeScalarLiteralType = RawType.UnicodeScalarLiteralType - - public init(unicodeScalarLiteral value: RawType.UnicodeScalarLiteralType) { - self.init(rawValue: RawType(unicodeScalarLiteral: value)) - } + public typealias UnicodeScalarLiteralType = RawType.UnicodeScalarLiteralType + + public init(unicodeScalarLiteral value: RawType.UnicodeScalarLiteralType) { + self.init(rawValue: RawType(unicodeScalarLiteral: value)) + } } extension Id: ExpressibleByExtendedGraphemeClusterLiteral where RawType: ExpressibleByExtendedGraphemeClusterLiteral { - public typealias ExtendedGraphemeClusterLiteralType = RawType.ExtendedGraphemeClusterLiteralType - - public init(extendedGraphemeClusterLiteral value: RawType.ExtendedGraphemeClusterLiteralType) { - self.init(rawValue: RawType(extendedGraphemeClusterLiteral: value)) - } + public typealias ExtendedGraphemeClusterLiteralType = RawType.ExtendedGraphemeClusterLiteralType + + public init(extendedGraphemeClusterLiteral value: RawType.ExtendedGraphemeClusterLiteralType) { + self.init(rawValue: RawType(extendedGraphemeClusterLiteral: value)) + } } extension Id: ExpressibleByStringLiteral where RawType: ExpressibleByStringLiteral { - public typealias StringLiteralType = RawType.StringLiteralType - - public init(stringLiteral value: RawType.StringLiteralType) { - self.init(rawValue: RawType(stringLiteral: value)) - } + public typealias StringLiteralType = RawType.StringLiteralType + + public init(stringLiteral value: RawType.StringLiteralType) { + self.init(rawValue: RawType(stringLiteral: value)) + } } extension Id: ExpressibleByIntegerLiteral where RawType: ExpressibleByIntegerLiteral { - public typealias IntegerLiteralType = RawType.IntegerLiteralType - - public init(integerLiteral value: IntegerLiteralType) { - self.init(rawValue: RawType(integerLiteral: value)) - } + public typealias IntegerLiteralType = RawType.IntegerLiteralType + + public init(integerLiteral value: IntegerLiteralType) { + self.init(rawValue: RawType(integerLiteral: value)) + } } diff --git a/Sources/JSONAPITesting/Optional+Literal.swift b/Sources/JSONAPITesting/Optional+Literal.swift index e0d81b5..8c87fab 100644 --- a/Sources/JSONAPITesting/Optional+Literal.swift +++ b/Sources/JSONAPITesting/Optional+Literal.swift @@ -6,25 +6,25 @@ // extension Optional: ExpressibleByUnicodeScalarLiteral where Wrapped: ExpressibleByUnicodeScalarLiteral { - public typealias UnicodeScalarLiteralType = Wrapped.UnicodeScalarLiteralType + public typealias UnicodeScalarLiteralType = Wrapped.UnicodeScalarLiteralType - public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { - self = .some(Wrapped(unicodeScalarLiteral: value)) - } + public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { + self = .some(Wrapped(unicodeScalarLiteral: value)) + } } extension Optional: ExpressibleByExtendedGraphemeClusterLiteral where Wrapped: ExpressibleByExtendedGraphemeClusterLiteral { - public typealias ExtendedGraphemeClusterLiteralType = Wrapped.ExtendedGraphemeClusterLiteralType + public typealias ExtendedGraphemeClusterLiteralType = Wrapped.ExtendedGraphemeClusterLiteralType - public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { - self = .some(Wrapped(extendedGraphemeClusterLiteral: value)) - } + public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { + self = .some(Wrapped(extendedGraphemeClusterLiteral: value)) + } } extension Optional: ExpressibleByStringLiteral where Wrapped: ExpressibleByStringLiteral { - public typealias StringLiteralType = Wrapped.StringLiteralType + public typealias StringLiteralType = Wrapped.StringLiteralType - public init(stringLiteral value: StringLiteralType) { - self = .some(Wrapped(stringLiteral: value)) - } + public init(stringLiteral value: StringLiteralType) { + self = .some(Wrapped(stringLiteral: value)) + } } diff --git a/Sources/JSONAPITesting/Relationship+Literal.swift b/Sources/JSONAPITesting/Relationship+Literal.swift index 9af692c..551fd88 100644 --- a/Sources/JSONAPITesting/Relationship+Literal.swift +++ b/Sources/JSONAPITesting/Relationship+Literal.swift @@ -8,40 +8,40 @@ import JSONAPI extension ToOneRelationship: ExpressibleByNilLiteral where Identifiable.Identifier: ExpressibleByNilLiteral, MetaType == NoMetadata, LinksType == NoLinks { - public init(nilLiteral: ()) { + public init(nilLiteral: ()) { - self.init(id: Identifiable.Identifier(nilLiteral: ())) - } + self.init(id: Identifiable.Identifier(nilLiteral: ())) + } } extension ToOneRelationship: ExpressibleByUnicodeScalarLiteral where Identifiable.Identifier: ExpressibleByUnicodeScalarLiteral, MetaType == NoMetadata, LinksType == NoLinks { - public typealias UnicodeScalarLiteralType = Identifiable.Identifier.UnicodeScalarLiteralType + public typealias UnicodeScalarLiteralType = Identifiable.Identifier.UnicodeScalarLiteralType - public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { - self.init(id: Identifiable.Identifier(unicodeScalarLiteral: value)) - } + public init(unicodeScalarLiteral value: UnicodeScalarLiteralType) { + self.init(id: Identifiable.Identifier(unicodeScalarLiteral: value)) + } } extension ToOneRelationship: ExpressibleByExtendedGraphemeClusterLiteral where Identifiable.Identifier: ExpressibleByExtendedGraphemeClusterLiteral, MetaType == NoMetadata, LinksType == NoLinks { - public typealias ExtendedGraphemeClusterLiteralType = Identifiable.Identifier.ExtendedGraphemeClusterLiteralType + public typealias ExtendedGraphemeClusterLiteralType = Identifiable.Identifier.ExtendedGraphemeClusterLiteralType - public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { - self.init(id: Identifiable.Identifier(extendedGraphemeClusterLiteral: value)) - } + public init(extendedGraphemeClusterLiteral value: ExtendedGraphemeClusterLiteralType) { + self.init(id: Identifiable.Identifier(extendedGraphemeClusterLiteral: value)) + } } extension ToOneRelationship: ExpressibleByStringLiteral where Identifiable.Identifier: ExpressibleByStringLiteral, MetaType == NoMetadata, LinksType == NoLinks { - public typealias StringLiteralType = Identifiable.Identifier.StringLiteralType + public typealias StringLiteralType = Identifiable.Identifier.StringLiteralType - public init(stringLiteral value: StringLiteralType) { - self.init(id: Identifiable.Identifier(stringLiteral: value)) - } + public init(stringLiteral value: StringLiteralType) { + self.init(id: Identifiable.Identifier(stringLiteral: value)) + } } extension ToManyRelationship: ExpressibleByArrayLiteral where MetaType == NoMetadata, LinksType == NoLinks { - public typealias ArrayLiteralElement = Relatable.Identifier + public typealias ArrayLiteralElement = Relatable.Identifier - public init(arrayLiteral elements: ArrayLiteralElement...) { - self.init(ids: elements) - } + public init(arrayLiteral elements: ArrayLiteralElement...) { + self.init(ids: elements) + } } diff --git a/Sources/JSONAPITesting/ResourceObjectCheck.swift b/Sources/JSONAPITesting/ResourceObjectCheck.swift index 0749ec8..13c1724 100644 --- a/Sources/JSONAPITesting/ResourceObjectCheck.swift +++ b/Sources/JSONAPITesting/ResourceObjectCheck.swift @@ -8,29 +8,29 @@ import JSONAPI public enum ResourceObjectCheckError: Swift.Error { - /// The attributes should live in a struct, not - /// another type class. - case attributesNotStruct + /// The attributes should live in a struct, not + /// another type class. + case attributesNotStruct - /// The relationships should live in a struct, not - /// another type class. - case relationshipsNotStruct + /// The relationships should live in a struct, not + /// another type class. + case relationshipsNotStruct - /// All stored properties on an Attributes struct should - /// be one of the supplied Attribute types. - case nonAttribute(named: String) + /// All stored properties on an Attributes struct should + /// be one of the supplied Attribute types. + case nonAttribute(named: String) - /// All stored properties on a Relationships struct should - /// be one of the supplied Relationship types. - case nonRelationship(named: String) + /// All stored properties on a Relationships struct should + /// be one of the supplied Relationship types. + case nonRelationship(named: String) - /// It is explicitly stated by the JSON spec - /// a "none" value for arrays is an empty array, not `nil`. - case nullArray(named: String) + /// It is explicitly stated by the JSON spec + /// a "none" value for arrays is an empty array, not `nil`. + case nullArray(named: String) } public struct ResourceObjectCheckErrors: Swift.Error { - let problems: [ResourceObjectCheckError] + let problems: [ResourceObjectCheckError] } private protocol OptionalAttributeType {} @@ -55,40 +55,40 @@ extension TransformedAttribute: _AttributeType {} extension Attribute: _AttributeType {} public extension ResourceObject { - static func check(_ entity: ResourceObject) throws { - var problems = [ResourceObjectCheckError]() - - let attributesMirror = Mirror(reflecting: entity.attributes) - - if attributesMirror.displayStyle != .`struct` { - problems.append(.attributesNotStruct) - } - - for attribute in attributesMirror.children { - if attribute.value as? _AttributeType == nil, - attribute.value as? OptionalAttributeType == nil { - problems.append(.nonAttribute(named: attribute.label ?? "unnamed")) - } - if attribute.value as? AttributeTypeWithOptionalArray != nil { - problems.append(.nullArray(named: attribute.label ?? "unnamed")) - } - } - - let relationshipsMirror = Mirror(reflecting: entity.relationships) - - if relationshipsMirror.displayStyle != .`struct` { - problems.append(.relationshipsNotStruct) - } - - for relationship in relationshipsMirror.children { - if relationship.value as? _RelationshipType == nil, - relationship.value as? OptionalRelationshipType == nil { - problems.append(.nonRelationship(named: relationship.label ?? "unnamed")) - } - } - - guard problems.count == 0 else { - throw ResourceObjectCheckErrors(problems: problems) - } - } + static func check(_ entity: ResourceObject) throws { + var problems = [ResourceObjectCheckError]() + + let attributesMirror = Mirror(reflecting: entity.attributes) + + if attributesMirror.displayStyle != .`struct` { + problems.append(.attributesNotStruct) + } + + for attribute in attributesMirror.children { + if attribute.value as? _AttributeType == nil, + attribute.value as? OptionalAttributeType == nil { + problems.append(.nonAttribute(named: attribute.label ?? "unnamed")) + } + if attribute.value as? AttributeTypeWithOptionalArray != nil { + problems.append(.nullArray(named: attribute.label ?? "unnamed")) + } + } + + let relationshipsMirror = Mirror(reflecting: entity.relationships) + + if relationshipsMirror.displayStyle != .`struct` { + problems.append(.relationshipsNotStruct) + } + + for relationship in relationshipsMirror.children { + if relationship.value as? _RelationshipType == nil, + relationship.value as? OptionalRelationshipType == nil { + problems.append(.nonRelationship(named: relationship.label ?? "unnamed")) + } + } + + guard problems.count == 0 else { + throw ResourceObjectCheckErrors(problems: problems) + } + } }