Docs

Swift: Firestore-compatible API

Firebase-style collection, document and query references on top of Sovaria documents, for moving a Firebase app over with the Swift SDK.

Updated Oct 24, 2026

Firebase-style collection, document and query references on top of Sovaria documents, for moving a Firebase app over. Every call runs as the client's signed-in user, so your project's policies and row-level security apply. Types and members are listed in source order; each one links to its HTTP endpoint where it maps to one.

#Types and members

Firestore

The Firebase iOS SDK's Firestore API on Sovaria documents: move an app by changing imports and how db is made. Names, arguments and shapes follow Firebase (data(), exists, documentChanges, ListenerRegistration, data(as:) / setData(from:) for Codable). Underneath it is the Sovaria collection API, so collection rules and row policies decide every read and write. Differences: timestamps are stored as ISO-8601 strings (Timestamp and Date values you write are converted; read them back with Timestamp(iso:)), the transaction closure is async (reads go to the server), and there is no offline document cache.

public final class Firestore: @unchecked Sendable

Firestore.sovaria

A property.

public let sovaria: Sovaria

Firestore.callbackQueue

Where snapshot listeners are called: the main queue on Apple platforms (like Firebase), else the thread that received the change.

public var callbackQueue: DispatchQueue?

Set it before adding listeners.

Firestore.firestore

The Firestore handle for a Sovaria client (the same one while you keep it).

public static func firestore(_ sovaria: Sovaria) -> Firestore

Firestore.collection

collection("users") or collection("users/\(uid)/posts").

public func collection(_ collectionPath: String) -> CollectionReference

Firestore.document

document("users/\(uid)").

public func document(_ documentPath: String) -> DocumentReference

Firestore.collectionGroup

Every collection with this id at any depth (comments, posts/p1/comments, …).

public func collectionGroup(_ collectionID: String) -> Query

Firestore.batch

public func batch() -> WriteBatch

Firestore.runTransaction

Reads then writes atomically; retried (up to maxAttempts) when a document it read changed meanwhile.

public func runTransaction<T>(maxAttempts: Int = 5, _ body: (Transaction) async throws -> T) async throws -> T

Unlike Firebase's synchronous block, transaction.getDocument is async.

Timestamp

A point in time. Stored as an ISO-8601 string in Sovaria.

public struct Timestamp: Hashable, Comparable, Codable, Sendable

Timestamp.seconds

A property.

public let seconds: Int64

Timestamp.nanoseconds

A property.

public let nanoseconds: Int32

Timestamp.Timestamp.init

Create an instance.

public init(seconds: Int64, nanoseconds: Int32)

Timestamp.Timestamp.init

Create an instance.

public init(date: Date)

Timestamp.Timestamp.init

Read back a stored timestamp (an ISO string).

public init?(iso: String)

Timestamp.now

public static func now() -> Timestamp

Timestamp.dateValue

public func dateValue() -> Date

Timestamp.iso

A property.

public var iso: String

Timestamp.func

public static func < (a: Timestamp, b: Timestamp) -> Bool

VectorValue

A vector value (FieldValue.vector([...])); stored as an array of numbers.

public struct VectorValue: Hashable, Sendable

VectorValue.array

A property.

public let array: [Double]

VectorValue.VectorValue.init

Create an instance.

public init(_ array: [Double])

FieldPath

A field path: FieldPath(["address", "city"]), or FieldPath.documentID() to filter or order by the id.

public struct FieldPath: Hashable, Sendable

FieldPath.components

A property.

public let components: [String]

FieldPath.FieldPath.init

Create an instance.

public init(_ fieldNames: [String])

FieldPath.documentID

public static func documentID() -> FieldPath

FieldValue

Atomic field updates, applied by the server inside the commit.

public final class FieldValue: @unchecked Sendable

FieldValue.delete

public static func delete() -> FieldValue

FieldValue.serverTimestamp

public static func serverTimestamp() -> FieldValue

FieldValue.arrayUnion

public static func arrayUnion(_ elements: [Any]) -> FieldValue

FieldValue.arrayRemove

