mirror of
https://github.com/encounter/JSONAPI.git
synced 2026-07-10 12:18:40 -07:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cd75e9649b | |||
| c60dfc1584 | |||
| abe16dda0d | |||
| 5257fd79fa | |||
| f7a81df451 | |||
| c8fbc09582 | |||
| a88bb77bd0 | |||
| 247848e788 | |||
| 7adbdb4505 | |||
| ea663bb229 | |||
| f48c385f99 | |||
| c96bfadd82 | |||
| 88be701062 | |||
| 1e85e1d2a3 | |||
| 11a7727ac9 | |||
| e8bfbc881b | |||
| af757a2fac | |||
| 84955872f8 | |||
| cb2800abd4 | |||
| 85d5fef3c8 | |||
| e4ef61fd56 | |||
| 75ec4f156e | |||
| b45fc73188 | |||
| 3b73dc9989 | |||
| b2c81026f4 | |||
| 8d057b4398 | |||
| c8421cdd58 | |||
| cde10a8491 | |||
| ad05d3908a | |||
| 23b2b2e04f | |||
| 2988503d7d | |||
| 5ea83b07c1 | |||
| 2b59f54067 | |||
| 58a7c82436 | |||
| dc30cb3b9e | |||
| 7045373708 | |||
| 952fe8ba7e | |||
| 951c04ad44 | |||
| 57df6b147e | |||
| a88844fe5e | |||
| d1cf19f9fe | |||
| 59835fbe11 |
@@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import JSONAPI
|
||||
import Poly
|
||||
|
||||
// MARK: - Preamble (setup)
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
//: [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("====")
|
||||
@@ -63,7 +63,7 @@ public enum PersonDescription: EntityDescription {
|
||||
public typealias Person = ExampleEntity<PersonDescription>
|
||||
|
||||
public extension Entity where Description == PersonDescription, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == String {
|
||||
public init(id: Person.Id? = nil,name: [String], favoriteColor: String, friends: [Person], dogs: [Dog], home: House) throws {
|
||||
init(id: Person.Id? = nil,name: [String], favoriteColor: String, friends: [Person], dogs: [Dog], home: House) throws {
|
||||
self = Person(id: id ?? Person.Id(), attributes: .init(name: .init(value: name), favoriteColor: .init(value: favoriteColor)), relationships: .init(friends: .init(entities: friends), dogs: .init(entities: dogs), home: .init(entity: home)), meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
@@ -120,11 +120,11 @@ public enum AlternativeDogDescription: EntityDescription {
|
||||
public typealias AlternativeDog = ExampleEntity<AlternativeDogDescription>
|
||||
|
||||
public extension Entity where Description == DogDescription, MetaType == NoMetadata, LinksType == NoLinks, EntityRawIdType == String {
|
||||
public init(name: String, owner: Person?) throws {
|
||||
init(name: String, owner: Person?) throws {
|
||||
self = Dog(attributes: .init(name: .init(value: name)), relationships: DogDescription.Relationships(owner: .init(entity: owner)), meta: .none, links: .none)
|
||||
}
|
||||
|
||||
public init(name: String, owner: Person.Id) throws {
|
||||
init(name: String, owner: Person.Id) throws {
|
||||
self = Dog(attributes: .init(name: .init(value: name)), relationships: .init(owner: .init(id: owner)), meta: .none, links: .none)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
#
|
||||
# Be sure to run `pod spec lint JSONAPI.podspec' to ensure this is a
|
||||
# valid spec and to remove all comments including this before submitting the spec.
|
||||
#
|
||||
# To learn more about Podspec attributes see https://docs.cocoapods.org/specification.html
|
||||
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
|
||||
#
|
||||
|
||||
Pod::Spec.new do |spec|
|
||||
|
||||
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# These will help people to find your library, and whilst it
|
||||
# can feel like a chore to fill in it's definitely to your advantage. The
|
||||
# summary should be tweet-length, and the description more in depth.
|
||||
#
|
||||
|
||||
spec.name = "JSONAPI"
|
||||
spec.version = "0.19.0"
|
||||
spec.summary = "Swift Codable JSON API framework."
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
# * Think: What does it do? Why did you write it? What is the focus?
|
||||
# * Try to keep it short, snappy and to the point.
|
||||
# * Write the description between the DESC delimiters below.
|
||||
# * Finally, don't worry about the indent, CocoaPods strips it!
|
||||
spec.description = <<-DESC
|
||||
A Swift package for encoding to- and decoding from JSON API compliant requests and responses.
|
||||
|
||||
See the JSON API Spec here: https://jsonapi.org/format/
|
||||
DESC
|
||||
|
||||
spec.homepage = "https://github.com/mattpolzin/JSONAPI"
|
||||
# spec.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
|
||||
|
||||
|
||||
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Licensing your code is important. See https://choosealicense.com for more info.
|
||||
# CocoaPods will detect a license file if there is a named LICENSE*
|
||||
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
|
||||
#
|
||||
|
||||
# spec.license = "MIT"
|
||||
spec.license = { :type => "MIT", :file => "LICENSE.txt" }
|
||||
|
||||
|
||||
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Specify the authors of the library, with email addresses. Email addresses
|
||||
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
|
||||
# accepts just a name if you'd rather not provide an email address.
|
||||
#
|
||||
# Specify a social_media_url where others can refer to, for example a twitter
|
||||
# profile URL.
|
||||
#
|
||||
|
||||
spec.author = { "Mathew Polzin" => "matt.polzin@gmail.com" }
|
||||
# Or just: spec.author = "Mathew Polzin"
|
||||
# spec.authors = { "Mathew Polzin" => "matt.polzin@gmail.com" }
|
||||
# spec.social_media_url = "https://twitter.com/Mathew Polzin"
|
||||
|
||||
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# If this Pod runs only on iOS or OS X, then specify the platform and
|
||||
# the deployment target. You can optionally include the target after the platform.
|
||||
#
|
||||
|
||||
# spec.platform = :ios
|
||||
# spec.platform = :ios, "5.0"
|
||||
|
||||
# When using multiple platforms
|
||||
spec.ios.deployment_target = "8.0"
|
||||
spec.osx.deployment_target = "10.9"
|
||||
# spec.watchos.deployment_target = "2.0"
|
||||
# spec.tvos.deployment_target = "9.0"
|
||||
|
||||
|
||||
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Specify the location from where the source should be retrieved.
|
||||
# Supports git, hg, bzr, svn and HTTP.
|
||||
#
|
||||
|
||||
spec.source = { :git => "https://github.com/mattpolzin/JSONAPI.git", :tag => "#{spec.version}" }
|
||||
|
||||
|
||||
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# CocoaPods is smart about how it includes source code. For source files
|
||||
# giving a folder will include any swift, h, m, mm, c & cpp files.
|
||||
# For header files it will include any header in the folder.
|
||||
# Not including the public_header_files will make all headers public.
|
||||
#
|
||||
|
||||
spec.source_files = "Sources", "Sources/**/*.{swift}"
|
||||
# spec.exclude_files = "Classes/Exclude"
|
||||
|
||||
# spec.public_header_files = "Classes/**/*.h"
|
||||
|
||||
|
||||
# ――― Resources ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# A list of resources included with the Pod. These are copied into the
|
||||
# target bundle with a build phase script. Anything else will be cleaned.
|
||||
# You can preserve files from being cleaned, please don't preserve
|
||||
# non-essential files like tests, examples and documentation.
|
||||
#
|
||||
|
||||
# spec.resource = "icon.png"
|
||||
# spec.resources = "Resources/*.png"
|
||||
|
||||
# spec.preserve_paths = "FilesToSave", "MoreFilesToSave"
|
||||
|
||||
|
||||
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# Link your library with frameworks, or libraries. Libraries do not include
|
||||
# the lib prefix of their name.
|
||||
#
|
||||
|
||||
spec.framework = "Poly"
|
||||
# spec.frameworks = "SomeFramework", "AnotherFramework"
|
||||
|
||||
# spec.library = "iconv"
|
||||
# spec.libraries = "iconv", "xml2"
|
||||
|
||||
|
||||
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
|
||||
#
|
||||
# If your library depends on compiler flags you can set them in the xcconfig hash
|
||||
# where they will only apply to your library. If you depend on other Podspecs
|
||||
# you can include multiple dependencies to ensure it works.
|
||||
|
||||
spec.swift_version = "4.2"
|
||||
# spec.requires_arc = true
|
||||
|
||||
# spec.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" }
|
||||
spec.dependency "Poly", "~> 1.1"
|
||||
|
||||
end
|
||||
+2
-29
@@ -1,40 +1,13 @@
|
||||
{
|
||||
"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": "master",
|
||||
"revision": "77f45b8963a51c02d71fc4075eba5cff47ff0d07",
|
||||
"version": null
|
||||
}
|
||||
},
|
||||
{
|
||||
"package": "SwiftCheck",
|
||||
"repositoryURL": "https://github.com/typelift/SwiftCheck.git",
|
||||
"state": {
|
||||
"branch": null,
|
||||
"revision": "cf9958085b2ee1643e541e407c3233d1b76c18ff",
|
||||
"version": "0.11.0"
|
||||
"revision": "77f45b8963a51c02d71fc4075eba5cff47ff0d07",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
+3
-23
@@ -11,18 +11,10 @@ let package = Package(
|
||||
targets: ["JSONAPI"]),
|
||||
.library(
|
||||
name: "JSONAPITesting",
|
||||
targets: ["JSONAPITesting"]),
|
||||
.library(
|
||||
name: "JSONAPIArbitrary",
|
||||
targets: ["JSONAPIArbitrary"]),
|
||||
.library(
|
||||
name: "JSONAPIOpenAPI",
|
||||
targets: ["JSONAPIOpenAPI"])
|
||||
targets: ["JSONAPITesting"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/mattpolzin/Poly.git", .branch("master")),
|
||||
.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")
|
||||
.package(url: "https://github.com/mattpolzin/Poly.git", from: "1.0.0"),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
@@ -31,24 +23,12 @@ let package = Package(
|
||||
.target(
|
||||
name: "JSONAPITesting",
|
||||
dependencies: ["JSONAPI"]),
|
||||
.target(
|
||||
name: "JSONAPIArbitrary",
|
||||
dependencies: ["JSONAPI", "SwiftCheck"]),
|
||||
.target(
|
||||
name: "JSONAPIOpenAPI",
|
||||
dependencies: ["JSONAPI", "AnyCodable", "JSONAPIArbitrary"]),
|
||||
.testTarget(
|
||||
name: "JSONAPITests",
|
||||
dependencies: ["JSONAPI", "JSONAPITesting"]),
|
||||
.testTarget(
|
||||
name: "JSONAPITestingTests",
|
||||
dependencies: ["JSONAPI", "JSONAPITesting"]),
|
||||
.testTarget(
|
||||
name: "JSONAPIArbitraryTests",
|
||||
dependencies: ["JSONAPI", "SwiftCheck", "JSONAPIArbitrary"]),
|
||||
.testTarget(
|
||||
name: "JSONAPIOpenAPITests",
|
||||
dependencies: ["JSONAPI", "JSONAPIOpenAPI"])
|
||||
dependencies: ["JSONAPI", "JSONAPITesting"])
|
||||
],
|
||||
swiftLanguageVersions: [.v4_2]
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ See the JSON API Spec here: https://jsonapi.org/format/
|
||||
- [Caveat](#caveat)
|
||||
- [Dev Environment](#dev-environment)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [CocoaPods](#cocoapods)
|
||||
- [Xcode project](#xcode-project)
|
||||
- [Running the Playground](#running-the-playground)
|
||||
- [Project Status](#project-status)
|
||||
@@ -33,8 +34,8 @@ See the JSON API Spec here: https://jsonapi.org/format/
|
||||
- [`JSONAPI.Entity`](#jsonapientity)
|
||||
- [`Meta`](#meta)
|
||||
- [`Links`](#links)
|
||||
- [`IdType`](#idtype)
|
||||
- [`MaybeRawId`](#mayberawid)
|
||||
- [`RawIdType`](#rawidtype)
|
||||
- [Convenient `typealiases`](#convenient-typealiases)
|
||||
- [`JSONAPI.Relationships`](#jsonapirelationships)
|
||||
- [`JSONAPI.Attributes`](#jsonapiattributes)
|
||||
@@ -82,7 +83,15 @@ If you find something wrong with this library and it isn't already mentioned und
|
||||
|
||||
## Dev Environment
|
||||
### Prerequisites
|
||||
1. Swift 4.2+ and Swift Package Manager
|
||||
1. Swift 4.2+
|
||||
2. Swift Package Manager *OR* Cocoapods
|
||||
|
||||
### CocoaPods
|
||||
To use this framework in your project via Cocoapods instead of Swift Package Manager, add the following dependencies to your Podfile.
|
||||
```
|
||||
pod 'Poly', :git => 'https://github.com/mattpolzin/Poly.git'
|
||||
pod 'JSONAPI', :git => 'https://github.com/mattpolzin/JSONAPI.git'
|
||||
```
|
||||
|
||||
### Xcode project
|
||||
To create an Xcode project for JSONAPI, run
|
||||
@@ -258,23 +267,23 @@ An `Entity` needs to be specialized on four generic types. The first is the `Ent
|
||||
|
||||
#### `Meta`
|
||||
|
||||
The second generic specialization on `Entity` is `Meta`. This is described in its own section [below](#jsonapimeta). All `Meta` at any level of a JSON API Document follow the same rules.
|
||||
The second generic specialization on `Entity` is `Meta`. This is described in its own section [below](#jsonapimeta). All `Meta` at any level of a JSON API Document follow the same rules. You can use `NoMetadata` if you do not need to package any metadata with the `Entity`.
|
||||
|
||||
#### `Links`
|
||||
|
||||
The third generic specialization on `Entity` is `Links`. This is described in its own section [below](#jsonnapilinks). All `Links` at any level of a JSON API Document follow the same rules, although the **SPEC** makes different suggestions as to what types of links might live on which parts of the Document.
|
||||
|
||||
#### `IdType`
|
||||
|
||||
The second is the raw type of `Id` to use for the `Entity`. The actual `Id` of the `Entity` will not be a `RawIdType`, though. The `Id` will package a value of `RawIdType` with a specialized reference back to the `Entity` type it identifies. This just looks like `Id<RawIdType, Entity<EntityDescription, RawIdType>>`.
|
||||
|
||||
Having the `Entity` type associated with the `Id` makes it easy to store all of your entities in a hash broken out by `Entity` type; You can pass `Ids` around and always know where to look for the `Entity` to which the `Id` refers.
|
||||
|
||||
A `RawIdType` is the underlying type that uniquely identifies an `Entity`. This is often a `String` or a `UUID`.
|
||||
The third generic specialization on `Entity` is `Links`. This is described in its own section [below](#jsonnapilinks). All `Links` at any level of a JSON API Document follow the same rules, although the **SPEC** makes different suggestions as to what types of links might live on which parts of the Document. You can use `NoLinks` if you do not need to package any links with the `Entity`.
|
||||
|
||||
#### `MaybeRawId`
|
||||
|
||||
`MaybeRawId` is either a `RawIdType` that can be used to uniquely identify `Entities` or it is `Unidentified` which is used to indicate an `Entity` does not have an `Id` (which is useful when a client is requesting that the server create an `Entity` and assign it a new `Id`).
|
||||
The last generic specialization on `Entity` is `MaybeRawId`. This is either a `RawIdType` that can be used to uniquely identify `Entities` or it is `Unidentified` which is used to indicate an `Entity` does not have an `Id` (which is useful when a client is requesting that the server create an `Entity` and assign it a new `Id`).
|
||||
|
||||
##### `RawIdType`
|
||||
|
||||
The raw type of `Id` to use for the `Entity`. The actual `Id` of the `Entity` will not be a `RawIdType`, though. The `Id` will package a value of `RawIdType` with a specialized reference back to the `Entity` type it identifies. This just looks like `Id<RawIdType, Entity<EntityDescription, Meta, Links, RawIdType>>`.
|
||||
|
||||
Having the `Entity` type associated with the `Id` makes it easy to store all of your entities in a hash broken out by `Entity` type; You can pass `Ids` around and always know where to look for the `Entity` to which the `Id` refers. This encapsulation provides some type safety because the Ids of two `Entities` with the "raw ID" of `"1"` but different types will not compare as equal.
|
||||
|
||||
A `RawIdType` is the underlying type that uniquely identifies an `Entity`. This is often a `String` or a `UUID`.
|
||||
|
||||
#### Convenient `typealiases`
|
||||
|
||||
@@ -836,11 +845,7 @@ print(response.author)
|
||||
The `JSONAPI` framework is packaged with a test library to help you test your `JSONAPI` integration. The test library is called `JSONAPITesting`. It provides literal expressibility for `Attribute`, `ToOneRelationship`, and `Id` in many situations so that you can easily write test `Entity` values into your unit tests. It also provides a `check()` function for each `Entity` type that can be used to catch problems with your `JSONAPI` structures that are not caught by Swift's type system. You can see the `JSONAPITesting` in action in the Playground included with the `JSONAPI` repository.
|
||||
|
||||
# JSONAPI+Arbitrary
|
||||
The `JSONAPIArbitrary` framework adds `Arbitrary` support via `SwiftCheck`. With a little extra work on your part, this framework will allow you to create "arbitrary" (i.e. randomly generated) instances of your JSONAPI entities, includes, documents, etc.
|
||||
|
||||
This Framework is currently undocumented, but familiarity with `SwiftCheck` will likely afford the user enough information to use this library to aid in the generation of arbitrary JSONAPI Documents for testing purposes.
|
||||
This library has moved into its own Package. See https://github.com/mattpolzin/JSONAPI-Arbitrary
|
||||
|
||||
# JSONAPI+OpenAPI
|
||||
The `JSONAPIOpenAPI` framework adds the ability to generate OpenAPI compliant JSON documentation of a JSONAPI Document.
|
||||
|
||||
This library is in its infancy. The documentation will grow as the framework becomes more complete.
|
||||
This library has moved into its own Package. See https://github.com/mattpolzin/JSONAPI-OpenAPI
|
||||
|
||||
@@ -15,7 +15,7 @@ public extension TransformedAttribute {
|
||||
/// 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.
|
||||
public func map<T: Codable>(_ transform: (Transformer.To) throws -> T) rethrows -> Attribute<T> {
|
||||
func map<T: Codable>(_ transform: (Transformer.To) throws -> T) rethrows -> Attribute<T> {
|
||||
return Attribute<T>(value: try transform(value))
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ public extension 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.
|
||||
public func map<T: Codable>(_ transform: (ValueType) throws -> T) rethrows -> Attribute<T> {
|
||||
func map<T: Codable>(_ transform: (ValueType) throws -> T) rethrows -> Attribute<T> {
|
||||
return Attribute<T>(value: try transform(value))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,20 +397,20 @@ public extension Entity where EntityRawIdType: JSONAPI.RawIdType {
|
||||
/// An Entity.Pointer is a `ToOneRelationship` with no metadata or links.
|
||||
/// This is just a convenient way to reference an Entity so that
|
||||
/// other Entities' Relationships can be built up from it.
|
||||
public typealias Pointer = ToOneRelationship<Entity, NoMetadata, NoLinks>
|
||||
typealias Pointer = ToOneRelationship<Entity, NoMetadata, NoLinks>
|
||||
|
||||
/// Entity.Pointers is a `ToManyRelationship` with no metadata or links.
|
||||
/// This is just a convenient way to reference a bunch of Entities so
|
||||
/// that other Entities' Relationships can be built up from them.
|
||||
public typealias Pointers = ToManyRelationship<Entity, NoMetadata, NoLinks>
|
||||
typealias Pointers = ToManyRelationship<Entity, NoMetadata, NoLinks>
|
||||
|
||||
/// Get a pointer to this entity that can be used as a
|
||||
/// relationship to another entity.
|
||||
public var pointer: Pointer {
|
||||
var pointer: Pointer {
|
||||
return Pointer(entity: self)
|
||||
}
|
||||
|
||||
public func pointer<MType: JSONAPI.Meta, LType: JSONAPI.Links>(withMeta meta: MType, links: LType) -> ToOneRelationship<Entity, MType, LType> {
|
||||
func pointer<MType: JSONAPI.Meta, LType: JSONAPI.Links>(withMeta meta: MType, links: LType) -> ToOneRelationship<Entity, MType, LType> {
|
||||
return ToOneRelationship(entity: self, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
@@ -419,19 +419,19 @@ public extension Entity where EntityRawIdType: JSONAPI.RawIdType {
|
||||
public extension Entity where EntityRawIdType == Unidentified {
|
||||
/// Create a new Entity from this one with a newly created
|
||||
/// unique Id of the given type.
|
||||
public func identified<RawIdType: CreatableRawIdType>(byType: RawIdType.Type) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
func identified<RawIdType: CreatableRawIdType>(byType: RawIdType.Type) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
return .init(attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
|
||||
/// Create a new Entity from this one with the given Id.
|
||||
public func identified<RawIdType: JSONAPI.RawIdType>(by id: RawIdType) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
func identified<RawIdType: JSONAPI.RawIdType>(by id: RawIdType) -> Entity<Description, MetaType, LinksType, RawIdType> {
|
||||
return .init(id: Entity<Description, MetaType, LinksType, RawIdType>.Identifier(rawValue: id), attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
|
||||
public extension Entity where EntityRawIdType: CreatableRawIdType {
|
||||
/// Create a copy of this Entity with a new unique Id.
|
||||
public func withNewIdentifier() -> Entity {
|
||||
func withNewIdentifier() -> Entity {
|
||||
return Entity(attributes: attributes, relationships: relationships, meta: meta, links: links)
|
||||
}
|
||||
}
|
||||
@@ -485,14 +485,14 @@ 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 ~><OtherEntity: Identifiable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>>) -> OtherEntity.Identifier {
|
||||
static func ~><OtherEntity: Identifiable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>>) -> OtherEntity.Identifier {
|
||||
return entity.relationships[keyPath: path].id
|
||||
}
|
||||
|
||||
/// Access to an Id of an optional `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other?.id`.
|
||||
public static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier {
|
||||
static func ~><OtherEntity: OptionalRelatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier {
|
||||
// Implementation Note: This signature applies to `ToOneRelationship<E?, _, _>?`
|
||||
// whereas the one below applies to `ToOneRelationship<E, _, _>?`
|
||||
return entity.relationships[keyPath: path]?.id
|
||||
@@ -501,7 +501,7 @@ public extension EntityProxy {
|
||||
/// Access to an Id of an optional `ToOneRelationship`.
|
||||
/// This allows you to write `entity ~> \.other` instead
|
||||
/// of `entity.relationships.other?.id`.
|
||||
public static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier? {
|
||||
static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToOneRelationship<OtherEntity, MType, LType>?>) -> OtherEntity.Identifier? {
|
||||
// Implementation Note: This signature applies to `ToOneRelationship<E, _, _>?`
|
||||
// whereas the one above applies to `ToOneRelationship<E?, _, _>?`
|
||||
return entity.relationships[keyPath: path]?.id
|
||||
@@ -510,14 +510,14 @@ public extension EntityProxy {
|
||||
/// Access to all Ids of a `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others.ids`.
|
||||
public static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity, MType, LType>>) -> [OtherEntity.Identifier] {
|
||||
static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity, MType, LType>>) -> [OtherEntity.Identifier] {
|
||||
return entity.relationships[keyPath: path].ids
|
||||
}
|
||||
|
||||
/// Access to all Ids of an optional `ToManyRelationship`.
|
||||
/// This allows you to write `entity ~> \.others` instead
|
||||
/// of `entity.relationships.others?.ids`.
|
||||
public static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity, MType, LType>?>) -> [OtherEntity.Identifier]? {
|
||||
static func ~><OtherEntity: Relatable, MType: JSONAPI.Meta, LType: JSONAPI.Links>(entity: Self, path: KeyPath<Description.Relationships, ToManyRelationship<OtherEntity, MType, LType>?>) -> [OtherEntity.Identifier]? {
|
||||
return entity.relationships[keyPath: path]?.ids
|
||||
}
|
||||
}
|
||||
@@ -527,14 +527,14 @@ 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 {
|
||||
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] {
|
||||
static func ~><Identifier: IdType>(entity: Self, path: KeyPath<Description.Relationships, (Self) -> [Identifier]>) -> [Identifier] {
|
||||
return entity.relationships[keyPath: path](entity)
|
||||
}
|
||||
}
|
||||
@@ -552,7 +552,7 @@ private enum ResourceObjectCodingKeys: String, CodingKey {
|
||||
}
|
||||
|
||||
public extension Entity {
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: ResourceObjectCodingKeys.self)
|
||||
|
||||
try container.encode(Entity.jsonType, forKey: .type)
|
||||
@@ -578,7 +578,7 @@ public extension Entity {
|
||||
}
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
init(from decoder: Decoder) throws {
|
||||
|
||||
let container = try decoder.container(keyedBy: ResourceObjectCodingKeys.self)
|
||||
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
//
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
//
|
||||
// Attribute+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/15/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension Attribute: Arbitrary where RawValue: Arbitrary {
|
||||
public static var arbitrary: Gen<Attribute<RawValue>> {
|
||||
return RawValue.arbitrary.map { .init(value: $0) }
|
||||
}
|
||||
}
|
||||
|
||||
// Cannot conform TransformedAttribute to Arbitrary here
|
||||
// because there is no way to guarantee that an arbitrary
|
||||
// RawValue will successfully transform or that an
|
||||
// arbitrary Value will successfully reverse-transform.
|
||||
@@ -1,110 +0,0 @@
|
||||
//
|
||||
// Document+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/21/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension Document.Body.Data: Arbitrary where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
public static var arbitrary: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body.Data> {
|
||||
return Gen.compose { c in
|
||||
Document.Body.Data(primary: c.generate(),
|
||||
includes: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Document.Body: Arbitrary where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary {
|
||||
public static var arbitrary: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body> {
|
||||
return Gen.one(of: [
|
||||
arbitraryData,
|
||||
arbitraryErrors
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Document.Body where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
/// Arbitrary Document.Body with data (guaranteed to not
|
||||
/// be an error body).
|
||||
public static var arbitraryData: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body> {
|
||||
return Document.Body.Data.arbitrary.map(Document.Body.data)
|
||||
}
|
||||
}
|
||||
|
||||
extension Document.Body where MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary {
|
||||
/// Arbitrary Document.Body with errors (guaranteed to not
|
||||
/// be a data body).
|
||||
public static var arbitraryErrors: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body> {
|
||||
return Gen.compose { c in
|
||||
Document.Body.errors(c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Document.Body where Error: Arbitrary {
|
||||
/// Arbitrary Document.Body with errors but no
|
||||
/// metadata or links (also guaranteed to not
|
||||
/// be a data body).
|
||||
public static var arbitraryErrorsWithoutMetaOrLinks: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>.Body> {
|
||||
return Gen.compose { c in
|
||||
Document.Body.errors(c.generate(),
|
||||
meta: nil,
|
||||
links: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Document: Arbitrary where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary, APIDescription: Arbitrary {
|
||||
public static var arbitrary: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>> {
|
||||
return Gen.one(of: [
|
||||
arbitraryData,
|
||||
arbitraryErrors
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Document where PrimaryResourceBody: Arbitrary, IncludeType: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary, APIDescription: Arbitrary {
|
||||
/// Arbitrary Document with data (guaranteed to not
|
||||
/// be an error body).
|
||||
public static var arbitraryData: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>> {
|
||||
return Gen.compose { c in
|
||||
Document(apiDescription: c.generate(),
|
||||
body: c.generate(),
|
||||
includes: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Document where MetaType: Arbitrary, LinksType: Arbitrary, Error: Arbitrary, APIDescription: Arbitrary {
|
||||
/// Arbitrary Document with errors (guaranteed to not
|
||||
/// be a data body).
|
||||
public static var arbitraryErrors: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>> {
|
||||
return Gen.compose { c in
|
||||
Document(apiDescription: c.generate(),
|
||||
errors: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Document where Error: Arbitrary, APIDescription: Arbitrary {
|
||||
/// Arbitrary Document with errors but no
|
||||
/// metadata or links (also guaranteed to not
|
||||
/// be a data body).
|
||||
public static var arbitraryErrors: Gen<Document<PrimaryResourceBody, MetaType, LinksType, IncludeType, APIDescription, Error>> {
|
||||
return Gen.compose { c in
|
||||
Document(apiDescription: c.generate(),
|
||||
errors: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
//
|
||||
// Entity+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/14/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension NoMetadata: Arbitrary {
|
||||
public static var arbitrary: Gen<NoMetadata> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
|
||||
extension NoLinks: Arbitrary {
|
||||
public static var arbitrary: Gen<NoLinks> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
|
||||
extension NoAttributes: Arbitrary {
|
||||
public static var arbitrary: Gen<NoAttributes> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
|
||||
extension NoRelationships: Arbitrary {
|
||||
public static var arbitrary: Gen<NoRelationships> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: Arbitrary conformance for MetaType, LinksType, Description.Attributes,
|
||||
// and Description.Relationships must all be provided BY YOU for Entity to
|
||||
// gain Arbitrary conformance (with the exception of NoMetadata, NoLinks,
|
||||
// NoAttributes, and NoRelationships which all have Arbitrary conformance
|
||||
// out of the box).
|
||||
extension Entity: Arbitrary where MetaType: Arbitrary, LinksType: Arbitrary, Description.Attributes: Arbitrary, Description.Relationships: Arbitrary, EntityRawIdType: Arbitrary {
|
||||
public static var arbitrary: Gen<Entity<Description, MetaType, LinksType, EntityRawIdType>> {
|
||||
return Gen.compose { c in
|
||||
Entity(id: c.generate(),
|
||||
attributes: c.generate(),
|
||||
relationships: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Error+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/21/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension UnknownJSONAPIError: Arbitrary {
|
||||
public static var arbitrary: Gen<UnknownJSONAPIError> {
|
||||
return Gen.pure(.unknownError)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
//
|
||||
// Id+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/14/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension Unidentified: Arbitrary {
|
||||
public static var arbitrary: Gen<Unidentified> {
|
||||
return Gen.pure(.init())
|
||||
}
|
||||
}
|
||||
|
||||
extension Id: Arbitrary where RawType: Arbitrary {
|
||||
public static var arbitrary: Gen<Id<RawType, IdentifiableType>> {
|
||||
return RawType.arbitrary.map { Id(rawValue: $0) }
|
||||
}
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
//
|
||||
// Includes+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/21/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension Includes: Arbitrary where I: Arbitrary {
|
||||
public static var arbitrary: Gen<Includes<I>> {
|
||||
return I
|
||||
.arbitrary
|
||||
.proliferate
|
||||
.map(Includes.init(values:))
|
||||
}
|
||||
}
|
||||
|
||||
extension NoIncludes: Arbitrary {
|
||||
public static var arbitrary: Gen<NoIncludes> {
|
||||
return Gen.pure(NoIncludes())
|
||||
}
|
||||
}
|
||||
|
||||
extension Include1: Arbitrary where A: Arbitrary {
|
||||
public static var arbitrary: Gen<Include1<A>> {
|
||||
return Gen.one(of: [
|
||||
A.arbitrary.map(Include1.init)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include2: Arbitrary where A: Arbitrary, B: Arbitrary {
|
||||
public static var arbitrary: Gen<Include2<A, B>> {
|
||||
return Gen.one(of: [
|
||||
A.arbitrary.map(Include2.init),
|
||||
B.arbitrary.map(Include2.init)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include3: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary {
|
||||
public static var arbitrary: Gen<Include3<A, B, C>> {
|
||||
return Gen.one(of: [
|
||||
A.arbitrary.map(Include3.init),
|
||||
B.arbitrary.map(Include3.init),
|
||||
C.arbitrary.map(Include3.init)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include4: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary {
|
||||
public static var arbitrary: Gen<Include4<A, B, C, D>> {
|
||||
return Gen.one(of: [
|
||||
A.arbitrary.map(Include4.init),
|
||||
B.arbitrary.map(Include4.init),
|
||||
C.arbitrary.map(Include4.init),
|
||||
D.arbitrary.map(Include4.init)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include5: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary {
|
||||
public static var arbitrary: Gen<Include5<A, B, C, D, E>> {
|
||||
return Gen.one(of: [
|
||||
A.arbitrary.map(Include5.init),
|
||||
B.arbitrary.map(Include5.init),
|
||||
C.arbitrary.map(Include5.init),
|
||||
D.arbitrary.map(Include5.init),
|
||||
E.arbitrary.map(Include5.init)
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include6: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, F: Arbitrary {
|
||||
public static var arbitrary: Gen<Include6<A, B, C, D, E, F>> {
|
||||
// Note broken up because compiler cannot typecheck entire array
|
||||
// before it times out
|
||||
let set1: [Gen<Include6<A, B, C, D, E, F>>] = [
|
||||
A.arbitrary.map(Include6.init),
|
||||
B.arbitrary.map(Include6.init),
|
||||
C.arbitrary.map(Include6.init)
|
||||
]
|
||||
|
||||
let set2: [Gen<Include6<A, B, C, D, E, F>>] = [
|
||||
D.arbitrary.map(Include6.init),
|
||||
E.arbitrary.map(Include6.init),
|
||||
F.arbitrary.map(Include6.init)
|
||||
]
|
||||
|
||||
return Gen.one(of: set1 + set2)
|
||||
}
|
||||
}
|
||||
|
||||
extension Include7: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, F: Arbitrary, G: Arbitrary {
|
||||
public static var arbitrary: Gen<Include7<A, B, C, D, E, F, G>> {
|
||||
// Note broken up because compiler cannot typecheck entire array
|
||||
// before it times out
|
||||
let set1: [Gen<Include7<A, B, C, D, E, F, G>>] = [
|
||||
A.arbitrary.map(Include7.init),
|
||||
B.arbitrary.map(Include7.init),
|
||||
C.arbitrary.map(Include7.init)
|
||||
]
|
||||
|
||||
let set2: [Gen<Include7<A, B, C, D, E, F, G>>] = [
|
||||
D.arbitrary.map(Include7.init),
|
||||
E.arbitrary.map(Include7.init),
|
||||
F.arbitrary.map(Include7.init),
|
||||
G.arbitrary.map(Include7.init)
|
||||
]
|
||||
|
||||
return Gen.one(of: set1 + set2)
|
||||
}
|
||||
}
|
||||
|
||||
extension Include8: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, F: Arbitrary, G: Arbitrary, H: Arbitrary {
|
||||
public static var arbitrary: Gen<Include8<A, B, C, D, E, F, G, H>> {
|
||||
// Note broken up because compiler cannot typecheck entire array
|
||||
// before it times out
|
||||
let set1: [Gen<Include8<A, B, C, D, E, F, G, H>>] = [
|
||||
A.arbitrary.map(Include8.init),
|
||||
B.arbitrary.map(Include8.init),
|
||||
C.arbitrary.map(Include8.init)
|
||||
]
|
||||
|
||||
let set2: [Gen<Include8<A, B, C, D, E, F, G, H>>] = [
|
||||
D.arbitrary.map(Include8.init),
|
||||
E.arbitrary.map(Include8.init),
|
||||
F.arbitrary.map(Include8.init)
|
||||
]
|
||||
|
||||
let set3: [Gen<Include8<A, B, C, D, E, F, G, H>>] = [
|
||||
G.arbitrary.map(Include8.init),
|
||||
H.arbitrary.map(Include8.init)
|
||||
]
|
||||
|
||||
return Gen.one(of: set1 + set2 + set3)
|
||||
}
|
||||
}
|
||||
|
||||
extension Include9: Arbitrary where A: Arbitrary, B: Arbitrary, C: Arbitrary, D: Arbitrary, E: Arbitrary, F: Arbitrary, G: Arbitrary, H: Arbitrary, I: Arbitrary {
|
||||
public static var arbitrary: Gen<Include9<A, B, C, D, E, F, G, H, I>> {
|
||||
// Note broken up because compiler cannot typecheck entire array
|
||||
// before it times out
|
||||
let set1: [Gen<Include9<A, B, C, D, E, F, G, H, I>>] = [
|
||||
A.arbitrary.map(Include9.init),
|
||||
B.arbitrary.map(Include9.init),
|
||||
C.arbitrary.map(Include9.init)
|
||||
]
|
||||
|
||||
let set2: [Gen<Include9<A, B, C, D, E, F, G, H, I>>] = [
|
||||
D.arbitrary.map(Include9.init),
|
||||
E.arbitrary.map(Include9.init),
|
||||
F.arbitrary.map(Include9.init)
|
||||
]
|
||||
|
||||
let set3: [Gen<Include9<A, B, C, D, E, F, G, H, I>>] = [
|
||||
G.arbitrary.map(Include9.init),
|
||||
H.arbitrary.map(Include9.init),
|
||||
I.arbitrary.map(Include9.init)
|
||||
]
|
||||
|
||||
return Gen.one(of: set1 + set2 + set3)
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
//
|
||||
// Relationship+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/15/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension ToOneRelationship: Arbitrary where Identifiable.Identifier: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
public static var arbitrary: Gen<ToOneRelationship<Identifiable, MetaType, LinksType>> {
|
||||
return Gen.compose { c in
|
||||
return .init(id: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ToOneRelationship where MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
/// Create a generator of arbitrary ToOneRelationships that will all
|
||||
/// point to one of the given entities. This allows you to create
|
||||
/// arbitrary relationships that make sense in a broader context where
|
||||
/// the relationship must actually point to another entity.
|
||||
public static func arbitrary<E: EntityType>(givenEntities: [E]) -> Gen<ToOneRelationship<Identifiable, MetaType, LinksType>> where E.Id == Identifiable.Identifier {
|
||||
|
||||
return Gen.compose { c in
|
||||
let idGen = Gen.fromElements(of: givenEntities).map { $0.id }
|
||||
return .init(id: c.generate(using: idGen),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ToManyRelationship: Arbitrary where Relatable.Identifier: Arbitrary, MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
public static var arbitrary: Gen<ToManyRelationship<Relatable, MetaType, LinksType>> {
|
||||
return Gen.compose { c in
|
||||
return .init(ids: c.generate(),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ToManyRelationship where MetaType: Arbitrary, LinksType: Arbitrary {
|
||||
/// Create a generator of arbitrary ToManyRelationships that will all
|
||||
/// point to some number of the given entities. This allows you to create
|
||||
/// arbitrary relationships that make sense in a broader context where
|
||||
/// the relationship must actually point to other existing entities.
|
||||
public static func arbitrary<E: EntityType>(givenEntities: [E]) -> Gen<ToManyRelationship<Relatable, MetaType, LinksType>> where E.Id == Relatable.Identifier {
|
||||
return Gen.compose { c in
|
||||
let idsGen = Gen.fromElements(of: givenEntities).map { $0.id }.proliferate
|
||||
return .init(ids: c.generate(using: idsGen),
|
||||
meta: c.generate(),
|
||||
links: c.generate())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
//
|
||||
// ResourceBody+Arbitrary.swift
|
||||
// JSONAPIArbitrary
|
||||
//
|
||||
// Created by Mathew Polzin on 1/21/19.
|
||||
//
|
||||
|
||||
import SwiftCheck
|
||||
import JSONAPI
|
||||
|
||||
extension SingleResourceBody: Arbitrary where Entity: Arbitrary {
|
||||
public static var arbitrary: Gen<SingleResourceBody<Entity>> {
|
||||
return Entity.arbitrary.map(SingleResourceBody.init(entity:))
|
||||
}
|
||||
}
|
||||
|
||||
extension ManyResourceBody: Arbitrary where Entity: Arbitrary {
|
||||
public static var arbitrary: Gen<ManyResourceBody<Entity>> {
|
||||
return Entity.arbitrary.proliferate.map(ManyResourceBody.init(entities:))
|
||||
}
|
||||
}
|
||||
|
||||
extension NoResourceBody: Arbitrary {
|
||||
public static var arbitrary: Gen<NoResourceBody> {
|
||||
return Gen.pure(.none)
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
//
|
||||
// JSONAPIInclude+OpenAPI.swift
|
||||
// JSONAPIOpenAPI
|
||||
//
|
||||
// Created by Mathew Polzin on 1/22/19.
|
||||
//
|
||||
|
||||
import JSONAPI
|
||||
|
||||
extension Includes: OpenAPINodeType where I: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
let includeNode = try I.openAPINode()
|
||||
|
||||
return .array(.init(format: .generic,
|
||||
required: true),
|
||||
.init(items: includeNode,
|
||||
uniqueItems: true))
|
||||
}
|
||||
}
|
||||
|
||||
extension Include0: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
throw OpenAPITypeError.invalidNode
|
||||
}
|
||||
}
|
||||
|
||||
extension Include1: OpenAPINodeType where A: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [A.openAPINode()])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include2: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include3: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include4: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include5: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType, E: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode(),
|
||||
E.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include6: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType, E: OpenAPINodeType, F: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode(),
|
||||
E.openAPINode(),
|
||||
F.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include7: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType, E: OpenAPINodeType, F: OpenAPINodeType, G: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode(),
|
||||
E.openAPINode(),
|
||||
F.openAPINode(),
|
||||
G.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include8: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType, E: OpenAPINodeType, F: OpenAPINodeType, G: OpenAPINodeType, H: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode(),
|
||||
E.openAPINode(),
|
||||
F.openAPINode(),
|
||||
G.openAPINode(),
|
||||
H.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
extension Include9: OpenAPINodeType where A: OpenAPINodeType, B: OpenAPINodeType, C: OpenAPINodeType, D: OpenAPINodeType, E: OpenAPINodeType, F: OpenAPINodeType, G: OpenAPINodeType, H: OpenAPINodeType, I: OpenAPINodeType {
|
||||
public static func openAPINode() throws -> JSONNode {
|
||||
return try .one(of: [
|
||||
A.openAPINode(),
|
||||
B.openAPINode(),
|
||||
C.openAPINode(),
|
||||
D.openAPINode(),
|
||||
E.openAPINode(),
|
||||
F.openAPINode(),
|
||||
G.openAPINode(),
|
||||
H.openAPINode(),
|
||||
I.openAPINode()
|
||||
])
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user