Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/octane-db-package.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@tanstack/octane-db': minor
---

Add `@tanstack/octane-db`, an Octane framework adapter for TanStack DB with full hook parity to `@tanstack/react-db` and Octane compiler hook-slot forwarding.
23 changes: 23 additions & 0 deletions _artifacts/skill_tree.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,29 @@ skills:
- 'TanStack/db:packages/react-db/src/useLiveInfiniteQuery.ts'
- 'TanStack/db:packages/react-db/src/usePacedMutations.ts'

- name: 'Octane DB'
slug: 'octane-db'
type: 'framework'
domain: 'framework-integration'
path: 'skills/octane-db/SKILL.md'
package: 'packages/octane-db'
description: >
Octane bindings for TanStack DB. useLiveQuery hook with dependency arrays
and 8 overloads (query function, config object, pre-created collection,
disabled state). useLiveSuspenseQuery for Octane Suspense with error
boundaries. useLiveInfiniteQuery for cursor-based pagination (pageSize,
fetchNextPage, hasNextPage). usePacedMutations for debounced mutations.
useLiveQueryEffect for row enter/exit/update side effects.
Return shape: data, state, collection, status, isLoading, isReady, isError.
requires:
- 'db-core'
sources:
- 'TanStack/db:docs/framework/octane/overview.md'
- 'TanStack/db:packages/octane-db/src/useLiveQuery.ts'
- 'TanStack/db:packages/octane-db/src/useLiveInfiniteQuery.ts'
- 'TanStack/db:packages/octane-db/src/usePacedMutations.ts'
- 'TanStack/db:packages/octane-db/src/useLiveQueryEffect.ts'

- name: 'Vue DB'
slug: 'vue-db'
type: 'framework'
Expand Down
129 changes: 129 additions & 0 deletions docs/framework/octane/overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: TanStack DB Octane Adapter
id: adapter
---

## Installation

```sh
npm install @tanstack/octane-db octane @octanejs/vite-plugin
```

