Moved Examples.swift into a Playground, added some initialization code required to create entities and documents in code.

This commit is contained in:
Mathew Polzin
2018-11-18 17:47:26 -08:00
parent 713fd2ba3a
commit 3327a93df5
9 changed files with 158 additions and 81 deletions
-76
View File
@@ -1,76 +0,0 @@
//
// Examples.swift
// JSONAPI
//
// Created by Mathew Polzin on 11/12/18.
//
import Foundation
import JSONAPI
/*******
Please enjoy these examples, but allow me the forced casting and the lack of error checking for the sake of brevity.
********/
typealias ExampleEntity<Description: EntityDescription> = Entity<Description, Id<String, Description>>
// MARK: - A few resource objects (entities)
enum PersonDescription: EntityDescription {
static var type: String { return "people" }
struct Attributes: JSONAPI.Attributes {
let name: [String]
let favoriteColor: String
}
struct Relationships: JSONAPI.Relationships {
let friends: ToManyRelationship<Person>
let dogs: ToManyRelationship<Dog>
let home: ToOneRelationship<House>
}
}
typealias Person = ExampleEntity<PersonDescription>
enum DogDescription: EntityDescription {
static var type: String { return "dogs" }
struct Attributes: JSONAPI.Attributes {
let name: String
}
struct Relationships: JSONAPI.Relationships {
let owner: ToOneRelationship<Person?>
}
}
typealias Dog = ExampleEntity<DogDescription>
enum HouseDescription: EntityDescription {
static var type: String { return "houses" }
typealias Attributes = NoAttributes
typealias Relationships = NoRelatives
}
typealias House = ExampleEntity<HouseDescription>
// MARK: - Parse a response body with one Dog in it
typealias SingleDogResponse = JSONAPIDocument<SingleResourceBody<Dog>, NoIncludes, BasicJSONAPIError>
let dummyData = "".data(using: .utf8)!
let dogResponse = try! JSONDecoder().decode(SingleDogResponse.self, from: dummyData)
let dog = dogResponse.body.data?.primary.value
// MARK: Parse a response body with multiple people in it and dogs and houses included
typealias BatchPeopleResponse = JSONAPIDocument<ManyResourceBody<Person>, Include2<Dog, House>, BasicJSONAPIError>
let peopleResponse = try! JSONDecoder().decode(BatchPeopleResponse.self, from: dummyData)
let people = peopleResponse.body.data?.primary.values
let dogs = peopleResponse.body.data?.included[Dog.self]
let houses = peopleResponse.body.data?.included[House.self]
+34
View File
@@ -0,0 +1,34 @@
import Foundation
import JSONAPI
/*******
Please enjoy these examples, but allow me the forced casting and the lack of error checking for the sake of brevity.
********/
// MARK: - Create a request or response body with one Dog in it
let dogFromCode = try! Dog(name: "Buddy", owner: nil)
typealias SingleDogDocument = JSONAPIDocument<SingleResourceBody<Dog>, NoIncludes, BasicJSONAPIError>
let singleDogDocument = SingleDogDocument(body: SingleResourceBody(entity: dogFromCode))
let singleDogData = try! JSONEncoder().encode(singleDogDocument)
// MARK: - Parse a request or response body with one Dog in it
let dogResponse = try! JSONDecoder().decode(SingleDogDocument.self, from: singleDogData)
let dogFromData = dogResponse.body.data?.primary.value
// MARK: - Create a request or response with multiple people and dogs and houses included
//let people
//typealias BatchPeopleDocument = JSONAPIDocument<ManyResourceBody<Person>, Include2<Dog, House>, BasicJSONAPIError>
// MARK: - Parse a request or response body with multiple people in it and dogs and houses included
//let peopleResponse = try! JSONDecoder().decode(BatchPeopleResponse.self, from: dummyData)
//let people = peopleResponse.body.data?.primary.values
//let dogs = peopleResponse.body.data?.included[Dog.self]
//let houses = peopleResponse.body.data?.included[House.self]
+85
View File
@@ -0,0 +1,85 @@
//
// Examples.swift
// JSONAPI
//
// Created by Mathew Polzin on 11/12/18.
//
import Foundation
import JSONAPI
/*******
Please enjoy these examples, but allow me the forced casting and the lack of error checking for the sake of brevity.
********/
// MARK: - String as CreatableRawIdType
var GlobalStringId: Int = 0
extension String: CreatableRawIdType {
public static func unique() -> String {
GlobalStringId += 1
return String(GlobalStringId)
}
}
// MARK: - Entity typealias for convenience
public typealias ExampleEntity<Description: EntityDescription> = Entity<Description, Id<String, Description>>
// MARK: - A few resource objects (entities)
public enum PersonDescription: EntityDescription {
public static var type: String { return "people" }
public struct Attributes: JSONAPI.Attributes {
public let name: Attribute<[String]>
public let favoriteColor: Attribute<String>
}
public struct Relationships: JSONAPI.Relationships {
public let friends: ToManyRelationship<Person>
public let dogs: ToManyRelationship<Dog>
public let home: ToOneRelationship<House>
}
}
public typealias Person = ExampleEntity<PersonDescription>
public extension Entity where Description == PersonDescription, Identifier == Id<String, PersonDescription> {
public init(name: [String], favoriteColor: String, friends: [Person], dogs: [Dog], home: House) throws {
self = try Person(attributes: .init(name: .init(rawValue: name), favoriteColor: .init(rawValue: favoriteColor)), relationships: .init(friends: .init(entities: friends), dogs: .init(entities: dogs), home: .init(entity: home)))
}
}
public enum DogDescription: EntityDescription {
public static var type: String { return "dogs" }
public struct Attributes: JSONAPI.Attributes {
public let name: Attribute<String>
}
public struct Relationships: JSONAPI.Relationships {
public let owner: ToOneRelationship<Person?>
}
}
public typealias Dog = ExampleEntity<DogDescription>
public extension Entity where Description == DogDescription, Identifier == Id<String, DogDescription> {
public init(name: String, owner: Person?) throws {
self = try Dog(attributes: .init(name: .init(rawValue: name)), relationships: DogDescription.Relationships(owner: .init(entity: owner)))
}
}
public enum HouseDescription: EntityDescription {
public static var type: String { return "houses" }
public typealias Attributes = NoAttributes
public typealias Relationships = NoRelatives
}
public typealias House = ExampleEntity<HouseDescription>
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<playground version='5.0' target-platform='macos' executeOnSourceChanges='false'>
<timeline fileName='timeline.xctimeline'/>
</playground>
+14
View File
@@ -32,6 +32,20 @@ public struct JSONAPIDocument<ResourceBody: JSONAPI.ResourceBody, Include: Inclu
return (primary: body, included: includes)
}
}
public init(errors: [Error]) {
body = .errors(errors)
}
public init(body: ResourceBody, includes: Includes<Include>) {
self.body = .data(primary: body, included: includes)
}
}
extension JSONAPIDocument where Include == NoIncludes {
public init(body: ResourceBody) {
self.body = .data(primary: body, included: .none)
}
}
extension JSONAPIDocument: Codable {
+9 -1
View File
@@ -52,6 +52,12 @@ public struct Includes<I: IncludeDecoder>: Codable, Equatable {
}
}
extension Includes where I == NoIncludes {
public init() {
values = []
}
}
// MARK: - Decoding
func decode<Entity: JSONAPI.EntityType>(_ type: Entity.Type, from container: SingleValueDecodingContainer) throws -> Result<Entity, EncodingError> {
@@ -73,7 +79,9 @@ func decode<Entity: JSONAPI.EntityType>(_ type: Entity.Type, from container: Sin
public protocol _Include0: IncludeDecoder { }
public struct Include0: _Include0 {
public init() {}
public init(from decoder: Decoder) throws {
}
@@ -10,10 +10,18 @@ public protocol ResourceBody: Codable, Equatable {
public struct SingleResourceBody<Entity: JSONAPI.EntityType>: ResourceBody {
public let value: Entity?
public init(entity: Entity?) {
self.value = entity
}
}
public struct ManyResourceBody<Entity: JSONAPI.EntityType>: ResourceBody {
public let values: [Entity]
public init(entities: [Entity]) {
values = entities
}
}
// MARK: Decodable
+2 -2
View File
@@ -16,10 +16,10 @@ public struct TransformAttribute<RawValue: Codable, Transformer: JSONAPI.Transfo
}
}
public typealias Attribute<T: Codable> = TransformAttribute<T, IdentityTransformer<T>>
extension TransformAttribute: Equatable where Transformer.From: Equatable, Transformer.To: Equatable {}
public typealias Attribute<T: Codable> = TransformAttribute<T, IdentityTransformer<T>>
// MARK: - Codable
extension TransformAttribute {
public init(from decoder: Decoder) throws {
+2 -2
View File
@@ -25,8 +25,8 @@ extension ToOneRelationship where Relatable.WrappedIdentifier == Relatable.Ident
}
extension ToOneRelationship where Relatable.WrappedIdentifier == Optional<Relatable.Identifier> {
public init(entity: Entity<Relatable.Description, Relatable.Identifier>) {
id = entity.id
public init(entity: Entity<Relatable.Description, Relatable.Identifier>?) {
id = entity?.id
}
}