diff --git a/packages/powersync_core/analysis_options.yaml b/packages/powersync_core/analysis_options.yaml index dee8927a..4be9ff7b 100644 --- a/packages/powersync_core/analysis_options.yaml +++ b/packages/powersync_core/analysis_options.yaml @@ -13,6 +13,12 @@ include: package:lints/recommended.yaml +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + # Uncomment the following section to specify additional rules. # linter: diff --git a/packages/powersync_core/example/getting_started.dart b/packages/powersync_core/example/getting_started.dart index eb291b3b..13f43642 100644 --- a/packages/powersync_core/example/getting_started.dart +++ b/packages/powersync_core/example/getting_started.dart @@ -91,7 +91,7 @@ Future getDatabasePath() async { return join(dir, dbFilename); } -openDatabase() async { +Future openDatabase() async { // Setup the database. final psFactory = PowerSyncDartOpenFactory(path: await getDatabasePath()); db = PowerSyncDatabase.withFactory(psFactory, schema: schema); diff --git a/packages/powersync_core/lib/src/bucket_storage.dart b/packages/powersync_core/lib/src/bucket_storage.dart index 804a278c..6815e8d9 100644 --- a/packages/powersync_core/lib/src/bucket_storage.dart +++ b/packages/powersync_core/lib/src/bucket_storage.dart @@ -21,7 +21,7 @@ class BucketStorage { _init(); } - _init() {} + void _init() {} // Use only for read statements Future select(String query, @@ -36,7 +36,8 @@ class BucketStorage { 'SELECT name as bucket, cast(last_op as TEXT) as op_id FROM ps_buckets WHERE pending_delete = 0 AND name != \'\$local\''); return [ for (var row in rows) - BucketState(bucket: row['bucket'], opId: row['op_id']) + BucketState( + bucket: row['bucket'] as String, opId: row['op_id'] as String) ]; } @@ -157,14 +158,16 @@ class BucketStorage { Checkpoint checkpoint) async { final rs = await select("SELECT powersync_validate_checkpoint(?) as result", [jsonEncode(checkpoint)]); - final result = jsonDecode(rs[0]['result']); - if (result['valid']) { + final result = + jsonDecode(rs[0]['result'] as String) as Map; + if (result['valid'] as bool) { return SyncLocalDatabaseResult(ready: true); } else { return SyncLocalDatabaseResult( checkpointValid: false, ready: false, - checkpointFailures: result['failed_buckets'].cast()); + checkpointFailures: + (result['failed_buckets'] as List).cast()); } } @@ -232,7 +235,7 @@ class BucketStorage { // Nothing to update return false; } - int seqBefore = rs.first['seq']; + int seqBefore = rs.first['seq'] as int; var opId = await checkpointCallback(); return await writeTransaction((tx) async { @@ -244,7 +247,7 @@ class BucketStorage { .execute('SELECT seq FROM sqlite_sequence WHERE name = \'ps_crud\''); assert(rs.isNotEmpty); - int seqAfter = rs.first['seq']; + int seqAfter = rs.first['seq'] as int; if (seqAfter != seqBefore) { // New crud data may have been uploaded since we got the checkpoint. Abort. return false; @@ -362,12 +365,13 @@ class SyncBucketData { this.nextAfter}); SyncBucketData.fromJson(Map json) - : bucket = json['bucket'], - hasMore = json['has_more'] ?? false, - after = json['after'], - nextAfter = json['next_after'], - data = - (json['data'] as List).map((e) => OplogEntry.fromJson(e)).toList(); + : bucket = json['bucket'] as String, + hasMore = json['has_more'] as bool? ?? false, + after = json['after'] as String?, + nextAfter = json['next_after'] as String?, + data = (json['data'] as List) + .map((e) => OplogEntry.fromJson(e as Map)) + .toList(); Map toJson() { return { @@ -407,16 +411,25 @@ class OplogEntry { required this.checksum}); OplogEntry.fromJson(Map json) - : opId = json['op_id'], - op = OpType.fromJson(json['op']), - rowType = json['object_type'], - rowId = json['object_id'], - checksum = json['checksum'], - data = json['data'] is String ? json['data'] : jsonEncode(json['data']), - subkey = json['subkey'] is String ? json['subkey'] : null; + : opId = json['op_id'] as String, + op = OpType.fromJson(json['op'] as String), + rowType = json['object_type'] as String?, + rowId = json['object_id'] as String?, + checksum = json['checksum'] as int, + data = switch (json['data']) { + String data => data, + var other => jsonEncode(other), + }, + subkey = switch (json['subkey']) { + String subkey => subkey, + _ => null, + }; Map? get parsedData { - return data == null ? null : jsonDecode(data!); + return switch (data) { + final data? => jsonDecode(data) as Map, + null => null, + }; } /// Key to uniquely represent a source entry in a bucket. @@ -463,8 +476,8 @@ class SyncLocalDatabaseResult { @override int get hashCode { - return Object.hash( - ready, checkpointValid, const ListEquality().hash(checkpointFailures)); + return Object.hash(ready, checkpointValid, + const ListEquality().hash(checkpointFailures)); } @override @@ -472,7 +485,7 @@ class SyncLocalDatabaseResult { return other is SyncLocalDatabaseResult && other.ready == ready && other.checkpointValid == checkpointValid && - const ListEquality() + const ListEquality() .equals(other.checkpointFailures, checkpointFailures); } } diff --git a/packages/powersync_core/lib/src/connector.dart b/packages/powersync_core/lib/src/connector.dart index f8d58460..acb7b961 100644 --- a/packages/powersync_core/lib/src/connector.dart +++ b/packages/powersync_core/lib/src/connector.dart @@ -90,13 +90,13 @@ class PowerSyncCredentials { } factory PowerSyncCredentials.fromJson(Map parsed) { - String token = parsed['token']; + String token = parsed['token'] as String; DateTime? expiresAt = getExpiryDate(token); return PowerSyncCredentials( - endpoint: parsed['endpoint'], - token: parsed['token'], - userId: parsed['user_id'], + endpoint: parsed['endpoint'] as String, + token: token, + userId: parsed['user_id'] as String?, expiresAt: expiresAt); } @@ -110,9 +110,9 @@ class PowerSyncCredentials { // dart:convert doesn't like missing padding final rawData = base64Url.decode(base64.normalize(parts[1])); final text = Utf8Decoder().convert(rawData); - Map payload = jsonDecode(text); - if (payload.containsKey('exp') && payload['exp'] is int) { - return DateTime.fromMillisecondsSinceEpoch(payload['exp'] * 1000); + final payload = jsonDecode(text) as Map; + if (payload['exp'] case int exp) { + return DateTime.fromMillisecondsSinceEpoch(exp * 1000); } } return null; @@ -131,7 +131,7 @@ class PowerSyncCredentials { return Uri.parse(endpoint).resolve(path); } - _validateEndpoint() { + void _validateEndpoint() { final parsed = Uri.parse(endpoint); if ((!parsed.isScheme('http') && !parsed.isScheme('https')) || parsed.host.isEmpty) { @@ -162,14 +162,14 @@ class DevCredentials { factory DevCredentials.fromJson(Map parsed) { return DevCredentials( - endpoint: parsed['endpoint'], - token: parsed['token'], - userId: parsed['user_id']); + endpoint: parsed['endpoint'] as String, + token: parsed['token'] as String?, + userId: parsed['user_id'] as String?); } factory DevCredentials.fromString(String credentials) { var parsed = jsonDecode(credentials); - return DevCredentials.fromJson(parsed); + return DevCredentials.fromJson(parsed as Map); } static DevCredentials? fromOptionalString(String? credentials) { @@ -255,10 +255,12 @@ class DevConnector extends PowerSyncBackendConnector { if (res.statusCode == 200) { var parsed = jsonDecode(res.body); + var data = parsed['data'] as Map; + storeDevCredentials(DevCredentials( endpoint: endpoint, - token: parsed['data']['token'], - userId: parsed['data']['user_id'])); + token: data['token'] as String?, + userId: data['user_id'] as String?)); } else { throw http.ClientException(res.reasonPhrase ?? 'Request failed', uri); } @@ -281,7 +283,8 @@ class DevConnector extends PowerSyncBackendConnector { throw http.ClientException(res.reasonPhrase ?? 'Request failed', uri); } - return PowerSyncCredentials.fromJson(jsonDecode(res.body)['data']); + return PowerSyncCredentials.fromJson( + jsonDecode(res.body)['data'] as Map); } /// Upload changes using the PowerSync dev API. @@ -319,7 +322,7 @@ class DevConnector extends PowerSyncBackendConnector { final body = jsonDecode(response.body); // writeCheckpoint is optional, but reduces latency between writing, // and reading back the same change. - final String? writeCheckpoint = body['data']['write_checkpoint']; + final writeCheckpoint = body['data']['write_checkpoint'] as String?; await batch.complete(writeCheckpoint: writeCheckpoint); } } diff --git a/packages/powersync_core/lib/src/crud.dart b/packages/powersync_core/lib/src/crud.dart index 5a11ae4d..3cf6afaf 100644 --- a/packages/powersync_core/lib/src/crud.dart +++ b/packages/powersync_core/lib/src/crud.dart @@ -81,9 +81,15 @@ class CrudEntry { this.opData); factory CrudEntry.fromRow(sqlite.Row row) { - final data = jsonDecode(row['data']); - return CrudEntry(row['id'], UpdateType.fromJsonChecked(data['op'])!, - data['type'], data['id'], row['tx_id'], data['data']); + final data = jsonDecode(row['data'] as String); + return CrudEntry( + row['id'] as int, + UpdateType.fromJsonChecked(data['op'] as String)!, + data['type'] as String, + data['id'] as String, + row['tx_id'] as int, + data['data'] as Map?, + ); } /// Converts the change to JSON format, as required by the dev crud API. @@ -111,13 +117,13 @@ class CrudEntry { other.op == op && other.table == table && other.id == id && - const MapEquality().equals(other.opData, opData)); + const MapEquality().equals(other.opData, opData)); } @override int get hashCode { return Object.hash(transactionId, clientId, op.toJson(), table, id, - const MapEquality().hash(opData)); + const MapEquality().hash(opData)); } } diff --git a/packages/powersync_core/lib/src/database/native/native_powersync_database.dart b/packages/powersync_core/lib/src/database/native/native_powersync_database.dart index a2a6d028..0b61898c 100644 --- a/packages/powersync_core/lib/src/database/native/native_powersync_database.dart +++ b/packages/powersync_core/lib/src/database/native/native_powersync_database.dart @@ -143,10 +143,10 @@ class PowerSyncDatabaseImpl await isInitialized; final dbRef = database.isolateConnectionFactory(); ReceivePort rPort = ReceivePort(); - StreamSubscription? crudUpdateSubscription; + StreamSubscription? crudUpdateSubscription; rPort.listen((data) async { if (data is List) { - String action = data[0]; + String action = data[0] as String; if (action == "getCredentials") { await (data[1] as PortCompleter).handle(() async { final token = await connector.getCredentialsCached(); @@ -159,7 +159,7 @@ class PowerSyncDatabaseImpl await connector.prefetchCredentials(); }); } else if (action == 'init') { - SendPort port = data[1]; + SendPort port = data[1] as SendPort; var crudStream = database.onChange(['ps_crud'], throttle: crudThrottleTime); crudUpdateSubscription = crudStream.listen((event) { @@ -173,7 +173,7 @@ class PowerSyncDatabaseImpl await connector.uploadData(this); }); } else if (action == 'status') { - final SyncStatus status = data[1]; + final SyncStatus status = data[1] as SyncStatus; setStatus(status); } else if (action == 'close') { // Clear status apart from lastSyncedAt @@ -181,7 +181,7 @@ class PowerSyncDatabaseImpl rPort.close(); crudUpdateSubscription?.cancel(); } else if (action == 'log') { - LogRecord record = data[1]; + LogRecord record = data[1] as LogRecord; logger.log( record.level, record.message, record.error, record.stackTrace); } @@ -290,7 +290,7 @@ Future _powerSyncDatabaseIsolate( rPort.listen((message) async { if (message is List) { - String action = message[0]; + String action = message[0] as String; if (action == 'update') { crudUpdateController.add('update'); } else if (action == 'close') { diff --git a/packages/powersync_core/lib/src/database/powersync_db_mixin.dart b/packages/powersync_core/lib/src/database/powersync_db_mixin.dart index a5fb93a5..39bf8014 100644 --- a/packages/powersync_core/lib/src/database/powersync_db_mixin.dart +++ b/packages/powersync_core/lib/src/database/powersync_db_mixin.dart @@ -87,7 +87,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection { try { final row = await database.get('SELECT powersync_rs_version() as version'); - version = row['version']; + version = row['version'] as String; } catch (e) { throw SqliteException( 1, 'The powersync extension is not loaded correctly. Details: $e'); @@ -291,7 +291,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection { /// A connection factory that can be passed to different isolates. /// /// Use this to access the database in background isolates. - isolateConnectionFactory() { + IsolateConnectionFactory isolateConnectionFactory() { return database.isolateConnectionFactory(); } @@ -309,10 +309,10 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection { final row = await getOptional( 'SELECT SUM(cast(data as blob) + 20) as size, count(*) as count FROM ps_crud'); return UploadQueueStats( - count: row?['count'] ?? 0, size: row?['size'] ?? 0); + count: row?['count'] as int? ?? 0, size: row?['size'] as int? ?? 0); } else { final row = await getOptional('SELECT count(*) as count FROM ps_crud'); - return UploadQueueStats(count: row?['count'] ?? 0); + return UploadQueueStats(count: row?['count'] as int? ?? 0); } } @@ -331,7 +331,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection { /// This method does include transaction ids in the result, but does not group /// data by transaction. One batch may contain data from multiple transactions, /// and a single transaction may be split over multiple batches. - Future getCrudBatch({limit = 100}) async { + Future getCrudBatch({int limit = 100}) async { final rows = await getAll( 'SELECT id, tx_id, data FROM ps_crud ORDER BY id ASC LIMIT ?', [limit + 1]); @@ -384,7 +384,7 @@ mixin PowerSyncDatabaseMixin implements SqliteConnection { if (first == null) { return null; } - final int? txId = first['tx_id']; + final txId = first['tx_id'] as int?; List all; if (txId == null) { all = [CrudEntry.fromRow(first)]; diff --git a/packages/powersync_core/lib/src/exceptions.dart b/packages/powersync_core/lib/src/exceptions.dart index 82d55d1f..983876a2 100644 --- a/packages/powersync_core/lib/src/exceptions.dart +++ b/packages/powersync_core/lib/src/exceptions.dart @@ -87,8 +87,8 @@ String? _stringOrFirst(Object? details) { return null; } else if (details is String) { return details; - } else if (details is List && details[0] is String) { - return details[0]; + } else if (details case [final String first, ...]) { + return first; } else { return null; } diff --git a/packages/powersync_core/lib/src/isolate_completer.dart b/packages/powersync_core/lib/src/isolate_completer.dart index 7307ce8a..7192a59c 100644 --- a/packages/powersync_core/lib/src/isolate_completer.dart +++ b/packages/powersync_core/lib/src/isolate_completer.dart @@ -26,7 +26,7 @@ class IsolateResult { return PortCompleter(receivePort.sendPort); } - close() { + void close() { receivePort.close(); } } @@ -43,10 +43,10 @@ class PortCompleter { } void completeError(Object error, [StackTrace? stackTrace]) { - sendPort.send(PortResult.error(error, stackTrace)); + sendPort.send(PortResult.error(error, stackTrace)); } - addExitHandler() { + void addExitHandler() { Isolate.current.addOnExitListener(sendPort, response: abortedResponse); } diff --git a/packages/powersync_core/lib/src/setup_web.dart b/packages/powersync_core/lib/src/setup_web.dart index 6e62f980..f1e72c0f 100644 --- a/packages/powersync_core/lib/src/setup_web.dart +++ b/packages/powersync_core/lib/src/setup_web.dart @@ -116,8 +116,8 @@ bool coreVersionIsInRange(String tag) { } dynamic getPackageFromConfig(dynamic packageConfig, String packageName) { - final pkg = (packageConfig['packages'] ?? []).firstWhere( - (e) => e['name'] == packageName, + final pkg = (packageConfig['packages'] as List? ?? []).firstWhere( + (dynamic e) => e['name'] == packageName, orElse: () => null, ); if (pkg == null) { @@ -128,7 +128,8 @@ dynamic getPackageFromConfig(dynamic packageConfig, String packageName) { String getPubspecVersion( File packageConfigFile, dynamic package, String packageName) { - final rootUri = packageConfigFile.uri.resolve(package['rootUri'] ?? ''); + final rootUri = + packageConfigFile.uri.resolve(package['rootUri'] as String? ?? ''); print('Using package:$packageName from ${rootUri.toFilePath()}'); String pubspec = @@ -150,7 +151,7 @@ Future> getLatestTagsFromRelease(HttpClient httpClient) async { var response = await request.close(); if (response.statusCode == HttpStatus.ok) { var res = await response.transform(utf8.decoder).join(); - List jsonObj = json.decode(res); + var jsonObj = json.decode(res) as List; List tags = []; for (dynamic obj in jsonObj) { final tagName = obj['tag_name'] as String; diff --git a/packages/powersync_core/lib/src/stream_utils.dart b/packages/powersync_core/lib/src/stream_utils.dart index 37aee207..46be2f42 100644 --- a/packages/powersync_core/lib/src/stream_utils.dart +++ b/packages/powersync_core/lib/src/stream_utils.dart @@ -75,19 +75,19 @@ Stream newlines(ByteStream input) { return lineInput; } -void pauseAll(List subscriptions) { +void pauseAll(List> subscriptions) { for (var sub in subscriptions) { sub.pause(); } } -void resumeAll(List subscriptions) { +void resumeAll(List> subscriptions) { for (var sub in subscriptions) { sub.resume(); } } -Future cancelAll(List subscriptions) async { +Future cancelAll(List> subscriptions) async { final futures = subscriptions.map((sub) => sub.cancel()); await Future.wait(futures); } diff --git a/packages/powersync_core/lib/src/streaming_sync.dart b/packages/powersync_core/lib/src/streaming_sync.dart index 6f4191ff..f8a15566 100644 --- a/packages/powersync_core/lib/src/streaming_sync.dart +++ b/packages/powersync_core/lib/src/streaming_sync.dart @@ -43,7 +43,7 @@ class StreamingSyncImplementation implements StreamingSync { final StreamController _internalCrudTriggerController = StreamController.broadcast(); - final Stream crudUpdateTriggerStream; + final Stream crudUpdateTriggerStream; final StreamController _statusStreamController = StreamController.broadcast(); @@ -505,7 +505,7 @@ class StreamingSyncImplementation implements StreamingSync { /// Delays the standard `retryDelay` Duration, but exits early if /// an abort has been requested. Future _delayRetry() async { - await Future.any([Future.delayed(retryDelay), _abort!.onAbort]); + await Future.any([Future.delayed(retryDelay), _abort!.onAbort]); } } diff --git a/packages/powersync_core/lib/src/sync_types.dart b/packages/powersync_core/lib/src/sync_types.dart index 46eeb959..5ff51de0 100644 --- a/packages/powersync_core/lib/src/sync_types.dart +++ b/packages/powersync_core/lib/src/sync_types.dart @@ -9,10 +9,10 @@ class Checkpoint { {required this.lastOpId, required this.checksums, this.writeCheckpoint}); Checkpoint.fromJson(Map json) - : lastOpId = json['last_op_id'], - writeCheckpoint = json['write_checkpoint'], + : lastOpId = json['last_op_id'] as String, + writeCheckpoint = json['write_checkpoint'] as String?, checksums = (json['buckets'] as List) - .map((b) => BucketChecksum.fromJson(b)) + .map((b) => BucketChecksum.fromJson(b as Map)) .toList(); Map toJson() { @@ -41,10 +41,10 @@ class BucketChecksum { this.lastOpId}); BucketChecksum.fromJson(Map json) - : bucket = json['bucket'], - checksum = json['checksum'], - count = json['count'], - lastOpId = json['last_op_id']; + : bucket = json['bucket'] as String, + checksum = json['checksum'] as int, + count = json['count'] as int?, + lastOpId = json['last_op_id'] as String?; } class StreamingSyncCheckpoint { @@ -66,12 +66,12 @@ class StreamingSyncCheckpointDiff { this.lastOpId, this.updatedBuckets, this.removedBuckets); StreamingSyncCheckpointDiff.fromJson(Map json) - : lastOpId = json['last_op_id'], - writeCheckpoint = json['write_checkpoint'], + : lastOpId = json['last_op_id'] as String, + writeCheckpoint = json['write_checkpoint'] as String?, updatedBuckets = (json['updated_buckets'] as List) - .map((e) => BucketChecksum.fromJson(e)) + .map((e) => BucketChecksum.fromJson(e as Map)) .toList(), - removedBuckets = List.from(json['removed_buckets']); + removedBuckets = (json['removed_buckets'] as List).cast(); } class StreamingSyncCheckpointComplete { @@ -80,7 +80,7 @@ class StreamingSyncCheckpointComplete { StreamingSyncCheckpointComplete(this.lastOpId); StreamingSyncCheckpointComplete.fromJson(Map json) - : lastOpId = json['last_op_id']; + : lastOpId = json['last_op_id'] as String; } class StreamingSyncKeepalive { @@ -89,19 +89,20 @@ class StreamingSyncKeepalive { StreamingSyncKeepalive(this.tokenExpiresIn); StreamingSyncKeepalive.fromJson(Map json) - : tokenExpiresIn = json['token_expires_in']; + : tokenExpiresIn = json['token_expires_in'] as int; } Object? parseStreamingSyncLine(Map line) { if (line.containsKey('checkpoint')) { - return Checkpoint.fromJson(line['checkpoint']); + return Checkpoint.fromJson(line['checkpoint'] as Map); } else if (line.containsKey('checkpoint_diff')) { - return StreamingSyncCheckpointDiff.fromJson(line['checkpoint_diff']); + return StreamingSyncCheckpointDiff.fromJson( + line['checkpoint_diff'] as Map); } else if (line.containsKey('checkpoint_complete')) { return StreamingSyncCheckpointComplete.fromJson( - line['checkpoint_complete']); + line['checkpoint_complete'] as Map); } else if (line.containsKey('data')) { - return SyncBucketData.fromJson(line['data']); + return SyncBucketData.fromJson(line['data'] as Map); } else if (line.containsKey('token_expires_in')) { return StreamingSyncKeepalive.fromJson(line); } else { diff --git a/packages/powersync_core/lib/src/web/sync_worker.dart b/packages/powersync_core/lib/src/web/sync_worker.dart index 59c0d9a9..ebe6d586 100644 --- a/packages/powersync_core/lib/src/web/sync_worker.dart +++ b/packages/powersync_core/lib/src/web/sync_worker.dart @@ -9,6 +9,7 @@ import 'dart:js_interop'; import 'package:async/async.dart'; import 'package:fetch_client/fetch_client.dart'; +import 'package:logging/logging.dart'; import 'package:powersync_core/powersync_core.dart'; import 'package:powersync_core/sqlite_async.dart'; import 'package:powersync_core/src/database/powersync_db_mixin.dart'; @@ -59,7 +60,7 @@ class _ConnectedClient { final _SyncWorker _worker; _SyncRunner? _runner; - StreamSubscription? _logSubscription; + StreamSubscription? _logSubscription; _ConnectedClient(MessagePort port, this._worker) { channel = WorkerCommunicationChannel( diff --git a/packages/powersync_core/lib/src/web/sync_worker_protocol.dart b/packages/powersync_core/lib/src/web/sync_worker_protocol.dart index 9d8b8484..d5281e3d 100644 --- a/packages/powersync_core/lib/src/web/sync_worker_protocol.dart +++ b/packages/powersync_core/lib/src/web/sync_worker_protocol.dart @@ -201,8 +201,8 @@ final class WorkerCommunicationChannel { final Map> _pendingRequests = {}; int _nextRequestId = 0; bool _hasError = false; - StreamSubscription? _incomingMessages; - StreamSubscription? _incomingErrors; + StreamSubscription? _incomingMessages; + StreamSubscription? _incomingErrors; final MessagePort port; final FutureOr<(JSAny?, JSArray?)> Function(SyncWorkerMessageType, JSAny) diff --git a/packages/powersync_core/test/bucket_storage_test.dart b/packages/powersync_core/test/bucket_storage_test.dart index beb05d16..95d2e58c 100644 --- a/packages/powersync_core/test/bucket_storage_test.dart +++ b/packages/powersync_core/test/bucket_storage_test.dart @@ -486,7 +486,7 @@ void main() { await expectLater(() async { await powersync.execute('SELECT * FROM assets'); }, - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message.contains('no such table'))); await powersync.close(); @@ -521,7 +521,7 @@ void main() { await expectLater( () async => await powersync.execute('SELECT * FROM assets'), - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message.contains('no such table'))); await powersync.close(); diff --git a/packages/powersync_core/test/connected_test.dart b/packages/powersync_core/test/connected_test.dart index ff6a9b0c..d42afc52 100644 --- a/packages/powersync_core/test/connected_test.dart +++ b/packages/powersync_core/test/connected_test.dart @@ -49,7 +49,7 @@ void main() { addTearDown(() => {db.close()}); await db.initialize(); - final connectedCompleter = Completer(); + final connectedCompleter = Completer(); db.statusStream.listen((status) { if (status.connected) { @@ -69,7 +69,7 @@ void main() { test('should trigger uploads when connection is re-established', () async { int uploadCounter = 0; - Completer uploadTriggeredCompleter = Completer(); + var uploadTriggeredCompleter = Completer(); final testServer = await createTestServer(); final connector = TestConnector(() async { return PowerSyncCredentials( @@ -99,9 +99,9 @@ void main() { uploadTriggeredCompleter = Completer(); // Connect the PowerSync instance - final connectedCompleter = Completer(); + final connectedCompleter = Completer(); // The first connection attempt will fail - final connectedErroredCompleter = Completer(); + final connectedErroredCompleter = Completer(); db.statusStream.listen((status) { if (status.connected && !connectedCompleter.isCompleted) { @@ -185,7 +185,7 @@ void main() { await db.connect(connector: connector); await db.statusStream .firstWhere((status) => status.connected && status.downloading); - await Future.delayed(Duration(milliseconds: 20)); + await Future.delayed(Duration(milliseconds: 20)); expect( await db.getAll('select name from customers'), equals([ @@ -241,7 +241,7 @@ void main() { await db.connect(connector: connector); await db.statusStream .firstWhere((status) => status.connected && status.downloading); - await Future.delayed(Duration(milliseconds: 20)); + await Future.delayed(Duration(milliseconds: 20)); expect(await db.getAll('select name from customers'), equals([])); }); }); diff --git a/packages/powersync_core/test/crud_test.dart b/packages/powersync_core/test/crud_test.dart index 3a4ab635..e73a961b 100644 --- a/packages/powersync_core/test/crud_test.dart +++ b/packages/powersync_core/test/crud_test.dart @@ -72,7 +72,7 @@ void main() { 'INSERT INTO assets(id, description) VALUES(?, ?)', [testId, 'test3']); }, - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message.contains('UNIQUE constraint failed'))); }); @@ -132,7 +132,7 @@ void main() { 'INSERT INTO assets(id, description) VALUES(?, ?) ON CONFLICT DO UPDATE SET description = ?', [testId, 'test2', 'test3']); }, - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message.contains('cannot UPSERT a view'))); }); diff --git a/packages/powersync_core/test/offline_online_test.dart b/packages/powersync_core/test/offline_online_test.dart index 2fb1ed6d..b51766a6 100644 --- a/packages/powersync_core/test/offline_online_test.dart +++ b/packages/powersync_core/test/offline_online_test.dart @@ -118,7 +118,7 @@ void main() { }); final crud = (await db.getAll('SELECT data FROM ps_crud ORDER BY id')) - .map((d) => jsonDecode(d['data'])) + .map((d) => jsonDecode(d['data'] as String)) .toList(); expect( crud, diff --git a/packages/powersync_core/test/performance_shared_test.dart b/packages/powersync_core/test/performance_shared_test.dart index f4a20431..1d5222f3 100644 --- a/packages/powersync_core/test/performance_shared_test.dart +++ b/packages/powersync_core/test/performance_shared_test.dart @@ -77,7 +77,7 @@ void main() { final timer = Stopwatch()..start(); await db.writeTransaction((tx) async { - List futures = []; + List> futures = []; for (var i = 0; i < 1000; i++) { var future = tx.execute( 'INSERT INTO customers(id, name, email) VALUES(uuid(), ?, ?)', diff --git a/packages/powersync_core/test/powersync_native_test.dart b/packages/powersync_core/test/powersync_native_test.dart index a94aaa10..0be588bf 100644 --- a/packages/powersync_core/test/powersync_native_test.dart +++ b/packages/powersync_core/test/powersync_native_test.dart @@ -70,7 +70,7 @@ void main() { await expectLater(() async { await db.getAll('INSERT INTO assets(id) VALUES(?)', ['test']); }, - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message .contains('attempt to write in a read-only transaction'))); @@ -83,7 +83,7 @@ void main() { await db.getAll( "WITH test AS (SELECT 1 AS one) INSERT INTO assets(id) SELECT one FROM test"); }, - throwsA((e) => + throwsA((dynamic e) => e is SqliteException && e.message .contains('attempt to write in a read-only transaction'))); diff --git a/packages/powersync_core/test/powersync_shared_test.dart b/packages/powersync_core/test/powersync_shared_test.dart index 34405eb6..145cd3df 100644 --- a/packages/powersync_core/test/powersync_shared_test.dart +++ b/packages/powersync_core/test/powersync_shared_test.dart @@ -27,7 +27,9 @@ void main() { await db.writeTransaction((tx) async { await expectLater(() async { await db.execute('INSERT INTO assets(id) VALUES(?)', ['test']); - }, throwsA((e) => e is LockError && e.message.contains('tx.execute'))); + }, + throwsA((dynamic e) => + e is LockError && e.message.contains('tx.execute'))); }); }); @@ -41,7 +43,9 @@ void main() { // allow it by default. await expectLater(() async { await db.getAll('SELECT * FROM assets'); - }, throwsA((e) => e is LockError && e.message.contains('tx.getAll'))); + }, + throwsA((dynamic e) => + e is LockError && e.message.contains('tx.getAll'))); }); await db.readTransaction((tx) async { @@ -51,7 +55,9 @@ void main() { // opens another connection, but doesn't use it. await expectLater(() async { await db.getAll('SELECT * FROM assets'); - }, throwsA((e) => e is LockError && e.message.contains('tx.getAll'))); + }, + throwsA((dynamic e) => + e is LockError && e.message.contains('tx.getAll'))); }); }); @@ -63,16 +69,16 @@ void main() { await expectLater(() async { await db.getOptional('SELECT * FROM assets'); }, - throwsA( - (e) => e is LockError && e.message.contains('tx.getOptional'))); + throwsA((dynamic e) => + e is LockError && e.message.contains('tx.getOptional'))); }); await db.readLock((tx) async { await expectLater(() async { await db.getOptional('SELECT * FROM assets'); }, - throwsA( - (e) => e is LockError && e.message.contains('tx.getOptional'))); + throwsA((dynamic e) => + e is LockError && e.message.contains('tx.getOptional'))); }); }); diff --git a/packages/powersync_core/test/schema_test.dart b/packages/powersync_core/test/schema_test.dart index efa03552..7c8b8f33 100644 --- a/packages/powersync_core/test/schema_test.dart +++ b/packages/powersync_core/test/schema_test.dart @@ -76,7 +76,7 @@ void main() { // Updated expect(versionAfter2['schema_version'], - greaterThan(versionAfter['schema_version'])); + greaterThan(versionAfter['schema_version'] as int)); final schema3 = Schema([ Table('assets', [ @@ -106,7 +106,7 @@ void main() { // Updated again (index) expect(versionAfter3['schema_version'], - greaterThan(versionAfter2['schema_version'])); + greaterThan(versionAfter2['schema_version'] as int)); }); /// The assets table is locked after performing the EXPLAIN QUERY diff --git a/packages/powersync_core/test/stream_test.dart b/packages/powersync_core/test/stream_test.dart index 3550122e..4806269a 100644 --- a/packages/powersync_core/test/stream_test.dart +++ b/packages/powersync_core/test/stream_test.dart @@ -19,7 +19,7 @@ void main() { [int count = 50, Object? error]) async* { for (var i = 0; i < count; i++) { yield "$prefix $i"; - await Future.delayed(delay); + await Future.delayed(delay); } if (error != null) { throw error; @@ -70,7 +70,7 @@ void main() { Stream stream2 = genStream('S2:', Duration(milliseconds: 20)).asBroadcastStream(); - var controller = StreamController(); + var controller = StreamController(); var stream1 = controller.stream; var merged = addBroadcast(stream1, stream2); diff --git a/packages/powersync_core/test/streaming_sync_test.dart b/packages/powersync_core/test/streaming_sync_test.dart index 5238dd05..ae9e95b1 100644 --- a/packages/powersync_core/test/streaming_sync_test.dart +++ b/packages/powersync_core/test/streaming_sync_test.dart @@ -14,7 +14,7 @@ import 'utils/test_utils_impl.dart'; final testUtils = TestUtils(); class TestConnector extends PowerSyncBackendConnector { - final Function _fetchCredentials; + final Future Function() _fetchCredentials; final Future Function(PowerSyncDatabase)? _uploadData; TestConnector(this._fetchCredentials, @@ -63,7 +63,7 @@ void main() { var connector = TestConnector(credentialsCallback); pdb.connect(connector: connector); - await Future.delayed(Duration(milliseconds: random.nextInt(100))); + await Future.delayed(Duration(milliseconds: random.nextInt(100))); if (random.nextBool()) { server.close(); } @@ -73,7 +73,8 @@ void main() { // Give some time for connections to close final watch = Stopwatch()..start(); while (server.connectionCount != 0 && watch.elapsedMilliseconds < 100) { - await Future.delayed(Duration(milliseconds: random.nextInt(10))); + await Future.delayed( + Duration(milliseconds: random.nextInt(10))); } expect(server.connectionCount, equals(0)); @@ -116,7 +117,7 @@ void main() { // var stream = impl.streamingSyncRequest(StreamingSyncRequest([])); // 2ms: HttpException: HttpServer is not bound to a socket // 20ms: Connection closed while receiving data - await Future.delayed(Duration(milliseconds: 20)); + await Future.delayed(Duration(milliseconds: 20)); server.close(); } await pdb.close(); @@ -142,16 +143,16 @@ void main() { // Wait for at least one connection while (server.connectionCount < 1 && watch.elapsedMilliseconds < 500) { - await Future.delayed(Duration(milliseconds: random.nextInt(10))); + await Future.delayed(Duration(milliseconds: random.nextInt(10))); } // Give some time for a second connection if any - await Future.delayed(Duration(milliseconds: random.nextInt(50))); + await Future.delayed(Duration(milliseconds: random.nextInt(50))); await pdb.close(); // Give some time for connections to close while (server.connectionCount != 0 && watch.elapsedMilliseconds < 1000) { - await Future.delayed(Duration(milliseconds: random.nextInt(10))); + await Future.delayed(Duration(milliseconds: random.nextInt(10))); } expect(server.connectionCount, equals(0)); diff --git a/packages/powersync_core/test/test_server.dart b/packages/powersync_core/test/test_server.dart index 8054582e..6b456076 100644 --- a/packages/powersync_core/test/test_server.dart +++ b/packages/powersync_core/test/test_server.dart @@ -41,7 +41,7 @@ class TestServer { var blob = "*" * 5000; for (var i = 0; i < 50; i++) { yield {"token_expires_in": tokenExpiresIn, "blob": blob}; - await Future.delayed(Duration(microseconds: 1)); + await Future.delayed(Duration(microseconds: 1)); } } diff --git a/packages/powersync_core/test/upload_test.dart b/packages/powersync_core/test/upload_test.dart index 3044ec6a..62e952ed 100644 --- a/packages/powersync_core/test/upload_test.dart +++ b/packages/powersync_core/test/upload_test.dart @@ -15,7 +15,7 @@ const partialWarning = 'Potentially previously uploaded CRUD entries are still present'; class TestConnector extends PowerSyncBackendConnector { - final Function _fetchCredentials; + final Future Function() _fetchCredentials; final Future Function(PowerSyncDatabase database) _uploadData; TestConnector(this._fetchCredentials, this._uploadData); @@ -78,7 +78,7 @@ void main() { 'INSERT INTO assets(id, description) VALUES(?, ?)', [testId, 'test']); // Wait for the uploadData to be called. - await Future.delayed(Duration(milliseconds: 100)); + await Future.delayed(Duration(milliseconds: 100)); // Create something else with CRUD in it. await powersync.execute( diff --git a/packages/powersync_core/test/watch_test.dart b/packages/powersync_core/test/watch_test.dart index 55bd4c86..4aa9a4d4 100644 --- a/packages/powersync_core/test/watch_test.dart +++ b/packages/powersync_core/test/watch_test.dart @@ -57,7 +57,7 @@ void main() { await powersync.execute( 'INSERT INTO assets(id, make, customer_id) VALUES (uuid(), ?, ?)', ['test', id]); - await Future.delayed( + await Future.delayed( Duration(milliseconds: Random().nextInt(baseTime * 2))); } } @@ -74,7 +74,7 @@ void main() { var lastCount = 0; for (var r in results) { - final count = r.first['count']; + final count = r.first['count'] as int; // This is not strictly incrementing, since we can't guarantee the // exact order between reads and writes. // We can guarantee that there will always be a read after the last write, @@ -84,7 +84,8 @@ void main() { } // The number of read queries must not be greater than the number of writes overall. - expect(numberOfQueries, lessThanOrEqualTo(results.last.first['count'])); + expect(numberOfQueries, + lessThanOrEqualTo(results.last.first['count'] as int)); DateTime? lastTime; for (var r in times) { @@ -112,7 +113,7 @@ void main() { while (!done) { await powersync.execute( 'INSERT INTO assets(id, make) VALUES (uuid(), ?)', ['test']); - await Future.delayed( + await Future.delayed( Duration(milliseconds: Random().nextInt(baseTime))); } }