Compare commits

...

63 Commits

Author SHA1 Message Date
Mathew Polzin dc30cb3b9e Make Attribute Sampleable where its RawValue is Sampleable. Allow Sampleable things to provide a best guess for their node type based on the result of encoding and then deserializing them. 2019-01-24 00:47:24 -08:00
Mathew Polzin 7045373708 update and make sure all Playground pages run 2019-01-23 23:24:53 -08:00
Mathew Polzin 952fe8ba7e Remove encoder requirement to almost all Open API Node constructors. Made a new protocol for the few places where an encoder did need to be passed in. 2019-01-23 23:21:16 -08:00
Mathew Polzin 951c04ad44 Add Sampleable conformances. Make blanket JSONEncoder change I am not happy with; will try to walk back requirement that encoder gets passed to all functions creating OpenAPI Nodes 2019-01-23 22:21:27 -08:00
Mathew Polzin 57df6b147e Add Sampleable conformance to UnknownJSONAPIError. Add Sampleable conformance to all Include types and the Includes type. 2019-01-23 11:52:16 -08:00
Mathew Polzin a88844fe5e Switch to Poly 1.0.0 (same commit as previously used but by version rather than branch) 2019-01-23 00:34:14 -08:00
Mathew Polzin 850a713dcb Merge pull request #13 from mattpolzin/feature/OpenAPISchema
Add Include support to OpenAPI schema of JSONAPI Document.
2019-01-22 12:01:40 -08:00
Mathew Polzin e3c637a41e update README and add associated type labels to patterns for clarity 2019-01-22 11:57:18 -08:00
Mathew Polzin 9cbc626410 Add Include support to OpenAPI schema of JSONAPI Document. 2019-01-22 11:53:32 -08:00
Mathew Polzin 6dd14daf53 Merge pull request #12 from mattpolzin/feature/OpenAPISchema
Testing, Documentation, more Arbitrary conformance, "example" support.
2019-01-22 08:21:22 -08:00
Mathew Polzin 744e08acf4 Update linuxmain 2019-01-21 23:00:13 -08:00
Mathew Polzin 5da4a963d4 Update README and code documentation slightly 2019-01-21 22:50:19 -08:00
Mathew Polzin 5433dddc81 Add support for 'const' via OpenAPI 3.0 workaround suggested by others: Use 'enum' with one value. Add Sampleable support for requesting samples representing 'success' and 'failure' if available. 2019-01-21 22:47:03 -08:00
Mathew Polzin 95f9d8084d Add Arbitrary conformance for UnknownJSONAPIError. Fix weird encoding exception that I cannot quite figure out or explain at the moment. 2019-01-21 21:56:33 -08:00
Mathew Polzin d6911f170c Add example to JSONNode 2019-01-21 20:57:54 -08:00
Mathew Polzin 9972d13a4e Document zip(with:) on optionals 2019-01-21 15:37:41 -08:00
Mathew Polzin 4dc63167d6 Rename a couple of files 2019-01-21 15:35:54 -08:00
Mathew Polzin 845d085455 Fill out a fair bit of OpenAPI Entity testing 2019-01-21 15:32:38 -08:00
Mathew Polzin 45eb7d06bd Merge branch 'master' into feature/OpenAPISchema 2019-01-21 13:18:59 -08:00
Mathew Polzin 6ce962cec9 Merge pull request #11 from mattpolzin/feature/Arbitrary
Add Arbitrary support for the rest of JSONAPI's key types.
2019-01-21 13:16:46 -08:00
Mathew Polzin 477dae0a73 Add Arbitrary support for the rest of JSONAPI's key types. 2019-01-21 13:13:09 -08:00
Mathew Polzin 4afe4cfb31 Rename first JSONAPI+Testing header to Testing to remove conflict in GitHub Markdown links. 2019-01-21 11:52:02 -08:00
Mathew Polzin 65144d27ae Merge pull request #10 from mattpolzin/feature/OpenAPISchema
Feature/open api schema
2019-01-21 11:50:02 -08:00
Mathew Polzin 1ec4b21c34 Add missing case in Sampleable generic OpenAPINode implementation. Add info on new auxiliary frameworks to the README. 2019-01-20 19:18:10 -08:00
Mathew Polzin 15e13e2cc7 Remove unused error and add a bit of code documentation 2019-01-20 18:54:37 -08:00
Mathew Polzin 1d8ceef317 Update README, add a bit more code documentation 2019-01-20 18:52:21 -08:00
Mathew Polzin e546614c15 merge with Arbitrary branch 2019-01-20 18:41:54 -08:00
Mathew Polzin 8939d637d4 Add placeholder test to arbitrary test target. 2019-01-20 18:34:24 -08:00
Mathew Polzin e3b005b89a Update README 2019-01-20 18:25:28 -08:00
Mathew Polzin 2de6580519 Add some tests around Attribute OpenAPI descriptions 2019-01-20 18:18:35 -08:00
Mathew Polzin 875d938b95 Add id and type properties to Entity OpenAPI Schema 2019-01-20 16:19:26 -08:00
Mathew Polzin 1ed34b00dc Add todos for Entity Id and type. Add example usage of OpenAPI entity schema support in Playground 2019-01-20 16:10:31 -08:00
Mathew Polzin 531a7f35bd Cleanup and a bit of documentation 2019-01-20 15:50:46 -08:00
Mathew Polzin dc42ec27fc Not crazy about how I got there, but now it is relatively easy to print arbitrary enum's allCases as the list of possible values in the format specced out by OpenAPI. 2019-01-20 15:39:54 -08:00
Mathew Polzin cf746e182f currently in a pretty broken state with support for enumerations being turned into allowed values via reflection. I think I am going to have to give up type safety if I want to use reflection and keep things open ended 2019-01-19 15:30:09 -08:00
Mathew Polzin 52d2e9819d Update README project status to include OpenAPI and Arbitrary work. 2019-01-15 09:40:49 -08:00
Mathew Polzin 81b78cd749 Add more Arbitrary conformances 2019-01-15 09:27:09 -08:00
Mathew Polzin 3a0ede2372 Get rid of OpenAPI namespace because a compiler bug was making it more hassle than it was worth. 2019-01-14 23:46:39 -08:00
Mathew Polzin cb04a01e71 Add some todos and delete an old file 2019-01-14 23:29:49 -08:00
Mathew Polzin 3c29244540 fill out some of the relationship tests 2019-01-14 23:14:25 -08:00
Mathew Polzin a9e1e49a79 Add test helpers for Open API test target 2019-01-14 21:18:49 -08:00
Mathew Polzin 9e6e713ad2 Add Codable for the parts of OpenAPI that are built so far. 2019-01-14 21:17:07 -08:00
Mathew Polzin 308f168a8c Trying to map out the Open API Schema Object using Swift enums 2019-01-13 23:24:02 -08:00
Mathew Polzin 8726bcc9fa Update all references to JSONAPITestLib to reflect renaming 2019-01-13 18:35:20 -08:00
Mathew Polzin 25bda795a7 Rename JSONAPITestLib to JSONAPITesting to fit with naming convention I am adopting going forward. Added OpenAPI JSON schema types. Added default schema types for a handful of Swift primitives. 2019-01-13 18:28:41 -08:00
Mathew Polzin 14a0256885 Add new targets 2019-01-13 17:27:10 -08:00
Mathew Polzin b2041e9bc8 Update to bleeding edge Poly library 2019-01-13 07:47:20 -08:00
Mathew Polzin fd9a626551 Ditch unused test constant. 2019-01-13 07:42:13 -08:00
Mathew Polzin 69bb40aa00 Move JSONAPITestLib tests into their own test target. 2019-01-13 07:16:46 -08:00
Mathew Polzin 060e0e3898 Move PolyWrapped out of Poly and into JSONAPI. 2019-01-12 21:51:51 -08:00
Mathew Polzin b374367234 Move Poly into its own library. 2019-01-12 21:30:20 -08:00
Mathew Polzin b363db30cd Add MIT license docuemnt 2019-01-12 18:41:04 -08:00
Mathew Polzin 6904416623 Begin making Poly more useful in a broader context than JSONAPI. 2019-01-12 17:08:46 -08:00
Mathew Polzin c04d3301b6 Add Meta-Relationship access. 2019-01-08 21:23:17 -08:00
Mathew Polzin 5a64bebc99 Merge branch 'master' of github.com:mattpolzin/JSONAPI 2019-01-08 20:13:11 -08:00
Mathew Polzin 790b0fbf52 Change capitalization 2019-01-06 18:20:18 -08:00
Mathew Polzin 539ecc451a Remove swift syntax highlighting from JSON snippet. 2019-01-03 22:26:25 -08:00
Mathew Polzin 7eb1b05eae Add swift syntax highlighting to README. 2019-01-03 22:23:17 -08:00
Mathew Polzin 3408263c2a Add warning note to README 2019-01-03 22:09:43 -08:00
Mathew Polzin 1d6e5d3810 Added Meta-Attribute support and documentation 2019-01-02 22:49:38 -08:00
Mathew Polzin d68404db36 update README to reflect change made in v0.12.0 2019-01-02 19:46:30 -08:00
Mathew Polzin 4f7db98a87 Update playground files to work with v0.12.0 changes 2019-01-02 19:42:32 -08:00
Mathew Polzin 072b081ac3 Breaking - Rename static var type: String to static var jsonType:String to avoid unnecessary conflict with Swift.type(of:) 2019-01-02 19:35:50 -08:00
73 changed files with 4469 additions and 1435 deletions
@@ -1,5 +1,6 @@
import Foundation
import JSONAPI
import Poly
// MARK: - Preamble (setup)
@@ -40,7 +41,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 +53,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>
@@ -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(using: encoder))
print("Dog Document Schema")
print("====")
print(dogDocumentSchemaData.map { String(data: $0, encoding: .utf8)! } ?? "Schema Construction Failed")
print("====")
let batchPersonSchemaData = try? encoder.encode(BatchPeopleDocument.openAPINodeWithExample(using: encoder))
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)
+6 -4
View File
@@ -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
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
<pages>
<page name='Test Library'/>
<page name='Usage'/>
<page name='Full Document Verbose Generation'/>
<page name='Full Client &amp; Server Example'/>
<page name='Full Document Verbose Generation'/>
</pages>
</playground>
+7
View File
@@ -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
View File
@@ -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
View File
@@ -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]
)
+246 -103
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -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
+3 -1
View File
@@ -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: []) }
+1 -1
View File
@@ -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
+32 -6
View File
@@ -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
+7 -7
View File
@@ -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