Typesafe ODM for Firestore - A lightweight wrapper that adds type safety and schema validation
to your Firestore database operations in TypeScript.
Firetype extends the existing Firestore SDK functionality while maintaining all its native features
and requiring the original SDK to be installed. It provides a folder-based schema definition system
that automatically generates fully type-safe APIs for your Firestore collections and documents.
⚠️ Important: Firetype extends the Firestore SDK and is not a replacement. You’ll still need
to install and use either firebase-admin or firebase/firestore as your primary SDK.
✨ Features
- 🎯 Full Type Safety: Complete TypeScript type inference for all Firestore operations with zero
runtime overhead
- 📁 Folder-Based Schema: Organize your database structure naturally in directories, including
nested collections
- 🔄 Runtime Validation: Optional Zod-powered schema validation with detailed error messages
- 🛠️ Powerful CLI: Generate type definitions with flexible configuration options
- ⚡ SDK Agnostic: Works seamlessly with both
firebase-admin and firebase/firestore SDKs
- 🔗 Nested Collections: Full support for subcollections with automatic path generation
- 📊 Collection Groups: Type-safe collection group queries across all subcollections
- 🎨 Zero Config: Just define your schemas and let Firetype handle the rest
📦 Installation
Install Firetype using your preferred package manager:
# npm
npm install @anonymous-dev/firetype
# yarn
yarn add @anonymous-dev/firetype
# pnpm
pnpm add @anonymous-dev/firetype
# bun
bun add @anonymous-dev/firetype
Peer Dependencies
Firetype requires one of the following Firestore SDKs (choose based on your environment):
# For server-side applications (Node.js, Cloud Functions, etc.)
npm install firebase-admin
# For client-side applications (browsers, React Native, etc.)
npm install firebase
💡 Tip: Firetype works with both SDKs simultaneously if you need to support both client and
server environments.
🚀 Quick Start
Get started with Firetype in 5 minutes. This guide shows you how to set up type-safe Firestore
operations.
1. Set up your schema directory
Create a directory structure for your Firestore database schemas:
mkdir -p schemas/database
2. Define your first collection schema
Create schemas/database/users/schema.ts:
import { z } from 'zod';
export const schema = z.object({
name: z.string().min(1, 'Name is required'),
email: z.string().email('Invalid email format'),
age: z.number().int().positive().optional(),
createdAt: z.date(),
metadata: z.object({
lastLogin: z.date().optional(),
isVerified: z.boolean().default(false),
preferences: z.record(z.string()).optional(),
}),
});
3. Generate type definitions
Use the Firetype CLI to generate your types:
# Generate types for both admin and client SDKs (output written to input folder)
npx @anonymous-dev/firetype generate --input=./schemas/database
# Generate only admin SDK types
npx @anonymous-dev/firetype generate --mode=admin --input=./schemas
# Generate only client SDK types
npx @anonymous-dev/firetype generate --mode=client --input=./schemas
This creates an index.ts file in your input folder with your fully typed Firestore API.
4. Use in your application
Server-side (Admin SDK)
import { createFireTypeAdmin } from './types';
import { getFirestore } from 'firebase-admin/firestore';
const db = getFirestore();
const firetype = createFireTypeAdmin(db);
// Type-safe collection operations
const usersCollection = firetype.users.getCollectionRef();
const allUsers = await usersCollection.get();
// Type-safe document operations
const userDoc = firetype.users.getDocumentRef('user123');
const userSnapshot = await userDoc.get();
const userData = userSnapshot.data(); // Fully typed!
// Add new user with validation
await usersCollection.add({
name: 'John Doe',
email: 'john@example.com',
age: 30,
createdAt: new Date(),
metadata: {
isVerified: false,
preferences: { theme: 'dark' },
},
});
Client-side (Web SDK)
import { createFireTypeClient } from './types';
import { getFirestore, getDocs } from 'firebase/firestore';
const db = getFirestore();
const firetype = createFireTypeClient(db);
// Type-safe operations
const usersRef = firetype.users.getCollectionRef();
const usersSnapshot = await getDocs(usersRef);
usersSnapshot.forEach((doc) => {
const user = doc.data(); // Fully typed user object
console.log(`${user.name}: ${user.email}`);
});
5. Add subcollections (Optional)
Create nested collections by adding subdirectories. For user comments:
schemas/database/users/comments/schema.ts:
import { z } from 'zod';
export const schema = z.object({
content: z.string().min(1, 'Comment cannot be empty'),
authorId: z.string(),
createdAt: z.date(),
likes: z.number().default(0),
});
Now you can access nested collections:
// Get comments for a specific user
const userComments = firetype.users.comments.getCollectionRef({
usersId: 'user123',
});
const comments = await userComments.get();
📚 Documentation Sections
🆘 Need Help?