diff --git a/Sources/PubNub/APIs/Objects+PubNub.swift b/Sources/PubNub/APIs/Objects+PubNub.swift index 78a3cf02..6c17709e 100644 --- a/Sources/PubNub/APIs/Objects+PubNub.swift +++ b/Sources/PubNub/APIs/Objects+PubNub.swift @@ -14,8 +14,10 @@ public extension PubNub { enum MembershipSortProperty: Hashable { /// Sort based on the nested object (UUID or Channel) belonging to the Membership case object(ObjectSortProperty) - + /// Sort on the status property of the Membership case status + /// Sort on the type property of the Membership + case type /// Sort on the last updated property of the Membership case updated @@ -25,6 +27,8 @@ public extension PubNub { return "\(objectType).\(property)" case .status: return "status" + case .type: + return "type" case .updated: return "updated" } @@ -46,6 +50,12 @@ public extension PubNub { /// The direction of the sort public let ascending: Bool + + /// Creates a new `MembershipSortField` instance + /// + /// - Parameters: + /// - property: The property to sort by + /// - ascending: The direction of the sort public init(property: MembershipSortProperty, ascending: Bool = true) { self.property = property self.ascending = ascending @@ -58,6 +68,8 @@ public extension PubNub { public var customFields: Bool /// The `PubNubChannelMetadata` instance of the Membership public var channelFields: Bool + /// The `type` field of the `Membership` object + public var typeField: Bool /// The `status` field of the `Membership` object public var statusField: Bool /// The `type` field of the `PubNubChannelMetadata` instance in Membership @@ -70,10 +82,12 @@ public extension PubNub { public var totalCount: Bool /// Default init + /// /// - Parameters: /// - customFields: The `custom` dictionary for the Object /// - channelFields: The `PubNubChannelMetadata` instance of the Membership /// - statusField: The `status` field of the Membership + /// - typeField: The `type` field of the Membership /// - channelCustomFields: The `custom` dictionary of the `PubNubChannelMetadata` for the Membership object /// - channelTypeField: The `type` field of the `PubNubChannelMetadata` for the Membership object /// - channelStatusField: The `status` field of the `PubNubChannelMetadata` for the Membership object @@ -82,6 +96,7 @@ public extension PubNub { customFields: Bool = true, channelFields: Bool = false, statusField: Bool = false, + typeField: Bool = false, channelCustomFields: Bool = false, channelTypeField: Bool = false, channelStatusField: Bool = false, @@ -90,6 +105,7 @@ public extension PubNub { self.customFields = customFields self.channelFields = channelFields self.statusField = statusField + self.typeField = typeField self.channelCustomFields = channelCustomFields self.channelTypeField = channelTypeField self.channelStatusField = channelStatusField @@ -102,6 +118,7 @@ public extension PubNub { if customFields { includes.append(.custom) } if channelFields { includes.append(.channel) } if statusField { includes.append(.status) } + if typeField { includes.append(.type) } if channelCustomFields { includes.append(.channelCustom) } if channelTypeField { includes.append(.channelType) } if channelStatusField { includes.append(.channelStatus) } @@ -117,6 +134,8 @@ public extension PubNub { public var uuidFields: Bool /// The `status` field of the `Membership` object public var statusField: Bool + /// The `type` field of the `Membership` object + public var typeField: Bool /// The `type` field of the `PubNubUUIDMetadata` instance in Membership public var uuidTypeField: Bool /// The `status` field of the `PubNubUUIDMetadata` instance in Membership @@ -127,10 +146,12 @@ public extension PubNub { public var totalCount: Bool /// Default init + /// /// - Parameters: /// - customFields: The `custom` dictionary for the Object /// - uuidFields: The `PubNubUUIDMetadata` instance of the Membership /// - statusField: The `status` field of the Membership + /// - typeField: The `type` field of the Membership /// - uuidCustomFields: The `custom` dictionary of the `PubNubUUIDMetadata` for the Membership object /// - uuidTypeField: The `type` field of the `PubNubUUIDMetadata` for the Membership object /// - uuidStatusField: The `status` field of the `PubNubUUIDMetadata` for the Membership object @@ -139,6 +160,7 @@ public extension PubNub { customFields: Bool = true, uuidFields: Bool = false, statusField: Bool = false, + typeField: Bool = false, uuidCustomFields: Bool = false, uuidTypeField: Bool = false, uuidStatusField: Bool = false, @@ -147,6 +169,7 @@ public extension PubNub { self.customFields = customFields self.uuidFields = uuidFields self.statusField = statusField + self.typeField = typeField self.uuidCustomFields = uuidCustomFields self.uuidTypeField = uuidTypeField self.uuidStatusField = uuidStatusField @@ -159,6 +182,7 @@ public extension PubNub { if customFields { includes.append(.custom) } if uuidFields { includes.append(.uuid) } if statusField { includes.append(.status) } + if typeField { includes.append(.type) } if uuidCustomFields { includes.append(.uuidCustom) } if uuidTypeField { includes.append(.uuidType) } if uuidStatusField { includes.append(.uuidStatus) } @@ -175,6 +199,7 @@ public extension PubNub { public var totalCount: Bool /// Default init + /// /// - Parameters: /// - custom: Whether to include `custom` data in the response /// - totalCount: Whether to include `totalCount` in the response @@ -231,9 +256,10 @@ extension Array where Element == PubNub.MembershipSortField { // MARK: - UUID Metadat Objects public extension PubNub { - /// Gets metadata for all UUIDs + /// Gets metadata for all UUIDs. /// /// Returns a paginated list of UUID Metadata objects, optionally including the custom data object for each. + /// /// - Parameters: /// - include: Include respective additional fields in the response. /// - filter: Expression used to filter the results. Only objects whose properties satisfy the given expression are returned. The filter language is defined [here](https://www.pubnub.com/docs/swift/stream-filtering-tutorial#filtering-language-definition). @@ -270,9 +296,10 @@ public extension PubNub { } } - /// Get Metadata for a UUID + /// Get Metadata for a UUID. /// /// Returns metadata for the specified UUID, optionally including the custom data object for each. + /// /// - Parameters: /// - uuid: Unique UUID Metadata identifier. If not supplied, then it will use the request configuration and then the default configuration /// - include: Include respective additional fields in the response. @@ -299,7 +326,7 @@ public extension PubNub { } } - /// Set UUID Metadata + /// Set UUID Metadata. /// /// Set metadata for a UUID in the database, optionally including the custom data object for each. /// - Parameters: @@ -327,9 +354,8 @@ public extension PubNub { } } - /// Remove UUID Metadata - /// /// Remove metadata for a specified UUID. + /// /// - Parameters: /// - uuid: Unique UUID Metadata identifier to remove. If not supplied, then it will use the request configuration and then the default configuration /// - custom: Custom configuration overrides for this request @@ -360,7 +386,7 @@ public extension PubNub { // MARK: - Channel Metadata Objects public extension PubNub { - /// Get Metadata for All Channels + /// Get Metadata for All Channels. /// /// Returns a paginated list of metadata objects for channels, optionally including custom data objects. /// - Parameters: @@ -399,9 +425,8 @@ public extension PubNub { } } - /// Get Metadata for a Channel - /// /// Returns metadata for the specified channel including the channel's custom data. + /// /// - Parameters: /// - channel: Unique Channel Metadata identifier /// - include: Include respective additional fields in the response. @@ -427,9 +452,8 @@ public extension PubNub { } } - /// Set Channel Metadata - /// /// Set metadata for a channel in the database. + /// /// - Parameters: /// - channel: The `PubNubChannelMetadata` to set /// - include: Include respective additional fields in the response. @@ -455,9 +479,8 @@ public extension PubNub { } } - /// Remove Channel Metadata + /// Remove metadata for a specified channel. /// - /// Remove metadata for a specified channel /// - Parameters: /// - channel: Unique Channel Metadata identifier to remove. /// - custom: Custom configuration overrides for this request @@ -485,9 +508,10 @@ public extension PubNub { // MARK: - Memberships public extension PubNub { - /// Get Channel Memberships + /// Get Channel Memberships. /// /// The method returns a list of channel memberships for a user. It does not return a user's subscriptions. + /// /// - Parameters: /// - uuid: Unique UUID identifier. If not supplied, then it will use the request configuration and then the default configuration /// - include: Include respective additional fields in the response. @@ -536,9 +560,10 @@ public extension PubNub { } } - /// Get Channel Members + /// Get Channel Members. /// /// The method returns a list of members in a channel. The list will include user metadata for members that have additional metadata stored in the database. + /// /// - Parameters: /// - channel: Unique Channel identifier. /// - include: Include respective additional fields in the response. @@ -583,6 +608,7 @@ public extension PubNub { } /// Set Channel memberships for a UUID. + /// /// - Parameters: /// - uuid: Unique UUID identifier. If not supplied, then it will use the request configuration and then the default configuration /// - channels: Array of `PubNubMembershipMetadata` with the `PubNubChannelMetadata` or `channelMetadataId` provided @@ -614,6 +640,7 @@ public extension PubNub { } /// Remove Channel memberships for a UUID. + /// /// - Parameters: /// - uuid: Unique UUID identifier. If not supplied, then it will use the request configuration and then the default configuration /// - channels: Array of `PubNubMembershipMetadata` with the `PubNubChannelMetadata` or `channelMetadataId` provided @@ -644,7 +671,8 @@ public extension PubNub { ) } - /// Modify the Channel membership list for a UUID + /// Modify the Channel membership list for a UUID. + /// /// - Parameters: /// - uuid: Unique UUID identifier. If not supplied, then it will use the request configuration and then the default configuration /// - setting: Array of `PubNubMembershipMetadata` with the `PubNubChannelMetadata` or `channelMetadataId` provided @@ -676,10 +704,10 @@ public extension PubNub { uuidMetadataId: metadataId, customFields: include.customIncludes, totalCount: include.totalCount, changes: .init( set: channelMembershipSets.map { - .init(metadataId: $0.channelMetadataId, status: $0.status, custom: $0.custom) + .init(metadataId: $0.channelMetadataId, status: $0.status, type: $0.type, custom: $0.custom) }, delete: channelMembershipDeletes.map { - .init(metadataId: $0.channelMetadataId, status: $0.status, custom: $0.custom) + .init(metadataId: $0.channelMetadataId, status: $0.status, type: $0.type, custom: $0.custom) } ), filter: filter, sort: sort.membershipURLValue, @@ -701,6 +729,7 @@ public extension PubNub { } /// Get the specified user's space memberships. + /// /// - Parameters: /// - channel: Unique Channel identifier. /// - uuids: Array of `PubNubMembershipMetadata` with the `PubNubUUIDMetadata` or `uuidMetadataId` provided @@ -732,6 +761,7 @@ public extension PubNub { } /// Remove UUID members from a Channel. + /// /// - Parameters: /// - channel: Unique Channel identifier. /// - uuids: Array of `PubNubMembershipMetadata` with the `PubNubUUIDMetadata` or `uuidMetadataId` provided @@ -762,7 +792,8 @@ public extension PubNub { ) } - /// Modify the UUID member list for a Channel + /// Modify the UUID member list for a Channel. + /// /// - Parameters: /// - channel: Unique Channel identifier. /// - setting: Array of `PubNubMembershipMetadata` with the `PubNubUUIDMetadata` or `uuidMetadataId` provided @@ -791,8 +822,8 @@ public extension PubNub { let router = ObjectsMembershipsRouter(.setMembers( channelMetadataId: metadataId, customFields: include.customIncludes, totalCount: include.totalCount, changes: .init( - set: uuidMembershipSets.map { .init(metadataId: $0.uuidMetadataId, status: $0.status, custom: $0.custom) }, - delete: uuidMembershipDeletes.map { .init(metadataId: $0.uuidMetadataId, status: $0.status, custom: $0.custom) } + set: uuidMembershipSets.map { .init(metadataId: $0.uuidMetadataId, status: $0.status, type: $0.type, custom: $0.custom) }, + delete: uuidMembershipDeletes.map { .init(metadataId: $0.uuidMetadataId, status: $0.status, type: $0.type, custom: $0.custom) } ), filter: filter, sort: sort.memberURLValue, limit: limit, start: page?.start, end: page?.end diff --git a/Sources/PubNub/Models/PubNubMembershipMetadata.swift b/Sources/PubNub/Models/PubNubMembershipMetadata.swift index 55ea0c05..92500821 100644 --- a/Sources/PubNub/Models/PubNubMembershipMetadata.swift +++ b/Sources/PubNub/Models/PubNubMembershipMetadata.swift @@ -18,8 +18,10 @@ public protocol PubNubMembershipMetadata { var uuidMetadataId: String { get } /// The unique identifier of the associated Channel var channelMetadataId: String { get } - /// The current state of the MembershipMetadata + /// The current status of the MembershipMetadata var status: String? { get set } + /// The current type of the MembershipMetadata + var type: String? { get set } /// The associated UUID metadata var uuid: PubNubUUIDMetadata? { get set } /// The associated Channel metadata @@ -63,23 +65,19 @@ public extension PubNubMembershipMetadata { public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { public let uuidMetadataId: String public let channelMetadataId: String - public var status: String? + public var type: String? var concreteUUID: PubNubUUIDMetadataBase? public var uuid: PubNubUUIDMetadata? { get { concreteUUID } - set { - concreteUUID = try? newValue?.transcode() - } + set { concreteUUID = try? newValue?.transcode() } } var concreteChannel: PubNubChannelMetadataBase? public var channel: PubNubChannelMetadata? { get { concreteChannel } - set { - concreteChannel = try? newValue?.transcode() - } + set { concreteChannel = try? newValue?.transcode() } } var concreteCustom: [String: JSONCodableScalarType]? @@ -95,6 +93,7 @@ public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { uuidMetadataId: String, channelMetadataId: String, status: String? = nil, + type: String? = nil, uuid: PubNubUUIDMetadataBase? = nil, channel: PubNubChannelMetadataBase? = nil, custom concreteCustom: [String: JSONCodableScalar]? = nil, @@ -107,6 +106,7 @@ public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { self.channel = channel self.concreteCustom = concreteCustom?.mapValues { $0.scalarValue } self.status = status + self.type = type self.updated = updated self.eTag = eTag } @@ -116,6 +116,7 @@ public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { uuidMetadataId: other.uuidMetadataId, channelMetadataId: other.channelMetadataId, status: other.status, + type: other.type, uuid: try other.uuid?.transcode(), channel: try other.channel?.transcode(), custom: other.custom, @@ -130,6 +131,7 @@ public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { uuidMetadataId: uuid.metadataId, channelMetadataId: identifier, status: partial.status, + type: partial.type, uuid: uuid.metadataObject, custom: partial.custom, updated: partial.updated, @@ -140,6 +142,7 @@ public struct PubNubMembershipMetadataBase: PubNubMembershipMetadata, Hashable { uuidMetadataId: identifier, channelMetadataId: channel.metadataId, status: partial.status, + type: partial.type, channel: channel.metadataObject, custom: partial.custom, updated: partial.updated, @@ -156,6 +159,7 @@ extension PubNubMembershipMetadataBase: Codable { case uuid case channel case status + case type case custom case updated case eTag @@ -170,6 +174,9 @@ extension PubNubMembershipMetadataBase: Codable { updated = try container.decodeIfPresent(Date.self, forKey: .updated) eTag = try container.decodeIfPresent(String.self, forKey: .eTag) concreteCustom = try container.decodeIfPresent([String: JSONCodableScalarType].self, forKey: .custom) + status = try container.decodeIfPresent(String.self, forKey: .status) + type = try container.decodeIfPresent(String.self, forKey: .type) + if let concreteChannel = try? container.decodeIfPresent(PubNubChannelMetadataBase.self, forKey: .channel) { self.concreteChannel = concreteChannel channelMetadataId = concreteChannel.metadataId @@ -194,7 +201,9 @@ extension PubNubMembershipMetadataBase: Codable { try container.encodeIfPresent(updated, forKey: .updated) try container.encodeIfPresent(eTag, forKey: .eTag) try container.encodeIfPresent(custom?.mapValues { $0.scalarValue }, forKey: .custom) - + try container.encodeIfPresent(status, forKey: .status) + try container.encodeIfPresent(type, forKey: .type) + if let channelObject = concreteChannel { try container.encode(channelObject, forKey: .channel) } else { diff --git a/Sources/PubNub/Networking/Routers/ObjectsMembershipsRouter.swift b/Sources/PubNub/Networking/Routers/ObjectsMembershipsRouter.swift index 4bce6646..8d2e70e5 100644 --- a/Sources/PubNub/Networking/Routers/ObjectsMembershipsRouter.swift +++ b/Sources/PubNub/Networking/Routers/ObjectsMembershipsRouter.swift @@ -76,6 +76,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { case uuidType = "uuid.type" case uuidStatus = "uuid.status" case status + case type static func merge(_ other: [Include]?) -> [String] { var includes = [Include.status] @@ -102,12 +103,14 @@ public struct ObjectsMembershipsRouter: HTTPRouter { public struct MembershipChange: JSONCodable, Equatable { let metadataId: String let status: String? + let type: String? let custom: [String: JSONCodableScalar]? // swiftlint:disable:next nesting enum CodingKeys: String, CodingKey { case object = "channel" case status + case type case custom } @@ -116,9 +119,10 @@ public struct ObjectsMembershipsRouter: HTTPRouter { case metadataId = "id" } - public init(metadataId: String, status: String?, custom: [String: JSONCodableScalar]?) { + public init(metadataId: String, status: String?, type: String?, custom: [String: JSONCodableScalar]?) { self.metadataId = metadataId self.status = status + self.type = type self.custom = custom } @@ -126,6 +130,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { let container = try decoder.container(keyedBy: CodingKeys.self) custom = try container.decodeIfPresent([String: JSONCodableScalarType].self, forKey: .custom) status = try container.decodeIfPresent(String.self, forKey: .status) + type = try container.decodeIfPresent(String.self, forKey: .type) let nestedContainer = try container.nestedContainer(keyedBy: NestedCodingKeys.self, forKey: .object) metadataId = try nestedContainer.decode(String.self, forKey: .metadataId) @@ -135,6 +140,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(custom?.mapValues { $0.scalarValue }, forKey: .custom) try container.encodeIfPresent(status, forKey: .status) + try container.encodeIfPresent(type, forKey: .type) var nestedContainer = container.nestedContainer(keyedBy: NestedCodingKeys.self, forKey: .object) try nestedContainer.encode(metadataId, forKey: .metadataId) @@ -146,9 +152,8 @@ public struct ObjectsMembershipsRouter: HTTPRouter { ) -> Bool { return lhs.metadataId == rhs.metadataId && lhs.status == rhs.status && - lhs.custom? - .mapValues { $0.codableValue } == rhs.custom? - .mapValues { $0.codableValue } + lhs.type == rhs.type && + lhs.custom?.mapValues { $0.codableValue } == rhs.custom?.mapValues { $0.codableValue } } } @@ -168,11 +173,13 @@ public struct ObjectsMembershipsRouter: HTTPRouter { public struct MemberChange: JSONCodable, Equatable { let metadataId: String let status: String? + let type: String? let custom: [String: JSONCodableScalar]? - public init(metadataId: String, status: String?, custom: [String: JSONCodableScalar]?) { + public init(metadataId: String, status: String?, type: String?, custom: [String: JSONCodableScalar]?) { self.metadataId = metadataId self.status = status + self.type = type self.custom = custom } @@ -180,6 +187,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { enum CodingKeys: String, CodingKey { case object = "uuid" case status + case type case custom } @@ -192,6 +200,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { let container = try decoder.container(keyedBy: CodingKeys.self) custom = try container.decodeIfPresent([String: JSONCodableScalarType].self, forKey: .custom) status = try container.decodeIfPresent(String.self, forKey: .status) + type = try container.decodeIfPresent(String.self, forKey: .type) let nestedContainer = try container.nestedContainer(keyedBy: NestedCodingKeys.self, forKey: .object) metadataId = try nestedContainer.decode(String.self, forKey: .metadataId) @@ -201,6 +210,7 @@ public struct ObjectsMembershipsRouter: HTTPRouter { var container = encoder.container(keyedBy: CodingKeys.self) try container.encodeIfPresent(custom?.mapValues { $0.scalarValue }, forKey: .custom) try container.encodeIfPresent(status, forKey: .status) + try container.encodeIfPresent(type, forKey: .type) var nestedContainer = container.nestedContainer(keyedBy: NestedCodingKeys.self, forKey: .object) try nestedContainer.encode(metadataId, forKey: .metadataId) @@ -212,9 +222,8 @@ public struct ObjectsMembershipsRouter: HTTPRouter { ) -> Bool { return lhs.metadataId == rhs.metadataId && lhs.status == rhs.status && - lhs.custom? - .mapValues { $0.codableValue } == rhs.custom? - .mapValues { $0.codableValue } + lhs.type == rhs.type && + lhs.custom?.mapValues { $0.codableValue } == rhs.custom?.mapValues { $0.codableValue } } } @@ -414,6 +423,7 @@ public struct ObjectMetadataPartial: Codable { let channel: PartialMetadata? let uuid: PartialMetadata? let status: String? + let type: String? let custom: [String: JSONCodableScalarType]? let updated: Date let eTag: String @@ -427,6 +437,7 @@ public struct ObjectMetadataPartial: Codable { case channel case uuid case status + case type case custom case updated case eTag @@ -440,6 +451,7 @@ public struct ObjectMetadataPartial: Codable { channel: PartialMetadata?, uuid: PartialMetadata?, status: String?, + type: String?, updated: Date, eTag: String, custom: [String: JSONCodableScalarType]? @@ -448,6 +460,7 @@ public struct ObjectMetadataPartial: Codable { self.uuid = uuid self.updated = updated self.status = status + self.type = type self.eTag = eTag self.custom = custom } @@ -457,8 +470,8 @@ public struct ObjectMetadataPartial: Codable { custom = try container.decodeIfPresent([String: JSONCodableScalarType].self, forKey: .custom) updated = try container.decode(Date.self, forKey: .updated) eTag = try container.decode(String.self, forKey: .eTag) - status = try container.decodeIfPresent(String.self, forKey: .status) + type = try container.decodeIfPresent(String.self, forKey: .type) if let channel = try? container.decodeIfPresent(PubNubChannelMetadataBase.self, forKey: .channel) { self.channel = .init(metadataId: channel.metadataId, metadataObject: channel) @@ -477,6 +490,7 @@ public struct ObjectMetadataPartial: Codable { try container.encode(updated, forKey: .updated) try container.encode(eTag, forKey: .eTag) try container.encodeIfPresent(status, forKey: .status) + try container.encodeIfPresent(type, forKey: .type) try container.encodeIfPresent(custom, forKey: .custom) if uuid?.metadataObject != nil || channel?.metadataObject != nil { diff --git a/Sources/PubNub/Networking/Routers/ObjectsUUIDRouter.swift b/Sources/PubNub/Networking/Routers/ObjectsUUIDRouter.swift index ad85d305..a98f1c29 100644 --- a/Sources/PubNub/Networking/Routers/ObjectsUUIDRouter.swift +++ b/Sources/PubNub/Networking/Routers/ObjectsUUIDRouter.swift @@ -12,9 +12,7 @@ import Foundation public struct ObjectsUUIDRouter: HTTPRouter { public enum Endpoint: CustomStringConvertible { - case all( - customFields: Bool, totalCount: Bool, filter: String?, sort: [String], limit: Int?, start: String?, end: String? - ) + case all(customFields: Bool, totalCount: Bool, filter: String?, sort: [String], limit: Int?, start: String?, end: String?) case fetch(metadataId: String, customFields: Bool) case set(metadata: PubNubUUIDMetadata, customFields: Bool) case remove(metadataId: String)