You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -42,6 +42,24 @@ Before implementing the PowerSync SDK in your project, make sure you have comple
42
42
*[Configured your backend database](/installation/database-setup) and connected it to your PowerSync instance.
43
43
*[Installed](/client-sdk-references/flutter#installation) the PowerSync Flutter SDK.
44
44
45
+
<Note>
46
+
For this reference document, we assume that you have created a Flutter project and have the following directory structure:
47
+
48
+
```plaintext
49
+
lib/
50
+
├── models/
51
+
├── schema.dart
52
+
└── todolist.dart
53
+
├── powersync/
54
+
├── my_backend_connector.dart
55
+
└── powersync.dart
56
+
├── widgets/
57
+
├── lists_widget.dart
58
+
├── todos_widget.dart
59
+
├── main.dart
60
+
```
61
+
</Note>
62
+
45
63
### 1\. Define the Schema
46
64
47
65
The first step is defining the schema for the local SQLite database. This will be provided as a `schema` parameter to the [PowerSyncDatabase](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/PowerSyncDatabase.html) constructor.
@@ -60,8 +78,7 @@ The types available are `text`, `integer` and `real`. These should map directly
60
78
61
79
**Example**:
62
80
63
-
```dart
64
-
// lib/models/schema.dart
81
+
```dart lib/models/schema.dart
65
82
import 'package:powersync/powersync.dart';
66
83
67
84
const schema = Schema(([
@@ -99,10 +116,12 @@ To instantiate `PowerSyncDatabase`, inject the Schema you defined in the previou
final dir = await getApplicationSupportDirectory();
@@ -117,9 +136,49 @@ openDatabase() async {
117
136
118
137
Once you've instantiated your PowerSync database, you will need to call the [connect()](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/connect.html) method to activate it. This method requires the backend connector that will be created in the next step.
119
138
120
-
```dart
121
-
// Uses the backend connector that will be created in the next step
122
-
db.connect(connector: MyBackendConnector(db));
139
+
```dart lib/main.dart {35}
140
+
import 'package:flutter/material.dart';
141
+
import 'package:powersync/powersync.dart';
142
+
143
+
import 'powersync/powersync.dart';
144
+
145
+
late PowerSyncDatabase db;
146
+
147
+
Future<void> main() async {
148
+
WidgetsFlutterBinding.ensureInitialized();
149
+
150
+
await openDatabase();
151
+
runApp(const DemoApp());
152
+
}
153
+
154
+
class DemoApp extends StatefulWidget {
155
+
const DemoApp({super.key});
156
+
157
+
@override
158
+
State<DemoApp> createState() => _DemoAppState();
159
+
}
160
+
161
+
class _DemoAppState extends State<DemoApp> {
162
+
@override
163
+
Widget build(BuildContext context) {
164
+
return MaterialApp(
165
+
title: 'Demo',
166
+
home: // TODO: Implement your own UI here.
167
+
// You could listen for authentication state changes to connect or disconnect from PowerSync
168
+
StreamBuilder(
169
+
stream: // TODO: some stream,
170
+
builder: (ctx, snapshot) {,
171
+
// TODO: implement your own condition here
172
+
if ( ... ) {
173
+
// Uses the backend connector that will be created in the next step
174
+
db.connect(connector: MyBackendConnector());
175
+
// TODO: implement your own UI here
176
+
}
177
+
},
178
+
)
179
+
);
180
+
}
181
+
}
123
182
```
124
183
125
184
### 3\. Integrate with your Backend
@@ -139,12 +198,8 @@ Accordingly, the connector must implement two methods:
class MyBackendConnector extends PowerSyncBackendConnector {
150
205
PowerSyncDatabase db;
@@ -159,18 +214,41 @@ class MyBackendConnector extends PowerSyncBackendConnector {
159
214
160
215
// See example implementation here: https://pub.dev/documentation/powersync/latest/powersync/DevConnector/fetchCredentials.html
161
216
162
-
return {
163
-
endpoint: '[Your PowerSync instance URL or self-hosted endpoint]',
164
-
// Use a development token (see Authentication Setup https://docs.powersync.com/installation/authentication-setup/development-tokens) to get up and running quickly
// Use a development token (see Authentication Setup https://docs.powersync.com/installation/authentication-setup/development-tokens) to get up and running quickly
220
+
token: 'An authentication token'
221
+
);
167
222
}
223
+
224
+
// Implement uploadData to send local changes to your backend service
225
+
// You can omit this method if you only want to sync data from the server to the client
226
+
// See example implementation here: https://docs.powersync.com/client-sdk-references/flutter#3-integrate-with-your-backend
// Implement uploadData to send local changes to your backend service
171
-
// You can omit this method if you only want to sync data from the server to the client
229
+
// This function is called whenever there is data to upload, whether the
230
+
// device is online or offline.
231
+
// If this call throws an error, it is retried periodically.
232
+
233
+
final transaction = await database.getNextCrudTransaction();
234
+
if (transaction == null) {
235
+
return;
236
+
}
172
237
173
-
// See example implementation here: https://docs.powersync.com/client-sdk-references/flutter#3-integrate-with-your-backend
238
+
// The data that needs to be changed in the remote db
239
+
for (var op in transaction.crud) {
240
+
switch (op.op) {
241
+
case UpdateType.put:
242
+
// TODO: Instruct your backend API to CREATE a record
243
+
case UpdateType.patch:
244
+
// TODO: Instruct your backend API to PATCH a record
245
+
case UpdateType.delete:
246
+
//TODO: Instruct your backend API to DELETE a record
247
+
}
248
+
}
249
+
250
+
// Completes the transaction and moves onto the next one
251
+
await transaction.complete();
174
252
}
175
253
}
176
254
@@ -187,12 +265,43 @@ The most commonly used CRUD functions to interact with your SQLite data are:
187
265
*[PowerSyncDatabase.watch](/client-sdk-references/flutter#watching-queries-powersync.watch)\- execute a read query every time source tables are modified.
188
266
*[PowerSyncDatabase.execute](/client-sdk-references/flutter#mutations-powersync.execute)\- execute a write (INSERT/UPDATE/DELETE) query.
189
267
268
+
For the following examples, we will define a `TodoList` model class that represents a List of todos.
269
+
270
+
```dart lib/models/todolist.dart
271
+
/// This is a simple model class representing a TodoList
The [get](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/get.html) method executes a read-only (SELECT) query and returns a single result. It throws an exception if no result is found. Use [getOptional](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/getOptional.html) to return a single optional result (returns `null` if no result is found).
193
299
194
-
```dart
195
-
// Find a list item by ID
300
+
The following is an example of selecting a list item by ID
301
+
```dart lib/widgets/lists_widget.dart
302
+
import '../main.dart';
303
+
import '../models/todolist.dart';
304
+
196
305
Future<TodoList> find(id) async {
197
306
final result = await db.get('SELECT * FROM lists WHERE id = ?', [id]);
The [getAll](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/getAll.html) method returns a set of rows from a table.
205
314
206
-
```dart
207
-
/// Get all list IDs
315
+
```dart lib/widgets/lists_widget.dart
316
+
import 'package:powersync/sqlite3.dart';
317
+
import '../main.dart';
318
+
208
319
Future<List<String>> getLists() async {
209
320
ResultSet results = await db.getAll('SELECT id FROM lists WHERE id IS NOT NULL');
210
321
List<String> ids = results.map((row) => row['id'] as String).toList();
211
322
return ids;
212
323
}
213
324
```
325
+
214
326
### Watching Queries (PowerSync.watch)
215
327
216
328
The [watch](https://pub.dev/documentation/powersync/latest/sqlite_async/SqliteQueries/watch.html) method executes a read query whenever a change to a dependent table is made.
217
329
218
-
```dart
219
-
StreamBuilder(
220
-
// You can watch any SQL query
221
-
stream: db.watch('SELECT * FROM customers ORDER BY id asc'),
222
-
builder: (context, snapshot) {
223
-
if (snapshot.hasData) {
224
-
// TODO: implement your own UI here based on the result set
The [execute](https://pub.dev/documentation/powersync/latest/powersync/PowerSyncDatabase/execute.html) method can be used for executing single SQLite write statements.
236
364
237
-
```dart
238
-
FloatingActionButton(
239
-
onPressed: () async {
240
-
await db.execute(
241
-
'INSERT INTO customers(id, name, email) VALUES(uuid(), ?, ?)',
242
-
['Fred', 'fred@example.org'],
365
+
```dart lib/widgets/todos_widget.dart {12-15}
366
+
import 'package:flutter/material.dart';
367
+
import '../main.dart';
368
+
369
+
// Example Todos widget
370
+
class TodosWidget extends StatelessWidget {
371
+
const TodosWidget({super.key});
372
+
373
+
@override
374
+
Widget build(BuildContext context) {
375
+
return FloatingActionButton(
376
+
onPressed: () async {
377
+
await db.execute(
378
+
'INSERT INTO lists(id, created_at, name, owner_id) VALUES(uuid(), datetime(), ?, ?)',
0 commit comments