public static func arrayRemove(_ elements: [Any]) -> FieldValue

FieldValue.increment

public static func increment(_ n: Int64) -> FieldValue

FieldValue.increment

public static func increment(_ n: Double) -> FieldValue

FieldValue.vector

public static func vector(_ values: [Double]) -> VectorValue

DocumentReference

public final class DocumentReference: Hashable, @unchecked Sendable

DocumentReference.firestore

A property.

public let firestore: Firestore

DocumentReference.path

A property.

public let path: String

DocumentReference.documentID

A property.

public var documentID: String

DocumentReference.parent

A property.

public var parent: CollectionReference

DocumentReference.collection

public func collection(_ collectionPath: String) -> CollectionReference

DocumentReference.getDocument

public func getDocument() async throws -> DocumentSnapshot

DocumentReference.setData

Replace the document, or merge into it with merge: true.

public func setData(_ documentData: [String: Any], merge: Bool = false) async throws

DocumentReference.setData

Merge only these fields (String or FieldPath).

public func setData(_ documentData: [String: Any], mergeFields: [Any]) async throws

DocumentReference.setData

Codable: try await ref.setData(from: user).

public func setData<T: Encodable>(from value: T, merge: Bool = false) async throws

DocumentReference.updateData

Change fields ("a.b" dotted paths and FieldPath keys allowed); fails with 404 when it doesn't exist.

public func updateData(_ fields: [AnyHashable: Any]) async throws

DocumentReference.delete

public func delete() async throws

DocumentReference.addSnapshotListener

The document now and after every change.

public func addSnapshotListener(_ listener: @escaping (DocumentSnapshot?, Error?) -> Void) -> ListenerRegistration

Keep the registration; remove() stops it.

DocumentReference.func

public static func == (a: DocumentReference, b: DocumentReference) -> Bool

DocumentReference.hash

public func hash(into h: inout Hasher)

Filter

One filter or an or / and group: whereFilter(Filter.orFilter([Filter.whereField("a", isEqualTo: 1), …])).

public struct Filter: @unchecked Sendable

Filter.whereField

public static func whereField(_ field: Any, isEqualTo value: Any?) -> Filter

Filter.whereField

public static func whereField(_ field: Any, isNotEqualTo value: Any?) -> Filter

Filter.whereField

public static func whereField(_ field: Any, isLessThan value: Any) -> Filter

Filter.whereField

public static func whereField(_ field: Any, isLessThanOrEqualTo value: Any) -> Filter

Filter.whereField

public static func whereField(_ field: Any, isGreaterThan value: Any) -> Filter

Filter.whereField

public static func whereField(_ field: Any, isGreaterThanOrEqualTo value: Any) -> Filter

Filter.whereField

public static func whereField(_ field: Any, arrayContains value: Any) -> Filter

Filter.whereField

public static func whereField(_ field: Any, arrayContainsAny values: [Any]) -> Filter

Filter.whereField

public static func whereField(_ field: Any, in values: [Any]) -> Filter

Filter.whereField

public static func whereField(_ field: Any, notIn values: [Any]) -> Filter

Filter.orFilter

Documents matching any of the filters (at most 30 OR terms after expansion).

public static func orFilter(_ filters: [Filter]) -> Filter

Filter.andFilter

Documents matching all of the filters, for nesting inside orFilter.

public static func andFilter(_ filters: [Filter]) -> Filter

Query

public class Query: @unchecked Sendable

Query.firestore

A property.

public let firestore: Firestore

Query.parameters

The request body (for tests and debugging).

public var parameters: [String: Any]

Query.whereFilter

public func whereFilter(_ filter: Filter) -> Query

Query.whereField

public func whereField(_ field: Any, isEqualTo value: Any?) -> Query

Query.whereField

public func whereField(_ field: Any, isNotEqualTo value: Any?) -> Query

Query.whereField

public func whereField(_ field: Any, isLessThan value: Any) -> Query

Query.whereField

public func whereField(_ field: Any, isLessThanOrEqualTo value: Any) -> Query

Query.whereField

