sdk-for-apple icon indicating copy to clipboard operation
sdk-for-apple copied to clipboard

🚀 Feature: Binding realtime channels to an Enum

Open anelad opened this issue 5 months ago • 0 comments

🔖 Feature description

Currently to subscribe to a realtime channel we use string values documented in appwrite docs. The problem is we need to create channel strings everytime manually. Instead, we can use the power of Swift's Enums. I've already created and extension and I'm sharing it here. Unfortunately I have no time to send a PR for it right now. People can find and use it from here or maybe someone can open a PR on behalf of me.

🎤 Pitch

The Use Case: I'm using the example code shared in documentation here.

Currently we subscribe the channel like this; via manual typed strings:

import Appwrite
import AppwriteModels

let client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

let realtime = Realtime(client)

realtime.subscribe(channels: ["databases.A.collections.A.documents.A", "files"]) { response in
    // Callback will be executed on changes for documents A and all files.
    print(String(describing: response))
}

With my extension we can subscribe to channels without knowing what the channel's string is.


import Appwrite
import AppwriteModels

let client = Client()
    .setEndpoint("https://cloud.appwrite.io/v1")
    .setProject("<PROJECT_ID>")

let realtime = Realtime(client)

// Here we use my Channel extension to auto create required channel string
let channelToDocumentA = Realtime.Channel.document(databaseID: "A", collectionID: "A", documentID: "A")
let channelToFiles = Realtime.Channel.files

realtime.subscribe(channels: [channelToDocumentA.toString(), channelToFiles.toString()]) { response in
    // Callback will be executed on changes for documents A and all files.
    print(String(describing: response))
}

And here is the extension of mine:

import Foundation
import Appwrite

extension Realtime {
    
    /// All channels available you can subscribe to.
    public enum Channel {
        
        /// All account related events (session create, name update...)
        case account
        
        /// Any create/update/delete events to any document in a collection
        case documentsInCollection(databaseID: String, collectionID: String)
        /// Any create/update/delete events to any document
        case documents
        /// Any update/delete events to a given document
        case document(databaseID: String, collectionID: String, documentID: String)
        
        /// Any create/update/delete events to any file
        case files
        /// Any update/delete events to a given file of the given bucket
        case file(bucketID: String, fileID: String)
        /// Any update/delete events to any file of the given bucket
        case filesInBucket(bucketID: String)
        
        /// Any create/update/delete events to a any team
        case teams
        /// Any update/delete events to a given team
        case team(teamID: String)
        
        /// Any create/update/delete events to a any membership
        case memberships
        /// Any update/delete events to a given membership
        case membership(membershipID: String)
        
        /// Any update to executions
        case executions
        /// Any update to a given execution
        case execution(executionID: String)
        
        /// Any execution event to a given function
        case funtion(functionID: String)
        
        /// String representation of the channel used for subscribing
        public func toString() -> String {
            return switch self {
            case .account:
                "account"
                
            case .documentsInCollection(let databaseID, let collectionID):
                "databases.\(databaseID).collections.\(collectionID).documents"
                
            case .documents:
                "documents"
                
            case .document(let databaseID, let collectionID, let documentId):
                "databases.\(databaseID).collections.\(collectionID).documents.\(documentId)"
                
            case .files:
                "files"
                
            case .file(let bucketID, let fileID):
                "buckets.\(bucketID).files.\(fileID)"
                
            case .filesInBucket(let bucketID):
                "buckets.\(bucketID).files"
                
            case .teams:
                "teams"
                
            case .team(let teamID):
                "teams.\(teamID)"
                
            case .memberships:
                "memberships"
                
            case .membership(let membershipID):
                "memberships.\(membershipID)"
                
            case .executions:
                "executions"
                
            case .execution(let executionID):
                "executions.\(executionID)"
                
            case .funtion(let functionID):
                "functions.\(functionID)"
            }
        }
    }
}

extension Realtime.Channel: Comparable, Equatable, Identifiable {
    public typealias ID = String
    
    public var id: ID {
        self.toString()
    }
    
    public static func < (lhs: Realtime.Channel, rhs: Realtime.Channel) -> Bool {
        lhs.toString() < rhs.toString()
    }
    
    public static func == (lhs: Realtime.Channel, rhs: Realtime.Channel) -> Bool {
        lhs.toString() == rhs.toString()
    }    
}

👀 Have you spent some time to check if this issue has been raised before?

  • [X] I checked and didn't find similar issue

🏢 Have you read the Code of Conduct?

anelad avatar Feb 27 '24 08:02 anelad