Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions Firestore/Swift/Source/Combine/CollectionReference+Combine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if canImport(Combine) && swift(>=5.0)

import Combine
import FirebaseFirestore

@available(swift 5.0)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
extension CollectionReference {
public func addDocumentPublisher(data: [String: Any])
-> AnyPublisher<DocumentReference, Error> {
var reference: DocumentReference!
return Future { reference = self.addDocument(data: data, completion: $0) }
.map { reference }
.eraseToAnyPublisher()
}

public func addDocumentPublisher<T: Encodable>(from value: T,
encoder: Firestore.Encoder = Firestore
.Encoder()) -> AnyPublisher<
DocumentReference,
Error
> {
var reference: DocumentReference!
return Future { promise in
do {
try reference = self.addDocument(from: value, encoder: encoder, completion: promise)
} catch {
promise(.failure(error))
}
}
.map { reference }
.eraseToAnyPublisher()
}
}

#endif
110 changes: 110 additions & 0 deletions Firestore/Swift/Source/Combine/DocumentReference+Combine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if canImport(Combine) && swift(>=5.0)

import Combine
import FirebaseFirestore

@available(swift 5.0)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
extension DocumentReference {
func setDataPublisher(_ documentData: [String: Any]) -> Future<Void, Error> {
Future { self.setData(documentData, completion: $0) }
}

func setDataPublisher(_ documentData: [String: Any], merge: Bool) -> Future<Void, Error> {
Future { self.setData(documentData, merge: merge, completion: $0) }
}

func setDataPublisher(_ documentData: [String: Any],
mergeFields: [Any]) -> Future<Void, Error> {
Future { self.setData(documentData, mergeFields: mergeFields, completion: $0) }
}

func setDataPublisher<T: Encodable>(from value: T,
encoder: Firestore.Encoder = Firestore.Encoder()) -> Future<
Void,
Error
> {
Future { promise in
do {
try self.setData(from: value, completion: promise)
} catch {
promise(.failure(error))
}
}
}

func setDataPublisher<T: Encodable>(from value: T, merge: Bool,
encoder: Firestore.Encoder = Firestore.Encoder()) -> Future<
Void,
Error
> {
Future { promise in
do {
try self.setData(from: value, merge: merge, completion: promise)
} catch {
promise(.failure(error))
}
}
}

func setDataPublisher<T: Encodable>(from value: T, mergeFields: [Any],
encoder: Firestore.Encoder = Firestore.Encoder()) -> Future<
Void,
Error
> {
Future { promise in
do {
try self.setData(from: value, mergeFields: mergeFields, completion: promise)
} catch {
promise(.failure(error))
}
}
}

func updateDataPublisher(_ documentData: [String: Any]) -> Future<Void, Error> {
Future { self.updateData(documentData, completion: $0) }
}

func deletePublisher() -> Future<Void, Error> {
Future(delete)
}

func getDocumentPublisher(source: FirestoreSource = .default)
-> Future<DocumentSnapshot, Error> {
Future { self.getDocument(source: source, completion: $0) }
}

func addSnapshotListenerPublisher(includeMetadataChanges: Bool = false)
-> AnyPublisher<DocumentSnapshot, Error> {
let subject = PassthroughSubject<DocumentSnapshot, Error>()
let listenerHandle = addSnapshotListener { result in
switch result {
case let .success(output):
subject.send(output)
case let .failure(error):
subject.send(completion: .failure(error))
}
}
return subject
.handleEvents(receiveCancel: listenerHandle.remove)
.eraseToAnyPublisher()
}
}

#endif
46 changes: 46 additions & 0 deletions Firestore/Swift/Source/Combine/Query+Combine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if canImport(Combine) && swift(>=5.0)

import Combine
import FirebaseFirestore

