Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make GraphQLResponse a generic on the response type instead of on the operation type #1061

Merged
merged 3 commits into from
Mar 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Sources/Apollo/ApolloClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ public class ApolloClient {
}
}

private func handleOperationResult<Operation>(shouldPublishResultToStore: Bool,
context: UnsafeMutableRawPointer?,
_ result: Result<GraphQLResponse<Operation>, Error>,
resultHandler: @escaping GraphQLResultHandler<Operation.Data>) {
private func handleOperationResult<Data: GraphQLSelectionSet>(shouldPublishResultToStore: Bool,
context: UnsafeMutableRawPointer?,
_ result: Result<GraphQLResponse<Data>, Error>,
resultHandler: @escaping GraphQLResultHandler<Data>) {
switch result {
case .failure(let error):
resultHandler(.failure(error))
Expand Down
27 changes: 15 additions & 12 deletions Sources/Apollo/GraphQLResponse.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
/// Represents a GraphQL response received from a server.
public final class GraphQLResponse<Operation: GraphQLOperation> {
public let operation: Operation
public final class GraphQLResponse<Data: GraphQLSelectionSet> {
public let body: JSONObject

public init(operation: Operation, body: JSONObject) {
self.operation = operation
private let rootKey: String
private let variables: GraphQLMap?

public init<Operation: GraphQLOperation>(operation: Operation, body: JSONObject) where Operation.Data == Data {
self.body = body
rootKey = rootCacheKey(for: operation)
variables = operation.variables
}

func parseResult(cacheKeyForObject: CacheKeyForObject? = nil) throws -> Promise<(GraphQLResult<Operation.Data>, RecordSet?)> {
func parseResult(cacheKeyForObject: CacheKeyForObject? = nil) throws -> Promise<(GraphQLResult<Data>, RecordSet?)> {
let errors: [GraphQLError]?

if let errorsEntry = body["errors"] as? [JSONObject] {
Expand All @@ -24,15 +27,15 @@ public final class GraphQLResponse<Operation: GraphQLOperation> {

executor.cacheKeyForObject = cacheKeyForObject

let mapper = GraphQLSelectionSetMapper<Operation.Data>()
let mapper = GraphQLSelectionSetMapper<Data>()
let normalizer = GraphQLResultNormalizer()
let dependencyTracker = GraphQLDependencyTracker()

return firstly {
try executor.execute(selections: Operation.Data.selections,
try executor.execute(selections: Data.selections,
on: dataEntry,
withKey: rootCacheKey(for: operation),
variables: operation.variables,
withKey: rootKey,
variables: variables,
accumulator: zip(mapper, normalizer, dependencyTracker))
}.map { (data, records, dependentKeys) in
(
Expand Down Expand Up @@ -62,13 +65,13 @@ public final class GraphQLResponse<Operation: GraphQLOperation> {
return errorsEntry.map(GraphQLError.init)
}

func parseResultFast() throws -> GraphQLResult<Operation.Data> {
func parseResultFast() throws -> GraphQLResult<Data> {
let errors = self.parseErrorsOnlyFast()

if let dataEntry = body["data"] as? JSONObject {
let data = try decode(selectionSet: Operation.Data.self,
let data = try decode(selectionSet: Data.self,
from: dataEntry,
variables: operation.variables)
variables: variables)

return GraphQLResult(data: data,
errors: errors,
Expand Down
46 changes: 23 additions & 23 deletions Sources/Apollo/HTTPNetworkTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ public class HTTPNetworkTransport {
self.requestCreator = requestCreator
}

private func send<Operation>(operation: Operation,
isPersistedQueryRetry: Bool,
files: [GraphQLFile]?,
completionHandler: @escaping (_ results: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
private func send<Operation: GraphQLOperation>(operation: Operation,
isPersistedQueryRetry: Bool,
files: [GraphQLFile]?,
completionHandler: @escaping (_ results: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
let request: URLRequest
do {
request = try self.createRequest(for: operation,
Expand Down Expand Up @@ -231,10 +231,10 @@ public class HTTPNetworkTransport {
return task
}

private func handleGraphQLErrorsOrComplete<Operation>(operation: Operation,
private func handleGraphQLErrorsOrComplete<Operation: GraphQLOperation>(operation: Operation,
files: [GraphQLFile]?,
response: GraphQLResponse<Operation>,
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) {
response: GraphQLResponse<Operation.Data>,
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) {
guard
let delegate = self.delegate as? HTTPNetworkTransportGraphQLErrorDelegate,
let graphQLErrors = response.parseErrorsOnlyFast(),
Expand All @@ -261,12 +261,12 @@ public class HTTPNetworkTransport {
})
}

private func handleGraphQLErrorsIfNeeded<Operation>(operation: Operation,
files: [GraphQLFile]?,
for request: URLRequest,
body: JSONObject,
errors: [GraphQLError],
completionHandler: @escaping (_ results: Result<GraphQLResponse<Operation>, Error>) -> Void) {
private func handleGraphQLErrorsIfNeeded<Operation: GraphQLOperation>(operation: Operation,
files: [GraphQLFile]?,
for request: URLRequest,
body: JSONObject,
errors: [GraphQLError],
completionHandler: @escaping (_ results: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) {

let errorMessages = errors.compactMap { $0.message }
if self.enableAutoPersistedQueries,
Expand All @@ -283,12 +283,12 @@ public class HTTPNetworkTransport {
}
}

private func handleErrorOrRetry<Operation>(operation: Operation,
files: [GraphQLFile]?,
error: Error,
for request: URLRequest,
response: URLResponse?,
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) {
private func handleErrorOrRetry<Operation: GraphQLOperation>(operation: Operation,
files: [GraphQLFile]?,
error: Error,
for request: URLRequest,
response: URLResponse?,
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) {
guard
let delegate = self.delegate,
let retrier = delegate as? HTTPNetworkTransportRetryDelegate else {
Expand Down Expand Up @@ -439,7 +439,7 @@ public class HTTPNetworkTransport {

extension HTTPNetworkTransport: NetworkTransport {

public func send<Operation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
public func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
return send(operation: operation,
isPersistedQueryRetry: false,
files: nil,
Expand All @@ -451,9 +451,9 @@ extension HTTPNetworkTransport: NetworkTransport {

extension HTTPNetworkTransport: UploadingNetworkTransport {

public func upload<Operation>(operation: Operation,
files: [GraphQLFile],
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
public func upload<Operation: GraphQLOperation>(operation: Operation,
files: [GraphQLFile],
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
return send(operation: operation,
isPersistedQueryRetry: false,
files: files,
Expand Down
4 changes: 2 additions & 2 deletions Sources/Apollo/NetworkTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public protocol NetworkTransport: class {
/// - operation: The operation to send.
/// - completionHandler: A closure to call when a request completes. On `success` will contain the response received from the server. On `failure` will contain the error which occurred.
/// - Returns: An object that can be used to cancel an in progress request.
func send<Operation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable
func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable

/// The name of the client to send as a header value.
var clientName: String { get }
Expand Down Expand Up @@ -91,5 +91,5 @@ public protocol UploadingNetworkTransport: NetworkTransport {
/// - files: An array of `GraphQLFile` objects to send.
/// - completionHandler: The completion handler to execute when the request completes or errors
/// - Returns: An object that can be used to cancel an in progress request.
func upload<Operation>(operation: Operation, files: [GraphQLFile], completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable
func upload<Operation: GraphQLOperation>(operation: Operation, files: [GraphQLFile], completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable
}
2 changes: 1 addition & 1 deletion Sources/ApolloTestSupport/MockNetworkTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public final class MockNetworkTransport: NetworkTransport {
self.body = body
}

public func send<Operation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
public func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
DispatchQueue.global(qos: .default).async {
completionHandler(.success(GraphQLResponse(operation: operation, body: self.body)))
}
Expand Down
8 changes: 4 additions & 4 deletions Sources/ApolloWebSocket/SplitNetworkTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class SplitNetworkTransport {

extension SplitNetworkTransport: NetworkTransport {

public func send<Operation>(operation: Operation, completionHandler: @escaping (Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
public func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
if operation.operationType == .subscription {
return webSocketNetworkTransport.send(operation: operation, completionHandler: completionHandler)
} else {
Expand All @@ -55,9 +55,9 @@ extension SplitNetworkTransport: NetworkTransport {

extension SplitNetworkTransport: UploadingNetworkTransport {

public func upload<Operation>(operation: Operation,
files: [GraphQLFile],
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>, Error>) -> Void) -> Cancellable {
public func upload<Operation: GraphQLOperation>(operation: Operation,
files: [GraphQLFile],
completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>, Error>) -> Void) -> Cancellable {
return httpNetworkTransport.upload(operation: operation,
files: files,
completionHandler: completionHandler)
Expand Down
2 changes: 1 addition & 1 deletion Sources/ApolloWebSocket/WebSocketTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ public class WebSocketTransport {
// MARK: - HTTPNetworkTransport conformance

extension WebSocketTransport: NetworkTransport {
public func send<Operation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation>,Error>) -> Void) -> Cancellable {
public func send<Operation: GraphQLOperation>(operation: Operation, completionHandler: @escaping (_ result: Result<GraphQLResponse<Operation.Data>,Error>) -> Void) -> Cancellable {
if let error = self.error.value {
completionHandler(.failure(error))
return EmptyCancellable()
Expand Down
8 changes: 4 additions & 4 deletions Tests/ApolloTests/HTTPTransportTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class HTTPTransportTests: XCTestCase {
return transport
}()

private func validateHeroNameQueryResponse<Operation: GraphQLOperation>(result: Result<GraphQLResponse<Operation>, Error>,
expectation: XCTestExpectation,
file: StaticString = #file,
line: UInt = #line) {
private func validateHeroNameQueryResponse<Data: GraphQLSelectionSet>(result: Result<GraphQLResponse<Data>, Error>,
expectation: XCTestExpectation,
file: StaticString = #file,
line: UInt = #line) {
defer {
expectation.fulfill()
}
Expand Down