An open API service indexing awesome lists of open source software.

https://github.com/peterferguson/hono-rq

A zero-overhead React Query integration for Hono RPC clients with full type safety.
https://github.com/peterferguson/hono-rq

hono honojs react-query tanstack-react-query

Last synced: 10 months ago
JSON representation

A zero-overhead React Query integration for Hono RPC clients with full type safety.

Awesome Lists containing this project

README

          

# hono-rq

[![npm version](https://badge.fury.io/js/hono-rq.svg)](https://badge.fury.io/js/hono-rq)
[![MIT License](https://img.shields.io/badge/License-MIT-green.svg)](https://choosealicense.com/licenses/mit/)
[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript-%230074c1.svg)](http://www.typescriptlang.org/)

A zero-overhead React Query integration for [Hono](https://hono.dev/) RPC clients with full type safety.

## Features

- ๐Ÿ”’ **Full Type Safety** - Preserves all Hono RPC types end-to-end
- ๐Ÿš€ **Zero Runtime Overhead** - Minimal proxy-based implementation
- โšก **React Query Integration** - Generate `queryOptions`, `infiniteQueryOptions`, and `mutationOptions`
- ๐ŸŽฏ **Smart Query Keys** - Automatic, stable query key generation based on endpoint and parameters
- ๐ŸŒŸ **Developer Experience** - IntelliSense support with autocomplete for all endpoints
- ๐Ÿงช **Well Tested** - Comprehensive test coverage including browser and integration tests
- ๐Ÿ“ฆ **Tree Shakable** - Only bundle what you use

## Installation

```bash
npm install hono-rq @tanstack/react-query hono
```

```bash
pnpm add hono-rq @tanstack/react-query hono
```

```bash
yarn add hono-rq @tanstack/react-query hono
```

```bash
bun add hono-rq @tanstack/react-query hono
```

## Quick Start

### 1. Extend your Hono client

```typescript
import { extend } from 'hono-rq';
import { hc } from 'hono/client';
import type { AppType } from './server'; // Your Hono app type

const client = hc('http://localhost:3000');
const extendedClient = extend(client);
```

### 2. Use with React Query

```tsx
import { useQuery, useMutation } from '@tanstack/react-query';

function UsersList() {
// Generate query options for GET requests
const queryOptions = extendedClient.users.$get.queryOptions();
const { data, isLoading, error } = useQuery(queryOptions);

// Generate mutation options for POST requests
const mutationOptions = extendedClient.users.$post.mutationOptions();
const createUser = useMutation(mutationOptions);

if (isLoading) return

Loading...
;
if (error) return
Error: {error.message}
;

return (


{data?.users.map(user => (
{user.name}

))}
createUser.mutate({
json: { name: 'New User', email: 'user@example.com' }
})}
>
Add User


);
}
```

## API Reference

### `extend(client)`

Extends a Hono RPC client with React Query integration methods.

```typescript
import { extend } from 'hono-rq';

const extendedClient = extend(client);
```

**Parameters:**
- `client` - Any Hono RPC client created with `hc()`

**Returns:**
- Extended client with React Query methods added to each endpoint

### Query Options

Generate React Query options for GET endpoints:

```typescript
// Basic usage
const queryOptions = extendedClient.users.$get.queryOptions();

// With parameters
const queryOptions = extendedClient.users[':id'].$get.queryOptions({
param: { id: '123' }
});

// With query parameters
const queryOptions = extendedClient.users.$get.queryOptions({
query: { limit: '10', offset: '0' }
});

// With React Query options
const queryOptions = extendedClient.users.$get.queryOptions(
{ query: { limit: '10' } },
{
enabled: true,
staleTime: 5000,
retry: 3
}
);
```

### Infinite Query Options

Generate options for paginated data with React Query's infinite queries:

```typescript
const infiniteQueryOptions = extendedClient.posts.$get.infiniteQueryOptions(
(pageParam) => ({
query: {
page: pageParam?.toString() ?? '1',
limit: '10'
}
}),
{
initialPageParam: 1,
getNextPageParam: (lastPage, pages) =>
lastPage.hasMore ? pages.length + 1 : undefined,
}
);

const {
data,
fetchNextPage,
hasNextPage,
isLoading
} = useInfiniteQuery(infiniteQueryOptions);
```

### Mutation Options

Generate options for POST, PUT, PATCH, DELETE endpoints:

```typescript
// Basic mutation
const mutationOptions = extendedClient.users.$post.mutationOptions();

// With React Query options
const mutationOptions = extendedClient.users[':id'].$patch.mutationOptions(
undefined,
{
onSuccess: (data) => {
console.log('User updated:', data);
},
onError: (error) => {
console.error('Update failed:', error);
}
}
);

const mutation = useMutation(mutationOptions);
```

## TypeScript

hono-rq is built with TypeScript and provides full type safety:

```typescript
// All types are preserved from your Hono app
type UsersResponse = InferResponseType;
type CreateUserRequest = InferRequestType;

// Query options have correct types
const queryOptions = extendedClient.users.$get.queryOptions();
// queryOptions.queryFn return type matches your Hono endpoint

// Mutations are fully typed
const mutation = useMutation(
extendedClient.users.$post.mutationOptions()
);
// mutation.mutate() expects the correct request type
```

## Advanced Usage

### Error Handling

```typescript
const queryOptions = extendedClient.users.$get.queryOptions(undefined, {
retry: (failureCount, error) => {
// Custom retry logic
if (error.status === 404) return false;
return failureCount < 3;
},
onError: (error) => {
console.error('Query failed:', error);
}
});
```

## Examples

### Complete CRUD Example

```tsx
import { extend } from 'hono-rq';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';

const extendedClient = extend(client);

function UserManager() {
const queryClient = useQueryClient();

// List users
const usersQuery = useQuery(
extendedClient.users.$get.queryOptions()
);

// Get single user
const userQuery = useQuery(
extendedClient.users[':id'].$get.queryOptions({
param: { id: selectedUserId }
}, {
enabled: !!selectedUserId
})
);

// Create user
const createUser = useMutation(
extendedClient.users.$post.mutationOptions(undefined, {
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: extendedClient.users.$get.queryOptions().queryKey
});
}
})
);

// Update user
const updateUser = useMutation(
extendedClient.users[':id'].$patch.mutationOptions(undefined, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] });
}
})
);

// Delete user
const deleteUser = useMutation(
extendedClient.users[':id'].$delete.mutationOptions(undefined, {
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['users'] });
}
})
);

return (


{/* Your UI here */}

);
}
```

## Requirements

- **Node.js**: 18+
- **React**: 18+
- **@tanstack/react-query**: 5.0+
- **hono**: 4.0+
- **TypeScript**: 5.0+ (recommended)

## Contributing

We welcome contributions! Please see our [Contributing Guide](https://github.com/peterferguson/hono-rq/blob/main/CONTRIBUTING.md) for details.

## License

MIT ยฉ [Peter Ferguson](https://github.com/peterferguson)

## Related Projects

- [Hono](https://hono.dev/) - Ultrafast web framework for the Edges
- [TanStack Query](https://tanstack.com/query) - Powerful data synchronization for web applications
- [tRPC](https://trpc.io/) - End-to-end typesafe APIs made easy