Expand description
§Firebase Realtime Database module
This module ports core pieces of the Realtime Database from the Firebase JS SDK to Rust.
It wires the Database component into the FirebaseApp, provides an in-memory backend for quick tests, and can fall back to the REST API for basic reads and writes against an emulator or hosted backend.
Live streaming connections and the richer reference/query surface from the JS SDK are still pending.
It includes error handling, configuration options, and integration with Firebase apps.
§Features
- Component registration and shared get_database resolution
- Reference CRUD with auto-ID push and path navigation (parent/root)
- Priority-aware writes plus server value helpers (server_timestamp increment)
- Snapshot traversal (child, has_child, size, to_json) and value/child listeners
- Dual backends (in-memory + REST) with unit test coverage
§Porting status
- database 30%
[### ]
==As of October 21th, 2025==
Prompt: Compare the original JS/Typescript files in ./packages/database and the ported files in Rust in ./src/database, and give me an estimated guess, in percentage, of how much of the features/code of the Firebase JS SDK has been ported to Rust for this module
I’ll put together a clear bullet list showing about 30% of the JavaScript Realtime Database features appear ported to Rust, backing it with code references for implemented and missing parts, highlighting key TypeScript modules not yet ported, and finishing with suggestions like verifying features or updating documentation.
Port Estimate
- Roughly 30 % of the packages/database TypeScript surface is reflected in Rust; the port covers basic Database/ Reference CRUD, query builders, server values, and token-aware REST + in-memory backends.
- Implemented pieces include the Database component wiring and backend selection (src/database/api.rs:1499-1522, src/ database/backend.rs:15-205), core reference/query operations with listener dispatch (src/database/api.rs:773-960, src/database/api.rs:1078-1250), snapshot helpers (src/database/api.rs:140-210), push-ID generation, and server value helpers (src/database/server_value.rs:1-18), giving functional parity for simple reads/writes and REST filtering.
- Large swaths of the JS SDK remain unported: OnDisconnect actions error out (src/database/on_disconnect.rs:20- 50), transactions are stubbed (src/database/api.rs:905-913), and all realtime transports/Repo orchestration are placeholders (src/database/realtime.rs:3-56), so anything depending on core/Repo.ts, PersistentConnection.ts, or Transaction.ts is missing.
- Listener support is limited to local diffing; there is no remote event streaming (repo/SyncTree logic from packages/ database/src/core) or child-moved/query child events, nor off/once/isEqual/toString parity for QueryImpl/ReferenceImpl (see packages/database/src/api/Reference_impl.ts for the unported surface).
- Auxiliary controls such as goOnline/goOffline, emulator toggles, logging, connection stats, validation utilities, and Node-specific entry points (packages/database/src/api/Database.ts, core/util) are absent, indicating the broader environment/runtime features are still outstanding.
Next steps you might consider:
- Prioritise porting the Repo/persistent connection stack to unlock realtime listeners, transactions, and onDisconnect semantics.
- Flesh out the remaining public API surface (query equality/serialization helpers, off/once, refFromURL, logging/ emulator controls) and update src/database/README.md once significant pieces land.
§References to the Firebase JS SDK - firestore module
- QuickStart: https://firebase.google.com/docs/database/web/start
- API: https://firebase.google.com/docs/reference/js/database.md#database_package
- Github Repo - Module: https://github.com/firebase/firebase-js-sdk/tree/main/packages/database
- Github Repo - API: https://github.com/firebase/firebase-js-sdk/tree/main/packages/firebase/database
§Development status as of 14th October 2025
- Core functionalities: Mostly implemented
- Testing: 30 tests (passed)
- Documentation: Most public functions are documented
- Examples: 2 examples
DISCLAIMER: This is not an official Firebase product, nor it is guaranteed that it has no bugs or that it will work as intended.
§Quick Start Example
use firebase_rs_sdk::app::*;
use firebase_rs_sdk::database::{*, query as compose_query};
use serde_json::json;
#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Point to the Realtime Database emulator or a database URL.
let options = FirebaseOptions {
project_id: Some("demo-project".into()),
database_url: Some("http://127.0.0.1:9000/?ns=demo".into()),
..Default::default()
};
let app = initialize_app(options, Some(FirebaseAppSettings::default())).await?;
let database = get_database(Some(app)).await?;
let messages = database.reference("/messages")?;
messages.set(json!({ "greeting": "hello" })).await?;
let value = messages.get().await?;
assert_eq!(value, json!({ "greeting": "hello" }));
let recent = compose_query(
messages,
vec![order_by_child("timestamp"), limit_to_last(10)],
)?;
let latest = recent.get().await?;
println!("latest snapshot: {latest}");
Ok(())
}§Current State
- Database component registration via
register_database_componentsoget_databaseresolves out of the sharedFirebaseAppregistry. - Async-first surfaces for
get_database,DatabaseReferenceCRUD helpers, query listeners, and modular helpers so consumersawaitinstead of relying onblock_onshims. - Core reference operations (
reference,child,set,update,remove,get) that work against any backend and emitdatabase/invalid-argumenterrors for unsupported paths. - Auto-ID child creation via
DatabaseReference::push()/push_with_value()and the modularpush()helper, mirroring the JS SDK’s append semantics. - Priority-aware writes through
DatabaseReference::set_with_priority()/set_priority()(and modular helpers), persisting.value/.prioritymetadata compatible with RESTformat=export. - Server value helpers (
server_timestamp,increment) with local resolution for timestamp and atomic increment placeholders acrossset/update. - Child event listeners (
on_child_added,on_child_changed,on_child_removed) with in-memory diffing and snapshot traversal utilities for callback parity with the JS SDK. - Hierarchical navigation APIs (
DatabaseReference::parent/root) and snapshot helpers (child,has_child,has_children,size,to_json) that mirror the JSDataSnapshottraversal utilities. - Query builder helpers (
query,order_by_*,start_*,end_*,limit_*,equal_to*) withDatabaseQuery::get()and REST parameter serialisation. on_valuelisteners for references and queries that deliver an initial snapshot and replay callbacks after local writes, returningListenerRegistrationhandles for manual detach.- Backend selection that defaults to an in-memory store and upgrades to a REST backend (
reqwestPUT/PATCH/DELETE/GET) including base query propagation plus optional Auth/App Check token injection. - Unit tests covering in-memory semantics, validation edge cases, and REST request wiring through
httpmock. - Preliminary realtime hooks (
Database::go_online/go_offline) backed by a platform-aware transport selector. The Rust port now normalises listen specs, reference-counts active listeners, and—on native targets—establishes an async WebSocket session usingtokio-tungstenite, forwarding auth/App Check tokens and queuing listen/unlisten envelopes until the full persistent connection protocol is ported. Streaming payload handling is still pending. - WASM builds mirror the native realtime selector: the runtime first attempts a
web_sys::WebSocketconnection and automatically falls back to an HTTP long-poll loop when sockets are unavailable, keepingon_valuelisteners alive across restrictive environments. OnDisconnectscheduling (set,set_with_priority,update,remove,cancel) forwards to the realtime transport when a WebSocket is available, resolving server timestamp/increment placeholders before dispatch. Under the long-poll fallback, the operations are queued and executed when the client callsgo_offline(), providing a graceful degradation when WebSockets are unavailable.run_transactionis available and mirrors the JS API, returning aTransactionResultwithcommitted/snapshotfields. The current implementation uses an optimistic REST write when running against HTTP backends, so simultaneous writers should still implement retry loops.
§WASM Notes
- The module compiles on wasm targets when the
wasm-webfeature is enabled. Web builds attempt to establish a realtime WebSocket and transparently degrade to a long-poll fetch loop when sockets cannot open, reusing the same listener bookkeeping as native builds.OnDisconnectoperations require an active WebSocket; on the long-poll fallback they are queued locally and executed whengo_offline()runs, which does not fully replicate server-side disconnect handling. - Calling
get_database(None)is not supported on wasm because the default app lookup is asynchronous. Pass an explicitFirebaseAppinstance instead. go_online/go_offlineare currently stubs on wasm (and native) but provide the async surface needed for upcoming realtime work.
§Next Steps
- Real-time transports (
Repo,PersistentConnection,WebSocketConnection,BrowserPollConnection) soonValue/child events react to remote changes. - Child event parity:
on_child_moved, query-level child listeners, and server-orderedprev_namesemantics fromcore/SyncTree.ts. - Transactions (
runTransaction) with true concurrency control and long-pollOnDisconnectexecution, including offline queue handling and server timestamp resolution (Transaction.ts,OnDisconnect.ts). - Operational controls such as
connectDatabaseEmulator,goOnline/goOffline, and logging toggles fromDatabase.ts, plus emulator-focused integration tests.
§Immediate Porting Focus
- Child listener parity – Port the remaining event registrations (
onChildMoved, query listeners, cancellation hooks) fromReference_impl.tsandSyncTree.ts, reusing the new diffing infrastructure. - Realtime transport handshake – Wire the
realtime::Repolistener map into a fullPersistentConnectionport that sends listen/unlisten commands over the new native websocket task, surfaces errors, and forwards payloads intodispatch_listeners(mirrored on wasm viaweb_sys::WebSocket). - Transactions and OnDisconnect – Harden
run_transactionwith retries/ETag handling and extend the new OnDisconnect plumbing so operations continue to work when the transport falls back to long-polling, mirroring the queuing inPersistentConnection.ts.
Modules§
Structs§
- Child
Event - Data
Snapshot - Represents a data snapshot returned to listeners, analogous to the JS
DataSnapshottype. - Database
- Database
Query - Represents a composable database query, analogous to the JS
QueryImpl(packages/database/src/api/Reference_impl.ts). - Database
Reference - Listener
Registration - RAII-style listener registration; dropping the handle detaches the underlying listener.
- OnDisconnect
- Async handle for scheduling writes that run when the client disconnects.
- Query
Constraint - Represents a single constraint produced by helpers such as
order_by_child()(packages/database/src/api/Reference_impl.ts). - Transaction
Result - Result returned by
run_transaction, mirroring the JS SDK contract.
Enums§
Functions§
- end_at
- Mirrors the JS
endAt()constraint (Reference_impl.ts). - end_
at_ with_ key - Mirrors the JS
endAt(value, name)overload (Reference_impl.ts). - end_
before - Mirrors the JS
endBefore()constraint (Reference_impl.ts). - end_
before_ with_ key - Mirrors the JS
endBefore(value, name)overload (Reference_impl.ts). - equal_
to - Mirrors the JS
equalTo()constraint (Reference_impl.ts). - equal_
to_ with_ key - Mirrors the JS
equalTo(value, name)overload (Reference_impl.ts). - get_
database - increment
- Port of
increment()frompackages/database/src/api/ServerValue.ts. - limit_
to_ first - Mirrors the JS
limitToFirst()constraint (Reference_impl.ts). - limit_
to_ last - Mirrors the JS
limitToLast()constraint (Reference_impl.ts). - on_
child_ added - Registers a
child_addedlistener for the provided reference. - on_
child_ changed - Registers a
child_changedlistener for the provided reference. - on_
child_ removed - Registers a
child_removedlistener for the provided reference. - order_
by_ child - Produces a constraint that orders the results by the specified child path.
Mirrors
orderByChild()from the JS SDK. - order_
by_ key - Produces a constraint that orders nodes by key (
orderByKey()in JS). - order_
by_ priority - Produces a constraint that orders nodes by priority (
orderByPriority()in JS). - order_
by_ value - Produces a constraint that orders nodes by value (
orderByValue()in JS). - push
- Generates a child location with an auto-generated push ID.
- push_
with_ value - Generates a child location with an auto-generated push ID and writes the provided value.
- query
- Creates a derived query by applying the provided constraints, following the
semantics of
query()inpackages/database/src/api/Reference_impl.ts. - register_
database_ component - run_
transaction - Runs a transaction at the provided reference, mirroring the JS SDK.
- server_
timestamp - Port of
serverTimestamp()frompackages/database/src/api/ServerValue.ts. - set_
priority - Updates the priority for the current location, mirroring the modular
setPriority()helper (packages/database/src/api/Reference_impl.ts). - set_
with_ priority - Writes a value together with a priority, mirroring the modular
setWithPriority()helper (packages/database/src/api/Reference_impl.ts). - start_
after - Mirrors the JS
startAfter()constraint (Reference_impl.ts). - start_
after_ with_ key - Mirrors the JS
startAfter(value, name)overload (Reference_impl.ts). - start_
at - Mirrors the JS
startAt()constraint (Reference_impl.ts). - start_
at_ with_ key - Mirrors the JS
startAt(value, name)overload (Reference_impl.ts).