public func whereField(_ field: Any, isGreaterThan value: Any) -> Query

Query.whereField

public func whereField(_ field: Any, isGreaterThanOrEqualTo value: Any) -> Query

Query.whereField

public func whereField(_ field: Any, arrayContains value: Any) -> Query

Query.whereField

public func whereField(_ field: Any, arrayContainsAny values: [Any]) -> Query

Query.whereField

public func whereField(_ field: Any, in values: [Any]) -> Query

Query.whereField

public func whereField(_ field: Any, notIn values: [Any]) -> Query

Query.order

public func order(by field: Any, descending: Bool = false) -> Query

Query.limit

public func limit(to n: Int) -> Query

Query.limit

public func limit(toLast n: Int) -> Query

Query.start

public func start(at fieldValues: [Any]) -> Query

Query.start

public func start(after fieldValues: [Any]) -> Query

Query.end

public func end(at fieldValues: [Any]) -> Query

Query.end

public func end(before fieldValues: [Any]) -> Query

Query.start

public func start(atDocument d: DocumentSnapshot) -> Query

Query.start

public func start(afterDocument d: DocumentSnapshot) -> Query

Query.end

public func end(atDocument d: DocumentSnapshot) -> Query

Query.end

public func end(beforeDocument d: DocumentSnapshot) -> Query

Query.getDocuments

public func getDocuments() async throws -> QuerySnapshot

Query.addSnapshotListener

Live results: the listener runs with the first snapshot and after every change.

public func addSnapshotListener(_ listener: @escaping (QuerySnapshot?, Error?) -> Void) -> ListenerRegistration

remove() stops it.

Query.count

query.count.getAggregation(source: .server).count.

public var count: AggregateQuery

Query.aggregate

aggregate([.count(), .sum("price"), .average("rating")]).getAggregation(source: .server).

public func aggregate(_ fields: [AggregateField]) -> AggregateQuery

Query.findNearest

Vector search: this query's filters first, then the limit documents whose vectorField is closest.

public func findNearest(vectorField: Any, queryVector: VectorValue, limit: Int, distanceMeasure: DistanceMeasure,
                        distanceResultField: String? = nil, distanceThreshold: Double? = nil) -> VectorQuery

Query.findNearest

public func findNearest(vectorField: Any, queryVector: [Double], limit: Int, distanceMeasure: DistanceMeasure,
                        distanceResultField: String? = nil, distanceThreshold: Double? = nil) -> VectorQuery

CollectionReference

public final class CollectionReference: Query, @unchecked Sendable

CollectionReference.collectionID

A property.

public var collectionID: String

CollectionReference.collectionPath

A property.

public var collectionPath: String

CollectionReference.parent

The document this subcollection belongs to, or nil for a top-level collection.

public var parent: DocumentReference?

CollectionReference.document

A new document with a random id.

public func document() -> DocumentReference

CollectionReference.document

public func document(_ documentPath: String) -> DocumentReference

CollectionReference.addDocument

Create a document with a new id.

public func addDocument(data: [String: Any]) async throws -> DocumentReference

CollectionReference.addDocument

public func addDocument<T: Encodable>(from value: T) async throws -> DocumentReference

DistanceMeasure

public enum DistanceMeasure: String, Sendable

VectorQuery

public final class VectorQuery: @unchecked Sendable

VectorQuery.getDocuments

public func getDocuments() async throws -> QuerySnapshot

AggregateField

public struct AggregateField: Hashable, Sendable

AggregateField.count

public static func count() -> AggregateField

AggregateField.sum

public static func sum(_ field: String) -> AggregateField

AggregateField.sum

public static func sum(_ field: FieldPath) -> AggregateField

AggregateField.average

public static func average(_ field: String) -> AggregateField

AggregateField.average

public static func average(_ field: FieldPath) -> AggregateField

AggregateSource

public enum AggregateSource: Sendable

AggregateQuery

public final class AggregateQuery: @unchecked Sendable

AggregateQuery.query

A property.

public let query: Query

AggregateQuery.getAggregation

public func getAggregation(source: AggregateSource = .server) async throws -> AggregateQuerySnapshot

