Skip to main content

Overview

The QueryOperations class provides a lightweight, fluent API for building type-safe queries and mutations.

Creating QueryOperations

import { createQueryOperations } from '@codeleap/query'

const userOperations = createQueryOperations({ queryClient })
.query('getUser', async (id: string) => {
const response = await api.get(`/users/${id}`)
return response.data
})
.query('getUsers', async (filters?: UserFilters) => {
const response = await api.get('/users', { params: filters })
return response.data
})
.mutation('createUser', async (data: Omit<User, 'id'>) => {
const response = await api.post('/users', data)
return response.data
})
.mutation('updateUser', async (data: Partial<User> & { id: string }) => {
const response = await api.put(`/users/${data.id}`, data)
return response.data
})
.mutation('deleteUser', async (id: string) => {
await api.delete(`/users/${id}`)
return id
})

Using QueryOperations Hooks

Queries

function UserProfile({ userId }: { userId: string }) {
// Type-safe query with automatic parameter and return type inference
const userQuery = userOperations.useQuery('getUser', userId, {
enabled: !!userId,
staleTime: 5 * 60 * 1000
})

const usersQuery = userOperations.useQuery('getUsers',
{ status: 'active' },
{
refetchInterval: 30 * 1000
}
)

if (userQuery.isLoading) return <div>Loading...</div>
if (userQuery.error) return <div>Error: {userQuery.error.message}</div>

return (
<div>
<h1>{userQuery.data?.name}</h1>
<p>Total active users: {usersQuery.data?.length}</p>
</div>
)
}

Mutations

function UserForm() {
const createMutation = userOperations.useMutation('createUser', {
onSuccess: (newUser) => {
// 'newUser' is automatically typed
toast.success(`Created user: ${newUser.name}`)

// Invalidate related queries
queryClient.invalidateQueries({ queryKey: ['getUsers'] })
}
})

const updateMutation = userOperations.useMutation('updateUser')
const deleteMutation = userOperations.useMutation('deleteUser')

const handleCreate = (userData: Omit<User, 'id'>) => {
// Parameters are type-checked
createMutation.mutate(userData)
}

return (
<form onSubmit={(e) => {
e.preventDefault()
handleCreate({
name: 'John Doe',
email: 'john@example.com',
status: 'active',
createdAt: new Date().toISOString()
})
}}>
{/* Form fields */}
<button
type="submit"
disabled={createMutation.isPending}
>
Create User
</button>
</form>
)
}

Prefetching and Cache Access

// Prefetch data
await userOperations.prefetchQuery('getUser', 'user-123', {
staleTime: 10 * 60 * 1000
})

// Get cached data
const cachedUser = await userOperations.getQueryData('getUser', 'user-123')
if (cachedUser) {
console.log('User already in cache:', cachedUser.name)
}

// Access operations
const { queries, mutations } = userOperations
console.log('Available queries:', Object.keys(queries))
console.log('Available mutations:', Object.keys(mutations))