Configure the Octane compiler in your Vite app — see [Octane build tools](https://octanejs.dev/docs/build-tools).

`@tanstack/octane-db` re-exports everything from `@tanstack/db`. Import collections, query helpers, and hooks from `@tanstack/octane-db`.

## Octane Hooks

See the [Octane Functions Reference](./reference/index.md) for the full hook list.

For comprehensive documentation on writing queries (filtering, joins, aggregations, etc.), see the [Live Queries Guide](../../guides/live-queries).

## Basic Usage

The examples below assume `todosCollection` and `postsCollection` are collections you've already created (see the [Collections guide](../../guides/collections)), and that query helpers such as `eq` and `gt` are imported from `@tanstack/octane-db`.

### useLiveQuery

```tsx
import { useLiveQuery, eq } from '@tanstack/octane-db'

function TodoList() {
const { data, isLoading } = useLiveQuery((q) =>
q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.completed, false))
.select(({ todos }) => ({ id: todos.id, text: todos.text }))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
)

if (isLoading) return <div>Loading...</div>

return (
<ul>
{data.map(todo => <li key={todo.id}>{todo.text}</li>)}
</ul>
)
}
```

### Dependency Arrays

All query hooks (`useLiveQuery`, `useLiveInfiniteQuery`, `useLiveSuspenseQuery`) accept an optional dependency array as their last parameter. When any value in the array changes, the query is recreated and re-executed.

```tsx
function FilteredTodos({ minPriority }: { minPriority: number }) {
const { data } = useLiveQuery(
(q) => q.from({ todos: todosCollection })
.where(({ todos }) => gt(todos.priority, minPriority)),
[minPriority]
)

return <div>{data.length} high-priority todos</div>
}
```

### useLiveInfiniteQuery

```tsx
import { useLiveInfiniteQuery, eq } from '@tanstack/octane-db'

function PostFeed({ category }: { category: string }) {
const { data, fetchNextPage, hasNextPage } = useLiveInfiniteQuery(
(q) => q
.from({ posts: postsCollection })
.where(({ posts }) => eq(posts.category, category))
.orderBy(({ posts }) => posts.createdAt, 'desc'),
{
pageSize: 20,
getNextPageParam: (lastPage, allPages) =>
lastPage.length === 20 ? allPages.length : undefined
},
[category]
)

return (
<div>
<ul>
{data.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
{hasNextPage && (
<button onClick={() => fetchNextPage()}>Load more</button>
)}
</div>
)
}
```

### useLiveSuspenseQuery

Wrap components in Octane `Suspense` (and `@try` / `@catch` or an error boundary for failures):

```tsx
import { Suspense } from 'octane'
import { useLiveSuspenseQuery, eq } from '@tanstack/octane-db'

function TodoList({ filter }: { filter: string }) {
const { data } = useLiveSuspenseQuery(
(q) => q.from({ todos: todosCollection })
.where(({ todos }) => eq(todos.filter, filter)),
[filter]
)

return (
<ul>
{data.map(todo => <li key={todo.id}>{todo.text}</li>)}
</ul>
)
}

function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<TodoList filter="active" />
</Suspense>
)
}
```

### Incremental adoption from React

You can host compiled Octane components inside an existing React 19 app with `OctaneCompat` from `octane/react`. Islands can use `@tanstack/octane-db` hooks while the rest of the app keeps `@tanstack/react-db`. See [OctaneCompat](https://octanejs.dev/docs/differences-from-react).
9 changes: 9 additions & 0 deletions docs/framework/octane/reference/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Octane Functions Reference

Generated API reference for `@tanstack/octane-db`. Run `pnpm generate-docs` at the repo root to refresh these pages.

- [useLiveQuery](./functions/useLiveQuery.md)
- [useLiveSuspenseQuery](./functions/useLiveSuspenseQuery.md)
- [useLiveInfiniteQuery](./functions/useLiveInfiniteQuery.md)
- [usePacedMutations](./functions/usePacedMutations.md)
- [useLiveQueryEffect](./functions/useLiveQueryEffect.md)
8 changes: 8 additions & 0 deletions docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ npm install @tanstack/angular-db

TanStack DB is compatible with Angular v16.0.0+

## Octane

```sh
npm install @tanstack/octane-db octane @octanejs/vite-plugin
```

TanStack DB is compatible with Octane v0.1.0+. Configure the Octane compiler in your build tool — see [octanejs.dev](https://octanejs.dev/docs/build-tools).

## Vanilla JS

```sh
Expand Down
3 changes: 3 additions & 0 deletions domain_map.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,9 @@ skills:
- name: 'Angular'
package: '@tanstack/angular-db'
config_surface: 'injectLiveQuery with Signal, inject(DestroyRef)'
- name: 'Octane'
package: '@tanstack/octane-db'
config_surface: 'useLiveQuery, useLiveSuspenseQuery, useLiveInfiniteQuery, usePacedMutations, useLiveQueryEffect'
failure_modes:
- mistake: 'Missing external values in useLiveQuery dependency array'
mechanism: "When query uses external state (props, local state) not included in deps array, the query won't re-run when those values change, showing stale results"
Expand Down
2 changes: 1 addition & 1 deletion packages/db/src/live-query-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { CollectionStatus } from './types.js'
/**
* Shared helpers for the first-party framework adapters (`@tanstack/react-db`,
* `@tanstack/vue-db`, `@tanstack/svelte-db`, `@tanstack/solid-db`,
* `@tanstack/angular-db`).
* `@tanstack/angular-db`, `@tanstack/octane-db`).
*
* These centralize small pieces of logic every adapter used to duplicate, so
* they stay consistent across frameworks. They are intended for the official
Expand Down
5 changes: 5 additions & 0 deletions packages/octane-db/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# @tanstack/octane-db

## 0.0.1

Initial release of the Octane framework adapter for TanStack DB.
5 changes: 5 additions & 0 deletions packages/octane-db/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# @tanstack/octane-db

Octane hooks for TanStack DB. See [TanStack/db](https://github.com/TanStack/db) for more details.

Install `octane` alongside this package and configure the Octane compiler in your build tool (see [octanejs.dev](https://octanejs.dev/docs/build-tools)).
70 changes: 70 additions & 0 deletions packages/octane-db/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"name": "@tanstack/octane-db",
"version": "0.0.1",
"description": "Octane integration for @tanstack/db",
"author": "Kyle Mathews",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/TanStack/db.git",
"directory": "packages/octane-db"
},
"homepage": "https://tanstack.com/db",
"keywords": [
"optimistic",
"octane",
"typescript",
"tanstack-intent"
],
"octane": {
"hookSlots": {
"manual": [
"src"
]
}
},
"scripts": {
"build": "vite build",
"build:minified": "vite build --minify",
"dev": "vite build --watch",
"test": "vitest --run",
"lint": "eslint . --fix"
},
"type": "module",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.js",
"types": "dist/esm/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/esm/index.d.ts",
"default": "./dist/esm/index.js"
},
"require": {
"types": "./dist/cjs/index.d.cts",
"default": "./dist/cjs/index.cjs"
}
},
"./package.json": "./package.json"
},
"sideEffects": false,
"files": [
"dist",
"src",
"skills"
],
"dependencies": {
"@tanstack/db": "workspace:*"
},
"peerDependencies": {
"octane": ">=0.1.0"
},
"devDependencies": {
"@electric-sql/client": "^1.5.15",
"@octanejs/testing-library": "^0.1.10",
"@octanejs/vite-plugin": "^0.1.13",
"@vitest/coverage-istanbul": "^3.2.4",
"octane": "^0.1.13",
"vitest": "^3.2.4"
}
}
Loading
Loading