@api-buddy/use-buddy
v1.0.0
Published
Core data fetching hooks for API Buddy
Readme
@api-buddy/use-buddy
A powerful, type-safe React hooks library for managing API interactions, authentication, and data fetching. Part of the API Buddy ecosystem.
Features
- 🔄 React Query Integration - Built on top of
@tanstack/react-queryfor powerful data fetching and caching - 🔌 Adapter-based Architecture - Plug in different data sources (Auth, Database, Storage)
- 🛠 Type Safety - Full TypeScript support with strict typing
- ⚡ Performance Optimized - Efficient re-renders and request deduplication
- 🔄 Real-time Support - Built-in subscriptions for real-time data
- 🔐 Authentication - Complete auth flow with session management
- 🧩 Extensible - Create custom adapters for any API
Installation
# Using npm
npm install @api-buddy/use-buddy @tanstack/react-query
# Using Yarn
yarn add @api-buddy/use-buddy @tanstack/react-query
# Using pnpm (recommended)
pnpm add @api-buddy/use-buddy @tanstack/react-queryQuick Start
1. Wrap your app with BuddiesProvider
import { BuddiesProvider } from '@api-buddy/use-buddy';
import { QueryClient } from '@tanstack/react-query';
// Initialize adapters (example with Firebase)
import { authAdapter, databaseAdapter } from './adapters';
function App() {
const queryClient = new QueryClient();
return (
<BuddiesProvider
initialAdapters={{
auth: authAdapter,
database: databaseAdapter,
}}
queryClient={queryClient}
onError={(error) => console.error('API Error:', error)}
>
<YourApp />
</BuddiesProvider>
);
}2. Use the provided hooks
Authentication
import { useAuthBuddy } from '@api-buddy/use-buddy';
function LoginForm() {
const { signIn, user, isAuthenticated, isLoading } = useAuthBuddy();
if (isLoading) return <div>Loading...</div>;
if (isAuthenticated) {
return <div>Welcome, {user?.email}!</div>;
}
return (
<button onClick={() => signIn({ email: '[email protected]', password: 'password' })}>
Sign In
</button>
);
}Data Fetching
import { useDatabaseBuddy } from '@api-buddy/use-buddy';
function TodoList() {
const { useCollection, useCreateDocument } = useDatabaseBuddy();
// Fetch todos
const { data: todos = [], isLoading } = useCollection('todos');
// Add new todo
const { mutate: addTodo } = useCreateDocument('todos');
if (isLoading) return <div>Loading...</div>;
return (
<div>
{todos.map(todo => (
<div key={todo.id}>{todo.title}</div>
))}
<button onClick={() => addTodo({ title: 'New Todo' })}>
Add Todo
</button>
</div>
);
}Core Concepts
Adapters
Adapters connect use-buddy to different services. The library comes with built-in adapters for common services, and you can create your own.
Available Adapters
- Auth Adapter: Handle authentication flows
- Database Adapter: CRUD operations and real-time subscriptions
- Storage Adapter: File uploads and downloads
Hooks
useAuthBuddy()
Handles authentication state and methods.
const {
// State
user, // Current user (null if not authenticated)
isAuthenticated, // Boolean auth state
isLoading, // Loading state
error, // Error object if any operation failed
// Methods
signIn, // (credentials) => Promise<AuthSession>
signOut, // () => Promise<void>
signUp, // (credentials) => Promise<AuthSession>
resetPassword, // (email: string) => Promise<void>
updateProfile, // (updates) => Promise<void>
refreshSession, // () => Promise<AuthSession>
} = useAuthBuddy();useDatabaseBuddy()
Provides database operations with React Query integration.
const {
// Queries
useCollection, // (collection, options?) => QueryResult<T[]>
useDocument, // (collection, id, options?) => QueryResult<T>
// Mutations
useCreateDocument, // (collection) => { mutate: (data) => void }
useUpdateDocument, // (collection) => { mutate: (id, updates) => void }
useDeleteDocument, // (collection) => { mutate: (id) => void }
// Real-time
useSubscribeToCollection, // (collection, callback, options?) => UnsubscribeFn
useSubscribeToDocument, // (collection, id, callback) => UnsubscribeFn
} = useDatabaseBuddy<T>();Advanced Usage
Custom Query Options
All data fetching hooks accept React Query options:
const { data } = useCollection('todos', {
// React Query options
staleTime: 1000 * 60 * 5, // 5 minutes
refetchOnWindowFocus: false,
// Adapter-specific options
where: [['status', '==', 'active']],
orderBy: [['createdAt', 'desc']],
limit: 10,
});Real-time Subscriptions
import { useEffect, useState } from 'react';
import { useDatabaseBuddy } from '@api-buddy/use-buddy';
function RealtimeMessages() {
const [messages, setMessages] = useState([]);
const { useSubscribeToCollection } = useDatabaseBuddy();
useEffect(() => {
const unsubscribe = useSubscribeToCollection(
'messages',
(newMessages) => setMessages(newMessages),
{
orderBy: [['createdAt', 'desc']],
limit: 50
}
);
return () => unsubscribe();
}, []);
return (
<div>
{messages.map(msg => (
<div key={msg.id}>{msg.text}</div>
))}
</div>
);
}Type Safety
Extend the global types to match your data models:
declare module '@api-buddy/types' {
interface UserProfile {
id: string;
email: string;
name?: string;
// Add custom user fields
}
interface DatabaseSchema {
todos: {
id: string;
title: string;
completed: boolean;
createdAt: Date;
};
// Add other collections
}
}API Reference
<BuddiesProvider>
The root provider component that must wrap your application.
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| initialAdapters | { auth?, database?, storage? } | Yes | Initial adapters to register |
| queryClient | QueryClient | No | Custom React Query client |
| onError | (error: Error) => void | No | Global error handler |
| loadingComponent | ReactNode | No | Component to show while initializing |
| enableDevtools | boolean | No | Enable React Query DevTools (default: process.env.NODE_ENV === 'development') |
useBuddy()
Hook to access the Buddies context.
const {
adapters,
isInitialized,
isInitializing,
error,
registerAdapter,
unregisterAdapter,
getAdapter,
} = useBuddy();Creating Custom Adapters
Adapters implement a specific interface to connect to different services. Here's a minimal example:
import { AuthAdapter } from '@api-buddy/types';
const customAuthAdapter: AuthAdapter = {
type: 'auth',
async signIn(credentials) {
// Your sign in logic
return { user: { id: '1', email: '[email protected]' }, accessToken: '...' };
},
async signOut() {
// Your sign out logic
},
async getSession() {
// Return current session or null
},
// Other required methods...
};Examples
Custom Query Hook
import { useDatabaseBuddy } from '@api-buddy/use-buddy';
export function useUserTodos(userId: string) {
const { useCollection } = useDatabaseBuddy();
return useCollection('todos', {
where: [['userId', '==', userId]],
orderBy: [['createdAt', 'desc']],
});
}Contributing
Contributions are welcome! Please see our contributing guidelines for more details.
License
MIT
