Skip to content

Commit 5e2932f

Browse files
docs: add unofficial dexie collection (#576)
Co-authored-by: Kyle Mathews <[email protected]>
1 parent fbed513 commit 5e2932f

File tree

3 files changed

+144
-80
lines changed

3 files changed

+144
-80
lines changed

docs/community/resources.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Community Resources
2+
3+
This page contains a curated list of community-created packages, tools, and resources that extend or complement TanStack DB.
4+
5+
## Community Packages
6+
7+
### Dexie.js Integration (Unofficial)
8+
- **[tanstack-dexie-db-collection](https://github.com/yourusername/tanstack-dexie-db-collection)** - Community-maintained Dexie.js adapter for TanStack DB
9+
- Local persistence using [Dexie.js](https://dexie.org) (IndexedDB wrapper)
10+
- Lightweight integration for browser-based storage
11+
- Install: `npm install tanstack-dexie-db-collection`
12+
13+
### Contributing Your Package
14+
15+
Have you created a collection adapter or integration? We'd love to feature it here! [Submit a PR](https://github.com/TanStack/db/pulls) to add your package.
16+
17+
## Examples & Templates
18+
19+
### Starter Templates
20+
*Share your starter templates and boilerplates here*
21+
22+
### Example Applications
23+
*Community-built example apps showcasing TanStack DB features*
24+
25+
## Learning Resources
26+
27+
### Tutorials & Guides
28+
*Community tutorials and blog posts about TanStack DB*
29+
30+
### Videos & Courses
31+
*Video tutorials and online courses*
32+
33+
## Contributing
34+
35+
We welcome contributions to this community resources page! If you've created something useful for the TanStack DB ecosystem:
36+
37+
1. Fork the repository
38+
2. Add your resource to the appropriate section
39+
3. Include a brief description and link
40+
4. Submit a pull request
41+
42+
Please ensure all submissions are relevant to TanStack DB and provide value to the community.

docs/config.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@
104104
}
105105
]
106106
},
107+
{
108+
"label": "Community",
109+
"children": [
110+
{
111+
"label": "Resources & Packages",
112+
"to": "community/resources"
113+
}
114+
]
115+
},
107116
{
108117
"label": "API Reference",
109118
"children": [

docs/overview.md

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,8 @@ const todoCollection = createCollection(
186186
queryCollectionOptions({
187187
queryKey: ["todoItems"],
188188
queryFn: async () => {
189-
const response = await fetch("/api/todos");
190-
return response.json();
189+
const response = await fetch("/api/todos")
190+
return response.json()
191191
},
192192
getKey: (item) => item.id,
193193
schema: todoSchema, // any standard schema
@@ -301,7 +301,6 @@ This collection requires the following TrailBase-specific options:
301301

302302
A new collections doesn't start syncing until you call `collection.preload()` or you query it.
303303

304-
305304
#### `RxDBCollection`
306305

307306
[RxDB](https://rxdb.info) is a client-side database for JavaScript apps with replication, conflict resolution, and offline-first features.
@@ -335,7 +334,7 @@ await db.addCollections({
335334
export const todoCollection = createCollection(
336335
rxdbCollectionOptions({
337336
rxCollection: db.todos,
338-
startSync: true
337+
startSync: true,
339338
})
340339
)
341340
```
@@ -614,11 +613,11 @@ const addTodo = createOptimisticAction<string>({
614613
body: JSON.stringify({ text, completed: false }),
615614
})
616615
const result = await response.json()
617-
616+
618617
// IMPORTANT: Ensure server writes have synced back before returning
619618
// This ensures the optimistic state can be safely discarded
620619
await todoCollection.utils.refetch()
621-
620+
622621
return result
623622
},
624623
})
@@ -671,47 +670,54 @@ When multiple mutations operate on the same item within a transaction, TanStack
671670

672671
The merging behavior follows a truth table based on the mutation types:
673672

674-
| ExistingNew | Result | Description |
675-
|---|---|---|
676-
| **insert + update** | `insert` | Keeps insert type, merges changes, empty original |
677-
| **insert + delete** | *removed* | Mutations cancel each other out |
678-
| **update + delete** | `delete` | Delete dominates |
679-
| **update + update** | `update` | Union changes, keep first original |
680-
| **same type** | *latest* | Replace with most recent mutation |
673+
| ExistingNew | Result | Description |
674+
| ------------------- | --------- | ------------------------------------------------- |
675+
| **insert + update** | `insert` | Keeps insert type, merges changes, empty original |
676+
| **insert + delete** | _removed_ | Mutations cancel each other out |
677+
| **update + delete** | `delete` | Delete dominates |
678+
| **update + update** | `update` | Union changes, keep first original |
679+
| **same type** | _latest_ | Replace with most recent mutation |
681680

682681
#### Examples
683682

684683
**Insert followed by update:**
684+
685685
```ts
686686
const tx = createTransaction({ autoCommit: false, mutationFn })
687687
688688
// Insert a new todo
689-
tx.mutate(() => todoCollection.insert({
690-
id: '1',
691-
text: 'Buy groceries',
692-
completed: false
693-
}))
689+
tx.mutate(() =>
690+
todoCollection.insert({
691+
id: "1",
692+
text: "Buy groceries",
693+
completed: false,
694+
})
695+
)
694696
695697
// Update the same todo
696-
tx.mutate(() => todoCollection.update('1', (draft) => {
697-
draft.text = 'Buy organic groceries'
698-
draft.priority = 'high'
699-
}))
698+
tx.mutate(() =>
699+
todoCollection.update("1", (draft) => {
700+
draft.text = "Buy organic groceries"
701+
draft.priority = "high"
702+
})
703+
)
700704
701705
// Result: Single insert mutation with merged data
702706
// { id: '1', text: 'Buy organic groceries', completed: false, priority: 'high' }
703707
```
704708

705709
**Insert followed by delete:**
710+
706711
```ts
707712
// Insert then delete cancels out - no mutations sent to server
708-
tx.mutate(() => todoCollection.insert({ id: '1', text: 'Temp todo' }))
709-
tx.mutate(() => todoCollection.delete('1'))
713+
tx.mutate(() => todoCollection.insert({ id: "1", text: "Temp todo" }))
714+
tx.mutate(() => todoCollection.delete("1"))
710715
711716
// Result: No mutations (they cancel each other out)
712717
```
713718

714719
This intelligent merging ensures that:
720+
715721
- **Network efficiency**: Fewer mutations sent to the server
716722
- **User intent preservation**: Final state matches what user expects
717723
- **Optimistic UI consistency**: Local state always reflects user actions
@@ -899,32 +905,36 @@ import { queryCollectionOptions } from "@tanstack/query-db-collection"
899905
900906
// Load data into collections using TanStack Query.
901907
// It's common to define these in a `collections` module.
902-
const todoCollection = createCollection(queryCollectionOptions({
903-
queryKey: ["todos"],
904-
queryFn: async () => fetch("/api/todos"),
905-
getKey: (item) => item.id,
906-
schema: todoSchema, // any standard schema
907-
onInsert: async ({ transaction }) => {
908-
const { changes: newTodo } = transaction.mutations[0]
909-
910-
// Handle the local write by sending it to your API.
911-
await api.todos.create(newTodo)
912-
}
913-
// also add onUpdate, onDelete as needed.
914-
}))
915-
const listCollection = createCollection(queryCollectionOptions({
916-
queryKey: ["todo-lists"],
917-
queryFn: async () => fetch("/api/todo-lists"),
918-
getKey: (item) => item.id,
919-
schema: todoListSchema,
920-
onInsert: async ({ transaction }) => {
921-
const { changes: newTodo } = transaction.mutations[0]
922-
923-
// Handle the local write by sending it to your API.
924-
await api.todoLists.create(newTodo)
925-
}
926-
// also add onUpdate, onDelete as needed.
927-
}))
908+
const todoCollection = createCollection(
909+
queryCollectionOptions({
910+
queryKey: ["todos"],
911+
queryFn: async () => fetch("/api/todos"),
912+
getKey: (item) => item.id,
913+
schema: todoSchema, // any standard schema
914+
onInsert: async ({ transaction }) => {
915+
const { changes: newTodo } = transaction.mutations[0]
916+
917+
// Handle the local write by sending it to your API.
918+
await api.todos.create(newTodo)
919+
},
920+
// also add onUpdate, onDelete as needed.
921+
})
922+
)
923+
const listCollection = createCollection(
924+
queryCollectionOptions({
925+
queryKey: ["todo-lists"],
926+
queryFn: async () => fetch("/api/todo-lists"),
927+
getKey: (item) => item.id,
928+
schema: todoListSchema,
929+
onInsert: async ({ transaction }) => {
930+
const { changes: newTodo } = transaction.mutations[0]
931+
932+
// Handle the local write by sending it to your API.
933+
await api.todoLists.create(newTodo)
934+
},
935+
// also add onUpdate, onDelete as needed.
936+
})
937+
)
928938
929939
const Todos = () => {
930940
// Read the data using live queries. Here we show a live
@@ -935,19 +945,18 @@ const Todos = () => {
935945
.join(
936946
{ list: listCollection },
937947
({ todo, list }) => eq(list.id, todo.list_id),
938-
'inner'
948+
"inner"
939949
)
940950
.where(({ list }) => eq(list.active, true))
941951
.select(({ todo, list }) => ({
942952
id: todo.id,
943953
text: todo.text,
944954
status: todo.status,
945-
listName: list.name
955+
listName: list.name,
946956
}))
947957
)
948958
949959
// ...
950-
951960
}
952961
```
953962

@@ -960,37 +969,41 @@ One of the most powerful ways of using TanStack DB is with a sync engine, for a
960969
Here, we illustrate this pattern using [ElectricSQL](https://electric-sql.com) as the sync engine.
961970

962971
```tsx
963-
import type { Collection } from '@tanstack/db'
964-
import type { MutationFn, PendingMutation, createCollection } from '@tanstack/react-db'
965-
import { electricCollectionOptions } from '@tanstack/electric-db-collection'
966-
967-
export const todoCollection = createCollection(electricCollectionOptions({
968-
id: 'todos',
969-
schema: todoSchema,
970-
// Electric syncs data using "shapes". These are filtered views
971-
// on database tables that Electric keeps in sync for you.
972-
shapeOptions: {
973-
url: 'https://api.electric-sql.cloud/v1/shape',
974-
params: {
975-
table: 'todos'
976-
}
977-
},
978-
getKey: (item) => item.id,
979-
schema: todoSchema,
980-
onInsert: async ({ transaction }) => {
981-
const response = await api.todos.create(transaction.mutations[0].modified)
972+
import type { Collection } from "@tanstack/db"
973+
import type {
974+
MutationFn,
975+
PendingMutation,
976+
createCollection,
977+
} from "@tanstack/react-db"
978+
import { electricCollectionOptions } from "@tanstack/electric-db-collection"
982979
983-
return { txid: response.txid}
984-
}
985-
// You can also implement onUpdate, onDelete as needed.
986-
}))
980+
export const todoCollection = createCollection(
981+
electricCollectionOptions({
982+
id: "todos",
983+
schema: todoSchema,
984+
// Electric syncs data using "shapes". These are filtered views
985+
// on database tables that Electric keeps in sync for you.
986+
shapeOptions: {
987+
url: "https://api.electric-sql.cloud/v1/shape",
988+
params: {
989+
table: "todos",
990+
},
991+
},
992+
getKey: (item) => item.id,
993+
schema: todoSchema,
994+
onInsert: async ({ transaction }) => {
995+
const response = await api.todos.create(transaction.mutations[0].modified)
996+
997+
return { txid: response.txid }
998+
},
999+
// You can also implement onUpdate, onDelete as needed.
1000+
})
1001+
)
9871002
9881003
const AddTodo = () => {
9891004
return (
9901005
<Button
991-
onClick={() =>
992-
todoCollection.insert({ text: "🔥 Make app faster" })
993-
}
1006+
onClick={() => todoCollection.insert({ text: "🔥 Make app faster" })}
9941007
/>
9951008
)
9961009
}
@@ -1009,7 +1022,7 @@ npm install react-native-random-uuid
10091022
Then import it at the entry point of your React Native app (e.g., in your `App.js` or `index.js`):
10101023

10111024
```javascript
1012-
import 'react-native-random-uuid'
1025+
import "react-native-random-uuid"
10131026
```
10141027

10151028
This polyfill provides the `crypto.randomUUID()` function that TanStack DB uses internally for generating unique identifiers.

0 commit comments

Comments
 (0)