TanStack Query integration for CQRS commands and queries
npm install @leancodepl/react-query-cqrs-clientTanStack Query CQRS client with hooks for queries, operations, and commands.
- TanStack Query integration - Built-in caching, optimistic updates, and background refetching
- CQRS pattern - Separate queries, commands, and operations with proper typing
- Custom hooks - Hook factories for all operation types with loading states
- Error handling - Validation errors with custom error codes and handlers
- Authentication - Token handling with automatic refresh integration
- Cache management - Smart invalidation and query dependency management
``bash`
npm install @leancodepl/react-query-cqrs-clientor
yarn add @leancodepl/react-query-cqrs-client
Creates TanStack Query CQRS client with hooks for queries, operations, and commands.
Parameters:
- cqrsEndpoint: string - Base URL for CQRS API endpointsqueryClient: QueryClient
- - TanStack Query client instancetokenProvider?: Partial
- - Optional token provider for authenticationajaxOptions?: Omit
- - Optional RxJS Ajax configuration optionstokenHeader?: string
- - Header name for authentication token (default: "Authorization")
Returns: Object with createQuery, createOperation, and createCommand hook factories
`typescript
import { mkCqrsClient } from "@leancodepl/react-query-cqrs-client"
import { QueryClient } from "@tanstack/react-query"
const queryClient = new QueryClient()
const client = mkCqrsClient({
cqrsEndpoint: "https://api.example.com",
queryClient,
tokenProvider: {
getToken: () => Promise.resolve(localStorage.getItem("token")),
},
})
`
`typescript
import React from 'react';
interface GetUserQuery {
userId: string;
}
interface UserResult {
id: string;
name: string;
email: string;
}
const useGetUser = client.createQuery
function UserProfile({ userId }: { userId: string }) {
const { data, isLoading, error } = useGetUser({ userId });
if (isLoading) return
return (
{data?.email}
$3
`typescript
import React from 'react';interface CreateUserCommand {
name: string;
email: string;
}
const errorCodes = { EmailExists: 1, InvalidEmail: 2 } as const;
const useCreateUser = client.createCommand('CreateUser', errorCodes);
function CreateUserForm() {
const { mutate: createUser, isPending } = useCreateUser({
handler: (handle) =>
handle('success', () => 'User created successfully')
.handle('EmailExists', () => 'Email already exists')
.handle('failure', () => 'Failed to create user')
.check(),
});
const handleSubmit = () => {
createUser({ name: 'John', email: 'john@example.com' });
};
return (
);
}
`$3
`typescript
interface UploadFileOperation {
file: File;
folder: string;
}interface UploadResult {
url: string;
filename: string;
}
const useUploadFile = client.createOperation('UploadFile');
function FileUploader() {
const { mutate: uploadFile, isPending } = useUploadFile({
invalidateQueries: [['GetFiles']],
});
const handleUpload = (file: File) => {
uploadFile({ file, folder: 'documents' });
};
return (
type="file"
onChange={(e) => e.target.files?.[0] && handleUpload(e.target.files[0])}
disabled={isPending}
/>
);
}
``