Firebase Realtime Database Modeler

2.8.0 · active · verified Wed Apr 22

Firebase Database Modeler is a TypeScript-first library designed to enhance development with the Firebase Realtime Database by providing a structured, strongly-typed modeling layer. Currently at version 2.8.0, it aims to abstract the complexities of database path management and data serialization through a declarative model definition. It offers robust IntelliSense support, automatically converting between the defined model schema and the actual database structure. The library supports integration with `firebase`, `firebase-admin`, and `react-native-firebase`, making it versatile for various JavaScript environments. While a strict release cadence isn't published, the developer indicates active use in a real project, implying ongoing maintenance and feature evolution. Its key differentiation lies in bringing advanced type safety and a clear object-oriented approach to Firebase Realtime Database interactions, simplifying complex data structures and reducing common runtime errors associated with schema mismatches.

Common errors

Warnings

Install

Imports

Quickstart

This quickstart demonstrates defining a typed model for a Firebase Realtime Database 'stores' collection, initializing Firebase, setting the default database for the modeler, and performing type-safe create, update, and fetch operations using the defined model with dynamic path segments.

import { _, _$, _root, modelerSetDefaultDatabase } from 'firebase-database-modeler';
import firebase from 'firebase/compat/app';
import 'firebase/compat/database';

// Initialize Firebase (replace with your actual config)
const firebaseConfig = {
  apiKey: process.env.FIREBASE_API_KEY ?? 'YOUR_API_KEY',
  authDomain: process.env.FIREBASE_AUTH_DOMAIN ?? 'YOUR_AUTH_DOMAIN',
  projectId: process.env.FIREBASE_PROJECT_ID ?? 'YOUR_PROJECT_ID',
  storageBucket: process.env.FIREBASE_STORAGE_BUCKET ?? 'YOUR_STORAGE_BUCKET',
  messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID ?? 'YOUR_MESSAGING_SENDER_ID',
  appId: process.env.FIREBASE_APP_ID ?? 'YOUR_APP_ID',
  databaseURL: process.env.FIREBASE_DATABASE_URL ?? 'YOUR_DATABASE_URL'
};

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
}

const database = firebase.database();
modelerSetDefaultDatabase(database);

const stores = _('stores', {
  $storeId: _$1({
    name: _<string>('n'), // DB key 'n' for model property 'name'
    rating: _<number>('rating'),
    open: _<boolean>('open'),
    optionalProp: _<number | null>('oP'), // Optional property
    users: _('users', {
      $userId: _$1({
        name: _<string>('name')
      })
    })
  })
});

const root = _root({
  stores
});

async function createStore(storeId: string, userId: string, userName: string) {
  // All non-null model properties for the current path must be provided.
  await stores.$storeId._set({
    name: 'Cool Store', 
    rating: 4.2,
    open: true,
    users: {
      [userId]: {
        name: userName
      }
    }
  }, storeId);
  console.log(`Store ${storeId} created.`);
}

async function setStoreName(storeId: string, newName: string) {
  // To update a single field, target its specific path.
  await stores.$storeId.name._set(newName, storeId);
  console.log(`Store ${storeId} name updated to ${newName}.`);
}

async function getStore(storeId: string) {
  const store = await stores.$storeId._onceVal('value', storeId);
  console.log(`Fetched store ${storeId}:`, store);
  return store;
}

// Example usage
(async () => {
  const myStoreId = 'store_abc';
  const myUserId = 'user_123';
  await createStore(myStoreId, myUserId, 'Alice');
  await setStoreName(myStoreId, 'Super Cool Store');
  await getStore(myStoreId);
})();

view raw JSON →