Skip to content

Commit c645c73

Browse files
authored
Merge pull request #87 from mattpolzin/release/v5
Release/v5
2 parents f64ef95 + 6a7072e commit c645c73

35 files changed

Lines changed: 1079 additions & 252 deletions

.github/workflows/tests.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ jobs:
1818
- swift:5.2-focal
1919
- swift:5.2-centos8
2020
- swift:5.2-amazonlinux2
21-
- swiftlang/swift:nightly-5.3-xenial
22-
- swiftlang/swift:nightly-5.3-bionic
21+
- swift:5.3-xenial
22+
- swift:5.3-bionic
23+
- swift:5.3-focal
24+
- swift:5.3-centos8
25+
- swift:5.3-amazonlinux2
2326
container: ${{ matrix.image }}
2427
steps:
2528
- name: Checkout code

JSONAPI.playground/Pages/Full Client & Server Example.xcplaygroundpage/Contents.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ typealias UnidentifiedJSONEntity<Description: ResourceObjectDescription> = JSONA
3030
// Create relationship typealiases because we do not expect
3131
// JSON:API Relationships for this particular API to have
3232
// Metadata or Links associated with them.
33-
typealias ToOneRelationship<Entity: JSONAPIIdentifiable> = JSONAPI.ToOneRelationship<Entity, NoMetadata, NoLinks>
34-
typealias ToManyRelationship<Entity: Relatable> = JSONAPI.ToManyRelationship<Entity, NoMetadata, NoLinks>
33+
typealias ToOneRelationship<Entity: JSONAPIIdentifiable> = JSONAPI.ToOneRelationship<Entity, NoIdMetadata, NoMetadata, NoLinks>
34+
typealias ToManyRelationship<Entity: Relatable> = JSONAPI.ToManyRelationship<Entity, NoIdMetadata, NoMetadata, NoLinks>
3535

3636
// Create a typealias for a Document because we do not expect
3737
// JSON:API Documents for this particular API to have Metadata, Links,

JSONAPI.playground/Pages/Full Document Verbose Generation.xcplaygroundpage/Contents.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ enum AuthorDescription: ResourceObjectDescription {
7272
}
7373

7474
struct Relationships: JSONAPI.Relationships {
75-
let articles: ToManyRelationship<Article, ToManyRelationshipMetadata, ToManyRelationshipLinks>
75+
let articles: ToManyRelationship<Article, NoIdMetadata, ToManyRelationshipMetadata, ToManyRelationshipLinks>
7676
}
7777
}
7878

@@ -88,11 +88,11 @@ enum ArticleDescription: ResourceObjectDescription {
8888

8989
struct Relationships: JSONAPI.Relationships {
9090
/// The primary attributed author of the article.
91-
let primaryAuthor: ToOneRelationship<Author, NoMetadata, NoLinks>
91+
let primaryAuthor: ToOneRelationship<Author, NoIdMetadata, NoMetadata, NoLinks>
9292
/// All authors excluding the primary author.
9393
/// It is customary to print the primary author's
9494
/// name first, followed by the other authors.
95-
let otherAuthors: ToManyRelationship<Author, ToManyRelationshipMetadata, ToManyRelationshipLinks>
95+
let otherAuthors: ToManyRelationship<Author, NoIdMetadata, ToManyRelationshipMetadata, ToManyRelationshipLinks>
9696
}
9797
}
9898

