Skip to content

FirebaseFirestore improvements#80

Merged
marcprux merged 6 commits into
skiptools:mainfrom
IT-Guy007:firebase-firestore-improvements
May 17, 2026
Merged

FirebaseFirestore improvements#80
marcprux merged 6 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

IT-Guy007 commented May 16, 2026

Codable is giving issues during skip android build, not swift test. I need to some more time.

@IT-Guy007 IT-Guy007 marked this pull request as draft May 16, 2026 14:42
IT-Guy007 added 3 commits May 16, 2026 16:48
The Skip bridge generator includes ALL protocol conformances (both class
   declarations and extensions) when generating bridge classes. Moving Codable
   to an extension was insufficient.

   SwiftCustomBridged is the correct signal — used by skip-foundation's Date,
   Data, UUID, and URL for the same reason — to tell the bridge generator that
   these types handle their own bridging rather than auto-generating a standard
   bridge class that would fail to synthesize Codable with a JObject peer.
 SwiftCustomBridged is defined in SkipLib, but the generated bridge file
 only imports SkipBridge and Foundation, so the protocol is not in scope
 during the SKIP_BRIDGE compilation and causes a build error.
@IT-Guy007 IT-Guy007 marked this pull request as ready for review May 16, 2026 21:00
@IT-Guy007
Copy link
Copy Markdown
Contributor Author

@marcprux PR ready, my apologies it took so many attempts, learned a lot about the inner works of skip though

@marcprux marcprux merged commit 3868612 into skiptools:main May 17, 2026
2 checks passed
@marcprux
Copy link
Copy Markdown
Member

Great contribution, thanks for all the work!

@IT-Guy007 IT-Guy007 deleted the firebase-firestore-improvements branch May 24, 2026 16:17
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.

2 participants