From 1ae1dee2864bfe11561be32688f5d6f45a891c7c Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 19 Aug 2025 11:45:08 -0300 Subject: [PATCH 1/3] DRY up usage of PluginAPI.sharedInstance() Should have done this in b69a40d. --- .../AblyLiveObjects/Internal/ARTClientOptions+Objects.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift index dac94d1..e1f251a 100644 --- a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift +++ b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift @@ -14,7 +14,7 @@ internal extension ARTClientOptions { /// Can be overriden for testing purposes. var garbageCollectionOptions: InternalDefaultRealtimeObjects.GarbageCollectionOptions? { get { - let optionsValue = PluginAPI.sharedInstance().pluginOptionsValue( + let optionsValue = Plugin.defaultPluginAPI.pluginOptionsValue( forKey: Self.garbageCollectionOptionsKey, clientOptions: self, ) @@ -35,7 +35,7 @@ internal extension ARTClientOptions { preconditionFailure("Not implemented the ability to un-set GC options") } - PluginAPI.sharedInstance().setPluginOptionsValue( + Plugin.defaultPluginAPI.setPluginOptionsValue( Box(boxed: newValue), forKey: Self.garbageCollectionOptionsKey, clientOptions: self, From 5795e7cac5870ae644ee346d12032a692923728e Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 19 Aug 2025 18:25:33 -0300 Subject: [PATCH 2/3] Update for renamed AblyPlugin -> _AblyPluginSupportPrivate As required by the accompanying ably-cocoa submodule bump. --- .cursor/rules/swift.mdc | 2 +- .cursor/rules/testing.mdc | 2 +- Package.swift | 4 +- .../Internal/ARTClientOptions+Objects.swift | 2 +- .../AblyLiveObjects/Internal/CoreSDK.swift | 16 +++--- .../Internal/DefaultInternalPlugin.swift | 38 ++++++------- .../Internal/InternalDefaultLiveCounter.swift | 10 ++-- .../Internal/InternalDefaultLiveMap.swift | 18 +++--- .../InternalDefaultRealtimeObjects.swift | 6 +- .../Internal/InternalLiveObject.swift | 2 +- .../Internal/LiveObjectMutableState.swift | 2 +- .../Internal/ObjectCreationHelpers.swift | 2 +- .../Internal/ObjectsPool.swift | 14 ++--- .../Protocol/ObjectMessage.swift | 34 +++++------ .../Protocol/WireObjectMessage.swift | 4 +- .../Public/ARTRealtimeChannel+Objects.swift | 2 +- Sources/AblyLiveObjects/Public/Plugin.swift | 10 ++-- .../InternalLiveMapValue+ToPublic.swift | 4 +- .../PublicDefaultLiveCounter.swift | 6 +- .../PublicDefaultLiveMap.swift | 6 +- .../PublicDefaultRealtimeObjects.swift | 6 +- .../PublicObjectsStore.swift | 12 ++-- .../Utility/APLogger+Swift.swift | 4 +- .../AblyLiveObjects/Utility/WireValue.swift | 30 +++++----- .../AblyLiveObjectsTests.swift | 2 +- .../Helpers/TestFactories.swift | 2 +- .../Helpers/TestLogger.swift | 6 +- .../InternalDefaultLiveCounterTests.swift | 2 +- .../InternalDefaultLiveMapTests.swift | 2 +- .../InternalDefaultRealtimeObjectsTests.swift | 2 +- .../JS Integration Tests/ObjectsHelper.swift | 4 +- .../LiveObjectMutableStateTests.swift | 2 +- .../ObjectMessageTests.swift | 2 +- .../ObjectsPoolTests.swift | 2 +- .../WireObjectMessageTests.swift | 4 +- .../AblyLiveObjectsTests/WireValueTests.swift | 56 +++++++++---------- ably-cocoa | 2 +- 37 files changed, 162 insertions(+), 162 deletions(-) diff --git a/.cursor/rules/swift.mdc b/.cursor/rules/swift.mdc index 3fa734a..b4a23b5 100644 --- a/.cursor/rules/swift.mdc +++ b/.cursor/rules/swift.mdc @@ -14,7 +14,7 @@ When writing Swift: - When writing a JSON string, favour using Swift raw string literals instead of escaping double quotes. - When you need to import the following modules inside the AblyLiveObjects library code (that is, in non-test code), do so in the following way: - Ably: use `import Ably` - - AblyPlugin: use `internal import AblyPlugin` + - `_AblyPluginSupportPrivate`: use `internal import _AblyPluginSupportPrivate` - When writing an array literal that starts with an initializer expression, start the initializer expression on the line after the opening square bracket of the array literal. That is, instead of writing: ```swift objectMessages: [InboundObjectMessage( diff --git a/.cursor/rules/testing.mdc b/.cursor/rules/testing.mdc index 0736293..f21ef64 100644 --- a/.cursor/rules/testing.mdc +++ b/.cursor/rules/testing.mdc @@ -14,7 +14,7 @@ When writing tests: - When you need to import the following modules in the tests, do so in the following way: - Ably: use `import Ably` - AblyLiveObjects: use `@testable import AblyLiveObjects` - - AblyPlugin: use `import AblyPlugin`; _do not_ do `internal import` + - `_AblyPluginSupportPrivate`: use `import _AblyPluginSupportPrivate`; _do not_ do `internal import` - When you need to pass a logger to internal components in the tests, pass `TestLogger()`. - When you need to unwrap an optional value in the tests, favour using `#require` instead of `guard let`. - When creating `testsOnly_` property declarations, do not write generic comments of the form "Test-only access to the private createOperationIsMerged property"; the meaning of these properties is already well understood. diff --git a/Package.swift b/Package.swift index 25fd4fc..742aa4b 100644 --- a/Package.swift +++ b/Package.swift @@ -47,7 +47,7 @@ let package = Package( package: "ably-cocoa", ), .product( - name: "AblyPlugin", + name: "_AblyPluginSupportPrivate", package: "ably-cocoa", ), ], @@ -61,7 +61,7 @@ let package = Package( package: "ably-cocoa", ), .product( - name: "AblyPlugin", + name: "_AblyPluginSupportPrivate", package: "ably-cocoa", ), ], diff --git a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift index e1f251a..8797381 100644 --- a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift +++ b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate internal extension ARTClientOptions { private class Box { diff --git a/Sources/AblyLiveObjects/Internal/CoreSDK.swift b/Sources/AblyLiveObjects/Internal/CoreSDK.swift index 51f0546..0c93078 100644 --- a/Sources/AblyLiveObjects/Internal/CoreSDK.swift +++ b/Sources/AblyLiveObjects/Internal/CoreSDK.swift @@ -1,9 +1,9 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// The API that the internal components of the SDK (that is, `DefaultLiveObjects` and down) use to interact with our core SDK (i.e. ably-cocoa). /// -/// This provides us with a mockable interface to ably-cocoa, and it also allows internal components and their tests not to need to worry about some of the boring details of how we bridge Swift types to AblyPlugin's Objective-C API (i.e. boxing). +/// This provides us with a mockable interface to ably-cocoa, and it also allows internal components and their tests not to need to worry about some of the boring details of how we bridge Swift types to `_AblyPluginSupportPrivate`'s Objective-C API (i.e. boxing). internal protocol CoreSDK: AnyObject, Sendable { /// Implements the internal `#publish` method of RTO15. func publish(objectMessages: [OutboundObjectMessage]) async throws(InternalError) @@ -21,10 +21,10 @@ internal final class DefaultCoreSDK: CoreSDK { /// Used to synchronize access to internal mutable state. private let mutex = NSLock() - private let channel: AblyPlugin.RealtimeChannel - private let client: AblyPlugin.RealtimeClient + private let channel: _AblyPluginSupportPrivate.RealtimeChannel + private let client: _AblyPluginSupportPrivate.RealtimeClient private let pluginAPI: PluginAPIProtocol - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger /// If set to true, ``publish(objectMessages:)`` will behave like a no-op. /// @@ -34,10 +34,10 @@ internal final class DefaultCoreSDK: CoreSDK { private nonisolated(unsafe) var overriddenPublishImplementation: (([OutboundObjectMessage]) async throws -> Void)? internal init( - channel: AblyPlugin.RealtimeChannel, - client: AblyPlugin.RealtimeClient, + channel: _AblyPluginSupportPrivate.RealtimeChannel, + client: _AblyPluginSupportPrivate.RealtimeClient, pluginAPI: PluginAPIProtocol, - logger: AblyPlugin.Logger + logger: _AblyPluginSupportPrivate.Logger ) { self.channel = channel self.client = client diff --git a/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift b/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift index 207ffd8..970157e 100644 --- a/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift +++ b/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift @@ -1,14 +1,14 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate -// We explicitly import the NSObject class, else it seems to get transitively imported from `internal import AblyPlugin`, leading to the error "Class cannot be declared public because its superclass is internal". +// We explicitly import the NSObject class, else it seems to get transitively imported from `internal import _AblyPluginSupportPrivate`, leading to the error "Class cannot be declared public because its superclass is internal". import ObjectiveC.NSObject -/// The default implementation of `AblyPlugin`'s `LiveObjectsInternalPluginProtocol`. Implements the interface that ably-cocoa uses to access the functionality provided by the LiveObjects plugin. +/// The default implementation of `_AblyPluginSupportPrivate`'s `LiveObjectsInternalPluginProtocol`. Implements the interface that ably-cocoa uses to access the functionality provided by the LiveObjects plugin. @objc -internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInternalPluginProtocol { - private let pluginAPI: AblyPlugin.PluginAPIProtocol +internal final class DefaultInternalPlugin: NSObject, _AblyPluginSupportPrivate.LiveObjectsInternalPluginProtocol { + private let pluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol - internal init(pluginAPI: AblyPlugin.PluginAPIProtocol) { + internal init(pluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol) { self.pluginAPI = pluginAPI } @@ -20,7 +20,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte /// Retrieves the `RealtimeObjects` for this channel. /// /// We expect this value to have been previously set by ``prepare(_:)``. - internal static func realtimeObjects(for channel: AblyPlugin.RealtimeChannel, pluginAPI: AblyPlugin.PluginAPIProtocol) -> InternalDefaultRealtimeObjects { + internal static func realtimeObjects(for channel: _AblyPluginSupportPrivate.RealtimeChannel, pluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol) -> InternalDefaultRealtimeObjects { guard let pluginData = pluginAPI.pluginDataValue(forKey: pluginDataKey, channel: channel) else { // InternalPlugin.prepare was not called fatalError("To access LiveObjects functionality, you must pass the LiveObjects plugin in the client options when creating the ARTRealtime instance: `clientOptions.plugins = [.liveObjects: AblyLiveObjects.Plugin.self]`") @@ -33,7 +33,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte // MARK: - LiveObjectsInternalPluginProtocol // Populates the channel's `objects` property. - internal func prepare(_ channel: AblyPlugin.RealtimeChannel, client: AblyPlugin.RealtimeClient) { + internal func prepare(_ channel: _AblyPluginSupportPrivate.RealtimeChannel, client: _AblyPluginSupportPrivate.RealtimeClient) { let logger = pluginAPI.logger(for: channel) let callbackQueue = pluginAPI.callbackQueue(for: client) let options = pluginAPI.options(for: client) @@ -49,14 +49,14 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte } /// Retrieves the internally-typed `objects` property for the channel. - private func realtimeObjects(for channel: AblyPlugin.RealtimeChannel) -> InternalDefaultRealtimeObjects { + private func realtimeObjects(for channel: _AblyPluginSupportPrivate.RealtimeChannel) -> InternalDefaultRealtimeObjects { Self.realtimeObjects(for: channel, pluginAPI: pluginAPI) } /// A class that wraps an object message. /// - /// We need this intermediate type because we want object messages to be structs — because they're nicer to work with internally — but a struct can't conform to the class-bound `AblyPlugin.ObjectMessageProtocol`. - private final class ObjectMessageBox: AblyPlugin.ObjectMessageProtocol where T: Sendable { + /// We need this intermediate type because we want object messages to be structs — because they're nicer to work with internally — but a struct can't conform to the class-bound `_AblyPluginSupportPrivate.ObjectMessageProtocol`. + private final class ObjectMessageBox: _AblyPluginSupportPrivate.ObjectMessageProtocol where T: Sendable { internal let objectMessage: T init(objectMessage: T) { @@ -70,7 +70,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte format: EncodingFormat, error errorPtr: AutoreleasingUnsafeMutablePointer?, ) -> (any ObjectMessageProtocol)? { - let wireObject = WireValue.objectFromAblyPluginData(serialized) + let wireObject = WireValue.objectFrom_AblyPluginSupportPrivateData(serialized) do { let wireObjectMessage = try InboundWireObjectMessage( @@ -89,7 +89,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte } internal func encodeObjectMessage( - _ publicObjectMessage: any AblyPlugin.ObjectMessageProtocol, + _ publicObjectMessage: any _AblyPluginSupportPrivate.ObjectMessageProtocol, format: EncodingFormat, ) -> [String: Any] { guard let outboundObjectMessageBox = publicObjectMessage as? ObjectMessageBox else { @@ -97,14 +97,14 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte } let wireObjectMessage = outboundObjectMessageBox.objectMessage.toWire(format: format) - return wireObjectMessage.toWireObject.toAblyPluginDataDictionary + return wireObjectMessage.toWireObject.toPluginSupportDataDictionary } - internal func onChannelAttached(_ channel: AblyPlugin.RealtimeChannel, hasObjects: Bool) { + internal func onChannelAttached(_ channel: _AblyPluginSupportPrivate.RealtimeChannel, hasObjects: Bool) { realtimeObjects(for: channel).onChannelAttached(hasObjects: hasObjects) } - internal func handleObjectProtocolMessage(withObjectMessages publicObjectMessages: [any AblyPlugin.ObjectMessageProtocol], channel: AblyPlugin.RealtimeChannel) { + internal func handleObjectProtocolMessage(withObjectMessages publicObjectMessages: [any _AblyPluginSupportPrivate.ObjectMessageProtocol], channel: _AblyPluginSupportPrivate.RealtimeChannel) { guard let inboundObjectMessageBoxes = publicObjectMessages as? [ObjectMessageBox] else { preconditionFailure("Expected to receive the same InboundObjectMessage type as we emit") } @@ -116,7 +116,7 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte ) } - internal func handleObjectSyncProtocolMessage(withObjectMessages publicObjectMessages: [any AblyPlugin.ObjectMessageProtocol], protocolMessageChannelSerial: String?, channel: AblyPlugin.RealtimeChannel) { + internal func handleObjectSyncProtocolMessage(withObjectMessages publicObjectMessages: [any _AblyPluginSupportPrivate.ObjectMessageProtocol], protocolMessageChannelSerial: String?, channel: _AblyPluginSupportPrivate.RealtimeChannel) { guard let inboundObjectMessageBoxes = publicObjectMessages as? [ObjectMessageBox] else { preconditionFailure("Expected to receive the same InboundObjectMessage type as we emit") } @@ -133,8 +133,8 @@ internal final class DefaultInternalPlugin: NSObject, AblyPlugin.LiveObjectsInte internal static func sendObject( objectMessages: [OutboundObjectMessage], - channel: AblyPlugin.RealtimeChannel, - client: AblyPlugin.RealtimeClient, + channel: _AblyPluginSupportPrivate.RealtimeChannel, + client: _AblyPluginSupportPrivate.RealtimeClient, pluginAPI: PluginAPIProtocol, ) async throws(InternalError) { let objectMessageBoxes: [ObjectMessageBox] = objectMessages.map { .init(objectMessage: $0) } diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift index a5d7058..4169912 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin import Foundation /// This provides the implementation behind ``PublicDefaultLiveCounter``, via internal versions of the ``LiveCounter`` API. @@ -21,7 +21,7 @@ internal final class InternalDefaultLiveCounter: Sendable { } } - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -30,7 +30,7 @@ internal final class InternalDefaultLiveCounter: Sendable { internal convenience init( testsOnly_data data: Double, objectID: String, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock ) { @@ -40,7 +40,7 @@ internal final class InternalDefaultLiveCounter: Sendable { private init( data: Double, objectID: String, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock ) { @@ -56,7 +56,7 @@ internal final class InternalDefaultLiveCounter: Sendable { /// - objectID: The value for the "private objectId field" of RTO5c1b1a. internal static func createZeroValued( objectID: String, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> Self { diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift index 312affa..e952cdb 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// Protocol for accessing objects from the ObjectsPool. This is used by a LiveMap when it needs to return an object given an object ID. internal protocol LiveMapObjectPoolDelegate: AnyObject, Sendable { @@ -38,7 +38,7 @@ internal final class InternalDefaultLiveMap: Sendable { } } - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -48,7 +48,7 @@ internal final class InternalDefaultLiveMap: Sendable { testsOnly_data data: [String: InternalObjectsMapEntry], objectID: String, testsOnly_semantics semantics: WireEnum? = nil, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -66,7 +66,7 @@ internal final class InternalDefaultLiveMap: Sendable { data: [String: InternalObjectsMapEntry], objectID: String, semantics: WireEnum?, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -84,7 +84,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal static func createZeroValued( objectID: String, semantics: WireEnum? = nil, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> Self { @@ -398,7 +398,7 @@ internal final class InternalDefaultLiveMap: Sendable { using state: ObjectState, objectMessageSerialTimestamp: Date?, objectsPool: inout ObjectsPool, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, clock: SimpleClock, userCallbackQueue: DispatchQueue, ) -> LiveObjectUpdate { @@ -467,7 +467,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal mutating func mergeInitialValue( from operation: ObjectOperation, objectsPool: inout ObjectsPool, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { @@ -621,7 +621,7 @@ internal final class InternalDefaultLiveMap: Sendable { operationTimeserial: String?, operationData: ObjectData?, objectsPool: inout ObjectsPool, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { @@ -744,7 +744,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal mutating func applyMapCreateOperation( _ operation: ObjectOperation, objectsPool: inout ObjectsPool, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift index af12e8a..89770aa 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// This provides the implementation behind ``PublicDefaultRealtimeObjects``, via internal versions of the ``RealtimeObjects`` API. internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPoolDelegate { @@ -8,7 +8,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool private nonisolated(unsafe) var mutableState: MutableState! - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -91,7 +91,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool } } - internal init(logger: AblyPlugin.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, garbageCollectionOptions: GarbageCollectionOptions = .init()) { + internal init(logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, garbageCollectionOptions: GarbageCollectionOptions = .init()) { self.logger = logger self.userCallbackQueue = userCallbackQueue self.clock = clock diff --git a/Sources/AblyLiveObjects/Internal/InternalLiveObject.swift b/Sources/AblyLiveObjects/Internal/InternalLiveObject.swift index d80d53b..27b0d7e 100644 --- a/Sources/AblyLiveObjects/Internal/InternalLiveObject.swift +++ b/Sources/AblyLiveObjects/Internal/InternalLiveObject.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate /// Provides RTLO spec point functionality common to all LiveObjects. /// diff --git a/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift b/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift index f332620..b471677 100644 --- a/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift +++ b/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate /// This is the equivalent of the `LiveObject` abstract class described in RTLO. /// diff --git a/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift b/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift index b82f7d8..f061302 100644 --- a/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift +++ b/Sources/AblyLiveObjects/Internal/ObjectCreationHelpers.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate import CryptoKit import Foundation diff --git a/Sources/AblyLiveObjects/Internal/ObjectsPool.swift b/Sources/AblyLiveObjects/Internal/ObjectsPool.swift index d2ff648..a16cd24 100644 --- a/Sources/AblyLiveObjects/Internal/ObjectsPool.swift +++ b/Sources/AblyLiveObjects/Internal/ObjectsPool.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate /// Maintains the list of objects present on a channel, as described by RTO3. /// @@ -137,7 +137,7 @@ internal struct ObjectsPool { /// Creates an `ObjectsPool` whose root is a zero-value `LiveMap`. internal init( - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, testsOnly_otherEntries otherEntries: [String: Entry]? = nil, @@ -151,7 +151,7 @@ internal struct ObjectsPool { } private init( - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, otherEntries: [String: Entry]? @@ -187,7 +187,7 @@ internal struct ObjectsPool { /// - userCallbackQueue: The callback queue to use for any created LiveObject /// - clock: The clock to use for any created LiveObject /// - Returns: The existing or newly created object - internal mutating func createZeroValueObject(forObjectID objectID: String, logger: AblyPlugin.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock) -> Entry? { + internal mutating func createZeroValueObject(forObjectID objectID: String, logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock) -> Entry? { // RTO6a: If an object with objectId exists in ObjectsPool, do not create a new object if let existingEntry = entries[objectID] { return existingEntry @@ -220,7 +220,7 @@ internal struct ObjectsPool { /// Applies the objects gathered during an `OBJECT_SYNC` to this `ObjectsPool`, per RTO5c1 and RTO5c2. internal mutating func applySyncObjectsPool( _ syncObjectsPool: [SyncObjectsPoolEntry], - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -316,7 +316,7 @@ internal struct ObjectsPool { /// - Returns: The existing or newly created counter object internal mutating func getOrCreateCounter( creationOperation: ObjectCreationHelpers.CounterCreationOperation, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> InternalDefaultLiveCounter { @@ -360,7 +360,7 @@ internal struct ObjectsPool { /// - Returns: The existing or newly created map object internal mutating func getOrCreateMap( creationOperation: ObjectCreationHelpers.MapCreationOperation, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> InternalDefaultLiveMap { diff --git a/Sources/AblyLiveObjects/Protocol/ObjectMessage.swift b/Sources/AblyLiveObjects/Protocol/ObjectMessage.swift index 0a24019..ac846fc 100644 --- a/Sources/AblyLiveObjects/Protocol/ObjectMessage.swift +++ b/Sources/AblyLiveObjects/Protocol/ObjectMessage.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate import Foundation // This file contains the ObjectMessage types that we use within the codebase. We convert them to and from the corresponding wire types (e.g. `InboundWireObjectMessage`) for sending and receiving over the wire. @@ -97,7 +97,7 @@ internal extension InboundObjectMessage { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectMessage: InboundWireObjectMessage, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { id = wireObjectMessage.id clientId = wireObjectMessage.clientId @@ -121,7 +121,7 @@ internal extension OutboundObjectMessage { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> OutboundWireObjectMessage { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> OutboundWireObjectMessage { .init( id: id, clientId: clientId, @@ -145,7 +145,7 @@ internal extension ObjectOperation { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectOperation: WireObjectOperation, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { // Decode the action and objectId first they're not part of PartialObjectOperation action = wireObjectOperation.action @@ -177,7 +177,7 @@ internal extension ObjectOperation { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectOperation { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectOperation { let partialWireOperation = PartialObjectOperation( mapOp: mapOp, counterOp: counterOp, @@ -209,7 +209,7 @@ internal extension PartialObjectOperation { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( partialWireObjectOperation: PartialWireObjectOperation, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { mapOp = try partialWireObjectOperation.mapOp.map { wireObjectsMapOp throws(InternalError) in try .init(wireObjectsMapOp: wireObjectsMapOp, format: format) @@ -230,7 +230,7 @@ internal extension PartialObjectOperation { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> PartialWireObjectOperation { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> PartialWireObjectOperation { .init( mapOp: mapOp?.toWire(format: format), counterOp: counterOp, @@ -250,7 +250,7 @@ internal extension ObjectData { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectData: WireObjectData, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { objectId = wireObjectData.objectId boolean = wireObjectData.boolean @@ -302,7 +302,7 @@ internal extension ObjectData { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectData { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectData { // OD4: Encode data based on format let wireBytes: StringOrData? = if let bytes { switch format { @@ -354,7 +354,7 @@ internal extension ObjectsMapOp { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectsMapOp: WireObjectsMapOp, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { key = wireObjectsMapOp.key data = try wireObjectsMapOp.data.map { wireObjectData throws(InternalError) in @@ -366,7 +366,7 @@ internal extension ObjectsMapOp { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectsMapOp { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectsMapOp { .init( key: key, data: data?.toWire(format: format), @@ -382,7 +382,7 @@ internal extension ObjectsMapEntry { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectsMapEntry: WireObjectsMapEntry, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { tombstone = wireObjectsMapEntry.tombstone timeserial = wireObjectsMapEntry.timeserial @@ -398,7 +398,7 @@ internal extension ObjectsMapEntry { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectsMapEntry { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectsMapEntry { .init( tombstone: tombstone, timeserial: timeserial, @@ -415,7 +415,7 @@ internal extension ObjectsMap { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectsMap: WireObjectsMap, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { semantics = wireObjectsMap.semantics entries = try wireObjectsMap.entries?.ablyLiveObjects_mapValuesWithTypedThrow { wireMapEntry throws(InternalError) in @@ -427,7 +427,7 @@ internal extension ObjectsMap { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectsMap { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectsMap { .init( semantics: semantics, entries: entries?.mapValues { $0.toWire(format: format) }, @@ -443,7 +443,7 @@ internal extension ObjectState { /// - Throws: `InternalError` if JSON or Base64 decoding fails. init( wireObjectState: WireObjectState, - format: AblyPlugin.EncodingFormat + format: _AblyPluginSupportPrivate.EncodingFormat ) throws(InternalError) { objectId = wireObjectState.objectId siteTimeserials = wireObjectState.siteTimeserials @@ -461,7 +461,7 @@ internal extension ObjectState { /// /// - Parameters: /// - format: The format to use when applying the encoding rules of OD4. - func toWire(format: AblyPlugin.EncodingFormat) -> WireObjectState { + func toWire(format: _AblyPluginSupportPrivate.EncodingFormat) -> WireObjectState { .init( objectId: objectId, siteTimeserials: siteTimeserials, diff --git a/Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift b/Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift index fad740a..a8c55d5 100644 --- a/Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift +++ b/Sources/AblyLiveObjects/Protocol/WireObjectMessage.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate import Foundation // This file contains the ObjectMessage types that we send and receive over the wire. We convert them to and from the corresponding non-wire types (e.g. `InboundObjectMessage`) for use within the codebase. @@ -61,7 +61,7 @@ internal extension InboundWireObjectMessage { /// Decodes the `ObjectMessage` and then uses the containing `ProtocolMessage` to populate some absent fields per the rules of the specification. init( wireObject: [String: WireValue], - decodingContext: AblyPlugin.DecodingContextProtocol + decodingContext: _AblyPluginSupportPrivate.DecodingContextProtocol ) throws(InternalError) { // OM2a if let id = try wireObject.optionalStringValueForKey(WireObjectMessageWireKey.id.rawValue) { diff --git a/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift b/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift index da47917..67b8612 100644 --- a/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift +++ b/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin public extension ARTRealtimeChannel { /// A ``RealtimeObjects`` object. diff --git a/Sources/AblyLiveObjects/Public/Plugin.swift b/Sources/AblyLiveObjects/Public/Plugin.swift index 26a377d..870a932 100644 --- a/Sources/AblyLiveObjects/Public/Plugin.swift +++ b/Sources/AblyLiveObjects/Public/Plugin.swift @@ -1,6 +1,6 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate -// We explicitly import the NSObject class, else it seems to get transitively imported from `internal import AblyPlugin`, leading to the error "Class cannot be declared public because its superclass is internal". +// We explicitly import the NSObject class, else it seems to get transitively imported from `internal import _AblyPluginSupportPrivate`, leading to the error "Class cannot be declared public because its superclass is internal". import ObjectiveC.NSObject /// This plugin enables LiveObjects functionality in ably-cocoa. Set the `.liveObjects` key in the ably-cocoa `plugins` client option to this class in order to enable LiveObjects. @@ -22,10 +22,10 @@ import ObjectiveC.NSObject /// ``` @objc public class Plugin: NSObject { - /// The `AblyPlugin.PluginAPIProtocol` that the LiveObjects plugin should use by default (i.e. when one hasn't been injected for test purposes). - internal static let defaultPluginAPI: AblyPlugin.PluginAPIProtocol = AblyPlugin.PluginAPI.sharedInstance() + /// The `_AblyPluginSupportPrivate.PluginAPIProtocol` that the LiveObjects plugin should use by default (i.e. when one hasn't been injected for test purposes). + internal static let defaultPluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol = _AblyPluginSupportPrivate.PluginAPI.sharedInstance() - // MARK: - Informal conformance to AblyPlugin.LiveObjectsPluginProtocol + // MARK: - Informal conformance to _AblyPluginSupportPrivate.LiveObjectsPluginProtocol @objc private static let internalPlugin = DefaultInternalPlugin(pluginAPI: defaultPluginAPI) } diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift index bd88d2f..91fe81e 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate internal extension InternalLiveMapValue { // MARK: - Mapping to public types @@ -6,7 +6,7 @@ internal extension InternalLiveMapValue { struct PublicValueCreationArgs { internal var coreSDK: CoreSDK internal var mapDelegate: LiveMapObjectPoolDelegate - internal var logger: AblyPlugin.Logger + internal var logger: _AblyPluginSupportPrivate.Logger internal var toCounterCreationArgs: PublicObjectsStore.CounterCreationArgs { .init(coreSDK: coreSDK, logger: logger) diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift index 146d05e..6388aa5 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// Our default implementation of ``LiveCounter``. /// @@ -10,9 +10,9 @@ internal final class PublicDefaultLiveCounter: LiveCounter { // MARK: - Dependencies that hold a strong reference to `proxied` private let coreSDK: CoreSDK - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger - internal init(proxied: InternalDefaultLiveCounter, coreSDK: CoreSDK, logger: AblyPlugin.Logger) { + internal init(proxied: InternalDefaultLiveCounter, coreSDK: CoreSDK, logger: _AblyPluginSupportPrivate.Logger) { self.proxied = proxied self.coreSDK = coreSDK self.logger = logger diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift index 52e207d..a6674a4 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// Our default implementation of ``LiveMap``. /// @@ -11,9 +11,9 @@ internal final class PublicDefaultLiveMap: LiveMap { private let coreSDK: CoreSDK private let delegate: LiveMapObjectPoolDelegate - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger - internal init(proxied: InternalDefaultLiveMap, coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate, logger: AblyPlugin.Logger) { + internal init(proxied: InternalDefaultLiveMap, coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate, logger: _AblyPluginSupportPrivate.Logger) { self.proxied = proxied self.coreSDK = coreSDK self.delegate = delegate diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift index 3d97b8b..19a723c 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift @@ -1,5 +1,5 @@ +internal import _AblyPluginSupportPrivate import Ably -internal import AblyPlugin /// The class that provides the public API for interacting with LiveObjects, via the ``ARTRealtimeChannel/objects`` property. /// @@ -13,9 +13,9 @@ internal final class PublicDefaultRealtimeObjects: RealtimeObjects { // MARK: - Dependencies that hold a strong reference to `proxied` private let coreSDK: CoreSDK - private let logger: AblyPlugin.Logger + private let logger: _AblyPluginSupportPrivate.Logger - internal init(proxied: InternalDefaultRealtimeObjects, coreSDK: CoreSDK, logger: AblyPlugin.Logger) { + internal init(proxied: InternalDefaultRealtimeObjects, coreSDK: CoreSDK, logger: _AblyPluginSupportPrivate.Logger) { self.proxied = proxied self.coreSDK = coreSDK self.logger = logger diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift index 4be0753..a6e7033 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift @@ -1,4 +1,4 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate import Foundation /// Stores the public objects that wrap the SDK's internal components. @@ -21,7 +21,7 @@ internal final class PublicObjectsStore: Sendable { internal struct RealtimeObjectsCreationArgs { internal var coreSDK: CoreSDK - internal var logger: AblyPlugin.Logger + internal var logger: _AblyPluginSupportPrivate.Logger } /// Fetches the cached `PublicDefaultRealtimeObjects` that wraps a given `InternalDefaultRealtimeObjects`, creating a new public object if there isn't already one. @@ -33,7 +33,7 @@ internal final class PublicObjectsStore: Sendable { internal struct CounterCreationArgs { internal var coreSDK: CoreSDK - internal var logger: AblyPlugin.Logger + internal var logger: _AblyPluginSupportPrivate.Logger } /// Fetches the cached `PublicDefaultLiveCounter` that wraps a given `InternalDefaultLiveCounter`, creating a new public object if there isn't already one. @@ -46,7 +46,7 @@ internal final class PublicObjectsStore: Sendable { internal struct MapCreationArgs { internal var coreSDK: CoreSDK internal var delegate: LiveMapObjectPoolDelegate - internal var logger: AblyPlugin.Logger + internal var logger: _AblyPluginSupportPrivate.Logger } /// Fetches the cached `PublicDefaultLiveMap` that wraps a given `InternalDefaultLiveMap`, creating a new public object if there isn't already one. @@ -68,7 +68,7 @@ internal final class PublicObjectsStore: Sendable { /// Fetches the proxy that wraps `proxied`, creating a new proxy if there isn't already one. Stores a weak reference to the proxy. mutating func getOrCreate( proxying proxied: some AnyObject, - logger: AblyPlugin.Logger, + logger: _AblyPluginSupportPrivate.Logger, logObjectType: String, createProxy: () -> Proxy, ) -> Proxy { @@ -90,7 +90,7 @@ internal final class PublicObjectsStore: Sendable { return created } - private mutating func removeDeallocatedEntries(logger: AblyPlugin.Logger, logObjectType: String) { + private mutating func removeDeallocatedEntries(logger: _AblyPluginSupportPrivate.Logger, logObjectType: String) { var keysToRemove: Set = [] for (proxiedObjectIdentifier, weakProxyRef) in proxiesByProxiedObjectIdentifier where weakProxyRef.referenced == nil { logger.log("Clearing unused \(logObjectType) proxy from cache (proxied: \(proxiedObjectIdentifier))", level: .debug) diff --git a/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift b/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift index 276621d..9236155 100644 --- a/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift +++ b/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift @@ -1,6 +1,6 @@ -internal import AblyPlugin +internal import _AblyPluginSupportPrivate -internal extension AblyPlugin.Logger { +internal extension _AblyPluginSupportPrivate.Logger { /// A convenience method that provides default values for `file` and `line`. func log(_ message: String, level: ARTLogLevel, fileID: String = #fileID, line: Int = #line) { log(message, with: level, file: fileID, line: line) diff --git a/Sources/AblyLiveObjects/Utility/WireValue.swift b/Sources/AblyLiveObjects/Utility/WireValue.swift index e2e6f5d..e5d2996 100644 --- a/Sources/AblyLiveObjects/Utility/WireValue.swift +++ b/Sources/AblyLiveObjects/Utility/WireValue.swift @@ -1,7 +1,7 @@ import Ably import Foundation -/// A wire value that can be represents the kinds of data that we expect to find inside a deserialized wire object received from AblyPlugin, or which we may put inside a serialized wire object that we send to AblyPlugin. +/// A wire value that can be represents the kinds of data that we expect to find inside a deserialized wire object received from `_AblyPluginSupportPrivate`, or which we may put inside a serialized wire object that we send to `_AblyPluginSupportPrivate`. /// /// Its cases are a superset of those of ``JSONValue``, adding a further `data` case for binary data (we expect to be able to send and receive binary data in the case where ably-cocoa is using the MessagePack format). internal indirect enum WireValue: Sendable, Equatable { @@ -118,27 +118,27 @@ extension WireValue: ExpressibleByBooleanLiteral { // MARK: - Bridging with ably-cocoa internal extension WireValue { - /// Creates a `WireValue` from an AblyPlugin deserialized wire object. + /// Creates a `WireValue` from an `_AblyPluginSupportPrivate` deserialized wire object. /// - /// Specifically, `ablyPluginData` can be a value that was passed to `LiveObjectsPlugin.decodeObjectMessage:…`. - init(ablyPluginData: Any) { + /// Specifically, `pluginSupportData` can be a value that was passed to `LiveObjectsPlugin.decodeObjectMessage:…`. + init(pluginSupportData: Any) { // swiftlint:disable:next trailing_closure - let extendedJSONValue = ExtendedJSONValue(deserialized: ablyPluginData, createExtraValue: { deserializedExtraValue in + let extendedJSONValue = ExtendedJSONValue(deserialized: pluginSupportData, createExtraValue: { deserializedExtraValue in // We support binary data (used for MessagePack format) in addition to JSON values if let data = deserializedExtraValue as? Data { return .data(data) } // ably-cocoa is not conforming to our assumptions; our assumptions are probably wrong. Either way, bring this loudly to our attention instead of trying to carry on - preconditionFailure("WireValue(ablyPluginData:) was given unsupported value \(deserializedExtraValue)") + preconditionFailure("WireValue(pluginSupportData:) was given unsupported value \(deserializedExtraValue)") }) self.init(extendedJSONValue: extendedJSONValue) } - /// Creates a `WireValue` from an AblyPlugin deserialized wire object. Specifically, `ablyPluginData` can be a value that was passed to `LiveObjectsPlugin.decodeObjectMessage:…`. - static func objectFromAblyPluginData(_ ablyPluginData: [String: Any]) -> [String: WireValue] { - let wireValue = WireValue(ablyPluginData: ablyPluginData) + /// Creates a `WireValue` from an `_AblyPluginSupportPrivate` deserialized wire object. Specifically, `pluginSupportData` can be a value that was passed to `LiveObjectsPlugin.decodeObjectMessage:…`. + static func objectFrom_AblyPluginSupportPrivateData(_ pluginSupportData: [String: Any]) -> [String: WireValue] { + let wireValue = WireValue(pluginSupportData: pluginSupportData) guard case let .object(wireObject) = wireValue else { preconditionFailure() } @@ -146,10 +146,10 @@ internal extension WireValue { return wireObject } - /// Creates an AblyPlugin deserialized wire object from a `WireValue`. + /// Creates an `_AblyPluginSupportPrivate` deserialized wire object from a `WireValue`. /// - /// Used by `[String: WireValue].toAblyPluginDataDictionary`. - var toAblyPluginData: Any { + /// Used by `[String: WireValue].toPluginSupportDataDictionary`. + var toPluginSupportData: Any { // swiftlint:disable:next trailing_closure toExtendedJSONValue.serialized(serializeExtraValue: { extendedValue in switch extendedValue { @@ -161,11 +161,11 @@ internal extension WireValue { } internal extension [String: WireValue] { - /// Creates an AblyPlugin deserialized wire object from a dictionary that has string keys and `WireValue` values. + /// Creates an `_AblyPluginSupportPrivate` deserialized wire object from a dictionary that has string keys and `WireValue` values. /// /// Specifically, the value of this property can be returned from `APLiveObjectsPlugin.encodeObjectMessage:`. - var toAblyPluginDataDictionary: [String: Any] { - mapValues(\.toAblyPluginData) + var toPluginSupportDataDictionary: [String: Any] { + mapValues(\.toPluginSupportData) } } diff --git a/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift b/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift index e71959d..feaa871 100644 --- a/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift +++ b/Tests/AblyLiveObjectsTests/AblyLiveObjectsTests.swift @@ -1,6 +1,6 @@ +import _AblyPluginSupportPrivate import Ably @testable import AblyLiveObjects -import AblyPlugin import Testing struct AblyLiveObjectsTests { diff --git a/Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift b/Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift index 441bf12..89b2ddb 100644 --- a/Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift +++ b/Tests/AblyLiveObjectsTests/Helpers/TestFactories.swift @@ -1,5 +1,5 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Foundation // Note that this file was created entirely by Cursor upon my giving it some guidelines — I have not checked its contents in any detail and it may well turn out that there are mistakes here which we need to fix in the future. diff --git a/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift b/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift index 59c51e1..3b6d6f5 100644 --- a/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift +++ b/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift @@ -1,8 +1,8 @@ -import AblyPlugin +import _AblyPluginSupportPrivate import os -/// An implementation of `AblyPlugin.Logger` to use when testing internal components of the LiveObjects plugin. -final class TestLogger: NSObject, AblyPlugin.Logger { +/// An implementation of `_AblyPluginSupportPrivate.Logger` to use when testing internal components of the LiveObjects plugin. +final class TestLogger: NSObject, _AblyPluginSupportPrivate.Logger { // By default, we don’t log in tests to keep the test logs easy to read. You can set this property to `true` to temporarily turn logging on if you want to debug a test. static let loggingEnabled = false diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift index 039ec51..a474738 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift @@ -1,5 +1,5 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Foundation import Testing diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift index 9d982e9..0f33211 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift @@ -1,5 +1,5 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Foundation import Testing diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift index b4bedee..7d64d96 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift @@ -1,6 +1,6 @@ +import _AblyPluginSupportPrivate import Ably @testable import AblyLiveObjects -import AblyPlugin import Testing /// Tests for `InternalDefaultRealtimeObjects`. diff --git a/Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsHelper.swift b/Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsHelper.swift index 9f6671e..77b78e1 100644 --- a/Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsHelper.swift +++ b/Tests/AblyLiveObjectsTests/JS Integration Tests/ObjectsHelper.swift @@ -1,6 +1,6 @@ +import _AblyPluginSupportPrivate import Ably @testable import AblyLiveObjects -import AblyPlugin import Foundation // This file is copied from the file objects.test.js in ably-js. @@ -330,7 +330,7 @@ final class ObjectsHelper: Sendable { logger: channel.internal.logger, ) - let foundationObject = deserialized.toAblyPluginDataDictionary + let foundationObject = deserialized.toPluginSupportDataDictionary let protocolMessage = withExtendedLifetime(jsonLikeEncoderDelegate) { encoder.protocolMessage(from: foundationObject)! } diff --git a/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift b/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift index ff39d7d..06cae4b 100644 --- a/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift +++ b/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift @@ -1,6 +1,6 @@ +import _AblyPluginSupportPrivate import Ably @testable import AblyLiveObjects -import AblyPlugin import Testing /// Tests for `LiveObjectMutableState`. diff --git a/Tests/AblyLiveObjectsTests/ObjectMessageTests.swift b/Tests/AblyLiveObjectsTests/ObjectMessageTests.swift index a973dea..85fd9f4 100644 --- a/Tests/AblyLiveObjectsTests/ObjectMessageTests.swift +++ b/Tests/AblyLiveObjectsTests/ObjectMessageTests.swift @@ -1,5 +1,5 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Foundation import Testing diff --git a/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swift b/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swift index 89514d5..8a35002 100644 --- a/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swift +++ b/Tests/AblyLiveObjectsTests/ObjectsPoolTests.swift @@ -1,5 +1,5 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Testing struct ObjectsPoolTests { diff --git a/Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift b/Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift index 16c28f1..d222814 100644 --- a/Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift +++ b/Tests/AblyLiveObjectsTests/WireObjectMessageTests.swift @@ -1,11 +1,11 @@ +import _AblyPluginSupportPrivate @testable import AblyLiveObjects -import AblyPlugin import Foundation import Testing enum WireObjectMessageTests { // Helper: Fake decoding context - final class FakeDecodingContext: AblyPlugin.DecodingContextProtocol, @unchecked Sendable { + final class FakeDecodingContext: _AblyPluginSupportPrivate.DecodingContextProtocol, @unchecked Sendable { let parentID: String? let parentConnectionID: String? let parentTimestamp: Date? diff --git a/Tests/AblyLiveObjectsTests/WireValueTests.swift b/Tests/AblyLiveObjectsTests/WireValueTests.swift index 91e557e..74a31d3 100644 --- a/Tests/AblyLiveObjectsTests/WireValueTests.swift +++ b/Tests/AblyLiveObjectsTests/WireValueTests.swift @@ -4,35 +4,35 @@ import Foundation import Testing struct WireValueTests { - // MARK: Conversion from AblyPlugin data + // MARK: Conversion from _AblyPluginSupportPrivate data @Test(arguments: [ // object - (ablyPluginData: ["someKey": "someValue"], expectedResult: ["someKey": "someValue"]), + (pluginSupportData: ["someKey": "someValue"], expectedResult: ["someKey": "someValue"]), // array - (ablyPluginData: ["someElement"], expectedResult: ["someElement"]), + (pluginSupportData: ["someElement"], expectedResult: ["someElement"]), // string - (ablyPluginData: "someString", expectedResult: "someString"), + (pluginSupportData: "someString", expectedResult: "someString"), // number - (ablyPluginData: NSNumber(value: 0), expectedResult: 0), - (ablyPluginData: NSNumber(value: 1), expectedResult: 1), - (ablyPluginData: NSNumber(value: 123), expectedResult: 123), - (ablyPluginData: NSNumber(value: 123.456), expectedResult: 123.456), + (pluginSupportData: NSNumber(value: 0), expectedResult: 0), + (pluginSupportData: NSNumber(value: 1), expectedResult: 1), + (pluginSupportData: NSNumber(value: 123), expectedResult: 123), + (pluginSupportData: NSNumber(value: 123.456), expectedResult: 123.456), // bool - (ablyPluginData: NSNumber(value: true), expectedResult: true), - (ablyPluginData: NSNumber(value: false), expectedResult: false), + (pluginSupportData: NSNumber(value: true), expectedResult: true), + (pluginSupportData: NSNumber(value: false), expectedResult: false), // null - (ablyPluginData: NSNull(), expectedResult: .null), + (pluginSupportData: NSNull(), expectedResult: .null), // data - (ablyPluginData: Data([0x01, 0x02, 0x03]), expectedResult: .data(Data([0x01, 0x02, 0x03]))), - ] as[(ablyPluginData: Sendable, expectedResult: WireValue?)]) - func initWithAblyPluginData(ablyPluginData: Sendable, expectedResult: WireValue?) { - #expect(WireValue(ablyPluginData: ablyPluginData) == expectedResult) + (pluginSupportData: Data([0x01, 0x02, 0x03]), expectedResult: .data(Data([0x01, 0x02, 0x03]))), + ] as[(pluginSupportData: Sendable, expectedResult: WireValue?)]) + func initWithPluginSupportData(pluginSupportData: Sendable, expectedResult: WireValue?) { + #expect(WireValue(pluginSupportData: pluginSupportData) == expectedResult) } // Tests that it correctly handles an object deserialized by `JSONSerialization` (which is what ably-cocoa uses for JSON deserialization). @Test - func initWithAblyPluginData_endToEnd_json() throws { + func initWithPluginSupportData_endToEnd_json() throws { let jsonString = """ { "someArray": [ @@ -54,7 +54,7 @@ struct WireValueTests { } """ - let ablyPluginData = try JSONSerialization.jsonObject(with: #require(jsonString.data(using: .utf8))) + let pluginSupportData = try JSONSerialization.jsonObject(with: #require(jsonString.data(using: .utf8))) let expected: WireValue = [ "someArray": [ @@ -75,12 +75,12 @@ struct WireValueTests { ], ] - #expect(WireValue(ablyPluginData: ablyPluginData) == expected) + #expect(WireValue(pluginSupportData: pluginSupportData) == expected) } // Tests that it correctly handles an object deserialized by `ARTMsgPackEncoder` (which is what ably-cocoa uses for MessagePack deserialization). @Test - func initWithAblyPluginData_endToEnd_msgpack() throws { + func initWithPluginSupportData_endToEnd_msgpack() throws { // MessagePack representation of the same data structure as in the JSON test above, plus binary data // This represents: // { @@ -167,7 +167,7 @@ struct WireValueTests { 0xAE, 0x73, 0x6F, 0x6D, 0x65, 0x4F, 0x74, 0x68, 0x65, 0x72, 0x56, 0x61, 0x6C, 0x75, 0x65, // value (14 chars) ]) - let ablyPluginData = try ARTMsgPackEncoder().decode(msgpackData) + let pluginSupportData = try ARTMsgPackEncoder().decode(msgpackData) let expected: WireValue = [ "someArray": [ @@ -189,10 +189,10 @@ struct WireValueTests { ], ] - #expect(WireValue(ablyPluginData: ablyPluginData) == expected) + #expect(WireValue(pluginSupportData: pluginSupportData) == expected) } - // MARK: Conversion to AblyPlugin data + // MARK: Conversion to _AblyPluginSupportPrivate data @Test(arguments: [ // object @@ -214,15 +214,15 @@ struct WireValueTests { // data (value: .data(Data([0x01, 0x02, 0x03])), expectedResult: Data([0x01, 0x02, 0x03])), ] as[(value: WireValue, expectedResult: Sendable)]) - func toAblyPluginData(value: WireValue, expectedResult: Sendable) throws { - let resultAsNSObject = try #require(value.toAblyPluginData as? NSObject) + func toPluginSupportData(value: WireValue, expectedResult: Sendable) throws { + let resultAsNSObject = try #require(value.toPluginSupportData as? NSObject) let expectedResultAsNSObject = try #require(expectedResult as? NSObject) #expect(resultAsNSObject == expectedResultAsNSObject) } // Tests that it creates an object that can be serialized by `JSONSerialization` (which is what ably-cocoa uses for JSON serialization), and that the result of this serialization is what we’d expect. @Test - func toAblyPluginData_endToEnd_json() throws { + func toPluginSupportData_endToEnd_json() throws { let value: WireValue = [ "someArray": [ [ @@ -265,7 +265,7 @@ struct WireValueTests { let jsonSerializationOptions: JSONSerialization.WritingOptions = [.sortedKeys] - let valueData = try JSONSerialization.data(withJSONObject: value.toAblyPluginData, options: jsonSerializationOptions) + let valueData = try JSONSerialization.data(withJSONObject: value.toPluginSupportData, options: jsonSerializationOptions) let expectedData = try { let serialized = try JSONSerialization.jsonObject(with: #require(expectedJSONString.data(using: .utf8))) return try JSONSerialization.data(withJSONObject: serialized, options: jsonSerializationOptions) @@ -276,7 +276,7 @@ struct WireValueTests { // Tests that it creates an object that can be serialized by `ARTMsgPackEncoder` (which is what ably-cocoa uses for MessagePack serialization), and that the result of this serialization is what we’d expect. @Test - func toAblyPluginData_endToEnd_msgpack() throws { + func toPluginSupportData_endToEnd_msgpack() throws { let value: WireValue = [ "someArray": [ [ @@ -365,7 +365,7 @@ struct WireValueTests { 0xAE, 0x73, 0x6F, 0x6D, 0x65, 0x4F, 0x74, 0x68, 0x65, 0x72, 0x56, 0x61, 0x6C, 0x75, 0x65, // value (14 chars) ]) - let actualMsgPackData = try ARTMsgPackEncoder().encode(value.toAblyPluginData) + let actualMsgPackData = try ARTMsgPackEncoder().encode(value.toPluginSupportData) // Verify that both decode to the same Foundation object structure let expectedDecoded = try ARTMsgPackEncoder().decode(expectedMsgPackData) diff --git a/ably-cocoa b/ably-cocoa index 5096ca3..9f1a651 160000 --- a/ably-cocoa +++ b/ably-cocoa @@ -1 +1 @@ -Subproject commit 5096ca37c6c39f8f33e261f49faf2a6f9d03e529 +Subproject commit 9f1a65179b69b6041b3a65664c5fa6c48d722fec From b4e1899a86b063bf670f4b83407ba20f27458eb9 Mon Sep 17 00:00:00 2001 From: Lawrence Forooghian Date: Tue, 19 Aug 2025 09:00:59 -0300 Subject: [PATCH 3/3] Get ably-cocoa plugin APIs from an external repo As required by the accompanying ably-cocoa submodule bump (see the ably-cocoa commit message for explanation of why we're making this change). --- .../xcshareddata/swiftpm/Package.resolved | 11 +++- Package.resolved | 11 +++- Package.swift | 8 ++- .../Internal/ARTClientOptions+Objects.swift | 5 +- .../AblyLiveObjects/Internal/CoreSDK.swift | 12 ++--- .../Internal/DefaultInternalPlugin.swift | 12 +++-- .../Internal/InternalDefaultLiveCounter.swift | 8 +-- .../Internal/InternalDefaultLiveMap.swift | 16 +++--- .../InternalDefaultRealtimeObjects.swift | 4 +- .../Internal/LiveObjectMutableState.swift | 1 + .../Internal/ObjectsPool.swift | 12 ++--- .../Public/ARTRealtimeChannel+Objects.swift | 5 +- Sources/AblyLiveObjects/Public/Plugin.swift | 2 +- .../InternalLiveMapValue+ToPublic.swift | 2 +- .../PublicDefaultLiveCounter.swift | 4 +- .../PublicDefaultLiveMap.swift | 4 +- .../PublicDefaultRealtimeObjects.swift | 4 +- .../PublicObjectsStore.swift | 10 ++-- .../Utility/APLogger+Swift.swift | 8 --- Sources/AblyLiveObjects/Utility/Errors.swift | 3 +- .../Utility/InternalError.swift | 7 +++ Sources/AblyLiveObjects/Utility/Logger.swift | 41 ++++++++++++++ .../Utility/MarkerProtocolHelpers.swift | 54 +++++++++++++++++++ .../AblyLiveObjects/Utility/WireValue.swift | 2 +- .../Helpers/TestLogger.swift | 11 ++-- .../InternalDefaultLiveCounterTests.swift | 9 ++-- .../InternalDefaultLiveMapTests.swift | 17 +++--- .../InternalDefaultRealtimeObjectsTests.swift | 12 ++--- .../LiveObjectMutableStateTests.swift | 4 +- .../Mocks/MockCoreSDK.swift | 7 +-- ably-cocoa | 2 +- 31 files changed, 217 insertions(+), 91 deletions(-) delete mode 100644 Sources/AblyLiveObjects/Utility/APLogger+Swift.swift create mode 100644 Sources/AblyLiveObjects/Utility/Logger.swift create mode 100644 Sources/AblyLiveObjects/Utility/MarkerProtocolHelpers.swift diff --git a/AblyLiveObjects.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AblyLiveObjects.xcworkspace/xcshareddata/swiftpm/Package.resolved index bfe1d58..cd28d5b 100644 --- a/AblyLiveObjects.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/AblyLiveObjects.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "6884be3a1fb838d3f9a3288b0cb994d0dfce4e90c7d648bca08e61fb802c9cda", + "originHash" : "7ffc8893e3a0652bc31d38d048052def20308c84ae9888411b48b5c89c2ec6c6", "pins" : [ + { + "identity" : "ably-cocoa-plugin-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ably/ably-cocoa-plugin-support", + "state" : { + "revision" : "cec94ed123d60e39e3f8df665c30a57482d37612", + "version" : "0.1.0" + } + }, { "identity" : "delta-codec-cocoa", "kind" : "remoteSourceControl", diff --git a/Package.resolved b/Package.resolved index 773dea5..44dc373 100644 --- a/Package.resolved +++ b/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "9d42be7ef9d81adeb6ac28ccc2a7a4dd43dbf0d952b6f8331e73ab665d36df3a", + "originHash" : "cf81894c95bf31f3c45009841b1a7ee58b50fdcf93ceeecdade367eef5e57c58", "pins" : [ + { + "identity" : "ably-cocoa-plugin-support", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ably/ably-cocoa-plugin-support", + "state" : { + "revision" : "cec94ed123d60e39e3f8df665c30a57482d37612", + "version" : "0.1.0" + } + }, { "identity" : "delta-codec-cocoa", "kind" : "remoteSourceControl", diff --git a/Package.swift b/Package.swift index 742aa4b..ce7b62f 100644 --- a/Package.swift +++ b/Package.swift @@ -21,6 +21,10 @@ let package = Package( .package( path: "ably-cocoa", ), + .package( + url: "https://github.com/ably/ably-cocoa-plugin-support", + from: "0.1.0", + ), .package( url: "https://github.com/apple/swift-argument-parser", from: "1.5.0", @@ -48,7 +52,7 @@ let package = Package( ), .product( name: "_AblyPluginSupportPrivate", - package: "ably-cocoa", + package: "ably-cocoa-plugin-support", ), ], ), @@ -62,7 +66,7 @@ let package = Package( ), .product( name: "_AblyPluginSupportPrivate", - package: "ably-cocoa", + package: "ably-cocoa-plugin-support", ), ], resources: [ diff --git a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift index 8797381..6855434 100644 --- a/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift +++ b/Sources/AblyLiveObjects/Internal/ARTClientOptions+Objects.swift @@ -1,4 +1,5 @@ internal import _AblyPluginSupportPrivate +import Ably internal extension ARTClientOptions { private class Box { @@ -16,7 +17,7 @@ internal extension ARTClientOptions { get { let optionsValue = Plugin.defaultPluginAPI.pluginOptionsValue( forKey: Self.garbageCollectionOptionsKey, - clientOptions: self, + clientOptions: asPluginPublicClientOptions, ) guard let optionsValue else { @@ -38,7 +39,7 @@ internal extension ARTClientOptions { Plugin.defaultPluginAPI.setPluginOptionsValue( Box(boxed: newValue), forKey: Self.garbageCollectionOptionsKey, - clientOptions: self, + clientOptions: asPluginPublicClientOptions, ) } } diff --git a/Sources/AblyLiveObjects/Internal/CoreSDK.swift b/Sources/AblyLiveObjects/Internal/CoreSDK.swift index 0c93078..1e99994 100644 --- a/Sources/AblyLiveObjects/Internal/CoreSDK.swift +++ b/Sources/AblyLiveObjects/Internal/CoreSDK.swift @@ -14,7 +14,7 @@ internal protocol CoreSDK: AnyObject, Sendable { func testsOnly_overridePublish(with newImplementation: @escaping ([OutboundObjectMessage]) async throws(InternalError) -> Void) /// Returns the current state of the Realtime channel that this wraps. - var channelState: ARTRealtimeChannelState { get } + var channelState: _AblyPluginSupportPrivate.RealtimeChannelState { get } } internal final class DefaultCoreSDK: CoreSDK { @@ -24,7 +24,7 @@ internal final class DefaultCoreSDK: CoreSDK { private let channel: _AblyPluginSupportPrivate.RealtimeChannel private let client: _AblyPluginSupportPrivate.RealtimeClient private let pluginAPI: PluginAPIProtocol - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger /// If set to true, ``publish(objectMessages:)`` will behave like a no-op. /// @@ -37,7 +37,7 @@ internal final class DefaultCoreSDK: CoreSDK { channel: _AblyPluginSupportPrivate.RealtimeChannel, client: _AblyPluginSupportPrivate.RealtimeClient, pluginAPI: PluginAPIProtocol, - logger: _AblyPluginSupportPrivate.Logger + logger: Logger ) { self.channel = channel self.client = client @@ -81,8 +81,8 @@ internal final class DefaultCoreSDK: CoreSDK { } } - internal var channelState: ARTRealtimeChannelState { - channel.state + internal var channelState: _AblyPluginSupportPrivate.RealtimeChannelState { + pluginAPI.state(for: channel) } } @@ -97,7 +97,7 @@ internal extension CoreSDK { /// - operationDescription: A description of the operation being performed, used in error messages /// - Throws: `ARTErrorInfo` with code 90001 and statusCode 400 if the channel is in any of the invalid states func validateChannelState( - notIn invalidStates: [ARTRealtimeChannelState], + notIn invalidStates: [_AblyPluginSupportPrivate.RealtimeChannelState], operationDescription: String, ) throws(ARTErrorInfo) { let currentChannelState = channelState diff --git a/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift b/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift index 970157e..ac081fc 100644 --- a/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift +++ b/Sources/AblyLiveObjects/Internal/DefaultInternalPlugin.swift @@ -1,4 +1,5 @@ internal import _AblyPluginSupportPrivate +import Ably // We explicitly import the NSObject class, else it seems to get transitively imported from `internal import _AblyPluginSupportPrivate`, leading to the error "Class cannot be declared public because its superclass is internal". import ObjectiveC.NSObject @@ -34,10 +35,11 @@ internal final class DefaultInternalPlugin: NSObject, _AblyPluginSupportPrivate. // Populates the channel's `objects` property. internal func prepare(_ channel: _AblyPluginSupportPrivate.RealtimeChannel, client: _AblyPluginSupportPrivate.RealtimeClient) { - let logger = pluginAPI.logger(for: channel) + let pluginLogger = pluginAPI.logger(for: channel) let callbackQueue = pluginAPI.callbackQueue(for: client) - let options = pluginAPI.options(for: client) + let options = ARTClientOptions.castPluginPublicClientOptions(pluginAPI.options(for: client)) + let logger = DefaultLogger(pluginLogger: pluginLogger, pluginAPI: pluginAPI) logger.log("LiveObjects.DefaultInternalPlugin received prepare(_:)", level: .debug) let liveObjects = InternalDefaultRealtimeObjects( logger: logger, @@ -68,9 +70,9 @@ internal final class DefaultInternalPlugin: NSObject, _AblyPluginSupportPrivate. _ serialized: [String: Any], context: DecodingContextProtocol, format: EncodingFormat, - error errorPtr: AutoreleasingUnsafeMutablePointer?, + error errorPtr: AutoreleasingUnsafeMutablePointer<_AblyPluginSupportPrivate.PublicErrorInfo?>?, ) -> (any ObjectMessageProtocol)? { - let wireObject = WireValue.objectFrom_AblyPluginSupportPrivateData(serialized) + let wireObject = WireValue.objectFromPluginSupportData(serialized) do { let wireObjectMessage = try InboundWireObjectMessage( @@ -83,7 +85,7 @@ internal final class DefaultInternalPlugin: NSObject, _AblyPluginSupportPrivate. ) return ObjectMessageBox(objectMessage: objectMessage) } catch { - errorPtr?.pointee = error.toARTErrorInfo() + errorPtr?.pointee = error.toARTErrorInfo().asPluginPublicErrorInfo return nil } } diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift index 4169912..9c314bc 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveCounter.swift @@ -21,7 +21,7 @@ internal final class InternalDefaultLiveCounter: Sendable { } } - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -30,7 +30,7 @@ internal final class InternalDefaultLiveCounter: Sendable { internal convenience init( testsOnly_data data: Double, objectID: String, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock ) { @@ -40,7 +40,7 @@ internal final class InternalDefaultLiveCounter: Sendable { private init( data: Double, objectID: String, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock ) { @@ -56,7 +56,7 @@ internal final class InternalDefaultLiveCounter: Sendable { /// - objectID: The value for the "private objectId field" of RTO5c1b1a. internal static func createZeroValued( objectID: String, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> Self { diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift index e952cdb..84a94c2 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultLiveMap.swift @@ -38,7 +38,7 @@ internal final class InternalDefaultLiveMap: Sendable { } } - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -48,7 +48,7 @@ internal final class InternalDefaultLiveMap: Sendable { testsOnly_data data: [String: InternalObjectsMapEntry], objectID: String, testsOnly_semantics semantics: WireEnum? = nil, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -66,7 +66,7 @@ internal final class InternalDefaultLiveMap: Sendable { data: [String: InternalObjectsMapEntry], objectID: String, semantics: WireEnum?, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -84,7 +84,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal static func createZeroValued( objectID: String, semantics: WireEnum? = nil, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> Self { @@ -398,7 +398,7 @@ internal final class InternalDefaultLiveMap: Sendable { using state: ObjectState, objectMessageSerialTimestamp: Date?, objectsPool: inout ObjectsPool, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, clock: SimpleClock, userCallbackQueue: DispatchQueue, ) -> LiveObjectUpdate { @@ -467,7 +467,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal mutating func mergeInitialValue( from operation: ObjectOperation, objectsPool: inout ObjectsPool, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { @@ -621,7 +621,7 @@ internal final class InternalDefaultLiveMap: Sendable { operationTimeserial: String?, operationData: ObjectData?, objectsPool: inout ObjectsPool, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { @@ -744,7 +744,7 @@ internal final class InternalDefaultLiveMap: Sendable { internal mutating func applyMapCreateOperation( _ operation: ObjectOperation, objectsPool: inout ObjectsPool, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> LiveObjectUpdate { diff --git a/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift b/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift index 89770aa..c989756 100644 --- a/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift +++ b/Sources/AblyLiveObjects/Internal/InternalDefaultRealtimeObjects.swift @@ -8,7 +8,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool private nonisolated(unsafe) var mutableState: MutableState! - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger private let userCallbackQueue: DispatchQueue private let clock: SimpleClock @@ -91,7 +91,7 @@ internal final class InternalDefaultRealtimeObjects: Sendable, LiveMapObjectPool } } - internal init(logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, garbageCollectionOptions: GarbageCollectionOptions = .init()) { + internal init(logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, garbageCollectionOptions: GarbageCollectionOptions = .init()) { self.logger = logger self.userCallbackQueue = userCallbackQueue self.clock = clock diff --git a/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift b/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift index b471677..191d312 100644 --- a/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift +++ b/Sources/AblyLiveObjects/Internal/LiveObjectMutableState.swift @@ -1,4 +1,5 @@ internal import _AblyPluginSupportPrivate +import Ably /// This is the equivalent of the `LiveObject` abstract class described in RTLO. /// diff --git a/Sources/AblyLiveObjects/Internal/ObjectsPool.swift b/Sources/AblyLiveObjects/Internal/ObjectsPool.swift index a16cd24..3cef1de 100644 --- a/Sources/AblyLiveObjects/Internal/ObjectsPool.swift +++ b/Sources/AblyLiveObjects/Internal/ObjectsPool.swift @@ -137,7 +137,7 @@ internal struct ObjectsPool { /// Creates an `ObjectsPool` whose root is a zero-value `LiveMap`. internal init( - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, testsOnly_otherEntries otherEntries: [String: Entry]? = nil, @@ -151,7 +151,7 @@ internal struct ObjectsPool { } private init( - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, otherEntries: [String: Entry]? @@ -187,7 +187,7 @@ internal struct ObjectsPool { /// - userCallbackQueue: The callback queue to use for any created LiveObject /// - clock: The clock to use for any created LiveObject /// - Returns: The existing or newly created object - internal mutating func createZeroValueObject(forObjectID objectID: String, logger: _AblyPluginSupportPrivate.Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock) -> Entry? { + internal mutating func createZeroValueObject(forObjectID objectID: String, logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock) -> Entry? { // RTO6a: If an object with objectId exists in ObjectsPool, do not create a new object if let existingEntry = entries[objectID] { return existingEntry @@ -220,7 +220,7 @@ internal struct ObjectsPool { /// Applies the objects gathered during an `OBJECT_SYNC` to this `ObjectsPool`, per RTO5c1 and RTO5c2. internal mutating func applySyncObjectsPool( _ syncObjectsPool: [SyncObjectsPoolEntry], - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) { @@ -316,7 +316,7 @@ internal struct ObjectsPool { /// - Returns: The existing or newly created counter object internal mutating func getOrCreateCounter( creationOperation: ObjectCreationHelpers.CounterCreationOperation, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> InternalDefaultLiveCounter { @@ -360,7 +360,7 @@ internal struct ObjectsPool { /// - Returns: The existing or newly created map object internal mutating func getOrCreateMap( creationOperation: ObjectCreationHelpers.MapCreationOperation, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, userCallbackQueue: DispatchQueue, clock: SimpleClock, ) -> InternalDefaultLiveMap { diff --git a/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift b/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift index 67b8612..cec5ca9 100644 --- a/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift +++ b/Sources/AblyLiveObjects/Public/ARTRealtimeChannel+Objects.swift @@ -9,10 +9,11 @@ public extension ARTRealtimeChannel { private var nonTypeErasedObjects: PublicDefaultRealtimeObjects { let pluginAPI = Plugin.defaultPluginAPI - let underlyingObjects = pluginAPI.underlyingObjects(forPublicRealtimeChannel: self) + let underlyingObjects = pluginAPI.underlyingObjects(for: asPluginPublicRealtimeChannel) let internalObjects = DefaultInternalPlugin.realtimeObjects(for: underlyingObjects.channel, pluginAPI: pluginAPI) - let logger = pluginAPI.logger(for: underlyingObjects.channel) + let pluginLogger = pluginAPI.logger(for: underlyingObjects.channel) + let logger = DefaultLogger(pluginLogger: pluginLogger, pluginAPI: pluginAPI) let coreSDK = DefaultCoreSDK( channel: underlyingObjects.channel, diff --git a/Sources/AblyLiveObjects/Public/Plugin.swift b/Sources/AblyLiveObjects/Public/Plugin.swift index 870a932..799c354 100644 --- a/Sources/AblyLiveObjects/Public/Plugin.swift +++ b/Sources/AblyLiveObjects/Public/Plugin.swift @@ -23,7 +23,7 @@ import ObjectiveC.NSObject @objc public class Plugin: NSObject { /// The `_AblyPluginSupportPrivate.PluginAPIProtocol` that the LiveObjects plugin should use by default (i.e. when one hasn't been injected for test purposes). - internal static let defaultPluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol = _AblyPluginSupportPrivate.PluginAPI.sharedInstance() + internal static let defaultPluginAPI = _AblyPluginSupportPrivate.DependencyStore.sharedInstance().fetchPluginAPI() // MARK: - Informal conformance to _AblyPluginSupportPrivate.LiveObjectsPluginProtocol diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift index 91fe81e..fa7e7bb 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/InternalLiveMapValue+ToPublic.swift @@ -6,7 +6,7 @@ internal extension InternalLiveMapValue { struct PublicValueCreationArgs { internal var coreSDK: CoreSDK internal var mapDelegate: LiveMapObjectPoolDelegate - internal var logger: _AblyPluginSupportPrivate.Logger + internal var logger: Logger internal var toCounterCreationArgs: PublicObjectsStore.CounterCreationArgs { .init(coreSDK: coreSDK, logger: logger) diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift index 6388aa5..90a408d 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveCounter.swift @@ -10,9 +10,9 @@ internal final class PublicDefaultLiveCounter: LiveCounter { // MARK: - Dependencies that hold a strong reference to `proxied` private let coreSDK: CoreSDK - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger - internal init(proxied: InternalDefaultLiveCounter, coreSDK: CoreSDK, logger: _AblyPluginSupportPrivate.Logger) { + internal init(proxied: InternalDefaultLiveCounter, coreSDK: CoreSDK, logger: Logger) { self.proxied = proxied self.coreSDK = coreSDK self.logger = logger diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift index a6674a4..5aad18f 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultLiveMap.swift @@ -11,9 +11,9 @@ internal final class PublicDefaultLiveMap: LiveMap { private let coreSDK: CoreSDK private let delegate: LiveMapObjectPoolDelegate - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger - internal init(proxied: InternalDefaultLiveMap, coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate, logger: _AblyPluginSupportPrivate.Logger) { + internal init(proxied: InternalDefaultLiveMap, coreSDK: CoreSDK, delegate: LiveMapObjectPoolDelegate, logger: Logger) { self.proxied = proxied self.coreSDK = coreSDK self.delegate = delegate diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift index 19a723c..34221ad 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicDefaultRealtimeObjects.swift @@ -13,9 +13,9 @@ internal final class PublicDefaultRealtimeObjects: RealtimeObjects { // MARK: - Dependencies that hold a strong reference to `proxied` private let coreSDK: CoreSDK - private let logger: _AblyPluginSupportPrivate.Logger + private let logger: Logger - internal init(proxied: InternalDefaultRealtimeObjects, coreSDK: CoreSDK, logger: _AblyPluginSupportPrivate.Logger) { + internal init(proxied: InternalDefaultRealtimeObjects, coreSDK: CoreSDK, logger: Logger) { self.proxied = proxied self.coreSDK = coreSDK self.logger = logger diff --git a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift index a6e7033..264a92c 100644 --- a/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift +++ b/Sources/AblyLiveObjects/Public/Public Proxy Objects/PublicObjectsStore.swift @@ -21,7 +21,7 @@ internal final class PublicObjectsStore: Sendable { internal struct RealtimeObjectsCreationArgs { internal var coreSDK: CoreSDK - internal var logger: _AblyPluginSupportPrivate.Logger + internal var logger: Logger } /// Fetches the cached `PublicDefaultRealtimeObjects` that wraps a given `InternalDefaultRealtimeObjects`, creating a new public object if there isn't already one. @@ -33,7 +33,7 @@ internal final class PublicObjectsStore: Sendable { internal struct CounterCreationArgs { internal var coreSDK: CoreSDK - internal var logger: _AblyPluginSupportPrivate.Logger + internal var logger: Logger } /// Fetches the cached `PublicDefaultLiveCounter` that wraps a given `InternalDefaultLiveCounter`, creating a new public object if there isn't already one. @@ -46,7 +46,7 @@ internal final class PublicObjectsStore: Sendable { internal struct MapCreationArgs { internal var coreSDK: CoreSDK internal var delegate: LiveMapObjectPoolDelegate - internal var logger: _AblyPluginSupportPrivate.Logger + internal var logger: Logger } /// Fetches the cached `PublicDefaultLiveMap` that wraps a given `InternalDefaultLiveMap`, creating a new public object if there isn't already one. @@ -68,7 +68,7 @@ internal final class PublicObjectsStore: Sendable { /// Fetches the proxy that wraps `proxied`, creating a new proxy if there isn't already one. Stores a weak reference to the proxy. mutating func getOrCreate( proxying proxied: some AnyObject, - logger: _AblyPluginSupportPrivate.Logger, + logger: Logger, logObjectType: String, createProxy: () -> Proxy, ) -> Proxy { @@ -90,7 +90,7 @@ internal final class PublicObjectsStore: Sendable { return created } - private mutating func removeDeallocatedEntries(logger: _AblyPluginSupportPrivate.Logger, logObjectType: String) { + private mutating func removeDeallocatedEntries(logger: Logger, logObjectType: String) { var keysToRemove: Set = [] for (proxiedObjectIdentifier, weakProxyRef) in proxiesByProxiedObjectIdentifier where weakProxyRef.referenced == nil { logger.log("Clearing unused \(logObjectType) proxy from cache (proxied: \(proxiedObjectIdentifier))", level: .debug) diff --git a/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift b/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift deleted file mode 100644 index 9236155..0000000 --- a/Sources/AblyLiveObjects/Utility/APLogger+Swift.swift +++ /dev/null @@ -1,8 +0,0 @@ -internal import _AblyPluginSupportPrivate - -internal extension _AblyPluginSupportPrivate.Logger { - /// A convenience method that provides default values for `file` and `line`. - func log(_ message: String, level: ARTLogLevel, fileID: String = #fileID, line: Int = #line) { - log(message, with: level, file: fileID, line: line) - } -} diff --git a/Sources/AblyLiveObjects/Utility/Errors.swift b/Sources/AblyLiveObjects/Utility/Errors.swift index 941d3e8..1ab2e66 100644 --- a/Sources/AblyLiveObjects/Utility/Errors.swift +++ b/Sources/AblyLiveObjects/Utility/Errors.swift @@ -1,3 +1,4 @@ +internal import _AblyPluginSupportPrivate import Ably /** @@ -5,7 +6,7 @@ import Ably */ internal enum LiveObjectsError { // operationDescription should be a description of a method like "LiveCounter.value"; it will be interpolated into an error message - case objectsOperationFailedInvalidChannelState(operationDescription: String, channelState: ARTRealtimeChannelState) + case objectsOperationFailedInvalidChannelState(operationDescription: String, channelState: _AblyPluginSupportPrivate.RealtimeChannelState) case counterInitialValueInvalid(value: Double) case counterIncrementAmountInvalid(amount: Double) diff --git a/Sources/AblyLiveObjects/Utility/InternalError.swift b/Sources/AblyLiveObjects/Utility/InternalError.swift index e9fbf70..4492cf6 100644 --- a/Sources/AblyLiveObjects/Utility/InternalError.swift +++ b/Sources/AblyLiveObjects/Utility/InternalError.swift @@ -1,3 +1,4 @@ +internal import _AblyPluginSupportPrivate import Ably /// An error thrown by the internals of the LiveObjects SDK. @@ -35,3 +36,9 @@ internal extension ARTErrorInfo { .errorInfo(self) } } + +internal extension _AblyPluginSupportPrivate.PublicErrorInfo { + func toInternalError() -> InternalError { + ARTErrorInfo.castPluginPublicErrorInfo(self).toInternalError() + } +} diff --git a/Sources/AblyLiveObjects/Utility/Logger.swift b/Sources/AblyLiveObjects/Utility/Logger.swift new file mode 100644 index 0000000..94cfca9 --- /dev/null +++ b/Sources/AblyLiveObjects/Utility/Logger.swift @@ -0,0 +1,41 @@ +internal import _AblyPluginSupportPrivate + +/// A reference to a line within a source code file. +internal struct CodeLocation: Equatable { + /// A file identifier in the format used by Swift’s `#fileID` macro. For example, `"AblyChat/Room.swift"`. + internal var fileID: String + /// The line number in the source code file referred to by ``fileID``. + internal var line: Int +} + +internal protocol Logger: Sendable { + func log(_ message: String, level: _AblyPluginSupportPrivate.LogLevel, codeLocation: CodeLocation) +} + +internal extension AblyLiveObjects.Logger { + /// A convenience method that provides default values for `file` and `line`. + func log(_ message: String, level: _AblyPluginSupportPrivate.LogLevel, fileID: String = #fileID, line: Int = #line) { + let codeLocation = CodeLocation(fileID: fileID, line: line) + log(message, level: level, codeLocation: codeLocation) + } +} + +internal final class DefaultLogger: Logger { + private let pluginLogger: _AblyPluginSupportPrivate.Logger + private let pluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol + + internal init(pluginLogger: _AblyPluginSupportPrivate.Logger, pluginAPI: _AblyPluginSupportPrivate.PluginAPIProtocol) { + self.pluginLogger = pluginLogger + self.pluginAPI = pluginAPI + } + + internal func log(_ message: String, level: LogLevel, codeLocation: CodeLocation) { + pluginAPI.log( + message, + with: level, + file: codeLocation.fileID, + line: codeLocation.line, + logger: pluginLogger, + ) + } +} diff --git a/Sources/AblyLiveObjects/Utility/MarkerProtocolHelpers.swift b/Sources/AblyLiveObjects/Utility/MarkerProtocolHelpers.swift new file mode 100644 index 0000000..28bf619 --- /dev/null +++ b/Sources/AblyLiveObjects/Utility/MarkerProtocolHelpers.swift @@ -0,0 +1,54 @@ +internal import _AblyPluginSupportPrivate +import Ably + +/// Upcasts an instance of an `_AblyPluginSupportPrivate` marker protocol to the concrete type that this marker protocol represents. +internal func castPluginPublicMarkerProtocolValue(_ pluginMarkerProtocolValue: Any, to _: T.Type) -> T { + guard let actualPublicValue = pluginMarkerProtocolValue as? T else { + preconditionFailure("Expected \(T.self), got \(type(of: pluginMarkerProtocolValue))") + } + + return actualPublicValue +} + +internal extension ARTRealtimeChannel { + /// Downcasts this `ARTRealtimeChannel` to its `_AblyPluginSupportPrivate` equivalent type `PublicRealtimeChannel`. + /// + /// - Note: Swift compiler restrictions prevent us from declaring `ARTRealtimeChannel` as conforming to `PublicRealtimeChannel` (this is due to our use of `internal import`). + var asPluginPublicRealtimeChannel: _AblyPluginSupportPrivate.PublicRealtimeChannel { + // In order for this cast to succeed, we rely on the fact that ably-cocoa internally declares ARTRealtimeChannel as conforming to PublicRealtimeChannel. + // swiftlint:disable:next force_cast + self as! _AblyPluginSupportPrivate.PublicRealtimeChannel + } +} + +internal extension ARTClientOptions { + /// Downcasts this `ARTClientOptions` to its `_AblyPluginSupportPrivate` marker protocol type `PublicClientOptions`. + /// + /// - Note: Swift compiler restrictions prevent us from declaring `ARTClientOptions` as conforming to `PublicClientOptions` (this is due to our use of `internal import`). + var asPluginPublicClientOptions: _AblyPluginSupportPrivate.PublicClientOptions { + // In order for this cast to succeed, we rely on the fact that ably-cocoa internally declares ARTClientOptions as conforming to PublicClientOptions. + // swiftlint:disable:next force_cast + self as! _AblyPluginSupportPrivate.PublicClientOptions + } + + /// Upcasts an instance of `_AblyPluginSupportPrivate`'s `PublicClientOptions`, which is the marker protocol that it uses to represent an `ARTClientOptions`, to an `ARTClientOptions`. + static func castPluginPublicClientOptions(_ pluginPublicClientOptions: PublicClientOptions) -> Self { + castPluginPublicMarkerProtocolValue(pluginPublicClientOptions, to: Self.self) + } +} + +internal extension ARTErrorInfo { + /// Downcasts this `ARTErrorInfo` to its `_AblyPluginSupportPrivate` marker protocol type `PublicErrorInfo`. + /// + /// - Note: Swift compiler restrictions prevent us from declaring `ARTErrorInfo` as conforming to `PublicErrorInfo` (this is due to our use of `internal import`). + var asPluginPublicErrorInfo: _AblyPluginSupportPrivate.PublicErrorInfo { + // In order for this cast to succeed, we rely on the fact that ably-cocoa internally declares ARTErrorInfo as conforming to PublicErrorInfo. + // swiftlint:disable:next force_cast + self as! _AblyPluginSupportPrivate.PublicErrorInfo + } + + /// Upcasts an instance of `_AblyPluginSupportPrivate`'s `PublicErrorInfo`, which is the marker protocol that it uses to represent an `ARTErrorInfo`, to an `ARTErrorInfo`. + static func castPluginPublicErrorInfo(_ pluginPublicErrorInfo: PublicErrorInfo) -> Self { + castPluginPublicMarkerProtocolValue(pluginPublicErrorInfo, to: Self.self) + } +} diff --git a/Sources/AblyLiveObjects/Utility/WireValue.swift b/Sources/AblyLiveObjects/Utility/WireValue.swift index e5d2996..6e82a25 100644 --- a/Sources/AblyLiveObjects/Utility/WireValue.swift +++ b/Sources/AblyLiveObjects/Utility/WireValue.swift @@ -137,7 +137,7 @@ internal extension WireValue { } /// Creates a `WireValue` from an `_AblyPluginSupportPrivate` deserialized wire object. Specifically, `pluginSupportData` can be a value that was passed to `LiveObjectsPlugin.decodeObjectMessage:…`. - static func objectFrom_AblyPluginSupportPrivateData(_ pluginSupportData: [String: Any]) -> [String: WireValue] { + static func objectFromPluginSupportData(_ pluginSupportData: [String: Any]) -> [String: WireValue] { let wireValue = WireValue(pluginSupportData: pluginSupportData) guard case let .object(wireObject) = wireValue else { preconditionFailure() diff --git a/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift b/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift index 3b6d6f5..3d53bda 100644 --- a/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift +++ b/Tests/AblyLiveObjectsTests/Helpers/TestLogger.swift @@ -1,23 +1,24 @@ import _AblyPluginSupportPrivate +@testable import AblyLiveObjects import os -/// An implementation of `_AblyPluginSupportPrivate.Logger` to use when testing internal components of the LiveObjects plugin. -final class TestLogger: NSObject, _AblyPluginSupportPrivate.Logger { +/// An implementation of `Logger` to use when testing internal components of the LiveObjects plugin. +final class TestLogger: NSObject, AblyLiveObjects.Logger { // By default, we don’t log in tests to keep the test logs easy to read. You can set this property to `true` to temporarily turn logging on if you want to debug a test. static let loggingEnabled = false private let underlyingLogger = os.Logger() - func log(_ message: String, with level: ARTLogLevel, file fileName: UnsafePointer, line: Int) { + func log(_ message: String, level: LogLevel, codeLocation: CodeLocation) { guard Self.loggingEnabled else { return } - underlyingLogger.log(level: level.toOSLogType, "(\(String(cString: fileName)):\(line)): \(message)") + underlyingLogger.log(level: level.toOSLogType, "(\(codeLocation.fileID):\(codeLocation.line)): \(message)") } } -private extension ARTLogLevel { +private extension _AblyPluginSupportPrivate.LogLevel { var toOSLogType: OSLogType { // Not much thought has gone into this conversion switch self { diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift index a474738..048a64c 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultLiveCounterTests.swift @@ -1,4 +1,5 @@ import _AblyPluginSupportPrivate +import Ably @testable import AblyLiveObjects import Foundation import Testing @@ -7,8 +8,8 @@ struct InternalDefaultLiveCounterTests { /// Tests for the `value` property, covering RTLC5 specification points struct ValueTests { // @spec RTLC5b - @Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState]) - func valueThrowsIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func valueThrowsIfChannelIsDetachedOrFailed(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let counter = InternalDefaultLiveCounter.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) let coreSDK = MockCoreSDK(channelState: channelState) @@ -426,8 +427,8 @@ struct InternalDefaultLiveCounterTests { /// Tests for the `increment` method, covering RTLC12 specification points struct IncrementTests { // @spec RTLC12c - @Test(arguments: [.detached, .failed, .suspended] as [ARTRealtimeChannelState]) - func throwsErrorForInvalidChannelState(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed, .suspended] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func throwsErrorForInvalidChannelState(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let counter = InternalDefaultLiveCounter.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) let coreSDK = MockCoreSDK(channelState: channelState) diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift index 0f33211..f5b8890 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultLiveMapTests.swift @@ -1,4 +1,5 @@ import _AblyPluginSupportPrivate +import Ably @testable import AblyLiveObjects import Foundation import Testing @@ -7,8 +8,8 @@ struct InternalDefaultLiveMapTests { /// Tests for the `get` method, covering RTLM5 specification points struct GetTests { // @spec RTLM5c - @Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState]) - func getThrowsIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func getThrowsIfChannelIsDetachedOrFailed(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let map = InternalDefaultLiveMap.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) @@ -275,8 +276,8 @@ struct InternalDefaultLiveMapTests { // @spec RTLM11c // @spec RTLM12b // @spec RTLM13b - @Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState]) - func allPropertiesThrowIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func allPropertiesThrowIfChannelIsDetachedOrFailed(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let map = InternalDefaultLiveMap.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) let coreSDK = MockCoreSDK(channelState: channelState) @@ -1230,8 +1231,8 @@ struct InternalDefaultLiveMapTests { /// Tests for the `set` method, covering RTLM20 specification points struct SetTests { // @spec RTLM20c - @Test(arguments: [.detached, .failed, .suspended] as [ARTRealtimeChannelState]) - func throwsErrorForInvalidChannelState(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed, .suspended] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func throwsErrorForInvalidChannelState(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let map = InternalDefaultLiveMap.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) let coreSDK = MockCoreSDK(channelState: channelState) @@ -1330,8 +1331,8 @@ struct InternalDefaultLiveMapTests { /// Tests for the `remove` method, covering RTLM21 specification points struct RemoveTests { // @spec RTLM21c - @Test(arguments: [.detached, .failed, .suspended] as [ARTRealtimeChannelState]) - func throwsErrorForInvalidChannelState(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed, .suspended] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func throwsErrorForInvalidChannelState(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let logger = TestLogger() let map = InternalDefaultLiveMap.createZeroValued(objectID: "arbitrary", logger: logger, userCallbackQueue: .main, clock: MockSimpleClock()) let coreSDK = MockCoreSDK(channelState: channelState) diff --git a/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift b/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift index 7d64d96..0406224 100644 --- a/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift +++ b/Tests/AblyLiveObjectsTests/InternalDefaultRealtimeObjectsTests.swift @@ -672,8 +672,8 @@ struct InternalDefaultRealtimeObjectsTests { // MARK: - RTO1b Tests // @spec RTO1b - @Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState]) - func getRootThrowsIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func getRootThrowsIfChannelIsDetachedOrFailed(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let realtimeObjects = InternalDefaultRealtimeObjectsTests.createDefaultRealtimeObjects() let coreSDK = MockCoreSDK(channelState: channelState) @@ -1044,8 +1044,8 @@ struct InternalDefaultRealtimeObjectsTests { /// Tests for `InternalDefaultRealtimeObjects.createMap`, covering RTO11 specification points (these are largely a smoke test, the rest being tested in ObjectCreationHelpers tests) struct CreateMapTests { // @spec RTO11d - @Test(arguments: [.detached, .failed, .suspended] as [ARTRealtimeChannelState]) - func throwsIfChannelIsInInvalidState(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed, .suspended] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func throwsIfChannelIsInInvalidState(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let realtimeObjects = InternalDefaultRealtimeObjectsTests.createDefaultRealtimeObjects() let coreSDK = MockCoreSDK(channelState: channelState) let entries: [String: InternalLiveMapValue] = ["testKey": .string("testValue")] @@ -1175,8 +1175,8 @@ struct InternalDefaultRealtimeObjectsTests { /// Tests for `InternalDefaultRealtimeObjects.createCounter`, covering RTO12 specification points (these are largely a smoke test, the rest being tested in ObjectCreationHelpers tests) struct CreateCounterTests { // @spec RTO12d - @Test(arguments: [.detached, .failed, .suspended] as [ARTRealtimeChannelState]) - func throwsIfChannelIsInInvalidState(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed, .suspended] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func throwsIfChannelIsInInvalidState(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { let realtimeObjects = InternalDefaultRealtimeObjectsTests.createDefaultRealtimeObjects() let coreSDK = MockCoreSDK(channelState: channelState) diff --git a/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift b/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift index 06cae4b..dbb8857 100644 --- a/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift +++ b/Tests/AblyLiveObjectsTests/LiveObjectMutableStateTests.swift @@ -119,8 +119,8 @@ struct LiveObjectMutableStateTests { // @spec RTLO4b2 @available(iOS 17.0.0, tvOS 17.0.0, *) - @Test(arguments: [.detached, .failed] as [ARTRealtimeChannelState]) - func subscribeThrowsIfChannelIsDetachedOrFailed(channelState: ARTRealtimeChannelState) async throws { + @Test(arguments: [.detached, .failed] as [_AblyPluginSupportPrivate.RealtimeChannelState]) + func subscribeThrowsIfChannelIsDetachedOrFailed(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) async throws { var mutableState = LiveObjectMutableState(objectID: "foo") let queue = DispatchQueue.main let subscriber = Subscriber(callbackQueue: queue) diff --git a/Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift b/Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift index 3bb48bb..0c3980a 100644 --- a/Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift +++ b/Tests/AblyLiveObjectsTests/Mocks/MockCoreSDK.swift @@ -1,3 +1,4 @@ +import _AblyPluginSupportPrivate import Ably @testable import AblyLiveObjects @@ -5,10 +6,10 @@ final class MockCoreSDK: CoreSDK { /// Synchronizes access to all of this instance's mutable state. private let mutex = NSLock() - private nonisolated(unsafe) var _channelState: ARTRealtimeChannelState + private nonisolated(unsafe) var _channelState: _AblyPluginSupportPrivate.RealtimeChannelState private nonisolated(unsafe) var _publishHandler: (([OutboundObjectMessage]) async throws(InternalError) -> Void)? - init(channelState: ARTRealtimeChannelState) { + init(channelState: _AblyPluginSupportPrivate.RealtimeChannelState) { _channelState = channelState } @@ -24,7 +25,7 @@ final class MockCoreSDK: CoreSDK { protocolRequirementNotImplemented() } - var channelState: ARTRealtimeChannelState { + var channelState: _AblyPluginSupportPrivate.RealtimeChannelState { get { mutex.withLock { _channelState diff --git a/ably-cocoa b/ably-cocoa index 9f1a651..9e172dd 160000 --- a/ably-cocoa +++ b/ably-cocoa @@ -1 +1 @@ -Subproject commit 9f1a65179b69b6041b3a65664c5fa6c48d722fec +Subproject commit 9e172dd3e744c6d8c2bb0be09a22853aa702005b