diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift similarity index 99% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift index 4e8808c7ea..d3eee7a753 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient+HandleRequest.swift @@ -10,7 +10,6 @@ import Foundation import Combine import Amplify -@_spi(AppSyncRTC) extension AppSyncRealTimeClient { /** Submit an AppSync request to real-time server. diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient.swift similarity index 97% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient.swift index 205a038d44..1a411dd589 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeClient.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeClient.swift @@ -9,9 +9,9 @@ import Foundation import Combine import Amplify +@_spi(WebSocket) import AmplifyNetwork -@_spi(AppSyncRTC) -public protocol AppSyncRealTimeClientProtocol { +protocol AppSyncRealTimeClientProtocol { func connect() async throws func disconnectWhenIdel() async func disconnect() async @@ -23,8 +23,7 @@ public protocol AppSyncRealTimeClientProtocol { The AppSyncRealTimeClient conforms to the AppSync real-time WebSocket protocol. ref: https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html */ -@_spi(AppSyncRTC) -public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { +actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { static let jsonEncoder = JSONEncoder() static let jsonDecoder = JSONDecoder() @@ -59,7 +58,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { /// Writable data stream convert WebSocketEvent to AppSyncRealTimeResponse internal let subject = PassthroughSubject() - public var isConnected: Bool { + var isConnected: Bool { self.state.value == .connected } @@ -70,7 +69,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { - requestInterceptor: Interceptor for decocating AppSyncRealTimeRequest - webSocketClient: WebSocketClient for reading/writing to connection */ - public init( + init( endpoint: URL, requestInterceptor: AppSyncRequestInterceptor, webSocketClient: AppSyncWebSocketClientProtocol @@ -93,7 +92,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { /** Connecting to remote AppSync real-time server. */ - public func connect() async throws { + func connect() async throws { switch self.state.value { case .connecting, .connected: log.debug("[AppSyncRealTimeClient] client is already connecting or connected") @@ -125,7 +124,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { /** Disconnect only when there are no subscriptions exist. */ - public func disconnectWhenIdel() async { + func disconnectWhenIdel() async { if self.subscriptions.isEmpty { log.debug("[AppSyncRealTimeClient] no subscription exist, client is trying to disconnect") await disconnect() @@ -137,7 +136,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { /** Disconnect from AppSync real-time server. */ - public func disconnect() async { + func disconnect() async { guard self.state.value != .disconnecting else { log.debug("[AppSyncRealTimeClient] client already disconnecting") return @@ -161,7 +160,7 @@ public actor AppSyncRealTimeClient: AppSyncRealTimeClientProtocol { - Returns: A never fail data stream for AppSyncSubscriptionEvent. */ - public func subscribe(id: String, query: String) async throws -> AnyPublisher { + func subscribe(id: String, query: String) async throws -> AnyPublisher { log.debug("[AppSyncRealTimeClient] Received subscription request id: \(id), query: \(query)") let subscription = AppSyncRealTimeSubscription(id: id, query: query, appSyncRealTimeClient: self) subscriptions[id] = subscription diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift similarity index 92% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift index a08855d6ee..10fb87013a 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequest.swift @@ -9,18 +9,17 @@ import Foundation import Amplify -@_spi(AppSyncRTC) -public enum AppSyncRealTimeRequest { +enum AppSyncRealTimeRequest { case connectionInit case start(StartRequest) case stop(String) - public struct StartRequest { - public let id: String - public let data: String - public let auth: AppSyncRealTimeRequestAuth? + struct StartRequest { + let id: String + let data: String + let auth: AppSyncRealTimeRequestAuth? - public init(id: String, data: String, auth: AppSyncRealTimeRequestAuth?) { + init(id: String, data: String, auth: AppSyncRealTimeRequestAuth?) { self.id = id self.data = data self.auth = auth diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift similarity index 87% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift index 68db7f9de3..fffaf97faf 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeRequestAuth.swift @@ -8,41 +8,40 @@ import Foundation -@_spi(AppSyncRTC) -public enum AppSyncRealTimeRequestAuth { +enum AppSyncRealTimeRequestAuth { case authToken(AuthToken) case apiKey(ApiKey) case iam(IAM) - public struct AuthToken { + struct AuthToken { let host: String let authToken: String - public init(host: String, authToken: String) { + init(host: String, authToken: String) { self.host = host self.authToken = authToken } } - public struct ApiKey { + struct ApiKey { let host: String let apiKey: String let amzDate: String - public init(host: String, apiKey: String, amzDate: String) { + init(host: String, apiKey: String, amzDate: String) { self.host = host self.apiKey = apiKey self.amzDate = amzDate } } - public struct IAM { + struct IAM { let host: String let authToken: String let securityToken: String let amzDate: String - public init(host: String, authToken: String, securityToken: String, amzDate: String) { + init(host: String, authToken: String, securityToken: String, amzDate: String) { self.host = host self.authToken = authToken self.securityToken = securityToken @@ -50,16 +49,16 @@ public enum AppSyncRealTimeRequestAuth { } } - public struct URLQuery { + struct URLQuery { let header: AppSyncRealTimeRequestAuth let payload: String - public init(header: AppSyncRealTimeRequestAuth, payload: String = "{}") { + init(header: AppSyncRealTimeRequestAuth, payload: String = "{}") { self.header = header self.payload = payload } - public func withBaseURL(_ url: URL, encoder: JSONEncoder? = nil) -> URL { + func withBaseURL(_ url: URL, encoder: JSONEncoder? = nil) -> URL { let jsonEncoder: JSONEncoder = encoder ?? JSONEncoder() guard let headerJsonData = try? jsonEncoder.encode(header) else { return url diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift similarity index 70% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift index c6a0616047..36813b4bbb 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeResponse.swift @@ -8,14 +8,13 @@ import Foundation import Amplify -@_spi(AppSyncRTC) -public struct AppSyncRealTimeResponse { +struct AppSyncRealTimeResponse { - public let id: String? - public let payload: JSONValue? - public let type: EventType + let id: String? + let payload: JSONValue? + let type: EventType - public enum EventType: String, Codable { + enum EventType: String, Codable { case connectionAck = "connection_ack" case startAck = "start_ack" case stopAck = "complete" diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift similarity index 96% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift index 5517057306..88d891cb97 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRealTimeSubscription.swift @@ -9,15 +9,15 @@ import Foundation import Combine import Amplify +@_spi(WebSocket) import AmplifyNetwork /** AppSyncRealTimeSubscription reprensents one realtime subscription to AppSync realtime server. */ -@_spi(AppSyncRTC) -public actor AppSyncRealTimeSubscription { +actor AppSyncRealTimeSubscription { static let jsonEncoder = JSONEncoder() - public enum State { + enum State { case none case subscribing case subscribed @@ -36,8 +36,8 @@ public actor AppSyncRealTimeSubscription { private weak var appSyncRealTimeClient: AppSyncRealTimeClient? - public let id: String - public let query: String + let id: String + let query: String init(id: String, query: String, appSyncRealTimeClient: AppSyncRealTimeClient) { diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift similarity index 79% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift index b94c16ae70..92414ea28c 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncRequestInterceptor.swift @@ -8,7 +8,6 @@ import Foundation -@_spi(AppSyncRTC) -public protocol AppSyncRequestInterceptor { +protocol AppSyncRequestInterceptor { func interceptRequest(event: AppSyncRealTimeRequest, url: URL) async -> AppSyncRealTimeRequest } diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift similarity index 82% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift index 00404601ab..fbc0d27671 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncSubscriptionEvent.swift @@ -9,8 +9,7 @@ import Foundation import Amplify -@_spi(AppSyncRTC) -public enum AppSyncSubscriptionEvent { +enum AppSyncSubscriptionEvent { case subscribing case subscribed case data(JSONValue) diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift similarity index 85% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift index 570ca71689..2f43414296 100644 --- a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift +++ b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/AppSyncWebSocketClientProtocol.swift @@ -8,9 +8,9 @@ import Foundation import Combine +@_spi(WebSocket) import AmplifyNetwork -@_spi(AppSyncRTC) -public protocol AppSyncWebSocketClientProtocol: AnyObject { +protocol AppSyncWebSocketClientProtocol: AnyObject { var isConnected: Bool { get async } var publisher: AnyPublisher { get async } diff --git a/AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/README.md b/AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/README.md similarity index 100% rename from AmplifyPlugins/Internal/Sources/Network/AppSyncRealTimeClient/README.md rename to AmplifyPlugins/API/Sources/AWSAPIPlugin/AppSyncRealTimeClient/README.md diff --git a/AmplifyPlugins/API/Tests/APIHostApp/AWSAPIPluginFunctionalTests/AppSyncRealTimeClientTests.swift b/AmplifyPlugins/API/Tests/APIHostApp/AWSAPIPluginFunctionalTests/AppSyncRealTimeClientTests.swift index 5e1ed6b31c..b82da6f2d9 100644 --- a/AmplifyPlugins/API/Tests/APIHostApp/AWSAPIPluginFunctionalTests/AppSyncRealTimeClientTests.swift +++ b/AmplifyPlugins/API/Tests/APIHostApp/AWSAPIPluginFunctionalTests/AppSyncRealTimeClientTests.swift @@ -10,7 +10,8 @@ import XCTest import Combine @testable import Amplify @testable import AWSAPIPlugin -@testable @_spi(WebSocket) import AWSPluginsCore +@testable import AWSPluginsCore +@testable @_spi(WebSocket) import AmplifyNetwork class AppSyncRealTimeClientTests: XCTestCase { let subscriptionRequest = """ @@ -154,10 +155,12 @@ class AppSyncRealTimeClientTests: XCTestCase { maxSubscriptionReachedError.assertForOverFulfill = false let retryTriggerredAndSucceed = expectation(description: "Retry on max subscription reached error and succeed") cancellables.append(try await makeOneSubscription { event in - if case .error(let errors) = event { - XCTAssertTrue(errors.count == 1) - XCTAssertTrue(errors[0] is AppSyncRealTimeRequest.Error) - if case .maxSubscriptionsReached = errors[0] as! AppSyncRealTimeRequest.Error { + if case .error(let payload) = event, + let error = payload.errors { + let errors = error.asArray ?? [error] + let requestErrors = errors.compactMap(AppSyncRealTimeRequest.parseResponseError(error:)) + XCTAssertTrue(requestErrors.count == 1) + if case .maxSubscriptionsReached = requestErrors[0] { maxSubscriptionReachedError.fulfill() cancellables.dropLast(10).forEach { $0?.cancel() } } diff --git a/AmplifyPlugins/Internal/Tests/NetworkTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift similarity index 99% rename from AmplifyPlugins/Internal/Tests/NetworkTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift rename to AmplifyPlugins/API/Tests/AWSAPIPluginTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift index aac4155d67..3232fb3281 100644 --- a/AmplifyPlugins/Internal/Tests/NetworkTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift +++ b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AppSyncRealTimeClient/AppSyncRealTimeClientTests.swift @@ -10,6 +10,7 @@ import XCTest import Combine import Amplify @testable import AWSAPIPlugin +@_spi(WebSocket) import AmplifyNetwork class AppSyncRealTimeClientTests: XCTestCase { diff --git a/AmplifyPlugins/Internal/Tests/NetworkTests/AppSyncRealTimeClient/AppSyncRealTimeRequestAuthTests.swift b/AmplifyPlugins/API/Tests/AWSAPIPluginTests/AppSyncRealTimeClient/AppSyncRealTimeRequestAuthTests.swift similarity index 100% rename from AmplifyPlugins/Internal/Tests/NetworkTests/AppSyncRealTimeClient/AppSyncRealTimeRequestAuthTests.swift rename to AmplifyPlugins/API/Tests/AWSAPIPluginTests/AppSyncRealTimeClient/AppSyncRealTimeRequestAuthTests.swift