Skip to content

Commit d3f5e34

Browse files
SyncClient: support Sync filter variables #157
1 parent 47393b8 commit d3f5e34

File tree

3 files changed

+87
-8
lines changed

3 files changed

+87
-8
lines changed

objectbox/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
integer (`4_294_967_295`) that is used as the target object of a ToOne, correctly re-set the
99
target ID of the ToOne to `0`. [#740](https://github.com/objectbox/objectbox-dart/issues/740)
1010

11+
### Sync
12+
13+
- Support Sync server version 5.0.
14+
- **User-Specific Data Sync**: support configuring [Sync filter](https://sync.objectbox.io/sync-server/sync-filters)
15+
variables on `SyncClient`.
16+
1117
## 4.3.1 (2025-09-02)
1218

1319
* Requires at least Dart SDK 3.7 or Flutter SDK 3.29.

objectbox/lib/src/native/sync.dart

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ class SyncClient {
191191
/// Creates a Sync client associated with the given store and options.
192192
/// This does not initiate any connection attempts yet: call start() to do so.
193193
SyncClient._(
194-
this._store, List<String> serverUrls, List<SyncCredentials> credentials) {
194+
this._store, List<String> serverUrls, List<SyncCredentials> credentials,
195+
{Map<String, String>? filterVariables}) {
195196
if (serverUrls.isEmpty) {
196197
throw ArgumentError.value(
197198
serverUrls, "serverUrls", "Provide at least one server URL");
@@ -209,6 +210,8 @@ class SyncClient {
209210
C.sync_urls(InternalStoreAccess.ptr(_store), ptr, size),
210211
'failed to create Sync client'));
211212

213+
filterVariables?.forEach(putFilterVariable);
214+
212215
if (credentials.length == 1) {
213216
setCredentials(credentials[0]);
214217
} else {
@@ -258,6 +261,40 @@ class SyncClient {
258261
}
259262
}
260263

264+
/// Adds or replaces a [Sync filter](https://sync.objectbox.io/sync-server/sync-filters)
265+
/// variable value for the given name.
266+
///
267+
/// Eventually, existing values for the same name are replaced.
268+
///
269+
/// Sync client filter variables can be used in server-side Sync filters to
270+
/// filter out objects that do not match the filters. Filter variables must be
271+
/// added before login, so before calling `start()`.
272+
///
273+
/// See also [removeFilterVariable] and [removeAllFilterVariables].
274+
void putFilterVariable(String name, String value) {
275+
withNativeString(
276+
name,
277+
(nameCStr) => withNativeString(
278+
value,
279+
(valueCStr) => checkObx(
280+
C.sync_filter_variables_put(_ptr, nameCStr, valueCStr))));
281+
}
282+
283+
/// Removes a previously added Sync filter variable value.
284+
///
285+
/// See also [putFilterVariable] and [removeAllFilterVariables].
286+
void removeFilterVariable(String name) {
287+
withNativeString(name,
288+
(nameCStr) => checkObx(C.sync_filter_variables_remove(_ptr, nameCStr)));
289+
}
290+
291+
/// Removes all previously added Sync filter variable values.
292+
///
293+
/// See also [putFilterVariable] and [removeFilterVariable].
294+
void removeAllFilterVariables() {
295+
checkObx(C.sync_filter_variables_remove_all(_ptr));
296+
}
297+
261298
/// Configure authentication credentials, depending on your server config.
262299
void setCredentials(SyncCredentials creds) {
263300
if (creds is _SyncCredentialsNone) {
@@ -697,30 +734,43 @@ class Sync {
697734
///
698735
/// Before [SyncClient.start()], you can still configure some aspects of the
699736
/// client, e.g. its [SyncRequestUpdatesMode] mode.
737+
///
738+
/// To configure [Sync filter](https://sync.objectbox.io/sync-server/sync-filters)
739+
/// variables, pass variable names mapped to their value to [filterVariables].
740+
///
741+
/// Sync client filter variables can be used in server-side Sync filters to
742+
/// filter out objects that do not match the filter.
700743
static SyncClient client(
701-
Store store, String serverUrl, SyncCredentials credentials) =>
702-
clientMultiUrls(store, [serverUrl], credentials);
744+
Store store, String serverUrl, SyncCredentials credentials,
745+
{Map<String, String>? filterVariables}) =>
746+
clientMultiUrls(store, [serverUrl], credentials,
747+
filterVariables: filterVariables);
703748

704749
/// Like [client], but accepts a list of credentials.
705750
///
706751
/// When passing multiple credentials, does **not** support
707752
/// [SyncCredentials.none()].
708753
static SyncClient clientMultiCredentials(
709-
Store store, String serverUrl, List<SyncCredentials> credentials) =>
710-
clientMultiCredentialsMultiUrls(store, [serverUrl], credentials);
754+
Store store, String serverUrl, List<SyncCredentials> credentials,
755+
{Map<String, String>? filterVariables}) =>
756+
clientMultiCredentialsMultiUrls(store, [serverUrl], credentials,
757+
filterVariables: filterVariables);
711758

712759
/// Like [client], but accepts a list of URLs to work with multiple servers.
713760
static SyncClient clientMultiUrls(
714-
Store store, List<String> serverUrls, SyncCredentials credentials) =>
715-
clientMultiCredentialsMultiUrls(store, serverUrls, [credentials]);
761+
Store store, List<String> serverUrls, SyncCredentials credentials,
762+
{Map<String, String>? filterVariables}) =>
763+
clientMultiCredentialsMultiUrls(store, serverUrls, [credentials],
764+
filterVariables: filterVariables);
716765

717766
/// Like [client], but accepts a list of credentials and a list of URLs to
718767
/// work with multiple servers.
719768
///
720769
/// When passing multiple credentials, does **not** support
721770
/// [SyncCredentials.none()].
722771
static SyncClient clientMultiCredentialsMultiUrls(
723-
Store store, List<String> serverUrls, List<SyncCredentials> credentials) {
772+
Store store, List<String> serverUrls, List<SyncCredentials> credentials,
773+
{Map<String, String>? filterVariables}) {
724774
if (syncClientsStorage.containsKey(store)) {
725775
throw StateError('Only one sync client can be active for a store');
726776
}

objectbox_test/test/sync_test.dart

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,29 @@ void main() {
260260
]);
261261
});
262262

263+
test('SyncClient filter variables', () {
264+
final filterVariables = {
265+
'test-var-1': 'test value 1',
266+
'test-var-2': 'test value 2'
267+
};
268+
SyncClient client = Sync.client(
269+
store, serverUrl(), SyncCredentials.none(),
270+
filterVariables: filterVariables);
271+
addTearDown(() {
272+
client.close();
273+
});
274+
275+
client.putFilterVariable('test-var-2', 'test value 2');
276+
client.removeFilterVariable('test-var-2');
277+
client.putFilterVariable('test-var-2', '');
278+
client.removeAllFilterVariables();
279+
280+
expect(
281+
() => client.putFilterVariable('', 'value'),
282+
throwsA(isA<ArgumentError>().having((e) => e.message, 'message',
283+
contains('Filter variables must have a name'))));
284+
});
285+
263286
group('Server tests using sync-server in PATH', () {
264287
late SyncServer server;
265288

0 commit comments

Comments
 (0)