{"_id":"@asaidimu/remote-store","_rev":"2-7915b0dac96f150fb203732b58dc4c91","name":"@asaidimu/remote-store","dist-tags":{"latest":"1.0.6"},"versions":{"1.0.4":{"name":"@asaidimu/remote-store","version":"1.0.4","keywords":["react-query","react","typescript"],"author":{"name":"Saidimu","email":"47994458+asaidimu@users.noreply.github.com"},"license":"MIT","_id":"@asaidimu/remote-store@1.0.4","maintainers":[{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"}],"homepage":"https://github.com/asaidimu/remote-store#readme","bugs":{"url":"https://github.com/asaidimu/remote-store/issues"},"dist":{"shasum":"ca23b742cd7d867d09e59c00cf1183e9cc9ac682","tarball":"https://registry.npmjs.org/@asaidimu/remote-store/-/remote-store-1.0.4.tgz","fileCount":5,"integrity":"sha512-R7WGqADwCI7h9kWEBwSv7emQKY8NHAW079AJ8TdpM8hNs5KF/eQW0FwdktIDqjk9kHK1zythdiGzGpfIBj7DlA==","signatures":[{"sig":"MEYCIQDggY+Cus/cBsnU1khk3zAlszypZI+ujj4bacNYrw6ENwIhAL22jNJmGsKBGDkviC5e4bWSSyK/vIm4Z5UAcF9mfkn/","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14315},"main":"index.js","type":"module","types":"index.d.ts","gitHead":"390a5fcf5d12f487869aea895657c4a947916fad","_npmUser":{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"},"repository":{"url":"git+https://github.com/asaidimu/remote-store.git","type":"git"},"_npmVersion":"10.9.2","description":"A custom React Hook for interacting with a remote data store.","directories":{},"_nodeVersion":"20.8.1","dependencies":{"@tanstack/react-query":"^5.63.0"},"publishConfig":{"tag":"latest","access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/remote-store_1.0.4_1736522695566_0.006043641918996201","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@asaidimu/remote-store","version":"1.0.5","keywords":["react-query","react","typescript"],"author":{"name":"Saidimu","email":"47994458+asaidimu@users.noreply.github.com"},"license":"MIT","_id":"@asaidimu/remote-store@1.0.5","maintainers":[{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"}],"homepage":"https://github.com/asaidimu/remote-store#readme","bugs":{"url":"https://github.com/asaidimu/remote-store/issues"},"dist":{"shasum":"1002568fa42c694a94c579b87d86ef5af632208d","tarball":"https://registry.npmjs.org/@asaidimu/remote-store/-/remote-store-1.0.5.tgz","fileCount":5,"integrity":"sha512-GM8+iWAJJXLi6X/VJ8UsYp/mgg/6fOeapUwNKHVEsvrJ+wr02nL2WlsfiHZ/X1TMilfxBdIzFXA1Y29hkTt0gA==","signatures":[{"sig":"MEUCIQC4ycsBfEo+rl19fs1ZNZ53MLYCAcrr8JOPXsf7529SrwIgcIbrCF+t0AHyzUxBfxbAVZm9gVMFVtak0iITDLa5+d0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14315},"main":"index.js","type":"module","types":"index.d.ts","gitHead":"5c1bd113d88ad3eb7a4ca7680e1de86ca7778301","_npmUser":{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"},"repository":{"url":"git+https://github.com/asaidimu/remote-store.git","type":"git"},"_npmVersion":"10.9.2","description":"A custom React Hook for interacting with a remote data store.","directories":{},"_nodeVersion":"20.8.1","dependencies":{"@tanstack/react-query":"^5.63.0"},"publishConfig":{"tag":"latest","access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/remote-store_1.0.5_1737185679402_0.00972153125985864","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@asaidimu/remote-store","version":"1.0.6","description":"A custom React Hook for interacting with a remote data store.","main":"index.js","types":"index.d.ts","type":"module","keywords":["react-query","react","typescript"],"author":{"name":"Saidimu","email":"47994458+asaidimu@users.noreply.github.com"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/asaidimu/remote-store.git"},"bugs":{"url":"https://github.com/asaidimu/remote-store/issues"},"homepage":"https://github.com/asaidimu/remote-store#readme","publishConfig":{"registry":"https://registry.npmjs.org/","tag":"latest","access":"public"},"dependencies":{"@tanstack/react-query":"^5.66.0"},"_id":"@asaidimu/remote-store@1.0.6","gitHead":"5388bb7bc976194a330a25fd6d28321f35962d3d","_nodeVersion":"20.8.1","_npmVersion":"10.9.2","dist":{"integrity":"sha512-nX+N/RAn5e1Ot9qRbPsJO8DAuNU2qecMcjEXwL5zDAjgvKVOZf2NndTGNMpN0WATSTAxbpIYwqPBzOglCTWSYg==","shasum":"6b08b17fe28e691de7acbf4ee9460f079c909863","tarball":"https://registry.npmjs.org/@asaidimu/remote-store/-/remote-store-1.0.6.tgz","fileCount":5,"unpackedSize":14315,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDGFn3Kub9uKYq6aFBkdjtvg0KlibHjG5I1cHwMJlMDeQIgGJyOPZU6BIkfjqCiQkwryjQerkOpSQi7tvbNl0r/a6c="}]},"_npmUser":{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"},"directories":{},"maintainers":[{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/remote-store_1.0.6_1738489618225_0.16785168876143186"},"_hasShrinkwrap":false}},"time":{"created":"2025-01-10T15:24:55.439Z","modified":"2025-02-02T09:46:58.595Z","1.0.4":"2025-01-10T15:24:55.810Z","1.0.5":"2025-01-18T07:34:39.583Z","1.0.6":"2025-02-02T09:46:58.415Z"},"bugs":{"url":"https://github.com/asaidimu/remote-store/issues"},"author":{"name":"Saidimu","email":"47994458+asaidimu@users.noreply.github.com"},"license":"MIT","homepage":"https://github.com/asaidimu/remote-store#readme","keywords":["react-query","react","typescript"],"repository":{"type":"git","url":"git+https://github.com/asaidimu/remote-store.git"},"description":"A custom React Hook for interacting with a remote data store.","maintainers":[{"name":"asaidimu","email":"lolokilesaidimu@gmail.com"}],"readme":"# @asaidimu/remote-store\n\nA lightweight, type-safe remote data store for React applications with React Query integration.\n\n## Features\n\n- 🔒 Type-safe data operations\n- 🔄 Built-in React Query integration\n- 🎣 Simple hooks-based API\n- 🔌 Extensible adapter system\n- 📦 Zero config setup\n- 🎯 Focused mutations API\n\n## Installation\n\n```bash\nnpm install @asaidimu/remote-store @tanstack/react-query\n# or\nyarn add @asaidimu/remote-store @tanstack/react-query\n# or\nbun add @asaidimu/remote-store @tanstack/react-query\n# or\npnpm add @asaidimu/remote-store @tanstack/react-query\n```\n\n## Quick Start\n\n1. Create your store adapter:\n\n```typescript\n// adapters/rest.adapter.ts\nimport { BaseStore, RemoteStoreRecord } from '@asaidimu/remote-store';\n\nexport class RestAdapter<T extends RemoteStoreRecord> implements BaseStore<T> {\n  constructor(private baseUrl: string) {}\n\n  async find({ filter }: { filter: string }) {\n    const response = await fetch(`${this.baseUrl}?filter=${filter}`);\n    return response.json();\n  }\n\n  async read({ id }: { id: string }) {\n    const response = await fetch(`${this.baseUrl}/${id}`);\n    return response.json();\n  }\n\n  async list({ filter = '', page = 1, pageSize = 10 }) {\n    const response = await fetch(\n      `${this.baseUrl}?filter=${filter}&page=${page}&pageSize=${pageSize}`\n    );\n    return response.json();\n  }\n\n  async create({ data }: { data: Omit<T, 'id'> }) {\n    const response = await fetch(this.baseUrl, {\n      method: 'POST',\n      body: JSON.stringify(data),\n    });\n    return response.json();\n  }\n\n  async update({ id, data }: { id: string; data: Partial<T> }) {\n    const response = await fetch(`${this.baseUrl}/${id}`, {\n      method: 'PATCH',\n      body: JSON.stringify(data),\n    });\n    return response.json();\n  }\n\n  async delete({ id }: { id: string }) {\n    await fetch(`${this.baseUrl}/${id}`, { method: 'DELETE' });\n  }\n\n  async upload({ id, field, file }: { id: string; field: string; file: File }) {\n    const formData = new FormData();\n    formData.append(field, file);\n    \n    const response = await fetch(`${this.baseUrl}/${id}/upload`, {\n      method: 'POST',\n      body: formData,\n    });\n    return response.json();\n  }\n}\n```\n\n2. Create your store:\n\n```typescript\n// stores/user.store.ts\nimport { useRemoteStore } from '@asaidimu/remote-store';\nimport { RestAdapter } from '../adapters/rest.adapter';\nimport { useQueryClient } from '@tanstack/react-query';\n\ninterface User {\n  id: string;\n  name: string;\n  email: string;\n  avatar?: string;\n}\n\nexport function useUserStore() {\n  const queryClient = useQueryClient();\n  const adapter = new RestAdapter<User>('https://api.example.com/users');\n  \n  return useRemoteStore({\n    store: adapter,\n    queryClient,\n  })('users');\n}\n```\n\n3. Use in your components:\n\n```typescript\n// components/UserList.tsx\nimport { useUserStore } from '../stores/user.store';\n\nexport function UserList() {\n  const store = useUserStore();\n  \n  // Setup mutations\n  const createUser = store.create({\n    onSuccess: (user) => console.log('Created:', user),\n    onError: (error) => console.error('Failed:', error)\n  });\n  \n  const updateUser = store.update({\n    onSuccess: (user) => console.log('Updated:', user)\n  });\n  \n  // Query data\n  const { data: users, isLoading } = store.list({\n    pageSize: 20\n  });\n  \n  if (isLoading) return <div>Loading...</div>;\n  \n  return (\n    <div>\n      {users?.map(user => (\n        <div key={user.id}>\n          {user.name}\n          <button onClick={() => updateUser(user.id, { name: 'New Name' })}>\n            Update\n          </button>\n        </div>\n      ))}\n      \n      <button onClick={() => createUser({ \n        name: 'New User',\n        email: 'new@example.com'\n      })}>\n        Add User\n      </button>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### `useRemoteStore`\n\nMain hook for creating a store instance.\n\n```typescript\nfunction useRemoteStore<R extends RemoteStoreRecord>({\n  store: BaseStore<R>,\n  queryClient: QueryClient\n}): (collection: string) => Store<R>\n```\n\n### Store Methods\n\n#### Queries\n\n- `find({ filter, options? })` - Find a single record by filter\n- `read({ id, options? })` - Read a single record by ID\n- `list({ filter?, page?, pageSize?, options? })` - List multiple records\n\n#### Mutations\n\n- `create(callbacks?) => (data) => void` - Create a new record\n- `update(callbacks?) => (id, data) => void` - Update an existing record\n- `delete(callbacks?) => (id) => void` - Delete a record\n- `upload(callbacks?) => (id, field, file) => void` - Upload a file\n\n### Types\n\n#### `RemoteStoreRecord`\n```typescript\ninterface RemoteStoreRecord {\n  readonly id: string;\n  [key: string]: unknown;\n}\n```\n\n#### `BaseStore`\n```typescript\ninterface BaseStore<T extends RemoteStoreRecord> {\n  readonly find: (props: { filter: string; options?: QueryOptions }) => Promise<T>;\n  readonly read: (props: { id: string; options?: QueryOptions }) => Promise<T>;\n  readonly list: (props: ListOptions) => Promise<T[]>;\n  readonly update: (props: { id: string; data: Partial<T> }) => Promise<T>;\n  readonly delete: (props: { id: string }) => Promise<void>;\n  readonly create: (props: { data: Omit<T, 'id'> }) => Promise<T>;\n  readonly upload: (props: { id: string; field: string; file: File }) => Promise<T>;\n}\n```\n\n## Creating Adapters\n\nYou can create adapters for any data source by implementing the `BaseStore` interface. Here are some examples:\n\n### Firebase Adapter\n\n```typescript\nimport { BaseStore, RemoteStoreRecord } from '@asaidimu/remote-store';\nimport { collection, doc, getDoc, getDocs, query, where } from 'firebase/firestore';\n\nexport class FirebaseAdapter<T extends RemoteStoreRecord> implements BaseStore<T> {\n  constructor(\n    private db: Firestore,\n    private collectionName: string\n  ) {}\n\n  async find({ filter }) {\n    const q = query(\n      collection(this.db, this.collectionName),\n      where('field', '==', filter)\n    );\n    const snapshot = await getDocs(q);\n    return snapshot.docs[0].data() as T;\n  }\n\n  async read({ id }) {\n    const docRef = doc(this.db, this.collectionName, id);\n    const snapshot = await getDoc(docRef);\n    return snapshot.data() as T;\n  }\n\n  // ... implement other methods\n}\n```\n\n### Supabase Adapter\n\n```typescript\nimport { BaseStore, RemoteStoreRecord } from '@asaidimu/remote-store';\nimport { SupabaseClient } from '@supabase/supabase-js';\n\nexport class SupabaseAdapter<T extends RemoteStoreRecord> implements BaseStore<T> {\n  constructor(\n    private supabase: SupabaseClient,\n    private tableName: string\n  ) {}\n\n  async find({ filter }) {\n    const { data, error } = await this.supabase\n      .from(this.tableName)\n      .select()\n      .match(filter)\n      .single();\n      \n    if (error) throw error;\n    return data;\n  }\n\n  async create({ data }) {\n    const { data: created, error } = await this.supabase\n      .from(this.tableName)\n      .insert(data)\n      .single();\n      \n    if (error) throw error;\n    return created;\n  }\n\n  // ... implement other methods\n}\n```\n## Contributing\n\nWe welcome contributions! Please see our contributing guide for details.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}