AggregateQuerySnapshot

public final class AggregateQuerySnapshot: @unchecked Sendable

AggregateQuerySnapshot.count

A property.

public var count: NSNumber

AggregateQuerySnapshot.get

The value for field (an NSNumber, or nil when there was nothing to average).

public func get(_ field: AggregateField) -> Any?

SnapshotMetadata

public struct SnapshotMetadata: Hashable, Sendable

SnapshotMetadata.hasPendingWrites

A property.

public let hasPendingWrites: Bool

SnapshotMetadata.isFromCache

A property.

public let isFromCache: Bool

DocumentSnapshot

public class DocumentSnapshot: @unchecked Sendable

DocumentSnapshot.reference

A property.

public let reference: DocumentReference

DocumentSnapshot.documentID

A property.

public var documentID: String

DocumentSnapshot.exists

A property.

public var exists: Bool

DocumentSnapshot.metadata

A property.

public var metadata: SnapshotMetadata

DocumentSnapshot.data

The data, or nil when the document doesn't exist.

public func data() -> [String: Any]?

DocumentSnapshot.get

A field by dotted path (get("address.city")) or FieldPath; nil when missing.

public func get(_ field: Any) -> Any?

DocumentSnapshot.subscript

A property.

public subscript(field: Any) -> Any?

DocumentSnapshot.data

Codable: try snap.data(as: User.self).

public func data<T: Decodable>(as type: T.Type) throws -> T

QueryDocumentSnapshot

public final class QueryDocumentSnapshot: DocumentSnapshot, @unchecked Sendable

QueryDocumentSnapshot.data

public override func data() -> [String: Any]

DocumentChangeType

public enum DocumentChangeType: Sendable

DocumentChange

public struct DocumentChange: @unchecked Sendable

DocumentChange.type

A property.

public let type: DocumentChangeType

DocumentChange.document

A property.

public let document: QueryDocumentSnapshot

DocumentChange.oldIndex

UInt(NSNotFound) for an added document, like Firebase.

public let oldIndex: UInt

DocumentChange.newIndex

UInt(NSNotFound) for a removed document.

public let newIndex: UInt

QuerySnapshot

public final class QuerySnapshot: @unchecked Sendable

QuerySnapshot.query

A property.

public let query: Query

QuerySnapshot.documents

A property.

public let documents: [QueryDocumentSnapshot]

QuerySnapshot.documentChanges

A property.

public let documentChanges: [DocumentChange]

QuerySnapshot.count

A property.

public var count: Int

QuerySnapshot.isEmpty

A property.

public var isEmpty: Bool

QuerySnapshot.metadata

A property.

public var metadata: SnapshotMetadata

ListenerRegistration

public protocol ListenerRegistration: AnyObject

ListenerRegistration.remove

func remove()

WriteBatch

Writes committed together: every one or none.

public final class WriteBatch: @unchecked Sendable

WriteBatch.setData

public func setData(_ data: [String: Any], forDocument document: DocumentReference, merge: Bool = false) -> WriteBatch

WriteBatch.setData

public func setData(_ data: [String: Any], forDocument document: DocumentReference, mergeFields: [Any]) -> WriteBatch

WriteBatch.updateData

public func updateData(_ fields: [AnyHashable: Any], forDocument document: DocumentReference) -> WriteBatch

WriteBatch.deleteDocument

public func deleteDocument(_ document: DocumentReference) -> WriteBatch

WriteBatch.commit

public func commit() async throws

Transaction

Read every document first, then write; the commit fails (and is retried) if a read document changed.

public final class Transaction: @unchecked Sendable

Transaction.getDocument

public func getDocument(_ document: DocumentReference) async throws -> DocumentSnapshot

Transaction.setData

public func setData(_ data: [String: Any], forDocument document: DocumentReference, merge: Bool = false) -> Transaction

Transaction.updateData

public func updateData(_ fields: [AnyHashable: Any], forDocument document: DocumentReference) -> Transaction

Transaction.deleteDocument

public func deleteDocument(_ document: DocumentReference) -> Transaction