Skip to content

Commit 1948053

Browse files
committed
Update Readme with explanation
1 parent 105580c commit 1948053

File tree

6 files changed

+65
-52
lines changed

6 files changed

+65
-52
lines changed

demos/local-only-todolist/README.md

Lines changed: 63 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,33 @@
1-
# PowerSync + Supabase Flutter Local-Only to Online Mode Demo: Todo List App
1+
# PowerSync + Supabase Flutter Todo List App: Local-Only to Sync Mode Demo
22

3-
This demo app is an extension of the [Supabase Todo List App](../supabase-todolist/README.md) that demonstrates how to use the PowerSync SDK for Flutter in a local-only way without sync capabilities. It allows the user to use the app offline without having to sign in. After signing in data that was kept locally is synced up. For a step-by-step guide, see [here](https://docs.powersync.com/integration-guides/supabase).
3+
This demo app is an extension of the [Supabase Todo List App](../supabase-todolist/README.md) and demonstrates using the PowerSync Flutter client SDK to persist data locally without syncing, for users to use the app without having to register or sign in. It then demonstrates syncing this data to Supabase once the user registers at a later stage.
44

5-
# Running the app with local-only
5+
The recommended flow through this demo is:
6+
1. Run the app in local-only mode and create data. Notice how data persists even when closing and reopening the app.
7+
2. Enable user registration and sign in to the app.
8+
3. Notice how previously created data now seamlessly syncs with Supabase.
9+
10+
For an overview of the mechanics behind this, see [the explanation further below](#how-this-works).
11+
12+
# Run the app in local-only mode
613

7-
Note that if Supabase and PowerSync credentials have not been been configured, a user will not be able to login or sign up. There is a hardcoded check in `main.dart` for this.
814
Ensure you have [melos](https://melos.invertase.dev/~melos-latest/getting-started) installed.
915

1016
1. `cd demos/local-only-todolist`
1117
2. `melos prepare`
1218
3. `flutter run`
1319

14-
# Setting up sync functionality
20+
Create some data and notice how the data persists after a refresh or reopening the app.
21+
22+
It is expected that users cannot register or sign in at this stage. This is because Supabase and PowerSync credentials have not been been configured yet -- there is a hardcoded check in `main.dart` for this. We'll get to this next.
23+
24+
# Enable user registration and sign in
1525

16-
Insert your Supabase and PowerSync project credentials into `lib/app_config.dart` (See instructions below).
17-
A user should now be able to login or sign up, which enables the sync functionality.
26+
Create Supabase and PowerSync projects, and add their credentials to `lib/app_config.dart` to enable user registration and sign in.
1827

19-
# Set up Supabase Project
28+
## Set up your Supabase project
29+
30+
Detailed instructions for integrating PowerSync with Supabase can be found in [the integration guide](https://docs.powersync.com/integration-guides/supabase). Below are the main steps required to get this demo running.
2031

2132
Create a new Supabase project, and paste an run the contents of [database.sql](./database.sql) in the Supabase SQL editor.
2233

@@ -27,7 +38,7 @@ It does the following:
2738
3. Enable row level security, allowing users to only view and edit their own data.
2839
4. Create a trigger to populate some sample data when an user registers.
2940

30-
# Set up PowerSync Instance
41+
## Configure your PowerSync Instance
3142

3243
Create a new PowerSync instance, connecting to the database of the Supabase project.
3344

@@ -43,35 +54,55 @@ bucket_definitions:
4354
- select * from todos where list_id = bucket.list_id
4455
```
4556
46-
# Configure the app
57+
## Configure the app
58+
59+
Insert the credentials of your Supabase and PowerSync projects into `lib/app_config.dart`.
60+
61+
## Sign in to the app
62+
63+
Reload the app and sign up or sign in. Once successfully signed in, existing and new data should seamlessly sync with Supabase.
64+
65+
66+
# How this works
67+
68+
This app uses [local-only](https://pub.dev/documentation/powersync/latest/powersync/Table/Table.localOnly.html) tables to persist data until the user has registered or signed in. Local-only tables do not log updates in an upload queue, avoiding any overhead or growth in database size.
69+
70+
Once the user registers, the data is moved over to synced tables, at which point the data would be placed in the upload queue and will start syncing.
71+
72+
## Naive implementation
4773

48-
Insert the credentials of your new Supabase and PowerSync projects into `lib/app_config.dart`
74+
A barebones way to achieve the above is to store and query data from local-only tables before registration, copy this data to each corresponding synced table after registration and then store and query from the synced tables. This would look as follows:
4975

50-
# Explanation
76+
![diagram-0](./assets/local-only-readme-0.png)
77+
78+
The downside to this approach is that app queries would need to continuously differentiate between the two tables based on whether the user signed in or not.
79+
80+
## Recommended implementation
81+
82+
To keep app queries consistent between the two states, we utilize the [viewName](https://pub.dev/documentation/powersync/latest/powersync/Table/viewName.html) property, which allows overriding the default name of the view that is used in queries.
83+
84+
This looks as follows in the local-only state:
85+
86+
![diagram-1](./assets/local-only-readme-1.png)
87+
88+
The local-only tables (`local_lists` and `local_todos`) have their view names overriden to `listsAlias` and `todosAlias`, and these names are used in queries (e.g. `PowerSync.getAll("SELECT * FROM listsAlias");`). The `lists` and `todos` tables are not used in this state, but will become relevant in the next step.
89+
90+
When the user registers / signs in:
91+
92+
![diagram-2](./assets/local-only-readme-2.png)
93+
94+
The _synced_ tables (`lists` and `todos`) now have their view names overriden to `listsAlias` and `todosAlias`. Note that `updateSchema` must be run to update the view name. See the [schema](./lib/models/schema.dart) for details about this. The app query `PowerSync.getAll("SELECT * FROM listsAlias")` now reads data from the `lists` table.
95+
96+
Finally, copy data from the local-only tables to the synced tables, and delete data from the local-only tables to reduce database size:
97+
98+
![diagram-3](./assets/local-only-readme-3.png)
5199

52-
The demo implements local-only and synced modes by using two sets of schema definitions, which can be viewed [here](./lib/models/schema.dart).
53100

54-
The first set doesn't record changes in an upload queue, this is achieved by using the localOnly table definition.
55-
When the user registers and sync must start, copy the data in the first schema over to a second set of regular / synced schema
56101

57102
At this point, being signed in no longer determines which schema should be used, as the user's session expiring and explicitly signing out trigger different behaviors. If the session expires, the user can continue interacting with their data. However, if the user explicitly logs out, all data is cleared, effectively resetting the app. To manage this, an additional local storage mechanism is used to track which schema is currently in use, as seen [here](./lib/models/sync_mode.dart). Note that any other local storage solution would work as long as it's not using the PowerSync database (chicken and egg problem).
58103

59-
## Flow chart
60-
61-
```mermaid
62-
graph TD
63-
K[Start] --> A[App is empty and local-only]
64-
A --> B[User creates todos that are stored local-only]
65-
A --> C[User can login/register]
66-
B -->
67-
C --> D[Local-only data gets synced to PowerSync service]
68-
D --> E[User creates todos that will get synced]
69-
D --> F
70-
E --> F[User can logout explicitly]
71-
F --> A
72-
```
73104

74-
## Limitations
105+
# Limitations
75106

76-
`updateSchema` cannot be called inside a transaction, and it's recommended to perform the schema update when the database isn't connected.
77-
Additionally, the current implementation of the PowerSync SDK's `watch` method may not correctly track tables that are altered by `updateSchema`. Note that `refreshSchema` can be executed after updating the schema to resolve this (the demo uses it in `switchToSyncedSchema` which can be viewed [here](./lib/models/schema.dart)).
107+
- `updateSchema` cannot be called inside a transaction, and it's recommended to perform the schema update when the database isn't connected.
108+
- Additionally, the current implementation of the PowerSync SDK's `watch` method may not correctly track tables that are altered by `updateSchema`. Note that `refreshSchema` can be executed after updating the schema to resolve this (the demo uses it in `switchToSyncedSchema` which can be viewed [here](./lib/models/schema.dart)).
Loading
Loading
Loading
Loading

demos/local-only-todolist/lib/models/schema.dart

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,12 @@
11
import 'package:powersync/powersync.dart';
22
import 'package:powersync_flutter_local_only_demo/models/sync_mode.dart';
33

4-
/// This schema design supports a local-only to online workflow by managing data
4+
/// This schema design supports a local-only to sync workflow by managing data
55
/// across two versions of each table: one for local/offline use and one for
66
/// online/synced use. This approach simplifies the handling of data in different
77
/// connectivity states.
88
///
9-
/// For local-only, the views become:
10-
/// inactive_synced_todos
11-
/// todos
12-
/// inactive_synced_lists
13-
/// lists
14-
///
15-
/// - 'todos' and 'lists' refer to the local-only data.
16-
/// - 'inactive_synced_todos' and 'inactive_synced_lists' refer to the data that will be synced
17-
/// once online.
18-
///
19-
/// For online, we have these views:
20-
/// todos
21-
/// inactive_local_todos
22-
/// lists
23-
/// inactive_local_lists
24-
///
25-
/// - 'todos' and 'lists' refer to the synced/online data.
26-
/// - `inactive_local_todos' and 'inactive_local_lists' refer to the local-only data, allowing
27-
/// for temporary storage or operations before syncing.
9+
/// See the README for details.
2810
///
2911
/// For an offline-to-online transition [switchToSyncedSchema] copies data so that it ends up in the upload queue.
3012

0 commit comments

Comments
 (0)