diff --git a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift index 18e150b..62a8508 100644 --- a/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift +++ b/JSONAPI.playground/Pages/Usage.xcplaygroundpage/Contents.swift @@ -11,7 +11,7 @@ Please enjoy these examples, but allow me the forced casting and the lack of err // MARK: - Create a request or response body with one Dog in it let dogFromCode = try! Dog(name: "Buddy", owner: nil) -typealias SingleDogDocument = JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError> +typealias SingleDogDocument = JSONAPI.Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError> let singleDogDocument = SingleDogDocument(body: SingleResourceBody(entity: dogFromCode)) @@ -27,7 +27,7 @@ let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner let houses = [House(), House()] let people = try! [Person(id: personIds[0], name: ["Gary", "Doe"], favoriteColor: "Orange-Red", friends: [], dogs: [dogs[0], dogs[1]], home: houses[0]), Person(id: personIds[1], name: ["Elise", "Joy"], favoriteColor: "Red", friends: [], dogs: [dogs[2]], home: houses[1])] -typealias BatchPeopleDocument = JSONAPIDocument, NoMetadata, NoLinks, Include2, UnknownJSONAPIError> +typealias BatchPeopleDocument = JSONAPI.Document, NoMetadata, NoLinks, Include2, UnknownJSONAPIError> let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { BatchPeopleDocument.Include($0) } let batchPeopleDocument = BatchPeopleDocument(body: .init(entities: people), includes: .init(values: includes)) diff --git a/Sources/JSONAPI/Document/Document.swift b/Sources/JSONAPI/Document/Document.swift index f1f2d54..95f3a85 100644 --- a/Sources/JSONAPI/Document/Document.swift +++ b/Sources/JSONAPI/Document/Document.swift @@ -5,6 +5,14 @@ // Created by Mathew Polzin on 11/5/18. // +public protocol JSONAPIDocument: Codable, Equatable { + associatedtype ResourceBody: JSONAPI.ResourceBody + associatedtype MetaType: JSONAPI.Meta + associatedtype LinksType: JSONAPI.Links + associatedtype IncludeType: JSONAPI.Include + associatedtype Error: JSONAPIError +} + /// A JSON API Document represents the entire body /// of a JSON API request or the entire body of /// a JSON API response. @@ -12,7 +20,7 @@ /// API uses snake case, you will want to use /// a conversion such as the one offerred by the /// Foundation JSONEncoder/Decoder: `KeyDecodingStrategy` -public struct JSONAPIDocument: Equatable { +public struct Document: JSONAPIDocument { public typealias Include = IncludeType public let body: Body @@ -81,49 +89,49 @@ public struct JSONAPIDocument, links: LinksType) { self.body = .data(.init(primary: body, includes: includes, meta: .none, links: links)) } } -extension JSONAPIDocument where LinksType == NoLinks { +extension Document where LinksType == NoLinks { public init(body: ResourceBody, includes: Includes, meta: MetaType) { self.body = .data(.init(primary: body, includes: includes, meta: meta, links: .none)) } } -extension JSONAPIDocument where IncludeType == NoIncludes, LinksType == NoLinks { +extension Document where IncludeType == NoIncludes, LinksType == NoLinks { public init(body: ResourceBody, meta: MetaType) { self.body = .data(.init(primary: body, includes: .none, meta: meta, links: .none)) } } -extension JSONAPIDocument where IncludeType == NoIncludes, MetaType == NoMetadata { +extension Document where IncludeType == NoIncludes, MetaType == NoMetadata { public init(body: ResourceBody, links: LinksType) { self.body = .data(.init(primary: body, includes: .none, meta: .none, links: links)) } } -extension JSONAPIDocument where MetaType == NoMetadata, LinksType == NoLinks { +extension Document where MetaType == NoMetadata, LinksType == NoLinks { public init(body: ResourceBody, includes: Includes) { self.body = .data(.init(primary: body, includes: includes, meta: .none, links: .none)) } } -extension JSONAPIDocument where IncludeType == NoIncludes, MetaType == NoMetadata, LinksType == NoLinks { +extension Document where IncludeType == NoIncludes, MetaType == NoMetadata, LinksType == NoLinks { public init(body: ResourceBody) { self.body = .data(.init(primary: body, includes: .none, meta: .none, links: .none)) } } -extension JSONAPIDocument: Codable { +extension Document { private enum RootCodingKeys: String, CodingKey { case data case errors @@ -228,8 +236,8 @@ extension JSONAPIDocument: Codable { // MARK: - CustomStringConvertible -extension JSONAPIDocument: CustomStringConvertible { +extension Document: CustomStringConvertible { public var description: String { - return "JSONAPIDocument(body: \(String(describing: body))" + return "Document(body: \(String(describing: body))" } } diff --git a/Tests/JSONAPITests/Document/DocumentTests.swift b/Tests/JSONAPITests/Document/DocumentTests.swift index a947541..bde7d6a 100644 --- a/Tests/JSONAPITests/Document/DocumentTests.swift +++ b/Tests/JSONAPITests/Document/DocumentTests.swift @@ -11,7 +11,7 @@ import JSONAPI class DocumentTests: XCTestCase { func test_singleDocumentNull() { - let document = decoded(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_null) XCTAssertFalse(document.body.isError) @@ -23,12 +23,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNull_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_null) } func test_unknownErrorDocumentNoMeta() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_no_metadata) XCTAssertTrue(document.body.isError) @@ -48,12 +48,12 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentNoMeta_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_no_metadata) } func test_unknownErrorDocumentMissingMeta() { - let document = decoded(type: JSONAPIDocument.self, data: error_document_no_metadata) + let document = decoded(type: Document.self, data: error_document_no_metadata) XCTAssertTrue(document.body.isError) XCTAssertNil(document.body.meta) @@ -72,11 +72,11 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentMissingMeta_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, data: error_document_no_metadata) + test_DecodeEncodeEquality(type: Document.self, data: error_document_no_metadata) } func test_errorDocumentNoMeta() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_no_metadata) XCTAssertTrue(document.body.isError) @@ -96,12 +96,12 @@ class DocumentTests: XCTestCase { } func test_errorDocumentNoMeta_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_no_metadata) } func test_unknownErrorDocumentWithMeta() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_with_metadata) XCTAssertTrue(document.body.isError) @@ -120,12 +120,12 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentWithMeta_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_with_metadata) } func test_unknownErrorDocumentWithMetaWithLinks() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_with_metadata_with_links) XCTAssertTrue(document.body.isError) @@ -148,12 +148,12 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentWithMetaWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_with_metadata_with_links) } func test_unknownErrorDocumentWithLinks() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_with_links) XCTAssertTrue(document.body.isError) @@ -174,12 +174,12 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_with_links) } func test_unknownErrorDocumentMissingLinks() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: error_document_no_metadata) XCTAssertTrue(document.body.isError) @@ -197,12 +197,12 @@ class DocumentTests: XCTestCase { } func test_unknownErrorDocumentMissingLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: error_document_no_metadata) } func test_metaDataDocument() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: metadata_document) XCTAssertFalse(document.body.isError) @@ -213,12 +213,12 @@ class DocumentTests: XCTestCase { } func test_metaDataDocument_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: metadata_document) } func test_metaDataDocumentWithLinks() { - let document = decoded(type: JSONAPIDocument.self, + let document = decoded(type: Document.self, data: metadata_document_with_links) XCTAssertFalse(document.body.isError) @@ -233,18 +233,18 @@ class DocumentTests: XCTestCase { } func test_metaDataDocumentWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument.self, + test_DecodeEncodeEquality(type: Document.self, data: metadata_document_with_links) } func test_metaDocumentMissingMeta() { - XCTAssertThrowsError(try JSONDecoder().decode(JSONAPIDocument.self, from: metadata_document_missing_metadata)) + XCTAssertThrowsError(try JSONDecoder().decode(Document.self, from: metadata_document_missing_metadata)) - XCTAssertThrowsError(try JSONDecoder().decode(JSONAPIDocument.self, from: metadata_document_missing_metadata2)) + XCTAssertThrowsError(try JSONDecoder().decode(Document.self, from: metadata_document_missing_metadata2)) } func test_singleDocumentNoIncludes() { - let document = decoded(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) XCTAssertFalse(document.body.isError) @@ -256,12 +256,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNoIncludes_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) } func test_singleDocumentNoIncludesWithMetadata() { - let document = decoded(type: JSONAPIDocument, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_metadata) XCTAssertFalse(document.body.isError) @@ -273,12 +273,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNoIncludesWithMetadata_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_metadata) } func test_singleDocumentNoIncludesWithLinks() { - let document = decoded(type: JSONAPIDocument, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_links) XCTAssertFalse(document.body.isError) @@ -295,12 +295,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNoIncludesWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_links) } func test_singleDocumentNoIncludesWithMetadataWithLinks() { - let document = decoded(type: JSONAPIDocument, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_metadata_with_links) XCTAssertFalse(document.body.isError) @@ -317,20 +317,20 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNoIncludesWithMetadataWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes_with_metadata_with_links) } func test_singleDocumentNoIncludesWithMetadataMissingLinks() { - XCTAssertThrowsError(try JSONDecoder().decode(JSONAPIDocument, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes_with_metadata)) + XCTAssertThrowsError(try JSONDecoder().decode(Document, TestPageMetadata, TestLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes_with_metadata)) } func test_singleDocumentNoIncludesMissingMetadata() { - XCTAssertThrowsError(try JSONDecoder().decode(JSONAPIDocument, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes)) + XCTAssertThrowsError(try JSONDecoder().decode(Document, TestPageMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, from: single_document_no_includes)) } func test_singleDocumentSomeIncludes() { - let document = decoded(type: JSONAPIDocument, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes) XCTAssertFalse(document.body.isError) @@ -343,12 +343,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentSomeIncludes_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes) } func test_singleDocumentSomeIncludesWithMetadata() { - let document = decoded(type: JSONAPIDocument, TestPageMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + let document = decoded(type: Document, TestPageMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes_with_metadata) XCTAssertFalse(document.body.isError) @@ -362,12 +362,12 @@ class DocumentTests: XCTestCase { } func test_singleDocumentSomeIncludesWithMetadata_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, TestPageMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, TestPageMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes_with_metadata) } func test_singleDocumentNoIncludesWithSomeIncludesWithMetadataWithLinks() { - let document = decoded(type: JSONAPIDocument, TestPageMetadata, TestLinks, Include1, UnknownJSONAPIError>.self, + let document = decoded(type: Document, TestPageMetadata, TestLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes_with_metadata_with_links) XCTAssertFalse(document.body.isError) @@ -385,24 +385,24 @@ class DocumentTests: XCTestCase { } func test_singleDocumentNoIncludesWithSomeIncludesMetadataWithLinks_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, TestPageMetadata, TestLinks, Include1, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, TestPageMetadata, TestLinks, Include1, UnknownJSONAPIError>.self, data: single_document_some_includes_with_metadata_with_links) } func test_singleDocument_PolyPrimaryResource() { let article = Article(id: Id(rawValue: "1"), relationships: .init(author: ToOneRelationship(id: Id(rawValue: "33")))) - let document = decoded(type: JSONAPIDocument>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) + let document = decoded(type: Document>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) XCTAssertEqual(document.body.primaryData?.value?[Article.self], article) XCTAssertNil(document.body.primaryData?.value?[Author.self]) } func test_singleDocument_PolyPrimaryResource_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) + test_DecodeEncodeEquality(type: Document>, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: single_document_no_includes) } func test_manyDocumentNoIncludes() { - let document = decoded(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: many_document_no_includes) XCTAssertFalse(document.body.isError) @@ -416,12 +416,12 @@ class DocumentTests: XCTestCase { } func test_manyDocumentNoIncludes_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, NoLinks, NoIncludes, UnknownJSONAPIError>.self, data: many_document_no_includes) } func test_manyDocumentSomeIncludes() { - let document = decoded(type: JSONAPIDocument, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + let document = decoded(type: Document, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: many_document_some_includes) XCTAssertFalse(document.body.isError) @@ -439,7 +439,7 @@ class DocumentTests: XCTestCase { } func test_manyDocumentSomeIncludes_encode() { - test_DecodeEncodeEquality(type: JSONAPIDocument, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, + test_DecodeEncodeEquality(type: Document, NoMetadata, NoLinks, Include1, UnknownJSONAPIError>.self, data: many_document_some_includes) } }