{"_id":"@api-buddy/use-buddy","_rev":"2-4759232685e8a47daa8fd79157fc268f","name":"@api-buddy/use-buddy","dist-tags":{"latest":"1.0.0"},"versions":{"0.1.0":{"name":"@api-buddy/use-buddy","version":"0.1.0","_id":"@api-buddy/use-buddy@0.1.0","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"dist":{"shasum":"2ce03b6c26203a6fc78d9b1f7d85c2bd97029c99","tarball":"https://registry.npmjs.org/@api-buddy/use-buddy/-/use-buddy-0.1.0.tgz","fileCount":35,"integrity":"sha512-Z89MxJlJZRS/ab5hljyx5evkgiDc5ATtbcuIQGpvEJfZCTW9NYm309WFuIi7ykOUuoSoydRWP0+8IUdrahTbBw==","signatures":[{"sig":"MEYCIQDWDAzFkYRwQ7x1dFm4/eCnVZ/Pr4Pz8AOaA1ad31QRDwIhAORLwhhQZU7mU8joqm9OCHNMkEPch+S66rLcbCHFQKlc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":347548},"main":"dist/index.js","type":"module","_from":"file:api-buddy-use-buddy-0.1.0.tgz","types":"dist/index.d.ts","module":"dist/index.mjs","scripts":{"dev":"tsup --watch","lint":"eslint src --ext .ts,.tsx","test":"vitest run","build":"pnpm run clean && pnpm run build:js","clean":"rm -rf dist","build:js":"tsup","typecheck":"tsc --noEmit","test:watch":"vitest","build:types":"tsc -p tsconfig.types.json"},"_npmUser":{"name":"iamtomhanks","actor":{"name":"iamtomhanks","type":"user","email":"brechanson@gmail.com"},"email":"brechanson@gmail.com"},"_resolved":"/private/var/folders/w3/00m0j5k95zjfx4vwz3csj_vc0000gn/T/9589d54320ba328d4d6c1cc994fb7629/api-buddy-use-buddy-0.1.0.tgz","_integrity":"sha512-Z89MxJlJZRS/ab5hljyx5evkgiDc5ATtbcuIQGpvEJfZCTW9NYm309WFuIi7ykOUuoSoydRWP0+8IUdrahTbBw==","_npmVersion":"9.8.1","description":"Core data fetching hooks for API Buddy","directories":{},"sideEffects":false,"_nodeVersion":"18.18.0","dependencies":{"zod":"^3.22.0","@api-buddy/types":"3.0.0","@tanstack/react-query":"^5.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.0.0","vitest":"^1.0.0","typescript":"^5.0.0","@types/jest":"^30.0.0","@types/node":"^24.0.4","@types/react":"^18.2.0","@api-buddy/types":"3.0.0","@types/react-dom":"^18.2.0","vite-tsconfig-paths":"^4.3.2","@api-buddy/tsup-config":"2.0.0","@testing-library/react":"^14.1.2","@testing-library/jest-dom":"^6.1.4","@testing-library/user-event":"^14.5.1","@tanstack/react-query-devtools":"^5.81.2"},"peerDependencies":{"react":">=18.0.0","react-dom":">=18.0.0","@api-buddy/types":"3.0.0","@tanstack/react-query":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/use-buddy_0.1.0_1751333410609_0.39703615932062886","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@api-buddy/use-buddy","version":"1.0.0","description":"Core data fetching hooks for API Buddy","main":"dist/index.js","module":"dist/index.mjs","types":"dist/index.d.ts","type":"module","sideEffects":false,"peerDependencies":{"@tanstack/react-query":"^5.0.0","react":">=18.0.0","react-dom":">=18.0.0","@api-buddy/types":"4.0.0"},"dependencies":{"@tanstack/react-query":"^5.0.0","zod":"^3.22.0","@api-buddy/types":"4.0.0"},"devDependencies":{"@tanstack/react-query-devtools":"^5.81.2","@testing-library/jest-dom":"^6.1.4","@testing-library/react":"^14.1.2","@testing-library/user-event":"^14.5.1","@types/jest":"^30.0.0","@types/node":"^24.0.4","@types/react":"^18.2.0","@types/react-dom":"^18.2.0","eslint":"^8.0.0","typescript":"^5.0.0","vite-tsconfig-paths":"^4.3.2","vitest":"^1.0.0","@api-buddy/tsup-config":"3.0.0","@api-buddy/types":"4.0.0"},"publishConfig":{"access":"public"},"scripts":{"build:js":"tsup","build:types":"tsc -p tsconfig.types.json","build":"pnpm run clean && pnpm run build:js","dev":"tsup --watch","clean":"rm -rf dist","typecheck":"tsc --noEmit","test":"vitest run","test:watch":"vitest","lint":"eslint src --ext .ts,.tsx"},"_id":"@api-buddy/use-buddy@1.0.0","_integrity":"sha512-ChR6HEY5pbjkN7r4LdmhNhYOjJDZo8IsswFSkSQrkTjH0AUUUK2UcCteiuILsxxopLYXLLUqFdMk5UivIUguFw==","_resolved":"/private/var/folders/w3/00m0j5k95zjfx4vwz3csj_vc0000gn/T/1fb54080b1aed4e48b92727189c7bb09/api-buddy-use-buddy-1.0.0.tgz","_from":"file:api-buddy-use-buddy-1.0.0.tgz","_nodeVersion":"18.18.0","_npmVersion":"9.8.1","dist":{"integrity":"sha512-ChR6HEY5pbjkN7r4LdmhNhYOjJDZo8IsswFSkSQrkTjH0AUUUK2UcCteiuILsxxopLYXLLUqFdMk5UivIUguFw==","shasum":"33bb7683eba098b40e66070bcc7edd202873f189","tarball":"https://registry.npmjs.org/@api-buddy/use-buddy/-/use-buddy-1.0.0.tgz","fileCount":35,"unpackedSize":347154,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQC+XNZ+U74qZj9nXhvGix1lY5EJTikH4cEJ62YIubLLLgIgSAmHuvphk2IcvJ77ZnktnHr6n/Bd3YD50KXQVh+aVW4="}]},"_npmUser":{"name":"iamtomhanks","email":"brechanson@gmail.com","actor":{"name":"iamtomhanks","email":"brechanson@gmail.com","type":"user"}},"directories":{},"maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/use-buddy_1.0.0_1751386898853_0.040208773105310236"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-01T01:30:10.515Z","modified":"2025-07-01T16:21:39.245Z","0.1.0":"2025-07-01T01:30:10.798Z","1.0.0":"2025-07-01T16:21:39.069Z"},"description":"Core data fetching hooks for API Buddy","maintainers":[{"name":"iamtomhanks","email":"brechanson@gmail.com"}],"readme":"# @api-buddy/use-buddy\n\nA powerful, type-safe React hooks library for managing API interactions, authentication, and data fetching. Part of the API Buddy ecosystem.\n\n## Features\n\n- 🔄 **React Query Integration** - Built on top of `@tanstack/react-query` for powerful data fetching and caching\n- 🔌 **Adapter-based Architecture** - Plug in different data sources (Auth, Database, Storage)\n- 🛠 **Type Safety** - Full TypeScript support with strict typing\n- ⚡ **Performance Optimized** - Efficient re-renders and request deduplication\n- 🔄 **Real-time Support** - Built-in subscriptions for real-time data\n- 🔐 **Authentication** - Complete auth flow with session management\n- 🧩 **Extensible** - Create custom adapters for any API\n\n## Installation\n\n```bash\n# Using npm\nnpm install @api-buddy/use-buddy @tanstack/react-query\n\n# Using Yarn\nyarn add @api-buddy/use-buddy @tanstack/react-query\n\n# Using pnpm (recommended)\npnpm add @api-buddy/use-buddy @tanstack/react-query\n```\n\n## Quick Start\n\n### 1. Wrap your app with BuddiesProvider\n\n```tsx\nimport { BuddiesProvider } from '@api-buddy/use-buddy';\nimport { QueryClient } from '@tanstack/react-query';\n\n// Initialize adapters (example with Firebase)\nimport { authAdapter, databaseAdapter } from './adapters';\n\nfunction App() {\n  const queryClient = new QueryClient();\n  \n  return (\n    <BuddiesProvider\n      initialAdapters={{\n        auth: authAdapter,\n        database: databaseAdapter,\n      }}\n      queryClient={queryClient}\n      onError={(error) => console.error('API Error:', error)}\n    >\n      <YourApp />\n    </BuddiesProvider>\n  );\n}\n```\n\n### 2. Use the provided hooks\n\n#### Authentication\n\n```tsx\nimport { useAuthBuddy } from '@api-buddy/use-buddy';\n\nfunction LoginForm() {\n  const { signIn, user, isAuthenticated, isLoading } = useAuthBuddy();\n  \n  if (isLoading) return <div>Loading...</div>;\n  \n  if (isAuthenticated) {\n    return <div>Welcome, {user?.email}!</div>;\n  }\n  \n  return (\n    <button onClick={() => signIn({ email: 'user@example.com', password: 'password' })}>\n      Sign In\n    </button>\n  );\n}\n```\n\n#### Data Fetching\n\n```tsx\nimport { useDatabaseBuddy } from '@api-buddy/use-buddy';\n\nfunction TodoList() {\n  const { useCollection, useCreateDocument } = useDatabaseBuddy();\n  \n  // Fetch todos\n  const { data: todos = [], isLoading } = useCollection('todos');\n  \n  // Add new todo\n  const { mutate: addTodo } = useCreateDocument('todos');\n  \n  if (isLoading) return <div>Loading...</div>;\n  \n  return (\n    <div>\n      {todos.map(todo => (\n        <div key={todo.id}>{todo.title}</div>\n      ))}\n      <button onClick={() => addTodo({ title: 'New Todo' })}>\n        Add Todo\n      </button>\n    </div>\n  );\n}\n```\n\n## Core Concepts\n\n### Adapters\n\nAdapters connect `use-buddy` to different services. The library comes with built-in adapters for common services, and you can create your own.\n\n#### Available Adapters\n\n- **Auth Adapter**: Handle authentication flows\n- **Database Adapter**: CRUD operations and real-time subscriptions\n- **Storage Adapter**: File uploads and downloads\n\n### Hooks\n\n#### useAuthBuddy()\n\nHandles authentication state and methods.\n\n```typescript\nconst {\n  // State\n  user,             // Current user (null if not authenticated)\n  isAuthenticated,  // Boolean auth state\n  isLoading,        // Loading state\n  error,            // Error object if any operation failed\n  \n  // Methods\n  signIn,           // (credentials) => Promise<AuthSession>\n  signOut,          // () => Promise<void>\n  signUp,           // (credentials) => Promise<AuthSession>\n  resetPassword,    // (email: string) => Promise<void>\n  updateProfile,    // (updates) => Promise<void>\n  refreshSession,   // () => Promise<AuthSession>\n} = useAuthBuddy();\n```\n\n#### useDatabaseBuddy()\n\nProvides database operations with React Query integration.\n\n```typescript\nconst {\n  // Queries\n  useCollection,     // (collection, options?) => QueryResult<T[]>\n  useDocument,       // (collection, id, options?) => QueryResult<T>\n  \n  // Mutations\n  useCreateDocument, // (collection) => { mutate: (data) => void }\n  useUpdateDocument, // (collection) => { mutate: (id, updates) => void }\n  useDeleteDocument, // (collection) => { mutate: (id) => void }\n  \n  // Real-time\n  useSubscribeToCollection, // (collection, callback, options?) => UnsubscribeFn\n  useSubscribeToDocument,   // (collection, id, callback) => UnsubscribeFn\n} = useDatabaseBuddy<T>();\n```\n\n## Advanced Usage\n\n### Custom Query Options\n\nAll data fetching hooks accept React Query options:\n\n```tsx\nconst { data } = useCollection('todos', {\n  // React Query options\n  staleTime: 1000 * 60 * 5, // 5 minutes\n  refetchOnWindowFocus: false,\n  \n  // Adapter-specific options\n  where: [['status', '==', 'active']],\n  orderBy: [['createdAt', 'desc']],\n  limit: 10,\n});\n```\n\n### Real-time Subscriptions\n\n```tsx\nimport { useEffect, useState } from 'react';\nimport { useDatabaseBuddy } from '@api-buddy/use-buddy';\n\nfunction RealtimeMessages() {\n  const [messages, setMessages] = useState([]);\n  const { useSubscribeToCollection } = useDatabaseBuddy();\n\n  useEffect(() => {\n    const unsubscribe = useSubscribeToCollection(\n      'messages',\n      (newMessages) => setMessages(newMessages),\n      { \n        orderBy: [['createdAt', 'desc']],\n        limit: 50 \n      }\n    );\n\n    return () => unsubscribe();\n  }, []);\n\n  return (\n    <div>\n      {messages.map(msg => (\n        <div key={msg.id}>{msg.text}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n## Type Safety\n\nExtend the global types to match your data models:\n\n```typescript\ndeclare module '@api-buddy/types' {\n  interface UserProfile {\n    id: string;\n    email: string;\n    name?: string;\n    // Add custom user fields\n  }\n  \n  interface DatabaseSchema {\n    todos: {\n      id: string;\n      title: string;\n      completed: boolean;\n      createdAt: Date;\n    };\n    // Add other collections\n  }\n}\n```\n\n## API Reference\n\n### `<BuddiesProvider>`\n\nThe root provider component that must wrap your application.\n\n| Prop | Type | Required | Description |\n|------|------|----------|-------------|\n| `initialAdapters` | `{ auth?, database?, storage? }` | Yes | Initial adapters to register |\n| `queryClient` | `QueryClient` | No | Custom React Query client |\n| `onError` | `(error: Error) => void` | No | Global error handler |\n| `loadingComponent` | `ReactNode` | No | Component to show while initializing |\n| `enableDevtools` | `boolean` | No | Enable React Query DevTools (default: `process.env.NODE_ENV === 'development'`) |\n\n### `useBuddy()`\n\nHook to access the Buddies context.\n\n```typescript\nconst {\n  adapters,\n  isInitialized,\n  isInitializing,\n  error,\n  registerAdapter,\n  unregisterAdapter,\n  getAdapter,\n} = useBuddy();\n```\n\n## Creating Custom Adapters\n\nAdapters implement a specific interface to connect to different services. Here's a minimal example:\n\n```typescript\nimport { AuthAdapter } from '@api-buddy/types';\n\nconst customAuthAdapter: AuthAdapter = {\n  type: 'auth',\n  \n  async signIn(credentials) {\n    // Your sign in logic\n    return { user: { id: '1', email: 'user@example.com' }, accessToken: '...' };\n  },\n  \n  async signOut() {\n    // Your sign out logic\n  },\n  \n  async getSession() {\n    // Return current session or null\n  },\n  \n  // Other required methods...\n};\n```\n\n## Examples\n\n### Custom Query Hook\n\n```typescript\nimport { useDatabaseBuddy } from '@api-buddy/use-buddy';\n\nexport function useUserTodos(userId: string) {\n  const { useCollection } = useDatabaseBuddy();\n  \n  return useCollection('todos', {\n    where: [['userId', '==', userId]],\n    orderBy: [['createdAt', 'desc']],\n  });\n}\n```\n\n## Contributing\n\nContributions are welcome! Please see our [contributing guidelines](CONTRIBUTING.md) for more details.\n\n## License\n\nMIT","readmeFilename":"README.md"}