Skip to content

Commit 46664f8

Browse files
committed
Restructure log and exception exports.
1 parent 25c0e17 commit 46664f8

File tree

7 files changed

+113
-95
lines changed

7 files changed

+113
-95
lines changed

packages/powersync/lib/powersync.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33
/// Use [PowerSyncDatabase] to open a database.
44
library;
55

6-
export 'src/powersync_database.dart';
7-
export 'src/schema.dart';
86
export 'src/connector.dart';
97
export 'src/crud.dart';
8+
export 'src/exceptions.dart';
9+
export 'src/log.dart';
10+
export 'src/open_factory.dart';
11+
export 'src/powersync_database.dart';
12+
export 'src/schema.dart';
1013
export 'src/sync_status.dart';
1114
export 'src/uuid.dart';
12-
export 'src/open_factory.dart';
13-
export 'src/log.dart' show attachedLogger, autoLogger, debugLogger;

packages/powersync/lib/src/bucket_storage.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import 'dart:async';
22
import 'dart:convert';
33

44
import 'package:collection/collection.dart';
5+
import 'package:powersync/src/log_internal.dart';
56
import 'package:sqlite_async/mutex.dart';
67
import 'package:sqlite_async/sqlite3.dart' as sqlite;
78

89
import 'crud.dart';
910
import 'database_utils.dart';
10-
import 'log.dart';
1111
import 'schema_logic.dart';
1212
import 'sync_types.dart';
1313
import 'uuid.dart';
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import 'dart:async';
2+
import 'dart:convert' as convert;
3+
4+
import 'package:http/http.dart' as http;
5+
6+
/// This indicates an error with configured credentials.
7+
class CredentialsException implements Exception {
8+
String message;
9+
10+
CredentialsException(this.message);
11+
12+
@override
13+
toString() {
14+
return 'CredentialsException: $message';
15+
}
16+
}
17+
18+
/// An internal protocol exception.
19+
///
20+
/// This indicates that the server sent an invalid response.
21+
class PowerSyncProtocolException implements Exception {
22+
String message;
23+
24+
PowerSyncProtocolException(this.message);
25+
26+
@override
27+
toString() {
28+
return 'SyncProtocolException: $message';
29+
}
30+
}
31+
32+
/// An error that received from the sync service.
33+
///
34+
/// Examples include authorization errors (401) and temporary service issues (503).
35+
class SyncResponseException implements Exception {
36+
/// Parse an error response from the PowerSync service
37+
static Future<SyncResponseException> fromStreamedResponse(
38+
http.StreamedResponse response) async {
39+
try {
40+
final body = await response.stream.bytesToString();
41+
final decoded = convert.jsonDecode(body);
42+
final details = _stringOrFirst(decoded['error']?['details']) ?? body;
43+
final message = '${response.reasonPhrase ?? "Request failed"}: $details';
44+
return SyncResponseException(response.statusCode, message);
45+
} on Error catch (_) {
46+
return SyncResponseException(
47+
response.statusCode,
48+
response.reasonPhrase ?? "Request failed",
49+
);
50+
}
51+
}
52+
53+
/// Parse an error response from the PowerSync service
54+
static SyncResponseException fromResponse(http.Response response) {
55+
try {
56+
final body = response.body;
57+
final decoded = convert.jsonDecode(body);
58+
final details = _stringOrFirst(decoded['error']?['details']) ?? body;
59+
final message = '${response.reasonPhrase ?? "Request failed"}: $details';
60+
return SyncResponseException(response.statusCode, message);
61+
} on Error catch (_) {
62+
return SyncResponseException(
63+
response.statusCode,
64+
response.reasonPhrase ?? "Request failed",
65+
);
66+
}
67+
}
68+
69+
int statusCode;
70+
String description;
71+
72+
SyncResponseException(this.statusCode, this.description);
73+
74+
@override
75+
toString() {
76+
return 'SyncResponseException: $statusCode $description';
77+
}
78+
}
79+
80+
String? _stringOrFirst(Object? details) {
81+
if (details == null) {
82+
return null;
83+
} else if (details is String) {
84+
return details;
85+
} else if (details is List && details[0] is String) {
86+
return details[0];
87+
} else {
88+
return null;
89+
}
90+
}

packages/powersync/lib/src/log.dart

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
import 'package:logging/logging.dart';
2-
3-
// Duplicate from package:flutter/foundation.dart, so we don't need to depend on Flutter
4-
const bool kReleaseMode = bool.fromEnvironment('dart.vm.product');
5-
const bool kProfileMode = bool.fromEnvironment('dart.vm.profile');
6-
const bool kDebugMode = !kReleaseMode && !kProfileMode;
7-
8-
// Implementation note: The loggers here are only initialized if used - it adds
9-
// no overhead when not used in the client app.
10-
11-
final isolateLogger = Logger.detached('PowerSync');
2+
import 'package:powersync/src/log_internal.dart';
123

