Skip to content

Commit c265770

Browse files
Merge pull request #128 from NeedleInAJayStack/feature/error-extensions
Adds GraphQLError extensions
2 parents 518f5db + aed9770 commit c265770

File tree

10 files changed

+60
-41
lines changed

10 files changed

+60
-41
lines changed

.github/workflows/build.yml

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,21 @@ jobs:
2525

2626
macos:
2727
name: Build and test on macos-latest
28-
runs-on: macOS-latest
28+
runs-on: macos-latest
2929
steps:
30-
- uses: actions/checkout@v2
31-
- name: Set code coverage path
32-
run: echo "codecov_path=$(swift test --show-codecov-path)" >> $GITHUB_ENV
33-
- name: Test and publish code coverage to Code Climate
34-
uses: paulofaria/codeclimate-action@master
35-
env:
36-
CC_TEST_REPORTER_ID: ${{secrets.CC_TEST_REPORTER_ID}}
37-
with:
38-
downloadUrl: https://github.com/paulofaria/test-reporter/releases/download/0.9.0/test-reporter-0.9.0-darwin-amd64
39-
coverageCommand: swift test --enable-test-discovery --enable-code-coverage
40-
coverageLocations: ${{ env.codecov_path }}:lcov-json
30+
- uses: swift-actions/setup-swift@v1
31+
- uses: actions/checkout@v3
32+
- name: Test
33+
run: swift test
34+
4135
# ubuntu-latest is ubuntu-22.04 currently. Swift versions older than 5.7 don't have builds for 22.04. https://www.swift.org/download/
4236
ubuntu-old:
4337
name: Build ${{ matrix.swift }} on ${{ matrix.os }}
4438
runs-on: ${{ matrix.os }}
4539
strategy:
4640
matrix:
4741
os: [ubuntu-20.04]
48-
swift: ["5.4", "5.5", "5.6"]
42+
swift: ["5.5", "5.6"]
4943
steps:
5044
- uses: swift-actions/setup-swift@v1
5145
with:
@@ -60,7 +54,7 @@ jobs:
6054
strategy:
6155
matrix:
6256
os: [ubuntu-latest]
63-
swift: ["5.7"]
57+
swift: ["5.7", "5.8"]
6458
steps:
6559
- uses: swift-actions/setup-swift@v1
6660
with:

Sources/GraphQL/Error/GraphQLError.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ public struct GraphQLError: Error, Codable {
99
case message
1010
case locations
1111
case path
12+
case extensions
1213
}
1314

1415
/**
@@ -38,6 +39,12 @@ public struct GraphQLError: Error, Codable {
3839
*/
3940
public let path: IndexPath
4041

42+
/// Reserved for implementors to add additional information to errors
43+
/// however they see fit, and there are no restrictions on its contents.
44+
///
45+
/// See: https://spec.graphql.org/October2021/#sel-HAPHRPZCBiCBzG67F
46+
public let extensions: [String: Map]
47+
4148
/**
4249
* An array of GraphQL AST Nodes corresponding to this error.
4350
*/
@@ -65,7 +72,8 @@ public struct GraphQLError: Error, Codable {
6572
source: Source? = nil,
6673
positions: [Int] = [],
6774
path: IndexPath = [],
68-
originalError: Error? = nil
75+
originalError: Error? = nil,
76+
extensions: [String: Map] = [:]
6977
) {
7078
self.message = message
7179
self.nodes = nodes
@@ -92,16 +100,19 @@ public struct GraphQLError: Error, Codable {
92100

93101
self.path = path
94102
self.originalError = originalError
103+
self.extensions = extensions
95104
}
96105

97106
public init(
98107
message: String,
99108
locations: [SourceLocation],
100-
path: IndexPath = []
109+
path: IndexPath = [],
110+
extensions: [String: Map] = [:]
101111
) {
102112
self.message = message
103113
self.locations = locations
104114
self.path = path
115+
self.extensions = extensions
105116
nodes = []
106117
source = nil
107118
positions = []
@@ -120,6 +131,7 @@ public struct GraphQLError: Error, Codable {
120131
message = try container.decode(String.self, forKey: .message)
121132
locations = (try? container.decode([SourceLocation]?.self, forKey: .locations)) ?? []
122133
path = try container.decode(IndexPath.self, forKey: .path)
134+
extensions = try container.decodeIfPresent([String: Map].self, forKey: .extensions) ?? [:]
123135
}
124136

125137
public func encode(to encoder: Encoder) throws {
@@ -132,6 +144,10 @@ public struct GraphQLError: Error, Codable {
132144
}
133145

134146
try container.encode(path, forKey: .path)
147+
148+
if !extensions.isEmpty {
149+
try container.encode(extensions, forKey: .extensions)
150+
}
135151
}
136152
}
137153

Sources/GraphQL/Execution/Values.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ func coerceValue(value: Map, type: GraphQLInputType) throws -> Map {
149149
}
150150

151151
// Convert solitary value into single-value array
152-
return .array([try coerceValue(value: value, type: itemType)])
152+
return try .array([coerceValue(value: value, type: itemType)])
153153
}
154154

