amplify-swift/Amplify/Categories/API/Operation/AmplifyOperation+APIPublish...

112 lines
4.1 KiB
Swift

//
// Copyright Amazon.com Inc. or its affiliates.
// All Rights Reserved.
//
// SPDX-License-Identifier: Apache-2.0
//
import Combine
import Foundation
// MARK: - GraphQLOperation
// The overrides require a feature and bugfix introduced in Swift 5.2
#if swift(>=5.2)
@available(iOS 13.0, *)
public extension GraphQLOperation {
/// Publishes the final result of the operation
var resultPublisher: AnyPublisher<Success, Failure> {
internalResultPublisher
}
}
// MARK: - GraphQLSubscriptionOperation
@available(iOS 13.0, *)
public extension GraphQLSubscriptionOperation {
/// Publishes the state of the GraphQL subscription's underlying network connection.
///
/// Subscription termination will be reported as a `completion` on the
/// `subscriptionDataPublisher` completion, so this is really only useful if you
/// want to monitor the `.connected` state.
var connectionStatePublisher: AnyPublisher<SubscriptionConnectionState, APIError> {
// Suppress Void results from the result publisher, but continue to emit
// completions
let transformedResultPublisher = internalResultPublisher
.flatMap { _ in Empty<SubscriptionConnectionState, Failure>(completeImmediately: true) }
// Transform the in-process publisher to one that only outputs connectionState events
let transformedInProcessPublisher = internalInProcessPublisher
.compactMap { event -> SubscriptionConnectionState? in
switch event {
case .connection(let state):
return state
default:
return nil
}
}
.setFailureType(to: Failure.self)
// Now that the publisher signatures match, we can merge them
return transformedResultPublisher
.merge(with: transformedInProcessPublisher)
.eraseToAnyPublisher()
}
/// Publishes the data received from a GraphQL subscription.
///
/// The publisher emits `GraphQLResponse` events, which are standard Swift `Result`
/// values that contain either a successfully decoded response value, or a
/// `GraphQLResponseError` describing the reason that a value could not be
/// successfully decoded. Receiving a `.failure` response does not mean the
/// subscription is terminated--the subscription may still receive values, and each
/// value is independently evaluated. Thus, you may see a data stream containing a
/// mix of successfully decoded responses, partially decoded responses, or decoding
/// errors, none of which affect the state of the underlying subscription
/// connection.
///
/// When the subscription terminates with a cancellation or disconnection, this
/// publisher will receive a `completion`.
var subscriptionDataPublisher: AnyPublisher<GraphQLResponse<R>, Failure> {
// Suppress Void results from the result publisher, but continue to emit completions
let transformedResultPublisher = internalResultPublisher
.flatMap { _ in Empty<GraphQLResponse<R>, Failure>(completeImmediately: true) }
// Transform the in-process publisher to one that only outputs GraphQLResponse events
let transformedInProcessPublisher = internalInProcessPublisher
.compactMap { event -> GraphQLResponse<R>? in
switch event {
case .data(let result):
return result
default:
return nil
}
}
.setFailureType(to: Failure.self)
// Now that the publisher signatures match, we can merge them
return transformedResultPublisher
.merge(with: transformedInProcessPublisher)
.eraseToAnyPublisher()
}
}
// MARK: - RESTOperation
@available(iOS 13.0, *)
public extension AmplifyOperation
where
Request == RESTOperation.Request,
Success == RESTOperation.Success,
Failure == RESTOperation.Failure {
/// Publishes the final result of the operation
var resultPublisher: AnyPublisher<Success, Failure> {
internalResultPublisher
}
}
#endif