
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
tanstack-db-atom
Advanced tools
TanStack DB utilities for Effect Atom - provides reactive atoms that integrate with TanStack DB collections and queries
TanStack DB utilities for Effect Atom - provides reactive atoms that integrate with TanStack DB collections and queries.
Result.Result<T>npm install tanstack-db-atom
This package requires the following peer dependencies:
npm install @effect-atom/atom-react @tanstack/db effect
{
"dependencies": {
"tanstack-db-atom": "^1.0.0",
"@effect-atom/atom-react": "^1.0.0",
"@tanstack/db": "^0.5.0",
"effect": "^3.0.0"
}
}
import { createCollection } from '@tanstack/db'
const todoCollection = createCollection<Todo, string>({
id: 'todos',
getKey: (todo) => todo.id,
sync: {
sync: async (params) => {
const todos = await fetchTodosFromAPI()
params.begin()
for (const todo of todos) {
params.write({ type: 'insert', value: todo })
}
params.commit()
params.markReady()
}
},
startSync: true
})
import { makeQuery } from 'tanstack-db-atom'
import { useAtom } from '@effect-atom/atom-react'
import { Result } from '@effect-atom/atom-react'
import { eq } from '@tanstack/db'
const activeTodosAtom = makeQuery((q) =>
q.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.completed, false))
)
function TodoList() {
const todosResult = useAtom(activeTodosAtom)
return Result.match(todosResult, {
onInitial: () => <Loading />,
onFailure: (error) => <Error message={error.message} />,
onSuccess: (todos) => (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
})
}
Create an atom from a TanStack DB query with filtering and projection:
import { makeQuery } from 'tanstack-db-atom'
import { useAtom } from '@effect-atom/atom-react'
import { Result } from '@effect-atom/atom-react'
import { eq } from '@tanstack/db'
const activeTodosAtom = makeQuery((q) =>
q.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.completed, false))
.select(({ todos }) => ({
id: todos.id,
title: todos.title
}))
)
function TodoList() {
const todosResult = useAtom(activeTodosAtom)
return Result.match(todosResult, {
onInitial: () => <Loading />,
onFailure: (error) => <Error message={error.message} />,
onSuccess: (todos) => (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
)
})
}
For when you don't need error handling, use makeQueryUnsafe:
import { makeQueryUnsafe } from 'tanstack-db-atom'
import { useAtom } from '@effect-atom/atom-react'
const todosAtom = makeQueryUnsafe((q) =>
q.from({ todos: todoCollection })
)
function TodoList() {
const todos = useAtom(todosAtom) // Array<Todo> | undefined
if (!todos) return <Loading />
return <ul>{todos.map(todo => <TodoItem key={todo.id} {...todo} />)}</ul>
}
Queries that can be enabled/disabled based on runtime conditions:
import { makeQueryConditional } from 'tanstack-db-atom'
const userTodosAtom = makeQueryConditional((q) => {
const userId = getCurrentUserId()
if (!userId) return null // Disabled when no user
return q.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.userId, userId))
})
function UserTodos() {
const todosResult = useAtom(userTodosAtom)
if (!todosResult) return <div>Please log in</div>
return Result.match(todosResult, {
onInitial: () => <Loading />,
onFailure: (error) => <Error message={error.message} />,
onSuccess: (todos) => <TodoList todos={todos} />
})
}
For queries that return a single item:
const currentUserAtom = makeQuery((q) =>
q.from({ users: userCollection })
.where(({ users }) => eq(users.id, currentUserId))
.limit(1)
)
function UserProfile() {
const userResult = useAtom(currentUserAtom)
return Result.match(userResult, {
onInitial: () => <Loading />,
onFailure: () => <div>User not found</div>,
onSuccess: (users) => {
const user = users[0]
return user ? <UserProfileCard user={user} /> : null
}
})
}
Create atoms from pre-existing TanStack DB collections:
import { makeCollectionAtom, makeSingleCollectionAtom } from 'tanstack-db-atom'
// For collections that return arrays
const todosAtom = makeCollectionAtom(todoCollection)
// For collections with singleResult: true
const currentUserAtom = makeSingleCollectionAtom(currentUserCollection)
Configure query behavior with options:
const todosAtom = makeQuery(
(q) => q.from({ todos: todoCollection }),
{
gcTime: 5000, // Keep collection alive for 5s after unmount
startSync: true, // Start sync immediately
suspendOnWaiting: false // Don't suspend on waiting state
}
)
Create parameterized queries with Atom families:
import { Atom } from '@effect-atom/atom-react'
const todosByStatusFamily = Atom.family((completed: boolean) =>
makeQuery((q) =>
q.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.completed, completed))
)
)
function CompletedTodos() {
const completedTodos = useAtom(todosByStatusFamily(true))
return Result.match(completedTodos, {
onInitial: () => <Loading />,
onFailure: (error) => <Error message={error.message} />,
onSuccess: (todos) => <TodoList todos={todos} />
})
}
TanStack DB's query builder supports joins and complex transformations:
const enrichedTodosAtom = makeQuery((q) =>
q.from({ todos: todoCollection })
.join(
{ users: userCollection },
({ todos, users }) => eq(todos.userId, users.id)
)
.where(({ todos }) => eq(todos.completed, false))
.select(({ todos, users }) => ({
id: todos.id,
title: todos.title,
userName: users.name,
userAvatar: users.avatarUrl
}))
)
makeQueryCreates an Atom from a TanStack DB query function.
import type { QueryOptions } from 'tanstack-db-atom'
function makeQuery<TContext extends Context>(
queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>,
options?: QueryOptions
): Atom<Result<InferResultType<TContext>, Error>>
Parameters:
queryFn: Function that builds a TanStack DB queryoptions: Optional query configurationOptions:
gcTime?: number - Garbage collection time in milliseconds (default: 0)startSync?: boolean - Whether to start sync immediately (default: true)suspendOnWaiting?: boolean - Suspend on waiting state with Atom.result() (default: false)Returns: Atom<Result<T, Error>> - An atom that emits Result states
makeQueryUnsafeCreates an Atom that returns data or undefined (no Result wrapper).
function makeQueryUnsafe<TContext extends Context>(
queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext>,
options?: QueryOptions
): Atom<InferResultType<TContext> | undefined>
Returns: Atom<T | undefined> - Data when available, undefined when loading/error
makeQueryConditionalCreates an Atom from a conditional query function.
function makeQueryConditional<TContext extends Context>(
queryFn: (q: InitialQueryBuilder) => QueryBuilder<TContext> | null | undefined,
options?: QueryOptions
): Atom<Result<InferResultType<TContext>, Error> | undefined>
Behavior:
undefined atom when query function returns null or undefinedResult<T> atom when query function returns a QueryBuildermakeCollectionAtomCreates an Atom from an existing TanStack DB collection.
function makeCollectionAtom<T extends object, TKey extends string | number>(
collection: Collection<T, TKey, any> & NonSingleResult
): Atom<Result<Array<T>, Error>>
Best for: Collections that return arrays of items
makeSingleCollectionAtomCreates an Atom from a single-result collection.
function makeSingleCollectionAtom<T extends object, TKey extends string | number>(
collection: Collection<T, TKey, any> & SingleResult
): Atom<Result<T | undefined, Error>>
Best for: Collections with singleResult: true configuration
startSync: false)idle/loading → Result.initial(true) (waiting state)error → Result.fail(error)ready → Result.success(data)cleaned-up → Result.fail(error)collection.subscribeChanges()get.addFinalizer()TanStack DB uses D2 (Differential Datalog) for efficient incremental updates:
Works seamlessly with other Effect Atom features:
import { Atom } from '@effect-atom/atom-react'
// Combine with Atom.map
const todoCountAtom = Atom.map(
makeQueryUnsafe((q) => q.from({ todos: todoCollection })),
(todos) => todos?.length ?? 0
)
// Use with Atom.flatMap
const selectedTodoAtom = Atom.flatMap(
selectedIdAtom,
(id) => makeQuery((q) =>
q.from({ todos: todoCollection })
.where(({ todos }) => eq(todos.id, id))
.limit(1)
)
)
// Combine multiple queries
const dashboardDataAtom = Atom.all({
todos: makeQuery((q) => q.from({ todos: todoCollection })),
users: makeQuery((q) => q.from({ users: userCollection })),
stats: makeQuery((q) => q.from({ stats: statsCollection }))
})
This package uses the Result pattern for safe error handling:
import { Result } from '@effect-atom/atom-react'
// Type narrowing
if (Result.isSuccess(result)) {
// result is Result.Success<T>
console.log(result.value)
} else if (Result.isInitial(result)) {
// result is Result.Initial
console.log('Loading...', result.waiting)
}
// Pattern matching
const display = Result.match(result, {
onInitial: () => 'Loading...',
onFailure: (error) => `Error: ${error.message}`,
onSuccess: (data) => `Data: ${JSON.stringify(data)}`
})
// Get with fallback
const data = Result.getOrElse(result, () => [])
useLiveQuery and React Query patterns| Feature | useLiveQuery (React) | makeQuery (Effect Atom) |
|---|---|---|
| Framework | React | Framework-agnostic |
| Subscription | useSyncExternalStore | Atom finalizers |
| Error Handling | Status flags | Result types |
| Composability | Limited | High (Atom combinators) |
| TypeScript | Full inference | Full inference |
| Performance | Optimized | Optimized |
This package is written in TypeScript and provides full type inference:
// Type is inferred from the query
const todosAtom = makeQuery((q) =>
q.from({ todos: todoCollection })
.select(({ todos }) => ({
id: todos.id,
title: todos.title
}))
)
// Type is Atom<Result<Array<{id: string, title: string}>, Error>>
const result = useAtom(todosAtom)
if (Result.isSuccess(result)) {
// TypeScript knows result.value has {id, title}
console.log(result.value[0]?.title)
}
MIT
FAQs
TanStack DB utilities for Effect Atom - provides reactive atoms that integrate with TanStack DB collections and queries
The npm package tanstack-db-atom receives a total of 2 weekly downloads. As such, tanstack-db-atom popularity was classified as not popular.
We found that tanstack-db-atom demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.