Core Concepts
The Dual Interface
Section titled “The Dual Interface”Every Chimeric operation has two execution paths:
| Path | How you call it | When to use it |
|---|---|---|
| Idiomatic | getTodos({ limit: 10 }) | Orchestration, tests, scripts, server-side |
| Reactive | getTodos.useHook({ limit: 10 }) | Inside React components |
Both paths share the same TypeScript types, so refactoring between them is safe and mechanical.
Operation Types
Section titled “Operation Types”Chimeric defines six operation types, each designed for a different kind of work:
Synchronous operations that return a value immediately. Useful for reading from a state store.
// Idiomatic: reads directly from the storeconst todo = getTodoById({ id: '123' });
// Reactive: subscribes to store changes via a hookconst todo = getTodoById.useHook({ id: '123' });Asynchronous operations with manual invocation. The reactive path provides an invoke function and tracks loading state. Useful when dealing with promises and caching is not necessary.
// Idiomaticconst user = await fetchUser({ id: '123' });
// Reactiveconst { invoke, data, isPending, isError, error } = fetchUser.useHook();const handleClick = () => invoke({ id: '123' });EagerAsync
Section titled “EagerAsync”Like Async, but auto-executes when the component mounts or when parameters change. No manual invoke needed. Useful when dealing with promises that you want to invoke immediately, and caching is not necessary.
// Reactive — runs immediatelyconst { data, isPending } = fetchUser.useHook( { id: userId }, { options: { enabled: !!userId } },);Cached read operations backed by a query library (TanStack Query or RTK Query). Provides caching, background refetching, stale-while-revalidate, and more.
// Idiomatic — reads from or populates the cacheconst user = await getUser({ id: '123' });
// Reactive — subscribes to cached dataconst { data, isPending, refetch } = getUser.useHook({ id: '123' });Mutation
Section titled “Mutation”Write operations that modify server state. The reactive path provides invoke, loading state, and a reset function.
// Idiomaticconst result = await updateUser({ id: '123', name: 'New Name' });
// Reactiveconst { invoke, isPending, reset } = updateUser.useHook();await invoke({ id: '123', name: 'New Name' });InfiniteQuery
Section titled “InfiniteQuery”Paginated read operations. The reactive path provides pagination helpers like fetchNextPage and hasNextPage.
// Idiomatic — fetches all available pagesconst { pages, pageParams } = await getArchivedTodos();
// Reactiveconst { data, hasNextPage, fetchNextPage, isFetchingNextPage } = getArchivedTodos.useHook();Options Pattern
Section titled “Options Pattern”All query and mutation operations accept a two-level options structure as a second argument, keeping chimeric options separate from native library options:
// Idiomaticawait getUser( { id: '123' }, { options: { forceRefetch: true }, // chimeric options nativeOptions: { staleTime: 0 }, // library-specific options },);
// ReactivegetUser.useHook( { id: '123' }, { options: { enabled: !!userId }, // chimeric options nativeOptions: { refetchInterval: 5000 }, // library-specific options },);Chimeric options are consistent across all integrations:
- Query idiomatic:
forceRefetch— bypass cache staleness - Query reactive:
enabled— conditionally enable the query - InfiniteQuery idiomatic:
forceRefetch,pageParam— specify which page to fetch
Reducers
Section titled “Reducers”@chimeric/react provides sync reducer utilities for combining multiple services, and both @chimeric/react-query and @chimeric/rtk-query provide async reducer utilities:
- ChimericSyncReducer — combines multiple
ChimericSyncservices into a single derivedChimericSync - ChimericAsyncReducer — combines queries, eager async, and sync services into a
ChimericEagerAsync
const getDashboard = ChimericAsyncReducer<{ userId: string }>().build({ serviceList: [ { service: getUser, getParams: (p) => ({ id: p.userId }) }, { service: getUserPosts, getParams: (p) => ({ userId: p.userId }) }, ], reducer: ([user, posts]) => ({ user, posts, totalPosts: posts.length }),});
// Idiomaticconst dashboard = await getDashboard({ userId: '123' });
// Reactiveconst { data, isPending } = getDashboard.useHook({ userId: '123' });Type Guards
Section titled “Type Guards”Every operation type has runtime type guards for dynamic dispatch:
import { isChimericQuery, isChimericMutation } from '@chimeric/core';
if (isChimericQuery(operation)) { await operation.prefetch({ id: '123' });}