UNPKG

@api-buddy/firebase

Version:

Firebase integration for API Buddy

253 lines (197 loc) 5.84 kB
# @api-buddy/firebase Firebase integration for API Buddy. This package provides a set of utilities, type-safe operations, and React hooks for working with Firebase services in your API Buddy projects. ## Features - 🔒 Type-safe Firestore operations - ⚡ Real-time data subscriptions - 🎣 React hooks for easy integration - 🔄 Optimistic updates - 🔐 Security rules templates - 🚀 Batch and transaction support ## Installation ```bash pnpm add @api-buddy/firebase firebase ``` ## Quick Start ### Initialize Firebase ```typescript // lib/firebase.ts import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; import { getAuth } from 'firebase/auth'; const firebaseConfig = { apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, // ... other config }; const app = initializeApp(firebaseConfig); export const db = getFirestore(app); export const auth = getAuth(app); ``` ## Firestore Operations ### Basic CRUD Operations ```typescript import { FirestoreService } from '@api-buddy/firebase'; interface User { name: string; email: string; createdAt: Date; } const usersService = new FirestoreService<User>('users'); // Create export const createUser = async (id: string, userData: User) => { return usersService.create(id, userData); }; // Read export const getUser = async (id: string) => { return usersService.get(id); }; // Update export const updateUser = async (id: string, updates: Partial<User>) => { return usersService.update(id, updates); }; // Delete export const deleteUser = async (id: string) => { return usersService.delete(id); }; ``` ### Querying Data ```typescript // Get all active users, ordered by name const activeUsers = await usersService.query({ where: [['status', '==', 'active']], orderBy: [['name', 'asc']], limit: 10 }); // Pagination const firstPage = await usersService.query({ orderBy: [['createdAt', 'desc']], limit: 10 }); const nextPage = await usersService.query({ orderBy: [['createdAt', 'desc']], startAfter: firstPage[firstPage.length - 1], limit: 10 }); ``` ## React Hooks ### useDocument Hook ```tsx import { useDocument } from '@api-buddy/firebase'; function UserProfile({ userId }: { userId: string }) { const usersService = useFirestoreService<User>('users'); const { data: user, loading, error } = useDocument(usersService, userId); if (loading) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; if (!user) return <div>User not found</div>; return ( <div> <h1>{user.name}</h1> <p>Email: {user.email}</p> </div> ); } ``` ### useCollection Hook ```tsx import { useCollection } from '@api-buddy/firebase'; function UserList() { const usersService = useFirestoreService<User>('users'); const { data: users, loading, error, hasMore, fetchMore } = useCollection(usersService, { where: [['status', '==', 'active']], orderBy: [['createdAt', 'desc']], limit: 10 }); if (loading && !users?.length) return <div>Loading...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> {users.map(user => ( <UserCard key={user.id} user={user} /> ))} {hasMore && ( <button onClick={fetchMore} disabled={loading}> {loading ? 'Loading...' : 'Load More'} </button> )} </div> ); } ``` ### useRealtimeCollection Hook ```tsx import { useRealtimeCollection } from '@api-buddy/firebase'; function RealtimeComments({ postId }: { postId: string }) { const commentsService = useFirestoreService<Comment>('comments'); const { data: comments, loading, error } = useRealtimeCollection(commentsService, { where: [['postId', '==', postId]], orderBy: [['createdAt', 'asc']] }); if (loading) return <div>Loading comments...</div>; if (error) return <div>Error: {error.message}</div>; return ( <div> {comments.map(comment => ( <CommentItem key={comment.id} comment={comment} /> ))} </div> ); } ``` ## Security Rules We provide a set of recommended security rules in the `security-rules` directory. To deploy them: 1. Copy the rules to your Firebase project 2. Run the deployment script: ```bash # Set your Firebase project ID FIREBASE_PROJECT=your-project-id pnpm tsx scripts/deploy-rules.ts ``` ## Environment Variables ```env # Firebase Config NEXT_PUBLIC_FIREBASE_API_KEY=your-api-key NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com NEXT_PUBLIC_FIREBASE_PROJECT_ID=your-project-id NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=your-project.appspot.com NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=your-messaging-sender-id NEXT_PUBLIC_FIREBASE_APP_ID=your-app-id NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=G-XXXXXXXXXX # For local development FIREBASE_EMULATOR_HOST=localhost FIREBASE_FIRESTORE_EMULATOR_PORT=8080 FIREBASE_AUTH_EMULATOR_PORT=9099 ``` ## TypeScript Support All Firestore operations are fully typed. Define your data models as TypeScript interfaces: ```typescript interface Product { name: string; price: number; category: string; createdAt: Date; updatedAt: Date; } const productsService = new FirestoreService<Product>('products'); // All operations will be type-checked against the Product interface ``` ## Error Handling All operations throw standard Firebase errors. You can catch and handle them appropriately: ```typescript try { await usersService.update('user123', { name: 'New Name' }); } catch (error) { if (error.code === 'permission-denied') { console.error('You do not have permission to update this user'); } else { console.error('Error updating user:', error); } } ``` ## License MIT