# @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