155155
if let objectType = type as? GraphQLInputObjectType {

Sources/GraphQL/Language/Parser.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1331,7 +1331,7 @@ func many<T>(
13311331
parse: (Lexer) throws -> T
13321332
) throws -> [T] {
13331333
try expect(lexer: lexer, kind: openKind)
1334-
var nodes = [try parse(lexer)]
1334+
var nodes = try [parse(lexer)]
13351335
while try !skip(lexer: lexer, kind: closeKind) {
13361336
try nodes.append(parse(lexer))
13371337
}

Sources/GraphQL/Map/GraphQLJSONEncoder.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -473,11 +473,6 @@ extension JSONEncoderImpl: _SpecialTreatmentEncoder {
473473
return .string(url.absoluteString)
474474
case let decimal as Decimal:
475475
return .number(decimal.description)
476-
case let object as OrderedDictionary<
477-
String,
478-
Encodable
479-
>: // this emits a warning, but it works perfectly
480-
return try wrapObject(object, for: nil)
481476
case let date as Date:
482477
return try wrapDate(date, for: nil)
483478
default:
@@ -545,8 +540,6 @@ extension _SpecialTreatmentEncoder {
545540
return .string(url.absoluteString)
546541
case let decimal as Decimal:
547542
return .number(decimal.description)
548-
case let object as OrderedDictionary<String, Encodable>:
549-
return try wrapObject(object, for: additionalKey)
550543
default:
551544
let encoder = getEncoder(for: additionalKey)
552545
try encodable.encode(to: encoder)

Sources/GraphQL/Map/Map.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -701,16 +701,16 @@ extension Map: Codable {
701701

702702
/// A wrapper for dictionary keys which are Strings or Ints.
703703
/// This is copied from Swift core: https://github.com/apple/swift/blob/256a9c5ad96378daa03fa2d5197b4201bf16db27/stdlib/public/core/Codable.swift#L5508
704-
internal struct _DictionaryCodingKey: CodingKey {
705-
internal let stringValue: String
706-
internal let intValue: Int?
704+
struct _DictionaryCodingKey: CodingKey {
705+
let stringValue: String
706+
let intValue: Int?
707707

708-
internal init?(stringValue: String) {
708+
init?(stringValue: String) {
709709
self.stringValue = stringValue
710710
intValue = Int(stringValue)
711711
}
712712

713-
internal init?(intValue: Int) {
713+
init?(intValue: Int) {
714714
stringValue = "\(intValue)"
715715
self.intValue = intValue
716716
}

Sources/GraphQL/Utilities/NIO+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//
2-
// DictionaryFuture.swift
2+
// NIO+Extensions.swift
33
// GraphQL
44
//
55
// Created by Jeff Seibert on 3/9/18.

Sources/GraphQL/Utilities/ValueFromAST.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ func valueFromAST(
6565
}
6666

6767
// Convert solitary value into single-value array
68-
return .array([
69-
try valueFromAST(
68+
return try .array([
69+
valueFromAST(
7070
valueAST: valueAST,
7171
type: itemType,
7272
variables: variables

Tests/GraphQLTests/LanguageTests/ParserTests.swift

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ class ParserTests: XCTestCase {
2626
XCTAssertEqual(error.locations[0].column, 2)
2727
}
2828

29-
XCTAssertThrowsError(try parse(source: "{ ...MissingOn }\nfragment MissingOn Type\n")) { error in
29+
XCTAssertThrowsError(try parse(
30+
source: "{ ...MissingOn }\nfragment MissingOn Type\n"
31+
)) { error in
3032
guard let error = error as? GraphQLError else {
3133
return XCTFail()
3234
}
@@ -111,7 +113,9 @@ class ParserTests: XCTestCase {
111113
))
112114
}
113115

114-
XCTAssertThrowsError(try parse(source: "type WithImplementsButNoTypes implements {}")) { error in
116+
XCTAssertThrowsError(try parse(
117+
source: "type WithImplementsButNoTypes implements {}"
118+
)) { error in
115119
guard let error = error as? GraphQLError else {
116120
return XCTFail()
117121
}

Tests/GraphQLTests/SubscriptionTests/SubscriptionTests.swift

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ import XCTest
8787
type: GraphQLInt
8888
),
8989
],
90-
resolve: { emailAny, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
90+
resolve: { emailAny, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
91+
Any?
92+
> in
9193
guard let email = emailAny as? Email else {
9294
throw GraphQLError(
9395
message: "Source is not Email type: \(type(of: emailAny))"
@@ -98,7 +100,9 @@ import XCTest
98100
inbox: Inbox(emails: db.emails)
99101
))
100102
},
101-
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
103+
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
104+
Any?
105+
> in
102106
eventLoopGroup.next().makeSucceededFuture(db.publisher.subscribe())
103107
}
104108
),
@@ -109,7 +113,9 @@ import XCTest
109113
type: GraphQLInt
110114
),
111115
],
112-
resolve: { emailAny, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
116+
resolve: { emailAny, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
117+
Any?
118+
> in
113119
guard let email = emailAny as? Email else {
114120
throw GraphQLError(
115121
message: "Source is not Email type: \(type(of: emailAny))"
@@ -120,7 +126,9 @@ import XCTest
120126
inbox: Inbox(emails: db.emails)
121127
))
122128
},
123-
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
129+
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
130+
Any?
131+
> in
124132
eventLoopGroup.next().makeSucceededFuture(db.publisher.subscribe())
125133
}
126134
),
@@ -192,7 +200,9 @@ import XCTest
192200
resolve: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
193201
eventLoopGroup.next().makeSucceededFuture(nil)
194202
},
195-
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
203+
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
204+
Any?
205+
> in
196206
didResolveImportantEmail = true
197207
return eventLoopGroup.next()
198208
.makeSucceededFuture(db.publisher.subscribe())
@@ -203,7 +213,9 @@ import XCTest
203213
resolve: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
204214
eventLoopGroup.next().makeSucceededFuture(nil)
205215
},
206-
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<Any?> in
216+
subscribe: { _, _, _, eventLoopGroup, _ throws -> EventLoopFuture<
217+
Any?
218+
> in
207219
didResolveNonImportantEmail = true
208220
return eventLoopGroup.next()
209221
.makeSucceededFuture(db.publisher.subscribe())

0 commit comments

Comments
 (0)