Skip to content

FirebaseFirestore improvements#80

Open
IT-Guy007 wants to merge 3 commits into
skiptools:mainfrom
IT-Guy007:firebase-firestore-improvements
Open

FirebaseFirestore improvements#80
IT-Guy007 wants to merge 3 commits into
skiptools:mainfrom
IT-Guy007:firebase-firestore-improvements

Conversation

@IT-Guy007
Copy link
Copy Markdown
Contributor

SkipFirebaseCore.swift

  • Timestamp now conforms to Codable using internal sentinel keys (fts/ftn) for JSON round-tripping

SkipFirebaseFirestore.swift

  • GeoPoint class — Hashable, KotlinConverting (so it survives .kotlin() dict conversion), Codable
  • firestoreDeepSwift — replaces deepSwift calls throughout to also handle com.google.firebase.firestore.GeoPoint → GeoPoint
  • FirestoreCacheSizeUnlimited, FirestoreCacheSettings, MemoryGarbageCollectionSettings, MemoryLRUGCSettings, MemoryEagerGCSettings, MemoryCacheSettings, PersistentCacheSettings
  • FirestoreSettings class with host, isSSLEnabled, cacheSettings and toAndroid() builder
  • Firestore.settings get/set property — applies to the Android store on set
  • SnapshotMetadata.isFromCache
  • DocumentSnapshot.metadata, .reference, .get(_ fieldPath: FieldPath), .data() throws -> T
  • DocumentReference.getDocument(source:) async, setData(_:mergeFields:) async, setData<T: Encodable>(from:merge:) async, setData<T: Encodable>(from:mergeFields:) async
  • CollectionReference.addDocument(data:completion:)
  • FirestoreEncoder and FirestoreDecoder classes

One API note: Skip can't bridge T.Type parameters, so on Android the Codable decode is let m: MyModel = try snapshot.data() (return-type inference). On iOS you use FirebaseFirestoreSwift's snapshot.data(as:
MyModel.self) as normal. The encode direction (setData(from:)) works identically on both platforms.

Thank you for contributing to the Skip project! Please use this space to describe your change and add any labels (bug, enhancement, documentation, etc.) to help categorize your contribution.

Please review the contribution guide at https://skip.dev/docs/contributing/ for advice and guidance on making high-quality PRs.

Skip Pull Request Checklist:

  • REQUIRED: I have signed the Contributor Agreement
  • REQUIRED: I have tested my change locally with swift test
  • OPTIONAL: I have tested my change on an iOS simulator or device
  • OPTIONAL: I have tested my change on an Android emulator or device

  • AI was used to generate or assist with generating this PR. Please specify below how you used AI to help you, and what steps you have taken to manually verify the changes.

AI was used for documentation writes and codable implementation

SkipFirebaseCore.swift
  - Timestamp now conforms to Codable using internal sentinel keys (__fts__/__ftn__) for JSON round-tripping

  SkipFirebaseFirestore.swift
  - GeoPoint class — Hashable, KotlinConverting (so it survives .kotlin() dict conversion), Codable
  - firestoreDeepSwift — replaces deepSwift calls throughout to also handle com.google.firebase.firestore.GeoPoint → GeoPoint
  - FirestoreCacheSizeUnlimited, FirestoreCacheSettings, MemoryGarbageCollectionSettings, MemoryLRUGCSettings, MemoryEagerGCSettings, MemoryCacheSettings, PersistentCacheSettings
  - FirestoreSettings class with host, isSSLEnabled, cacheSettings and toAndroid() builder
  - Firestore.settings get/set property — applies to the Android store on set
  - SnapshotMetadata.isFromCache
  - DocumentSnapshot.metadata, .reference, .get(_ fieldPath: FieldPath), .data<T>() throws -> T
  - DocumentReference.getDocument(source:) async, setData(_:mergeFields:) async, setData<T: Encodable>(from:merge:) async, setData<T: Encodable>(from:mergeFields:) async
  - CollectionReference.addDocument(data:completion:)
  - FirestoreEncoder and FirestoreDecoder classes

  One API note: Skip can't bridge T.Type parameters, so on Android the Codable decode is let m: MyModel = try snapshot.data() (return-type inference). On iOS you use FirebaseFirestoreSwift's snapshot.data(as:
  MyModel.self) as normal. The encode direction (setData(from:)) works identically on both platforms.
@cla-bot cla-bot Bot added the cla-signed label May 15, 2026
@IT-Guy007 IT-Guy007 marked this pull request as draft May 15, 2026 17:27
@IT-Guy007
Copy link
Copy Markdown
Contributor Author

Just figured out that there are more methods that I need to support, converted to draft

SkipFirebaseCore.swift
  - Timestamp.init(from:) now handles a plain Double (seconds since epoch) in addition to the existing {"__fts__"/"__ftn__"} sentinel dict — enables Timestamp fields in Codable
  models to decode from the timeInterval doubles emitted by the new decoder path

  SkipFirebaseFirestore.swift

  Property wrappers (new):
  - @documentid<Value: Codable> — no-op on encode; on decode reads from decoder.userInfo[.firestoreDocumentID] (set by the decoder when a documentID is provided), with a
  keyed-container fallback for Skip runtimes where userInfo may not propagate
  - @ServerTimestamp — on encode: nil → {"__fts_server__": true} sentinel (restored to FieldValue.serverTimestamp() by the encoder pass); non-nil → actual Timestamp. On decode: reads
   Timestamp back normally
  - CodingUserInfoKey.firestoreDocumentID extension
  - _DocumentIDCodingKey and _FirestoreDateSentinelKeys private enum helpers

  FirestoreEncoder improvements:
  - Date → {"__firestore_date__": timeInterval} sentinel via custom dateEncodingStrategy, restored to Timestamp in restoreFirestoreTypes
  - {"__fts_server__": true} → FieldValue.serverTimestamp() in restoreFirestoreTypes
  - NSNumber Bool coercion in restoreFirestoreTypes (Android JSONSerialization returns 0/1 instead of native Bool)

  FirestoreDecoder improvements:
  - New decode(from:documentID:) overload — injects document ID into userInfo, sets dateDecodingStrategy = .secondsSince1970
  - prepareForJSON now converts Timestamp → Double (timeInterval) instead of sentinel dict, enabling both Date and Timestamp model fields to decode correctly
  - NSNumber Bool coercion in prepareForJSON
  - DocumentSnapshot.decoded() now passes documentID to the decoder

  New Codable overloads:
  - CollectionReference.addDocument(from: T) async throws
  - WriteBatch.setData(from: T, forDocument:) throws → WriteBatch (chainable)
  - WriteBatch.setData(from: T, forDocument:mergeFields:) throws → WriteBatch
Remove Codable from the main class declarations for Timestamp and GeoPoint and add separate extension-based Codable conformance. This prevents the Skip bridge generator from including Codable in the generated bridge class (which has a JObject peer that cannot auto-synthesize Codable); the existing encode/decode implementations already satisfy the conformance. Changes made in SkipFirebaseCore.swift and SkipFirebaseFirestore.swift.
@IT-Guy007
Copy link
Copy Markdown
Contributor Author

Codable gave issues, moved to extension implementation

@IT-Guy007
Copy link
Copy Markdown
Contributor Author

Ready for review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant