npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-query for 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-query

Quick 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