Skip to content

Commit 1d92463

Browse files
committed
Improve compatibility check for core extension
1 parent 0949fe1 commit 1d92463

File tree

5 files changed

+103
-19
lines changed

5 files changed

+103
-19
lines changed

packages/powersync_core/lib/powersync_core.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ export 'src/database/powersync_database.dart';
99
export 'src/exceptions.dart';
1010
export 'src/log.dart';
1111
export 'src/open_factory.dart';
12-
export 'src/powersync_database.dart';
1312
export 'src/schema.dart';
1413
export 'src/sync_status.dart';
1514
export 'src/uuid.dart';
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import 'package:sqlite_async/sqlite3_common.dart';
2+
3+
/// A parsed (major, minor, patch) version triple representing a version of the
4+
/// loaded core extension.
5+
extension type const PowerSyncCoreVersion((int, int, int) _tuple) {
6+
int get major => _tuple.$1;
7+
int get minor => _tuple.$2;
8+
int get patch => _tuple.$3;
9+
10+
int compareTo(PowerSyncCoreVersion other) {
11+
return switch (major.compareTo(other.major)) {
12+
0 => switch (minor.compareTo(other.minor)) {
13+
0 => patch.compareTo(other.patch),
14+
var other => other,
15+
},
16+
var other => other,
17+
};
18+
}
19+
20+
bool operator >=(PowerSyncCoreVersion other) => compareTo(other) >= 0;
21+
22+
String get versionString => '$major.$minor.$patch';
23+
24+
void checkSupported() {
25+
const isWeb = bool.fromEnvironment('dart.library.js_interop');
26+
27+
if (minimum >= this || this >= maximumExclusive) {
28+
var message =
29+
'Unsupported powersync extension version. This version of the '
30+
'PowerSync SDK needs >=${minimum.versionString} '
31+
'<${maximumExclusive.versionString}, '
32+
'but detected version $versionString.';
33+
if (isWeb) {
34+
message +=
35+
'\nTry downloading the updated assets: https://docs.powersync.com/client-sdk-references/flutter/flutter-web-support#assets';
36+
}
37+
38+
throw SqliteException(1, message);
39+
}
40+
}
41+
42+
/// Parses the output of `powersync_rs_version()`, e.g. `0.3.9/5d64f366`, into
43+
/// a [PowerSyncCoreVersion].
44+
static PowerSyncCoreVersion parse(String version) {
45+
try {
46+
final [major, minor, patch] =
47+
version.split(RegExp(r'[./]')).take(3).map(int.parse).toList();
48+
49+
return PowerSyncCoreVersion((major, minor, patch));
50+
} catch (e) {
51+
throw SqliteException(1,
52+
'Unsupported powersync extension version. Need >=0.2.0 <1.0.0, got: $version. Details: $e');
53+
}
54+
}
55+
56+
/// The minimum version of the sqlite core extensions we support. We check
57+
/// this version when opening databases to fail early and with an actionable
58+
/// error message.
59+
static const minimum = PowerSyncCoreVersion((0, 3, 11));
60+
61+
/// The first version of the core extensions that this version of the Dart
62+
/// SDK doesn't support.
63+
static const maximumExclusive = PowerSyncCoreVersion((1, 0, 0));
64+
}

packages/powersync_core/lib/src/database/powersync_db_mixin.dart

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import 'package:powersync_core/sqlite_async.dart';
77
import 'package:powersync_core/src/abort_controller.dart';
88
import 'package:powersync_core/src/connector.dart';
99
import 'package:powersync_core/src/crud.dart';
10+
import 'package:powersync_core/src/database/core_version.dart';
1011
import 'package:powersync_core/src/powersync_update_notification.dart';
1112
import 'package:powersync_core/src/schema.dart';
1213
import 'package:powersync_core/src/schema_logic.dart';
@@ -93,23 +94,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection {
9394
1, 'The powersync extension is not loaded correctly. Details: $e');
9495
}
9596

96-
// Parse version
97-
List<int> versionInts;
98-
try {
99-
versionInts =
100-
version.split(RegExp(r'[./]')).take(3).map(int.parse).toList();
101-
} catch (e) {
102-
throw SqliteException(1,
103-
'Unsupported powersync extension version. Need >=0.2.0 <1.0.0, got: $version. Details: $e');
104-
}
105-
106-
// Validate >=0.2.0 <1.0.0
107-
if (versionInts[0] != 0 ||
108-
(versionInts[1] < 2) ||
109-
(versionInts[1] == 2 && versionInts[2] < 0)) {
110-
throw SqliteException(1,
111-
'Unsupported powersync extension version. Need >=0.2.0 <1.0.0, got: $version');
112-
}
97+
PowerSyncCoreVersion.parse(version).checkSupported();
11398
}
11499

115100
/// Wait for initialization to complete.

packages/powersync_core/lib/src/powersync_database.dart

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import 'package:powersync_core/src/database/core_version.dart';
2+
import 'package:sqlite3/sqlite3.dart';
3+
import 'package:test/test.dart';
4+
5+
void main() {
6+
group('PowerSyncCoreVersion', () {
7+
test('parse', () {
8+
expect(PowerSyncCoreVersion.parse('0.3.9/5d64f366'), (0, 3, 9));
9+
});
10+
11+
test('compare', () {
12+
void expectLess(String a, String b) {
13+
final parsedA = PowerSyncCoreVersion.parse(a);
14+
final parsedB = PowerSyncCoreVersion.parse(b);
15+
16+
expect(parsedA.compareTo(parsedB), -1);
17+
expect(parsedB.compareTo(parsedA), 1);
18+
19+
expect(parsedA.compareTo(parsedA), 0);
20+
expect(parsedB.compareTo(parsedB), 0);
21+
}
22+
23+
expectLess('0.1.0', '1.0.0');
24+
expectLess('1.0.0', '1.2.0');
25+
expectLess('0.3.9', '0.3.11');
26+
});
27+
28+
test('checkSupported', () {
29+
expect(PowerSyncCoreVersion.parse('0.3.10').checkSupported,
30+
throwsA(isA<SqliteException>()));
31+
expect(PowerSyncCoreVersion.parse('0.4.5').checkSupported,
32+
isNot(throwsA(anything)));
33+
expect(PowerSyncCoreVersion.parse('1.0.0').checkSupported,
34+
throwsA(isA<SqliteException>()));
35+
});
36+
});
37+
}

0 commit comments

Comments
 (0)