JSONAPI.playground/Sources/Entities.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ extension String: CreatableRawIdType {
2525

2626
// MARK: - typealiases for convenience
2727
public typealias ExampleEntity<Description: ResourceObjectDescription> = ResourceObject<Description, NoMetadata, NoLinks, String>
28-
public typealias ToOne<E: JSONAPIIdentifiable> = ToOneRelationship<E, NoMetadata, NoLinks>
29-
public typealias ToMany<E: Relatable> = ToManyRelationship<E, NoMetadata, NoLinks>
28+
public typealias ToOne<E: JSONAPIIdentifiable> = ToOneRelationship<E, NoIdMetadata, NoMetadata, NoLinks>
29+
public typealias ToMany<E: Relatable> = ToManyRelationship<E, NoIdMetadata, NoMetadata, NoLinks>
3030

3131
// MARK: - A few resource objects (entities)
3232
public enum PersonDescription: ResourceObjectDescription {

JSONAPI.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Pod::Spec.new do |spec|
1616
#
1717

1818
spec.name = "MP-JSONAPI"
19-
spec.version = "4.0.0"
19+
spec.version = "5.0.0"
2020
spec.summary = "Swift Codable JSON API framework."
2121

2222
# This description is used to generate tags and improve search results.

Package.resolved

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# JSONAPI
2-
[![MIT license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT) [![Swift 5.2](http://img.shields.io/badge/Swift-5.2-blue.svg)](https://swift.org) [![Build Status](https://app.bitrise.io/app/c8295b9589aa401e/status.svg?token=vzcyqWD5bQ4xqQfZsaVzNw&branch=master)](https://app.bitrise.io/app/c8295b9589aa401e)
2+
[![MIT license](http://img.shields.io/badge/license-MIT-lightgrey.svg)](http://opensource.org/licenses/MIT) [![Swift 5.2+](http://img.shields.io/badge/Swift-5.2/5.3-blue.svg)](https://swift.org) [![Build Status](https://app.bitrise.io/app/c8295b9589aa401e/status.svg?token=vzcyqWD5bQ4xqQfZsaVzNw&branch=master)](https://app.bitrise.io/app/c8295b9589aa401e)
33

44
A Swift package for encoding to- and decoding from **JSON API** compliant requests and responses.
55

@@ -66,7 +66,7 @@ If you find something wrong with this library and it isn't already mentioned und
6666
### Swift Package Manager
6767
Just include the following in your package's dependencies and add `JSONAPI` to the dependencies for any of your targets.
6868
```swift
69-
.package(url: "https://github.com/mattpolzin/JSONAPI.git", from: "4.0.0")
69+
.package(url: "https://github.com/mattpolzin/JSONAPI.git", from: "5.0.0")
7070
```
7171

7272
### Xcode project

Sources/JSONAPI/Document/Includes.swift

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,15 @@ extension Includes: Decodable where I: Decodable {
7676
}
7777
}
7878
guard errors.count == error.individualTypeFailures.count else {
79-
throw IncludesDecodingError(error: error, idx: idx)
79+
throw IncludesDecodingError(error: error, idx: idx, totalIncludesCount: container.count ?? 0)
8080
}
8181
throw IncludesDecodingError(
8282
error: IncludeDecodingError(failures: errors),
83-
idx: idx
83+
idx: idx,
84+
totalIncludesCount: container.count ?? 0
8485
)
8586
} catch let error {
86-
throw IncludesDecodingError(error: error, idx: idx)
87+
throw IncludesDecodingError(error: error, idx: idx, totalIncludesCount: container.count ?? 0)
8788
}
8889
}
8990

@@ -208,7 +209,13 @@ extension Includes where I: _Poly11 {
208209
// MARK: - DecodingError
209210
public struct IncludesDecodingError: Swift.Error, Equatable {
210211
public let error: Swift.Error
212+
/// The zero-based index of the include that failed to decode.
211213
public let idx: Int
214+
/// The total count of includes in the document that failed to decode.
215+
///
216+
/// In other words, "of `totalIncludesCount` includes, the `(idx + 1)`th
217+
/// include failed to decode.
218+
public let totalIncludesCount: Int
212219

213220
public static func ==(lhs: Self, rhs: Self) -> Bool {
214221
return lhs.idx == rhs.idx
@@ -218,18 +225,55 @@ public struct IncludesDecodingError: Swift.Error, Equatable {
218225

219226
extension IncludesDecodingError: CustomStringConvertible {
220227
public var description: String {
221-
return "Include \(idx + 1) failed to parse: \(error)"
228+
let ordinalSuffix: String
229+
if (idx % 100) + 1 > 9 && (idx % 100) + 1 < 20 {
230+
// the teens
231+
ordinalSuffix = "th"
232+
} else {
233+
switch ((idx % 10) + 1) {
234+
case 1:
235+
ordinalSuffix = "st"
236+
case 2:
237+
ordinalSuffix = "nd"
238+
case 3:
239+
ordinalSuffix = "rd"
240+
default:
241+
ordinalSuffix = "th"
242+
}
243+
}
244+
let ordinalDescription = "\(idx + 1)\(ordinalSuffix)"
245+
246+
return "Out of the \(totalIncludesCount) includes in the document, the \(ordinalDescription) one failed to parse: \(error)"
222247
}
223248
}
224249

225250
public struct IncludeDecodingError: Swift.Error, Equatable, CustomStringConvertible {
226251
public let failures: [ResourceObjectDecodingError]
227252

228253
public var description: String {
254+
// concise error when all failures are mismatched JSON:API types:
255+
if case let .jsonTypeMismatch(foundType: foundType)? = failures.first?.cause,
256+
failures.allSatisfy({ $0.cause.isTypeMismatch }) {
257+
let expectedTypes = failures
258+
.compactMap { "'\($0.resourceObjectJsonAPIType)'" }
259+
.joined(separator: ", ")
260+
261+
return "Found JSON:API type '\(foundType)' but expected one of \(expectedTypes)"
262+
}
263+
264+
// concise error when all but failures but one are type mismatches because
265+
// we can assume the correct type was found but there was some other error:
266+
let nonTypeMismatches = failures.filter({ !$0.cause.isTypeMismatch})
267+
if nonTypeMismatches.count == 1, let nonTypeMismatch = nonTypeMismatches.first {
268+
return String(describing: nonTypeMismatch)
269+
}
270+
271+
// fall back to just describing all of the reasons it could not have been any of the available
272+
// types:
229273
return failures
230274
.enumerated()
231275
.map {
232-
"\nCould not have been Include Type \($0.offset + 1) because:\n\($0.element)"
276+
"\nCould not have been Include Type `\($0.element.resourceObjectJsonAPIType)` because:\n\($0.element)"
233277
}.joined(separator: "\n")
234278
}
235279
}

Sources/JSONAPI/Meta/Meta.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,10 @@ public struct NoMetadata: Meta, CustomStringConvertible {
2828

2929
public var description: String { return "No Metadata" }
3030
}
31+
32+
/// The type of metadata found in a Resource Identifier Object.
33+
///
34+
/// It is sometimes more legible to differentiate between types of metadata
35+
/// even when the underlying type is the same. This typealias is only here
36+
/// to make code more easily understandable.
37+
public typealias NoIdMetadata = NoMetadata

0 commit comments

Comments
 (0)