Skip to content

Commit 98d9f90

Browse files
committed
Updated examples.
1 parent 4ed91f5 commit 98d9f90

File tree

1 file changed

+62
-14
lines changed

1 file changed

+62
-14
lines changed

packages/powersync-db-collection/sync-stream-examples.md

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1-
## Calling sync streams automatically
1+
## Incorporating Sync Streams
22

3+
Ideally we would be able to map TanstackDB queries to sync streams automatically, if we can optimise the amount of data sync to
4+
the sqlite database from the service we have smaller set of data that needs to be considered when syncing from the sqlite database to TanstackDB collections.
5+
6+
As a stepping stone towards that, we now expose data loading hooks for both eager and on-demand sync modes that allow a user to call sync streams when a collection is defined (eager mode) or when a collection's data boundary changes based on the live queries predicates (on-demand).
37
For the these examples we assuming the follow sync stream exists:
48

59
```
10+
config:
11+
edition: 3
12+
613
streams:
714
lists:
815
query: SELECT * FROM lists WHERE owner_id = auth.user_id()
916
auto_subscribe: true
1017
todos:
1118
query: SELECT * FROM todos WHERE list_id = subscription.parameter('list') AND list_id IN (SELECT id FROM lists WHERE owner_id = auth.user_id())
12-
13-
config:
14-
edition: 2
1519
```
1620

1721
### Example 1: Eager mode basic usage
1822

23+
If you want an eager collection to subscribe to a sync stream when a collection loads, you can use the `onLoad` hook.
24+
The hook may return a cleanup function.
25+
26+
Consider the diagram as an example.
27+
We start with 4 todos in the PS service, only 2 todos get synced via the sync stream to the SQLite database. Because it's eager mode, both get synced from the SQLite database to the collection. Finally the TanstackDB query only returns the single todo that matches the live query predicate.
28+
1929
```typescript
2030
const collection = createCollection(
2131
powerSyncCollectionOptions({
@@ -25,7 +35,7 @@ const collection = createCollection(
2535
onLoad: async () => {
2636
console.log('onLoad')
2737
const subscription = await db
28-
.syncStream('todos', { list: '368b41f1-72fd-4a81-92ad-190711d72435' })
38+
.syncStream('todos', { list: 'list_1' })
2939
.subscribe({ ttl: 0 })
3040

3141
await subscription.waitForFirstSync()
@@ -39,8 +49,29 @@ const collection = createCollection(
3949
)
4050
```
4151

52+
A live query that filters by completed.
53+
54+
```typescript
55+
const liveQuery = createLiveQueryCollection({
56+
query: (q) =>
57+
q
58+
.from({ todo: collection })
59+
.where(({ todo }) => eq(todo.completed, 1))
60+
.select(({ todo }) => ({
61+
id: todo.id,
62+
completed: todo.completed,
63+
})),
64+
})
65+
```
66+
4267
### Example 2: On-demand basic usage
4368

69+
If you want to on-demand collection to subscribe to a sync stream whenever a subset of data is loaded (when the list of live queries against the collection change), you can use the `onLoadSubset` hook.
70+
The hook may return a cleanup function.
71+
72+
Consider the diagram as an example.
73+
We start with 4 todos in the PS service, only 2 todos get synced via the sync stream to the SQLite database. Because it's on-demand mode, only 1 todo matches gets synced from the SQLite database to the collection. Finally the TanstackDB query only returns the single todo that matches the live query predicate.
74+
4475
```typescript
4576
const collection = createCollection(
4677
powerSyncCollectionOptions({
@@ -50,7 +81,7 @@ const collection = createCollection(
5081
onLoadSubset: async (options) => {
5182
console.log('onLoadSubset')
5283
const subscription = await db
53-
.syncStream('todos', { list: '368b41f1-72fd-4a81-92ad-190711d72435' })
84+
.syncStream('todos', { list: 'list_1' })
5485
.subscribe({ ttl: 0 })
5586

5687
await subscription.waitForFirstSync()
@@ -64,6 +95,21 @@ const collection = createCollection(
6495
)
6596
```
6697

98+
A live query that filters by completed.
99+
100+
```typescript
101+
const liveQuery = createLiveQueryCollection({
102+
query: (q) =>
103+
q
104+
.from({ todo: collection })
105+
.where(({ todo }) => eq(todo.completed, 1))
106+
.select(({ todo }) => ({
107+
id: todo.id,
108+
completed: todo.completed,
109+
})),
110+
})
111+
```
112+
67113
### Example 3: Extract a single filter value using `extractSimpleComparisons`
68114

69115
Given a live query like:
@@ -72,9 +118,12 @@ Given a live query like:
72118
.where(({ todo }) => eq(todo.list_id, selectedListId))
73119
```
74120

75-
`onLoadSubset` receives options.where as an expression tree for eq(list_id, '<uuid>').
121+
`onLoadSubset` receives options.where as an expression tree `for eq(list_id, '<uuid>')`.
76122
We parse it to get the `list_id` value and pass it to `syncStream`.
77123

124+
Consider the diagram as an example. Note it differs from example 1 and 2 as it aims to illustrate `extractSimpleComparisons`.
125+
We start with 4 todos in the PS service, the sync stream subscription criteria (`list_id = "list_1"`) is derived from the live query registered against the collection. Only 2 todos get synced via the sync stream to the SQLite database. Two todos get synced from the SQLite database to the collection. Finally the TanstackDB query returns both todos as they both match `eq(todo.list_id, 'list_id')`.
126+
78127
#### Collection
79128

80129
```typescript
@@ -125,11 +174,10 @@ const liveQuery = createLiveQueryCollection({
125174
q
126175
.from({ todo: collection })
127176
.where(
128-
({ todo }) => eq(todo.list_id, '368b41f1-72fd-4a81-92ad-190711d72435'), // or some listId variable
177+
({ todo }) => eq(todo.list_id, 'list_id'), // or some listId variable
129178
)
130179
.select(({ todo }) => ({
131180
id: todo.id,
132-
description: todo.description,
133181
completed: todo.completed,
134182
})),
135183
})
@@ -149,6 +197,9 @@ todos:
149197

150198
Note: We keep the `list` parameter name as is (consistent with most of our examples), but to correctly work with the following example we need to map it to `list_id`. You may opt to name it as `list_id` in the sync stream definition and skip the mapping process.
151199

200+
Consider the diagram as an example.
201+
We start with 4 todos in the PS service, the sync stream subscription criteria (`list_id = "list_1" and completed = 1`) is derived from the live query registered against the collection. Only 1 todo gets synced via the sync stream to the SQLite database. One todos gets synced from the SQLite database to the collection. Finally the TanstackDB query returns 1 todo that matches `eq(todo.list_id, 'list_id') and eq(todo.completed, 1)`.
202+
152203
#### Collection
153204

154205
```typescript
@@ -210,14 +261,11 @@ const liveQuery = createLiveQueryCollection({
210261
q
211262
.from({ todo: collection })
212263
.where(({ todo }) =>
213-
and(
214-
eq(todo.list_id, '368b41f1-72fd-4a81-92ad-190711d72435'),
215-
eq(todo.completed, 1),
216-
),
264+
and(eq(todo.list_id, 'list_1'), eq(todo.completed, 1)),
217265
)
218266
.select(({ todo }) => ({
219267
id: todo.id,
220-
description: todo.description,
268+
completed: todo.completed,
221269
})),
222270
})
223271
```

0 commit comments

Comments
 (0)