Giter VIP home page Giter VIP logo

Comments (1)

nidegen avatar nidegen commented on July 2, 2024

example server:



import Firebase

import Fuse

import EchoData

class DataBindingHandler: BindingHandler {
  func remove() {
    observerHandle?.remove()
  }
  
  var observerHandle: ListenerRegistration?
}

class DataServer: Fuse.Server {
  func bind(toDataType type: Fusable.Type, completion: @escaping ([Fusable]) -> ()) -> BindingHandler {
    let handle = database.collection(type.typeId)
          .addSnapshotListener { (snapshot, error) in
            guard let querySnapshot = snapshot else { return }
            var newData = [Fusable]()
            for documentSnapshot in querySnapshot.documents {
              if let jsonData = documentSnapshot.jsonData() {
                do {
                  let data = try type.decode(fromData: jsonData)
                  newData.append(data)
                } catch {
                  print(error.localizedDescription)
                }
              }
            }
            completion(newData)
        }
        let handler = DataBindingHandler()
        handler.observerHandle = handle
        return handler
  }
  
  func bind(toIds ids: [Id], ofDataType type: Fusable.Type, completion: @escaping ([Fusable]) -> ()) -> BindingHandler {
    let handle = database.collection(type.typeId)
//      .whereField("id", isEqualTo: value)
      .addSnapshotListener { (snapshot, error) in
        guard let querySnapshot = snapshot else { return }
        var newData = [Fusable]()
        for documentSnapshot in querySnapshot.documents {
          if let jsonData = documentSnapshot.jsonData() {
              do {
                let data = try type.decode(fromData: jsonData)
                newData.append(data)
              } catch {
                print(error.localizedDescription)
              }
          }
        }
        completion(newData)
    }
    let handler = DataBindingHandler()
    handler.observerHandle = handle
    return handler
  }
  
  func bind(dataOfType type: Fusable.Type, whereDataField dataField: String, contains value: Any, completion: @escaping ([Fusable]) -> ()) -> BindingHandler {
    let handle = database.collection(type.typeId)
      .whereField(dataField, arrayContains: value)
      .addSnapshotListener { (snapshot, error) in
        guard let querySnapshot = snapshot else { return }
        var newData = [Fusable]()
        for documentSnapshot in querySnapshot.documents {
          if let jsonData = documentSnapshot.jsonData() {
              do {
                let data = try type.decode(fromData: jsonData)
                newData.append(data)
              } catch {
                print(error.localizedDescription)
              }
          }
        }
        completion(newData)
    }
    let handler = DataBindingHandler()
    handler.observerHandle = handle
    return handler
  }
  
  func bind(dataOfType type: Fusable.Type, whereDataField dataField: String, isEqualTo value: Any, orderField: String? = nil, descendingOrder: Bool = true, completion: @escaping ([Fusable]) -> ()) -> BindingHandler {
    var tmp = database.collection(type.typeId)
      .whereField(dataField, isEqualTo: value)
    if let orderField = orderField {
      tmp = tmp.order(by: orderField, descending: descendingOrder)
    }
    let handle = tmp.addSnapshotListener { (snapshot, error) in
        guard let querySnapshot = snapshot else { return }
        var newData = [Fusable]()
        for documentSnapshot in querySnapshot.documents {
          if let jsonData = documentSnapshot.jsonData() {
              do {
                let data = try type.decode(fromData: jsonData)
                newData.append(data)
              } catch {
                print(error.localizedDescription)
              }
          }
        }
        completion(newData)
    }
    let handler = DataBindingHandler()
    handler.observerHandle = handle
    return handler
  }
  
  func bind(toId id: Id, ofDataType type: Fusable.Type, completion: @escaping (Fusable?) -> ()) -> BindingHandler {
    if id == "" { return DataBindingHandler() }
    let handle = database.collection(type.typeId).document(id).addSnapshotListener { (snapshot, error) in
      if let jsonData = snapshot?.jsonData() {
        if let data = try? type.decode(fromData: jsonData) {
          completion(data)
        } else {
          debugFatalError()
        }
      }
    }
    let handler = DataBindingHandler()
    handler.observerHandle = handle
    return handler
  }
  