134
/// Logger that outputs to the console in debug mode, and nothing
145
/// in release and profile modes.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import 'package:logging/logging.dart';
2+
3+
// Duplicate from package:flutter/foundation.dart, so we don't need to depend on Flutter
4+
const bool kReleaseMode = bool.fromEnvironment('dart.vm.product');
5+
const bool kProfileMode = bool.fromEnvironment('dart.vm.profile');
6+
const bool kDebugMode = !kReleaseMode && !kProfileMode;
7+
8+
// Implementation note: The loggers here are only initialized if used - it adds
9+
// no overhead when not used in the client app.
10+
11+
final isolateLogger = Logger.detached('PowerSync');

packages/powersync/lib/src/powersync_database.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import 'dart:async';
22
import 'dart:isolate';
33

44
import 'package:logging/logging.dart';
5+
import 'package:powersync/src/log_internal.dart';
56
import 'package:sqlite_async/sqlite3.dart' as sqlite;
67
import 'package:sqlite_async/sqlite_async.dart';
78

packages/powersync/lib/src/streaming_sync.dart

Lines changed: 4 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import 'dart:convert' as convert;
33
import 'dart:io';
44

55
import 'package:http/http.dart' as http;
6+
import 'package:powersync/src/exceptions.dart';
7+
import 'package:powersync/src/log_internal.dart';
68

79
import 'bucket_storage.dart';
810
import 'connector.dart';
9-
import 'log.dart';
1011
import 'stream_utils.dart';
1112
import 'sync_status.dart';
1213
import 'sync_types.dart';
@@ -140,7 +141,7 @@ class StreamingSyncImplementation {
140141
}
141142
}
142143
if (response.statusCode != 200) {
143-
throw _getError(response);
144+
throw SyncResponseException.fromResponse(response);
144145
}
145146

146147
final body = convert.jsonDecode(response.body);
@@ -341,7 +342,7 @@ class StreamingSyncImplementation {
341342
}
342343
}
343344
if (res.statusCode != 200) {
344-
throw await _getStreamedError(res);
345+
throw await SyncResponseException.fromStreamedResponse(res);
345346
}
346347

347348
// Note: The response stream is automatically closed when this loop errors
@@ -351,49 +352,6 @@ class StreamingSyncImplementation {
351352
}
352353
}
353354

354-
SyncResponseException _getError(http.Response response) {
355-
try {
356-
final body = response.body;
357-
final decoded = convert.jsonDecode(body);
358-
final details = _stringOrFirst(decoded['error']?['details']) ?? body;
359-
final message = '${response.reasonPhrase ?? "Request failed"}: $details';
360-
return SyncResponseException(response.statusCode, message);
361-
} on Error catch (_) {
362-
return SyncResponseException(
363-
response.statusCode,
364-
response.reasonPhrase ?? "Request failed",
365-
);
366-
}
367-
}
368-
369-
Future<SyncResponseException> _getStreamedError(
370-
http.StreamedResponse response) async {
371-
try {
372-
final body = await response.stream.bytesToString();
373-
final decoded = convert.jsonDecode(body);
374-
final details = _stringOrFirst(decoded['error']?['details']) ?? body;
375-
final message = '${response.reasonPhrase ?? "Request failed"}: $details';
376-
return SyncResponseException(response.statusCode, message);
377-
} on Error catch (_) {
378-
return SyncResponseException(
379-
response.statusCode,
380-
response.reasonPhrase ?? "Request failed",
381-
);
382-
}
383-
}
384-
385-
String? _stringOrFirst(Object? details) {
386-
if (details == null) {
387-
return null;
388-
} else if (details is String) {
389-
return details;
390-
} else if (details is List && details[0] is String) {
391-
return details[0];
392-
} else {
393-
return null;
394-
}
395-
}
396-
397355
/// Attempt to give a basic summary of the error for cases where the full error
398356
/// is not logged.
399357
String _syncErrorMessage(Object? error) {
@@ -419,37 +377,3 @@ String _syncErrorMessage(Object? error) {
419377
return '${error.runtimeType}';
420378
}
421379
}
422-
423-
class CredentialsException implements Exception {
424-
String message;
425-
426-
CredentialsException(this.message);
427-
428-
@override
429-
toString() {
430-
return 'CredentialsException: $message';
431-
}
432-
}
433-
434-
class PowerSyncProtocolException implements Exception {
435-
String message;
436-
437-
PowerSyncProtocolException(this.message);
438-
439-
@override
440-
toString() {
441-
return 'SyncProtocolException: $message';
442-
}
443-
}
444-
445-
class SyncResponseException implements Exception {
446-
int statusCode;
447-
String description;
448-
449-
SyncResponseException(this.statusCode, this.description);
450-
451-
@override
452-
toString() {
453-
return 'SyncResponseException: $statusCode $description';
454-
}
455-
}

0 commit comments

Comments
 (0)