@available(swift 5.0)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
extension Query {
func getDocumentsPublisher(source: FirestoreSource = .default) -> Future<QuerySnapshot, Error> {
Future { self.getDocuments(source: source, completion: $0) }
}

func addSnapshotListenerPublisher(includeMetadataChanges: Bool = false)
-> AnyPublisher<QuerySnapshot, Error> {
let subject = PassthroughSubject<QuerySnapshot, Error>()
let listenerHandle = addSnapshotListener { result in
switch result {
case let .success(output):
subject.send(output)
case let .failure(error):
subject.send(completion: .failure(error))
}
}
return subject
.handleEvents(receiveCancel: listenerHandle.remove)
.eraseToAnyPublisher()
}
}

#endif
31 changes: 31 additions & 0 deletions Firestore/Swift/Source/Combine/Transaction+Combine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if canImport(Combine) && swift(>=5.0)

import Combine
import FirebaseFirestore

@available(swift 5.0)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
extension Firestore {
func runTransactionPublisher<T>(_ updateBlock: @escaping (Transaction) throws -> T)
-> Future<T, Error> {
Future { self.runTransaction(updateBlock, completion: $0) }
}
}

#endif
36 changes: 36 additions & 0 deletions Firestore/Swift/Source/Combine/WriteBatch+Combine.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#if canImport(Combine) && swift(>=5.0)

import Combine
import FirebaseFirestore

@available(swift 5.0)
@available(macOS 10.15, iOS 13, watchOS 6, tvOS 13, *)
extension WriteBatch {
/// Commits all of the writes in this write batch as a single atomic unit.
///
/// - Returns: A publisher that emits a `Void` value once all of the writes in the batch
/// have been successfully written to the backend as an atomic unit. This publisher will only
/// emits when the client is online and the commit has completed against the server.
/// The changes will be visible immediately.
func commitPublisher() -> Future<Void, Error> {
Future { self.commit(completion: $0) }
}
}

#endif
74 changes: 74 additions & 0 deletions Firestore/Swift/Source/Result/CollectionReference+Result.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright 2019 Google
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import FirebaseFirestore

#if swift(>=5.0)

extension CollectionReference {
/// Adds a new document to this collection with the specified data, assigning it a document ID automatically.
///
/// - Parameters:
/// - data: The `Dictionary` containing the data for the new document.
/// - completion: The closure to execute on successfully writing to the server or on receipt of an error.
/// It will not be called while the client is offline, though local changes will be visible immediately.
/// - result: The result of request. On success it is empty, otherwise it contains an `Error`.
/// - Returns: A `DocumentReference` pointing to the newly created document.
func addDocument(data: [String: Any],
completion: @escaping (_ result: Result<Void, Error>) -> Void)
-> DocumentReference {
addDocument(data: data, completion: mapResultClosure(completion))
}

/// Adds a new document to this collection encoding an instance of `Encodable`, assigning it a document ID automatically.
///
/// See Firestore.Encoder for more details about the encoding process.
///
/// - Parameters:
/// - value: The instance of Encodable to be encoded to a document.
/// - encoder: The encoder instance to use to run the encoding.
/// - completion: The closure to execute on successfully writing to the server or on receipt of an error.
/// It will not be called while the client is offline, though local changes will be visible immediately.
/// - result: The result of request. On success it is empty, otherwise it contains an `Error`.
/// - Throws: `Firestore.Encoder` encoding errors:
/// - *put list of possible errors*
/// - Returns: A `DocumentReference` pointing to the newly created document.
func addDocument<T: Encodable>(from value: T,
encoder: Firestore.Encoder = Firestore.Encoder(),
completion: @escaping (_ result: Result<Void, Error>)
-> Void) throws -> DocumentReference {
try addDocument(from: value, encoder: encoder, completion: mapResultClosure(completion))
}
}

/// Returns a closure mapped from the a given closure with a `Result` parameter.
///
/// - Parameters:
/// - completion: The closure to map.
/// - result: The parameter of the closure to map.
/// - Returns: A closure mapped from the given closure.
private func mapResultClosure<E>(_ completion: @escaping (_ result: Result<Void, E>) -> Void)
-> ((E?) -> Void) {
{ error in
if let error = error {
completion(.failure(error))
} else {
completion(.success(()))
}
}
}

#endif
Loading