  func get(id: Id, ofDataType type: Fusable.Type, completion: @escaping (Fusable?) -> ()) {
    if id == "" { completion(nil); return }
    database.collection(type.typeId).document(id).getDocument { (snapshot, error) in
      if let jsonData = snapshot?.jsonData() {
        if let storable = try? type.decode(fromData: jsonData) {
          completion(storable)
          return
        } else {
          debugFatalError()
        }
      }
      completion(nil)
    }
  }
  
  func get(ids: [Id], ofDataType type: Fusable.Type, completion: @escaping ([Fusable]) -> ()) {
    var storables = [Fusable]()
    var number = ids.count
    
    if number == 0 {
      completion(storables)
    }
    
    for id in ids {
      if id == "" { continue }
      database.collection(type.typeId).document(id).getDocument { (snapshot, error) in
        number -= 1
        if let jsonData = snapshot?.jsonData() {
          if let storable = try? type.decode(fromData: jsonData) {
            storables.append(storable)
          } else {
            debugFatalError()
          }
        }
        if number == 0 {
          completion(storables)
        }
      }
    }
  }
  
  func get(dataOfType type: Fusable.Type, whereDataField dataField: String, isEqualTo value: Any, orderField: String?, descendingOrder: Bool, completion: @escaping ([Fusable]) -> ()) {
    let callback: (QuerySnapshot?, Error?)->() = { (snapshot, error) in
      guard let query = snapshot else { return }
      var storables = [Fusable]()
      for jsonData in query.documents.compactMap({$0.jsonData()}) {
        if let storable = try? type.decode(fromData: jsonData) {
          storables.append(storable)
        } else {
          debugFatalError()
        }
      }
      completion(storables)
    }
    
    
    if let orderField = orderField {
      database.collection(type.typeId)
        .whereField(dataField, isEqualTo: value)
        .order(by: orderField, descending: descendingOrder)
        .getDocuments(completion: callback)
    } else {
      database.collection(type.typeId)
        .whereField(dataField, isEqualTo: value)
        .getDocuments(completion: callback)
    }
  }
  
  func set(_ storable: Fusable) {
    database.collection(type(of: storable).typeId).document(storable.id).setData(storable)
  }
  
  func delete(_ id: Id, forDataType type: Fusable.Type, completion: ((Error?) -> ())? = nil) {
    if id == "" { return }
    database.collection(type.typeId).document(id).delete { error in
      completion?(error)
    }
  }
  
  static var shared = DataServer()
  
  private init(){
    let settings = FirestoreSettings()
    settings.isPersistenceEnabled = true
    DefaultServerContainer.server = self
  }
  
  var database: DocumentReference {
    #if DEBUG
    return Firestore.firestore().collection("devel").document("debug")
    #else
    return Firestore.firestore().collection("releases").document(UserData.serverVersionString)
    #endif
  }
}

Firebase Codable

import Foundation

import Firebase

extension DocumentSnapshot {
  func jsonData() -> Data? {
    if let data = self.data() as NSDictionary?  {
      return try? JSONSerialization.data(withJSONObject: data, options: [])
    }
    return nil
  }
}

extension DocumentReference {
  func setData(_ encodableDocument: Encodable) {
    guard let dict = encodableDocument.dictionary else { return }
    self.setData(dict)
  }
}

extension DataSnapshot {
  func jsonData() -> Data? {
    if let data = self.value as? NSDictionary  {
      do {
        let jsonData = try JSONSerialization.data(withJSONObject: data, options: [])
        return jsonData
      } catch {
        print(error.localizedDescription)
      }
    }
    return nil
  }
}

extension DatabaseReference {
  func setEncodableValue(_ value: Encodable) {
    guard let dict = value.dictionary else { return }
    self.setValue(dict)
  }
}

extension Encodable {
  var dictionary: [String: Any]? {
    guard let data = try? JSONEncoder().encode(self) else { return nil }
    return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { $0 as? [String: Any] }
  }
}

from fuse.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.