{"id":30990322,"url":"https://github.com/peterferguson/hono-rq","last_synced_at":"2025-09-14T22:06:38.417Z","repository":{"id":314206661,"uuid":"1052537861","full_name":"peterferguson/hono-rq","owner":"peterferguson","description":"A zero-overhead React Query integration for Hono RPC clients with full type safety.","archived":false,"fork":false,"pushed_at":"2025-09-09T12:11:59.000Z","size":360,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-11T07:32:43.154Z","etag":null,"topics":["hono","honojs","react-query","tanstack-react-query"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/hono-rq","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/peterferguson.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-08T07:38:19.000Z","updated_at":"2025-09-09T12:17:00.000Z","dependencies_parsed_at":"2025-09-11T07:32:53.587Z","dependency_job_id":"e8d7bc32-2dbe-4afd-aff4-91ab5b88dc14","html_url":"https://github.com/peterferguson/hono-rq","commit_stats":null,"previous_names":["peterferguson/hono-rq"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/peterferguson/hono-rq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peterferguson%2Fhono-rq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peterferguson%2Fhono-rq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peterferguson%2Fhono-rq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peterferguson%2Fhono-rq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/peterferguson","download_url":"https://codeload.github.com/peterferguson/hono-rq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/peterferguson%2Fhono-rq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274863474,"owners_count":25364223,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-12T02:00:09.324Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hono","honojs","react-query","tanstack-react-query"],"created_at":"2025-09-12T19:08:38.864Z","updated_at":"2025-09-12T19:08:41.239Z","avatar_url":"https://github.com/peterferguson.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# hono-rq\n\n[![npm version](https://badge.fury.io/js/hono-rq.svg)](https://badge.fury.io/js/hono-rq)\n[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)\n[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)\n\nA zero-overhead React Query integration for [Hono](https://hono.dev/) RPC clients with full type safety.\n\n## Features\n\n- 🔒 **Full Type Safety** - Preserves all Hono RPC types end-to-end\n- 🚀 **Zero Runtime Overhead** - Minimal proxy-based implementation\n- ⚡ **React Query Integration** - Generate `queryOptions`, `infiniteQueryOptions`, and `mutationOptions` \n- 🎯 **Smart Query Keys** - Automatic, stable query key generation based on endpoint and parameters\n- 🌟 **Developer Experience** - IntelliSense support with autocomplete for all endpoints\n- 🧪 **Well Tested** - Comprehensive test coverage including browser and integration tests\n- 📦 **Tree Shakable** - Only bundle what you use\n\n## Installation\n\n```bash\nnpm install hono-rq @tanstack/react-query hono\n```\n\n```bash\npnpm add hono-rq @tanstack/react-query hono\n```\n\n```bash\nyarn add hono-rq @tanstack/react-query hono\n```\n\n```bash\nbun add hono-rq @tanstack/react-query hono\n```\n\n## Quick Start\n\n### 1. Extend your Hono client\n\n```typescript\nimport { extend } from 'hono-rq';\nimport { hc } from 'hono/client';\nimport type { AppType } from './server'; // Your Hono app type\n\nconst client = hc\u003cAppType\u003e('http://localhost:3000');\nconst extendedClient = extend(client);\n```\n\n### 2. Use with React Query\n\n```tsx\nimport { useQuery, useMutation } from '@tanstack/react-query';\n\nfunction UsersList() {\n  // Generate query options for GET requests\n  const queryOptions = extendedClient.users.$get.queryOptions();\n  const { data, isLoading, error } = useQuery(queryOptions);\n\n  // Generate mutation options for POST requests  \n  const mutationOptions = extendedClient.users.$post.mutationOptions();\n  const createUser = useMutation(mutationOptions);\n\n  if (isLoading) return \u003cdiv\u003eLoading...\u003c/div\u003e;\n  if (error) return \u003cdiv\u003eError: {error.message}\u003c/div\u003e;\n\n  return (\n    \u003cdiv\u003e\n      {data?.users.map(user =\u003e (\n        \u003cdiv key={user.id}\u003e{user.name}\u003c/div\u003e\n      ))}\n      \u003cbutton\n        onClick={() =\u003e createUser.mutate({ \n          json: { name: 'New User', email: 'user@example.com' }\n        })}\n      \u003e\n        Add User\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n```\n\n## API Reference\n\n### `extend(client)`\n\nExtends a Hono RPC client with React Query integration methods.\n\n```typescript\nimport { extend } from 'hono-rq';\n\nconst extendedClient = extend(client);\n```\n\n**Parameters:**\n- `client` - Any Hono RPC client created with `hc\u003cAppType\u003e()`\n\n**Returns:**\n- Extended client with React Query methods added to each endpoint\n\n### Query Options\n\nGenerate React Query options for GET endpoints:\n\n```typescript\n// Basic usage\nconst queryOptions = extendedClient.users.$get.queryOptions();\n\n// With parameters\nconst queryOptions = extendedClient.users[':id'].$get.queryOptions({\n  param: { id: '123' }\n});\n\n// With query parameters\nconst queryOptions = extendedClient.users.$get.queryOptions({\n  query: { limit: '10', offset: '0' }\n});\n\n// With React Query options\nconst queryOptions = extendedClient.users.$get.queryOptions(\n  { query: { limit: '10' } },\n  { \n    enabled: true,\n    staleTime: 5000,\n    retry: 3 \n  }\n);\n```\n\n### Infinite Query Options\n\nGenerate options for paginated data with React Query's infinite queries:\n\n```typescript\nconst infiniteQueryOptions = extendedClient.posts.$get.infiniteQueryOptions(\n  (pageParam) =\u003e ({\n    query: { \n      page: pageParam?.toString() ?? '1',\n      limit: '10' \n    }\n  }),\n  {\n    initialPageParam: 1,\n    getNextPageParam: (lastPage, pages) =\u003e \n      lastPage.hasMore ? pages.length + 1 : undefined,\n  }\n);\n\nconst { \n  data, \n  fetchNextPage, \n  hasNextPage, \n  isLoading \n} = useInfiniteQuery(infiniteQueryOptions);\n```\n\n### Mutation Options\n\nGenerate options for POST, PUT, PATCH, DELETE endpoints:\n\n```typescript\n// Basic mutation\nconst mutationOptions = extendedClient.users.$post.mutationOptions();\n\n// With React Query options\nconst mutationOptions = extendedClient.users[':id'].$patch.mutationOptions(\n  undefined,\n  {\n    onSuccess: (data) =\u003e {\n      console.log('User updated:', data);\n    },\n    onError: (error) =\u003e {\n      console.error('Update failed:', error);\n    }\n  }\n);\n\nconst mutation = useMutation(mutationOptions);\n```\n\n## TypeScript\n\nhono-rq is built with TypeScript and provides full type safety:\n\n```typescript\n// All types are preserved from your Hono app\ntype UsersResponse = InferResponseType\u003ctypeof extendedClient.users.$get\u003e;\ntype CreateUserRequest = InferRequestType\u003ctypeof extendedClient.users.$post\u003e;\n\n// Query options have correct types\nconst queryOptions = extendedClient.users.$get.queryOptions();\n// queryOptions.queryFn return type matches your Hono endpoint\n\n// Mutations are fully typed  \nconst mutation = useMutation(\n  extendedClient.users.$post.mutationOptions()\n);\n// mutation.mutate() expects the correct request type\n```\n\n## Advanced Usage\n\n### Error Handling\n\n```typescript\nconst queryOptions = extendedClient.users.$get.queryOptions(undefined, {\n  retry: (failureCount, error) =\u003e {\n    // Custom retry logic\n    if (error.status === 404) return false;\n    return failureCount \u003c 3;\n  },\n  onError: (error) =\u003e {\n    console.error('Query failed:', error);\n  }\n});\n```\n\n## Examples\n\n### Complete CRUD Example\n\n```tsx\nimport { extend } from 'hono-rq';\nimport { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';\n\nconst extendedClient = extend(client);\n\nfunction UserManager() {\n  const queryClient = useQueryClient();\n\n  // List users\n  const usersQuery = useQuery(\n    extendedClient.users.$get.queryOptions()\n  );\n\n  // Get single user\n  const userQuery = useQuery(\n    extendedClient.users[':id'].$get.queryOptions({\n      param: { id: selectedUserId }\n    }, {\n      enabled: !!selectedUserId\n    })\n  );\n\n  // Create user\n  const createUser = useMutation(\n    extendedClient.users.$post.mutationOptions(undefined, {\n      onSuccess: () =\u003e {\n        queryClient.invalidateQueries({ \n          queryKey: extendedClient.users.$get.queryOptions().queryKey \n        });\n      }\n    })\n  );\n\n  // Update user\n  const updateUser = useMutation(\n    extendedClient.users[':id'].$patch.mutationOptions(undefined, {\n      onSuccess: () =\u003e {\n        queryClient.invalidateQueries({ queryKey: ['users'] });\n      }\n    })\n  );\n\n  // Delete user\n  const deleteUser = useMutation(\n    extendedClient.users[':id'].$delete.mutationOptions(undefined, {\n      onSuccess: () =\u003e {\n        queryClient.invalidateQueries({ queryKey: ['users'] });\n      }\n    })\n  );\n\n  return (\n    \u003cdiv\u003e\n      {/* Your UI here */}\n    \u003c/div\u003e\n  );\n}\n```\n\n## Requirements\n\n- **Node.js**: 18+ \n- **React**: 18+\n- **@tanstack/react-query**: 5.0+\n- **hono**: 4.0+\n- **TypeScript**: 5.0+ (recommended)\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](https://github.com/peterferguson/hono-rq/blob/main/CONTRIBUTING.md) for details.\n\n## License\n\nMIT © [Peter Ferguson](https://github.com/peterferguson)\n\n## Related Projects\n\n- [Hono](https://hono.dev/) - Ultrafast web framework for the Edges\n- [TanStack Query](https://tanstack.com/query) - Powerful data synchronization for web applications\n- [tRPC](https://trpc.io/) - End-to-end typesafe APIs made easy\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeterferguson%2Fhono-rq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeterferguson%2Fhono-rq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeterferguson%2Fhono-rq/lists"}