mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-07-10 12:18:40 -07:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 57df6b147e | |||
| a88844fe5e | |||
| 850a713dcb | |||
| e3c637a41e | |||
| 9cbc626410 | |||
| 6dd14daf53 | |||
| 744e08acf4 | |||
| 5da4a963d4 | |||
| 5433dddc81 | |||
| 95f9d8084d | |||
| d6911f170c | |||
| 9972d13a4e | |||
| 4dc63167d6 | |||
| 845d085455 | |||
| 45eb7d06bd | |||
| 6ce962cec9 | |||
| 477dae0a73 | |||
| 4afe4cfb31 | |||
| 65144d27ae | |||
| 1ec4b21c34 | |||
| 15e13e2cc7 | |||
| 1d8ceef317 | |||
| e546614c15 | |||
| 8939d637d4 | |||
| e3b005b89a | |||
| 2de6580519 | |||
| 875d938b95 | |||
| 1ed34b00dc | |||
| 531a7f35bd | |||
| dc42ec27fc | |||
| cf746e182f | |||
| 52d2e9819d | |||
| 81b78cd749 | |||
| 3a0ede2372 | |||
| cb04a01e71 | |||
| 3c29244540 | |||
| a9e1e49a79 | |||
| 9e6e713ad2 | |||
| 308f168a8c | |||
| 8726bcc9fa | |||
| 25bda795a7 | |||
| 14a0256885 | |||
| b2041e9bc8 | |||
| fd9a626551 | |||
| 69bb40aa00 | |||
| 060e0e3898 | |||
| b374367234 | |||
| b363db30cd | |||
| 6904416623 | |||
| c04d3301b6 | |||
| 5a64bebc99 | |||
| 790b0fbf52 | |||
| 539ecc451a | |||
| 7eb1b05eae | |||
| 3408263c2a | |||
| 1d6e5d3810 | |||
| d68404db36 | |||
| 4f7db98a87 | |||
| 072b081ac3 |
+2
-2
@@ -40,7 +40,7 @@ typealias Document<PrimaryResourceBody: JSONAPI.ResourceBody, IncludeType: JSONA
|
||||
// MARK: Entity Definitions
|
||||
|
||||
enum AuthorDescription: EntityDescription {
|
||||
public static var type: String { return "authors" }
|
||||
public static var jsonType: String { return "authors" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public let name: Attribute<String>
|
||||
@@ -52,7 +52,7 @@ enum AuthorDescription: EntityDescription {
|
||||
typealias Author = JSONEntity<AuthorDescription>
|
||||
|
||||
enum ArticleDescription: EntityDescription {
|
||||
public static var type: String { return "articles" }
|
||||
public static var jsonType: String { return "articles" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public let title: Attribute<String>
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ struct ToManyRelationshipLinks: JSONAPI.Links {
|
||||
|
||||
/// Description of an Author entity.
|
||||
enum AuthorDescription: EntityDescription {
|
||||
static var type: String { return "authors" }
|
||||
static var jsonType: String { return "authors" }
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let name: Attribute<String>
|
||||
@@ -80,7 +80,7 @@ typealias Author = JSONAPI.Entity<AuthorDescription, EntityMetadata, EntityLinks
|
||||
|
||||
/// Description of an Article entity.
|
||||
enum ArticleDescription: EntityDescription {
|
||||
static var type: String { return "articles" }
|
||||
static var jsonType: String { return "articles" }
|
||||
|
||||
struct Attributes: JSONAPI.Attributes {
|
||||
let title: Attribute<String>
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//: [Previous](@previous)
|
||||
|
||||
import Foundation
|
||||
import JSONAPI
|
||||
import JSONAPIOpenAPI
|
||||
|
||||
// print Entity Schema
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = .prettyPrinted
|
||||
|
||||
let personSchemaData = try? encoder.encode(Person.openAPINode())
|
||||
|
||||
print("Person Schema")
|
||||
print("====")
|
||||
print(personSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed")
|
||||
print("====")
|
||||
|
||||
let dogDocumentSchemaData = try? encoder.encode(SingleDogDocument.openAPINodeWithExample())
|
||||
|
||||
print("Dog Document Schema")
|
||||
print("====")
|
||||
print(dogDocumentSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed")
|
||||
print("====")
|
||||
|
||||
let batchPersonSchemaData = try? encoder.encode(BatchPeopleDocument.openAPINodeWithExample())
|
||||
|
||||
print("Batch Person Document Schema")
|
||||
print("====")
|
||||
print(batchPersonSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed")
|
||||
print("====")
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import Foundation
|
||||
import JSONAPI
|
||||
import JSONAPITestLib
|
||||
import JSONAPITesting
|
||||
|
||||
/*******
|
||||
|
||||
@@ -11,12 +11,12 @@ Please enjoy these examples, but allow me the forced casting and the lack of err
|
||||
********/
|
||||
|
||||
// MARK: - Literal Expressibility
|
||||
// The JSONAPITestLib provides literal expressibility for key types to
|
||||
// The JSONAPITesting framework provides literal expressibility for key types to
|
||||
// make creating tests easier
|
||||
let dog = Dog(id: "1234", attributes: Dog.Attributes(name: "Buddy"), relationships: Dog.Relationships(owner: nil), meta: .none, links: .none)
|
||||
|
||||
// MARK: - JSON API structure checking
|
||||
// The JSONAPITestLib provides a `check` function for each Entity type
|
||||
// The JSONAPITesting framework provides a `check` function for each Entity type
|
||||
// that uses reflection to catch mistakes that are not forbidden by
|
||||
// Swift's type system but will result in unexpected results when
|
||||
// encoding/decoding. It is a good idea to add a `check` to each of
|
||||
|
||||
@@ -11,8 +11,6 @@ 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 = JSONAPI.Document<SingleResourceBody<Dog>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>
|
||||
|
||||
let singleDogDocument = SingleDogDocument(apiDescription: .none, body: .init(entity: dogFromCode), includes: .none, meta: .none, links: .none)
|
||||
|
||||
let singleDogData = try! JSONEncoder().encode(singleDogDocument)
|
||||
@@ -34,8 +32,6 @@ let dogs = try! [Dog(name: "Buddy", owner: personIds[0]), Dog(name: "Joy", owner
|
||||
let houses = [House(attributes: .none, relationships: .none, meta: .none, links: .none), House(attributes: .none, relationships: .none, meta: .none, links: .none)]
|
||||
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 = JSONAPI.Document<ManyResourceBody<Person>, NoMetadata, NoLinks, Include2<Dog, House>, NoAPIDescription, UnknownJSONAPIError>
|
||||
|
||||
let includes = dogs.map { BatchPeopleDocument.Include($0) } + houses.map { BatchPeopleDocument.Include($0) }
|
||||
let batchPeopleDocument = BatchPeopleDocument(apiDescription: .none, body: .init(entities: people), includes: .init(values: includes), meta: .none, links: .none)
|
||||
let batchPeopleData = try! JSONEncoder().encode(batchPeopleDocument)
|
||||
|
||||
@@ -31,7 +31,7 @@ public typealias ToMany<E: Relatable> = ToManyRelationship<E, NoMetadata, NoLink
|
||||
// MARK: - A few resource objects (entities)
|
||||
public enum PersonDescription: EntityDescription {
|
||||
|
||||
public static var type: String { return "people" }
|
||||
public static var jsonType: String { return "people" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public let name: Attribute<[String]>
|
||||
@@ -70,7 +70,7 @@ public extension Entity where Description == PersonDescription, MetaType == NoMe
|
||||
|
||||
public enum DogDescription: EntityDescription {
|
||||
|
||||
public static var type: String { return "dogs" }
|
||||
public static var jsonType: String { return "dogs" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public let name: Attribute<String>
|
||||
@@ -93,7 +93,7 @@ public typealias Dog = ExampleEntity<DogDescription>
|
||||
|
||||
public enum AlternativeDogDescription: EntityDescription {
|
||||
|
||||
public static var type: String { return "dogs" }
|
||||
public static var jsonType: String { return "dogs" }
|
||||
|
||||
public struct Attributes: JSONAPI.Attributes {
|
||||
public let name: Attribute<String>
|
||||
@@ -131,7 +131,7 @@ public extension Entity where Description == DogDescription, MetaType == NoMetad
|
||||
|
||||
public enum HouseDescription: EntityDescription {
|
||||
|
||||
public static var type: String { return "houses" }
|
||||
public static var jsonType: String { return "houses" }
|
||||
|
||||
public typealias Attributes = NoAttributes
|
||||
public typealias Relationships = NoRelationships
|
||||
@@ -139,4 +139,6 @@ public enum HouseDescription: EntityDescription {
|
||||
|
||||
public typealias House = ExampleEntity<HouseDescription>
|
||||
|
||||
public typealias SingleDogDocument = JSONAPI.Document<SingleResourceBody<Dog>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>
|
||||
|
||||
public typealias BatchPeopleDocument = JSONAPI.Document<ManyResourceBody<Person>, NoMetadata, NoLinks, Include2<Dog, House>, NoAPIDescription, UnknownJSONAPIError>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import Foundation
|
||||
import JSONAPI
|
||||
import JSONAPITesting // for the convenience of literal initialization
|
||||
import JSONAPIOpenAPI
|
||||
import SwiftCheck
|
||||
import JSONAPIArbitrary
|
||||
|
||||
extension PersonDescription.Attributes: Arbitrary, Sampleable {
|
||||
public static var arbitrary: Gen<PersonDescription.Attributes> {
|
||||
return Gen.compose { c in
|
||||
return PersonDescription.Attributes(name: c.generate(),
|
||||
favoriteColor: c.generate())
|
||||
}
|
||||
}
|
||||
|
||||
public static var sample: PersonDescription.Attributes {
|
||||
return .init(name: ["Abbie", "Eibba"], favoriteColor: "Blue")
|
||||
}
|
||||
}
|
||||
|
||||
extension PersonDescription.Relationships: Arbitrary, Sampleable {
|
||||
public static var arbitrary: Gen<PersonDescription.Relationships> {
|
||||
return Gen.compose { c in
|
||||
return PersonDescription.Relationships(friends: c.generate(),
|
||||
dogs: c.generate(),
|
||||
home: c.generate())
|
||||
}
|
||||
}
|
||||
|
||||
public static var sample: PersonDescription.Relationships {
|
||||
return .init(friends: ["1", "2"], dogs: ["2"], home: "1")
|
||||
}
|
||||
}
|
||||
|
||||
extension DogDescription.Attributes: Arbitrary, Sampleable {
|
||||
public static var arbitrary: Gen<DogDescription.Attributes> {
|
||||
return Gen.compose { c in
|
||||
return DogDescription.Attributes(name: c.generate())
|
||||
}
|
||||
}
|
||||
|
||||
public static var sample: DogDescription.Attributes {
|
||||
return DogDescription.Attributes.arbitrary.generate
|
||||
}
|
||||
}
|
||||
|
||||
extension DogDescription.Relationships: Arbitrary, Sampleable {
|
||||
public static var arbitrary: Gen<DogDescription.Relationships> {
|
||||
return Gen.compose { c in
|
||||
return DogDescription.Relationships(owner: c.generate())
|
||||
}
|
||||
}
|
||||
|
||||
public static var sample: DogDescription.Relationships {
|
||||
return DogDescription.Relationships.arbitrary.generate
|
||||
}
|
||||
}
|
||||
|
||||
extension Document: Sampleable where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary, APIDescription: Arbitrary {
|
||||
public static var sample: Document {
|
||||
return Document.arbitrary.generate
|
||||
}
|
||||
|
||||
public static var successSample: Document? {
|
||||
return Document.arbitraryData.generate
|
||||
}
|
||||
|
||||
public static var failureSample: Document? {
|
||||
return Document.arbitraryErrors.generate
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<pages>
|
||||
<page name='Test Library'/>
|
||||
<page name='Usage'/>
|
||||
<page name='Full Document Verbose Generation'/>
|
||||
<page name='Full Client & Server Example'/>
|
||||
<page name='Full Document Verbose Generation'/>
|
||||
</pages>
|
||||
</playground>
|
||||
@@ -0,0 +1,7 @@
|
||||
Copyright 2018 Mathew Polzin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
+36
-1
@@ -1,7 +1,42 @@
|
||||
{
|
||||
"object": {
|
||||
"pins": [
|
||||
|
||||
{
|
||||
"package": "AnyCodable",
|
||||
"repositoryURL": "https://github.com/Flight-School/AnyCodable.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "396ccc3dba5bdee04c1e742e7fab40582861401e",
|
||||
"version": "0.1.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "FileCheck",
|
||||
"repositoryURL": "https://github.com/llvm-swift/FileCheck.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "89b8480055f9adf8ce2f9ad5e2fac7ac1076242e",
|
||||
"version": "0.0.8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "Poly",
|
||||
"repositoryURL": "https://github.com/mattpolzin/Poly.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "77f45b8963a51c02d71fc4075eba5cff47ff0d07",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "SwiftCheck",
|
||||
"repositoryURL": "https://github.com/typelift/SwiftCheck.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "cf9958085b2ee1643e541e407c3233d1b76c18ff",
|
||||
"version": "0.11.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"version": 1
|
||||
|
||||
+29
-5
@@ -10,21 +10,45 @@ let package = Package(
|
||||
name: "JSONAPI",
|
||||
targets: ["JSONAPI"]),
|
||||
.library(
|
||||
name: "JSONAPITestLib",
|
||||
targets: ["JSONAPITestLib"])
|
||||
name: "JSONAPITesting",
|
||||
targets: ["JSONAPITesting"]),
|
||||
.library(
|
||||
name: "JSONAPIArbitrary",
|
||||
targets: ["JSONAPIArbitrary"]),
|
||||
.library(
|
||||
name: "JSONAPIOpenAPI",
|
||||
targets: ["JSONAPIOpenAPI"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/mattpolzin/Poly.git", from: "1.0.0"),
|
||||
.package(url: "https://github.com/Flight-School/AnyCodable.git", from: "0.1.0"),
|
||||
.package(url: "https://github.com/typelift/SwiftCheck.git", from: "0.11.0")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "JSONAPI",
|
||||
dependencies: []),
|
||||
dependencies: ["Poly"]),
|
||||
.target(
|
||||
name: "JSONAPITestLib",
|
||||
name: "JSONAPITesting",
|
||||
dependencies: ["JSONAPI"]),
|
||||
.target(
|
||||
name: "JSONAPIArbitrary",
|
||||
dependencies: ["JSONAPI", "SwiftCheck"]),
|
||||
.target(
|
||||
name: "JSONAPIOpenAPI",
|
||||
dependencies: ["JSONAPI", "AnyCodable", "JSONAPIArbitrary"]),
|
||||
.testTarget(
|
||||
name: "JSONAPITests",
|
||||
dependencies: ["JSONAPITestLib"])
|
||||
dependencies: ["JSONAPI", "JSONAPITesting"]),
|
||||
.testTarget(
|
||||
name: "JSONAPITestingTests",
|
||||
dependencies: ["JSONAPI", "JSONAPITesting"]),
|
||||
.testTarget(
|
||||
name: "JSONAPIArbitraryTests",
|
||||
dependencies: ["JSONAPI", "SwiftCheck", "JSONAPIArbitrary"]),
|
||||
.testTarget(
|
||||
name: "JSONAPIOpenAPITests",
|
||||
dependencies: ["JSONAPI", "JSONAPIOpenAPI"])
|
||||
],
|
||||
swiftLanguageVersions: [.v4_2]
|
||||
)
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// Created by Mathew Polzin on 11/5/18.
|
||||
//
|
||||
|
||||
import Poly
|
||||
|
||||
public protocol JSONAPIDocument: Codable, Equatable {
|
||||
associatedtype PrimaryResourceBody: JSONAPI.ResourceBody
|
||||
associatedtype MetaType: JSONAPI.Meta
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
// Created by Mathew Polzin on 11/10/18.
|
||||
//
|
||||
|
||||
public typealias Include = Poly
|
||||
import Poly
|
||||
|
||||
public typealias Include = JSONPoly
|
||||
|
||||
public struct Includes<I: Include>: Codable, Equatable {
|
||||
public static var none: Includes { return .init(values: []) }
|
||||
|
||||
@@ -16,7 +16,7 @@ public protocol AttributeType: Codable {
|
||||
|
||||
/// A TransformedAttribute takes a Codable type and attempts to turn it into another type.
|
||||
public struct TransformedAttribute<RawValue: Codable, Transformer: JSONAPI.Transformer>: AttributeType where Transformer.From == RawValue {
|
||||
let rawValue: RawValue
|
||||
public let rawValue: RawValue
|
||||
|
||||
public let value: Transformer.To
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ extension NoAttributes: CustomStringConvertible {
|
||||
/// Something that is JSONTyped provides a String representation
|
||||
/// of its type.
|
||||
public protocol JSONTyped {
|
||||
static var type: String { get }
|
||||
static var jsonType: String { get }
|
||||
}
|
||||
|
||||
/// An `EntityProxyDescription` is an `EntityDescription`
|
||||
@@ -81,7 +81,7 @@ public protocol EntityProxy: Equatable, JSONTyped {
|
||||
|
||||
extension EntityProxy {
|
||||
/// The JSON API compliant "type" of this `Entity`.
|
||||
public static var type: String { return Description.type }
|
||||
public static var jsonType: String { return Description.jsonType }
|
||||
}
|
||||
|
||||
/// EntityType is the protocol that Entity conforms to. This
|
||||
@@ -136,7 +136,7 @@ extension Entity: Identifiable, IdentifiableEntityType, Relatable where EntityRa
|
||||
|
||||
extension Entity: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return "Entity<\(Entity.type)>(id: \(String(describing: id)), attributes: \(String(describing: attributes)), relationships: \(String(describing: relationships)))"
|
||||
return "Entity<\(Entity.jsonType)>(id: \(String(describing: id)), attributes: \(String(describing: attributes)), relationships: \(String(describing: relationships)))"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,6 +471,15 @@ public extension EntityProxy {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Meta-Attribute Access
|
||||
public extension EntityProxy {
|
||||
/// Access an attribute requiring a transformation on the RawValue _and_
|
||||
/// a secondary transformation on this entity (self).
|
||||
subscript<T>(_ path: KeyPath<Description.Attributes, (Self) -> T>) -> T {
|
||||
return attributes[keyPath: path](self)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Relationship Access
|
||||
public extension EntityProxy {
|
||||
/// Access to an Id of a `ToOneRelationship`.
|
||||
@@ -513,6 +522,23 @@ public extension EntityProxy {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Meta-Relationship Access
|
||||
public extension EntityProxy {
|
||||
/// Access to an Id of a `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other.id`.
|
||||
public static func ~><Identifier: IdType>(entity: Self, path: KeyPath<Description.Relationships, (Self) -> Identifier>) -> Identifier {
|
||||
return entity.relationships[keyPath: path](entity)
|
||||
}
|
||||
|
||||
/// Access to all Ids of a `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others.ids`.
|
||||
public static func ~><Identifier: IdType>(entity: Self, path: KeyPath<Description.Relationships, (Self) -> [Identifier]>) -> [Identifier] {
|
||||
return entity.relationships[keyPath: path](entity)
|
||||
}
|
||||
}
|
||||
|
||||
infix operator ~>
|
||||
|
||||
// MARK: - Codable
|
||||
@@ -529,7 +555,7 @@ public extension Entity {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: ResourceObjectCodingKeys.self)
|
||||
|
||||
try container.encode(Entity.type, forKey: .type)
|
||||
try container.encode(Entity.jsonType, forKey: .type)
|
||||
|
||||
if EntityRawIdType.self != Unidentified.self {
|
||||
try container.encode(id, forKey: .id)
|
||||
@@ -558,8 +584,8 @@ public extension Entity {
|
||||
|
||||
let type = try container.decode(String.self, forKey: .type)
|
||||
|
||||
guard Entity.type == type else {
|
||||
throw JSONAPIEncodingError.typeMismatch(expected: Description.type, found: type)
|
||||
guard Entity.jsonType == type else {
|
||||
throw JSONAPIEncodingError.typeMismatch(expected: Description.jsonType, found: type)
|
||||
}
|
||||
|
||||
let maybeUnidentified = Unidentified() as? EntityRawIdType
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
//
|
||||
// Poly+PrimaryResource.swift
|
||||
// JSONAPI
|
||||
//
|
||||
// Created by Mathew Polzin on 11/22/18.
|
||||
//
|
||||
|
||||
import Poly
|
||||
|
||||
/// Poly is a protocol to which types that
|
||||
/// are polymorphic belong to. Specifically,
|
||||
/// Poly1, Poly2, Poly3, etc. types conform
|
||||
/// to the Poly protocol. These types allow
|
||||
/// typesafe grouping of a number of
|
||||
/// disparate types under one roof for
|
||||
/// the purposes of JSON API compliant
|
||||
/// encoding or decoding.
|
||||
public typealias JSONPoly = Poly & PrimaryResource
|
||||
|
||||
public typealias PolyWrapped = Codable & Equatable
|
||||
|
||||
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 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: PrimaryResource, MaybePrimaryResource where A: PolyWrapped {}
|
||||
|
||||
// MARK: - 2 types
|
||||
extension Poly2: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped {}
|
||||
|
||||
// MARK: - 3 types
|
||||
extension Poly3: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped {}
|
||||
|
||||
// MARK: - 4 types
|
||||
extension Poly4: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped {}
|
||||
|
||||
// MARK: - 5 types
|
||||
extension Poly5: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped {}
|
||||
|
||||
// MARK: - 6 types
|
||||
extension Poly6: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped {}
|
||||
|
||||
// MARK: - 7 types
|
||||
extension Poly7: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped {}
|
||||
|
||||
// MARK: - 8 types
|
||||
extension Poly8: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped {}
|
||||
|
||||
// MARK: - 9 types
|
||||
extension Poly9: PrimaryResource, MaybePrimaryResource where A: PolyWrapped, B: PolyWrapped, C: PolyWrapped, D: PolyWrapped, E: PolyWrapped, F: PolyWrapped, G: PolyWrapped, H: PolyWrapped, I: PolyWrapped {}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -134,7 +134,7 @@ public protocol OptionalRelatable: Identifiable where Identifier == Wrapped.Iden
|
||||
extension Optional: Identifiable, OptionalRelatable, JSONTyped where Wrapped: JSONAPI.Relatable {
|
||||
public typealias Identifier = Wrapped.Identifier?
|
||||
|
||||
public static var type: String { return Wrapped.type }
|
||||
public static var jsonType: String { return Wrapped.jsonType }
|
||||
}
|
||||
|
||||
// MARK: Codable
|
||||
@@ -180,8 +180,8 @@ extension ToOneRelationship: Codable where Identifiable.Identifier: OptionalId {
|
||||
|
||||
let type = try identifier.decode(String.self, forKey: .entityType)
|
||||
|
||||
guard type == Identifiable.type else {
|
||||
throw JSONAPIEncodingError.typeMismatch(expected: Identifiable.type, found: type)
|
||||
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))
|
||||
@@ -214,7 +214,7 @@ extension ToOneRelationship: Codable where Identifiable.Identifier: OptionalId {
|
||||
var identifier = container.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self, forKey: .data)
|
||||
|
||||
try identifier.encode(id.rawValue, forKey: .id)
|
||||
try identifier.encode(Identifiable.type, forKey: .entityType)
|
||||
try identifier.encode(Identifiable.jsonType, forKey: .entityType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,8 +242,8 @@ extension ToManyRelationship: Codable {
|
||||
|
||||
let type = try identifier.decode(String.self, forKey: .entityType)
|
||||
|
||||
guard type == Relatable.type else {
|
||||
throw JSONAPIEncodingError.typeMismatch(expected: Relatable.type, found: type)
|
||||
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)))
|
||||
@@ -268,7 +268,7 @@ extension ToManyRelationship: Codable {
|
||||
var identifier = identifiers.nestedContainer(keyedBy: ResourceIdentifierCodingKeys.self)
|
||||
|
||||
try identifier.encode(id.rawValue, forKey: .id)
|
||||
try identifier.encode(Relatable.type, forKey: .entityType)
|
||||
try identifier.encode(Relatable.jsonType, forKey: .entityType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
//
|
||||
// APIDescription+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/21/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension APIDescription: Arbitrary where Meta: Arbitrary {
|
||||
public static var arbitrary: Gen<APIDescription<Meta>> {
|
||||
return Gen.compose { c in
|
||||
APIDescription(version: c.generate(),
|
||||
meta: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension NoAPIDescription: Arbitrary {
|
||||
public static var arbitrary: Gen<NoAPIDescription> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user