Skip to content

Commit 1c039a3

Browse files
authoredJan 27, 2025··
Merge pull request #82 from powersync-ja/encryption-support
Package maintenance, prepare encryption and dart2wasm support
2 parents b20b3b3 + dbc501b commit 1c039a3

34 files changed

+228
-97
lines changed
 

‎.github/workflows/test.yaml

+5-5
Original file line numberDiff line numberDiff line change
@@ -35,19 +35,19 @@ jobs:
3535
include:
3636
- sqlite_version: "3440200"
3737
sqlite_url: "https://www.sqlite.org/2023/sqlite-autoconf-3440200.tar.gz"
38-
dart_sdk: 3.5.0
38+
dart_sdk: stable
3939
- sqlite_version: "3430200"
4040
sqlite_url: "https://www.sqlite.org/2023/sqlite-autoconf-3430200.tar.gz"
41-
dart_sdk: 3.5.0
41+
dart_sdk: stable
4242
- sqlite_version: "3420000"
4343
sqlite_url: "https://www.sqlite.org/2023/sqlite-autoconf-3420000.tar.gz"
44-
dart_sdk: 3.5.0
44+
dart_sdk: stable
4545
- sqlite_version: "3410100"
4646
sqlite_url: "https://www.sqlite.org/2023/sqlite-autoconf-3410100.tar.gz"
47-
dart_sdk: 3.5.0
47+
dart_sdk: stable
4848
- sqlite_version: "3380000"
4949
sqlite_url: "https://www.sqlite.org/2022/sqlite-autoconf-3380000.tar.gz"
50-
dart_sdk: 3.5.0
50+
dart_sdk: stable
5151
steps:
5252
- uses: actions/checkout@v3
5353
- uses: dart-lang/setup-dart@v1

‎melos.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ scripts:
4141

4242
test:
4343
description: Run tests in a specific package.
44-
run: dart test -p chrome,vm
44+
run: dart test -p chrome,vm --compiler dart2js,dart2wasm
4545
exec:
4646
concurrency: 1
4747
packageFilters:

‎packages/drift_sqlite_async/CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.2.1
2+
3+
- Fix lints.
4+
15
## 0.2.0
26

37
- Automatically run Drift migrations
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
library drift_sqlite_async;
2-
31
export './src/connection.dart';
42
export './src/executor.dart';

‎packages/drift_sqlite_async/lib/src/executor.dart

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import 'dart:async';
22

33
import 'package:drift/backends.dart';
4-
import 'package:drift/src/runtime/query_builder/query_builder.dart';
4+
import 'package:drift/drift.dart';
55
import 'package:sqlite_async/sqlite3_common.dart';
66
import 'package:sqlite_async/sqlite_async.dart';
77

@@ -19,6 +19,7 @@ class _SqliteAsyncDelegate extends _SqliteAsyncQueryDelegate
1919

2020
_SqliteAsyncDelegate(this.db) : super(db, db.writeLock);
2121

22+
@override
2223
bool isInTransaction = false; // unused
2324

2425
@override

‎packages/drift_sqlite_async/pubspec.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: drift_sqlite_async
2-
version: 0.2.0
2+
version: 0.2.1
33
homepage: https://github.com/powersync-ja/sqlite_async.dart
44
repository: https://github.com/powersync-ja/sqlite_async.dart
55
description: Use Drift with a sqlite_async database, allowing both to be used in the same application.
@@ -16,10 +16,12 @@ environment:
1616
dependencies:
1717
drift: ">=2.19.0 <3.0.0"
1818
sqlite_async: ^0.11.0
19+
1920
dev_dependencies:
2021
build_runner: ^2.4.8
2122
drift_dev: ">=2.19.0 <3.0.0"
2223
glob: ^2.1.2
24+
lints: ^5.0.0
2325
sqlite3: ^2.4.0
2426
test: ^1.25.2
2527
test_api: ^0.7.0

‎packages/drift_sqlite_async/test/basic_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// TODO
22
@TestOn('!browser')
3+
library;
4+
35
import 'dart:async';
46

57
import 'package:drift/drift.dart';

‎packages/drift_sqlite_async/test/db_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// TODO
22
@TestOn('!browser')
3+
library;
4+
35
import 'package:drift/drift.dart';
46
import 'package:sqlite_async/sqlite_async.dart';
57
import 'package:test/test.dart';

‎packages/drift_sqlite_async/test/generated/database.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class TodoDatabase extends _$TodoDatabase {
2121
}
2222

2323
class TodosMigrationDatabase extends TodoDatabase {
24-
TodosMigrationDatabase(SqliteConnection db) : super(db);
24+
TodosMigrationDatabase(super.db);
2525

2626
@override
2727
MigrationStrategy get migration {

‎packages/drift_sqlite_async/test/migration_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'package:sqlite_async/sqlite_async.dart';
35
import 'package:test/test.dart';
46

‎packages/sqlite_async/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 0.11.2
2+
3+
- Support latest version of `package:sqlite3_web`.
4+
- Support `dart2wasm`.
5+
16
## 0.11.1
27

38
- Remove remaining `dart:js_util` imports in favor of new interop APIs.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:lints/recommended.yaml

‎packages/sqlite_async/lib/src/web/database.dart

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import 'dart:async';
22
import 'dart:js_interop';
3+
import 'dart:js_interop_unsafe';
34

45
import 'package:sqlite3/common.dart';
56
import 'package:sqlite3_web/sqlite3_web.dart';
7+
import 'package:sqlite3_web/protocol_utils.dart' as proto;
68
import 'package:sqlite_async/sqlite_async.dart';
79
import 'package:sqlite_async/src/utils/shared_utils.dart';
810
import 'package:sqlite_async/src/web/database/broadcast_updates.dart';
@@ -256,9 +258,15 @@ class _ExclusiveTransactionContext extends _ExclusiveContext {
256258
// JavaScript object. This is the converted into a Dart ResultSet.
257259
return await wrapSqliteException(() async {
258260
var res = await _database._database.customRequest(CustomDatabaseMessage(
259-
CustomDatabaseMessageKind.executeInTransaction, sql, parameters));
260-
var result =
261-
Map<String, dynamic>.from((res as JSObject).dartify() as Map);
261+
CustomDatabaseMessageKind.executeInTransaction, sql, parameters))
262+
as JSObject;
263+
264+
if (res.has('format') && (res['format'] as JSNumber).toDartInt == 2) {
265+
// Newer workers use a serialization format more efficient than dartify().
266+
return proto.deserializeResultSet(res['r'] as JSObject);
267+
}
268+
269+
var result = Map<String, dynamic>.from(res.dartify() as Map);
262270
final columnNames = [
263271
for (final entry in result['columnNames']) entry as String
264272
];
@@ -303,9 +311,14 @@ Future<T> wrapSqliteException<T>(Future<T> Function() callback) async {
303311
try {
304312
return await callback();
305313
} on RemoteException catch (ex) {
314+
if (ex.exception case final serializedCause?) {
315+
throw serializedCause;
316+
}
317+
318+
// Older versions of package:sqlite_web reported SqliteExceptions as strings
319+
// only.
306320
if (ex.toString().contains('SqliteException')) {
307321
RegExp regExp = RegExp(r'SqliteException\((\d+)\)');
308-
// The SQLite Web package wraps these in remote errors
309322
throw SqliteException(
310323
int.parse(regExp.firstMatch(ex.message)?.group(1) ?? '0'),
311324
ex.message);

‎packages/sqlite_async/lib/src/web/protocol.dart

+17-4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
library;
44

55
import 'dart:js_interop';
6+
import 'package:sqlite3_web/protocol_utils.dart' as proto;
67

78
enum CustomDatabaseMessageKind {
89
requestSharedLock,
@@ -19,15 +20,24 @@ extension type CustomDatabaseMessage._raw(JSObject _) implements JSObject {
1920
required JSString rawKind,
2021
JSString rawSql,
2122
JSArray rawParameters,
23+
JSArrayBuffer typeInfo,
2224
});
2325

2426
factory CustomDatabaseMessage(CustomDatabaseMessageKind kind,
2527
[String? sql, List<Object?> parameters = const []]) {
26-
final rawSql = sql?.toJS ?? ''.toJS;
27-
final rawParameters =
28-
<JSAny?>[for (final parameter in parameters) parameter.jsify()].toJS;
28+
final rawSql = (sql ?? '').toJS;
29+
// Serializing parameters this way is backwards-compatible with dartify()
30+
// on the other end, but a bit more efficient while also suppporting sound
31+
// communcation between dart2js workers and dart2wasm clients.
32+
// Older workers ignore the typeInfo, but that's not a problem.
33+
final (rawParameters, typeInfo) = proto.serializeParameters(parameters);
34+
2935
return CustomDatabaseMessage._(
30-
rawKind: kind.name.toJS, rawSql: rawSql, rawParameters: rawParameters);
36+
rawKind: kind.name.toJS,
37+
rawSql: rawSql,
38+
rawParameters: rawParameters,
39+
typeInfo: typeInfo,
40+
);
3141
}
3242

3343
external JSString get rawKind;
@@ -36,6 +46,9 @@ extension type CustomDatabaseMessage._raw(JSObject _) implements JSObject {
3646

3747
external JSArray get rawParameters;
3848

49+
/// Not set in earlier versions of this package.
50+
external JSArrayBuffer? get typeInfo;
51+
3952
CustomDatabaseMessageKind get kind {
4053
return CustomDatabaseMessageKind.values.byName(rawKind.toDart);
4154
}

‎packages/sqlite_async/lib/src/web/web_sqlite_open_factory.dart

+3-4
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Map<String, FutureOr<WebSqlite>> webSQLiteImplementations = {};
1515
/// Web implementation of [AbstractDefaultSqliteOpenFactory]
1616
class DefaultSqliteOpenFactory
1717
extends AbstractDefaultSqliteOpenFactory<CommonDatabase>
18-
implements WebSqliteOpenFactory {
18+
with WebSqliteOpenFactory {
1919
late final Future<WebSqlite> _initialized = Future.sync(() {
2020
final cacheKey = sqliteOptions.webSqliteOptions.wasmUri +
2121
sqliteOptions.webSqliteOptions.workerUri;
@@ -45,9 +45,8 @@ class DefaultSqliteOpenFactory
4545
);
4646
}
4747

48-
@override
49-
5048
/// This is currently not supported on web
49+
@override
5150
CommonDatabase openDB(SqliteOpenOptions options) {
5251
throw UnimplementedError(
5352
'Direct access to CommonDatabase is not available on web.');
@@ -61,7 +60,7 @@ class DefaultSqliteOpenFactory
6160
/// Due to being asynchronous, the under laying CommonDatabase is not accessible
6261
Future<SqliteConnection> openConnection(SqliteOpenOptions options) async {
6362
final workers = await _initialized;
64-
final connection = await workers.connectToRecommended(path);
63+
final connection = await connectToWorker(workers, path);
6564

6665
// When the database is accessed through a shared worker, we implement
6766
// mutexes over custom messages sent through the shared worker. In other

‎packages/sqlite_async/lib/src/web/worker/throttled_common_database.dart

+1
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class ThrottledCommonDatabase extends CommonDatabase {
107107
@override
108108
VoidPredicate? get commitFilter => _db.commitFilter;
109109

110+
@override
110111
set commitFilter(VoidPredicate? filter) => _db.commitFilter = filter;
111112

112113
@override

‎packages/sqlite_async/lib/src/web/worker/worker_utils.dart

+37-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
import 'dart:js_interop';
2+
import 'dart:js_interop_unsafe';
23

4+
import 'package:meta/meta.dart';
35
import 'package:mutex/mutex.dart';
46
import 'package:sqlite3/wasm.dart';
57
import 'package:sqlite3_web/sqlite3_web.dart';
8+
import 'package:sqlite3_web/protocol_utils.dart' as proto;
9+
610
import 'throttled_common_database.dart';
711

812
import '../protocol.dart';
@@ -12,9 +16,9 @@ import '../protocol.dart';
1216
/// can be extended to perform custom requests.
1317
base class AsyncSqliteController extends DatabaseController {
1418
@override
15-
Future<WorkerDatabase> openDatabase(
16-
WasmSqlite3 sqlite3, String path, String vfs) async {
17-
final db = sqlite3.open(path, vfs: vfs);
19+
Future<WorkerDatabase> openDatabase(WasmSqlite3 sqlite3, String path,
20+
String vfs, JSAny? additionalData) async {
21+
final db = openUnderlying(sqlite3, path, vfs, additionalData);
1822

1923
// Register any custom functions here if needed
2024

@@ -23,6 +27,18 @@ base class AsyncSqliteController extends DatabaseController {
2327
return AsyncSqliteDatabase(database: throttled);
2428
}
2529

30+
/// Opens a database with the `sqlite3` package that will be wrapped in a
31+
/// [ThrottledCommonDatabase] for [openDatabase].
32+
@visibleForOverriding
33+
CommonDatabase openUnderlying(
34+
WasmSqlite3 sqlite3,
35+
String path,
36+
String vfs,
37+
JSAny? additionalData,
38+
) {
39+
return sqlite3.open(path, vfs: vfs);
40+
}
41+
2642
@override
2743
Future<JSAny?> handleCustomRequest(
2844
ClientConnection connection, JSAny? request) {
@@ -61,25 +77,32 @@ class AsyncSqliteDatabase extends WorkerDatabase {
6177
return database.autocommit.toJS;
6278
case CustomDatabaseMessageKind.executeInTransaction:
6379
final sql = message.rawSql.toDart;
64-
final parameters = [
65-
for (final raw in (message.rawParameters).toDart) raw.dartify()
66-
];
80+
final hasTypeInfo = message.typeInfo.isDefinedAndNotNull;
81+
final parameters = proto.deserializeParameters(
82+
message.rawParameters, message.typeInfo);
6783
if (database.autocommit) {
6884
throw SqliteException(0,
6985
"Transaction rolled back by earlier statement. Cannot execute: $sql");
7086
}
71-
var res = database.select(sql, parameters);
7287

73-
var dartMap = resultSetToMap(res);
74-
75-
var jsObject = dartMap.jsify();
88+
var res = database.select(sql, parameters);
89+
if (hasTypeInfo) {
90+
// If the client is sending a request that has parameters with type
91+
// information, it will also support a newer serialization format for
92+
// result sets.
93+
return JSObject()
94+
..['format'] = 2.toJS
95+
..['r'] = proto.serializeResultSet(res);
96+
} else {
97+
var dartMap = resultSetToMap(res);
98+
var jsObject = dartMap.jsify();
99+
return jsObject;
100+
}
76101

77-
return jsObject;
78102
case CustomDatabaseMessageKind.executeBatchInTransaction:
79103
final sql = message.rawSql.toDart;
80-
final parameters = [
81-
for (final raw in (message.rawParameters).toDart) raw.dartify()
82-
];
104+
final parameters = proto.deserializeParameters(
105+
message.rawParameters, message.typeInfo);
83106
if (database.autocommit) {
84107
throw SqliteException(0,
85108
"Transaction rolled back by earlier statement. Cannot execute: $sql");

‎packages/sqlite_async/lib/web.dart

+19-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
///
33
/// These expose methods allowing database instances to be shared across web
44
/// workers.
5-
library sqlite_async.web;
5+
library;
66

77
import 'package:sqlite3_web/sqlite3_web.dart';
88
import 'package:web/web.dart';
@@ -31,15 +31,29 @@ typedef WebDatabaseEndpoint = ({
3131
///
3232
/// The [DefaultSqliteOpenFactory] class implements this interface only when
3333
/// compiling for the web.
34-
abstract interface class WebSqliteOpenFactory
34+
abstract mixin class WebSqliteOpenFactory
3535
implements SqliteOpenFactory<CommonDatabase> {
3636
/// Opens a [WebSqlite] instance for the given [options].
3737
///
3838
/// This method can be overriden in scenarios where the way [WebSqlite] is
3939
/// opened needs to be customized. Implementers should be aware that the
4040
/// result of this method is cached and will be re-used by the open factory
4141
/// when provided with the same [options] again.
42-
Future<WebSqlite> openWebSqlite(WebSqliteOptions options);
42+
Future<WebSqlite> openWebSqlite(WebSqliteOptions options) async {
43+
return WebSqlite.open(
44+
worker: Uri.parse(options.workerUri),
45+
wasmModule: Uri.parse(options.wasmUri),
46+
);
47+
}
48+
49+
/// Uses [WebSqlite] to connects to the recommended database setup for [name].
50+
///
51+
/// This typically just calls [WebSqlite.connectToRecommended], but subclasses
52+
/// can customize the behavior where needed.
53+
Future<ConnectToRecommendedResult> connectToWorker(
54+
WebSqlite sqlite, String name) {
55+
return sqlite.connectToRecommended(name);
56+
}
4357
}
4458

4559
/// A [SqliteConnection] interface implemented by opened connections when
@@ -91,6 +105,7 @@ abstract class WebSqliteConnection implements SqliteConnection {
91105
/// This only has an effect when IndexedDB storage is used.
92106
///
93107
/// See [flush] for details.
108+
@override
94109
Future<T> writeLock<T>(Future<T> Function(SqliteWriteContext tx) callback,
95110
{Duration? lockTimeout, String? debugContext, bool? flush});
96111

@@ -101,6 +116,7 @@ abstract class WebSqliteConnection implements SqliteConnection {
101116
/// This only has an effect when IndexedDB storage is used.
102117
///
103118
/// See [flush] for details.
119+
@override
104120
Future<T> writeTransaction<T>(
105121
Future<T> Function(SqliteWriteContext tx) callback,
106122
{Duration? lockTimeout,

‎packages/sqlite_async/pubspec.yaml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: sqlite_async
22
description: High-performance asynchronous interface for SQLite on Dart and Flutter.
3-
version: 0.11.1
3+
version: 0.11.2
44
repository: https://github.com/powersync-ja/sqlite_async.dart
55
environment:
66
sdk: ">=3.5.0 <4.0.0"
@@ -13,16 +13,15 @@ topics:
1313

1414
dependencies:
1515
sqlite3: ^2.7.2
16-
sqlite3_web: ^0.2.2
16+
sqlite3_web: ^0.3.0
1717
async: ^2.10.0
1818
collection: ^1.17.0
1919
mutex: ^3.1.0
2020
meta: ^1.10.0
2121
web: ^1.0.0
2222

2323
dev_dependencies:
24-
dcli: ^4.0.0
25-
lints: ^3.0.0
24+
lints: ^5.0.0
2625
test: ^1.21.0
2726
test_api: ^0.7.0
2827
glob: ^2.1.1
@@ -31,6 +30,7 @@ dev_dependencies:
3130
shelf_static: ^1.1.2
3231
stream_channel: ^2.1.2
3332
path: ^1.9.0
33+
test_descriptor: ^2.0.2
3434

3535
platforms:
3636
android:

‎packages/sqlite_async/test/basic_test.dart

+58-38
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:test/test.dart';
66
import 'utils/test_utils_impl.dart';
77

88
final testUtils = TestUtils();
9+
const _isDart2Wasm = bool.fromEnvironment('dart.tool.dart2wasm');
910

1011
void main() {
1112
group('Shared Basic Tests', () {
@@ -125,48 +126,67 @@ void main() {
125126
expect(savedTx!.closed, equals(true));
126127
});
127128

128-
test('should properly report errors in transactions', () async {
129-
final db = await testUtils.setupDatabase(path: path);
130-
await createTables(db);
129+
test(
130+
'should properly report errors in transactions',
131+
() async {
132+
final db = await testUtils.setupDatabase(path: path);
133+
await createTables(db);
131134

132-
var tp = db.writeTransaction((tx) async {
133-
await tx.execute(
134-
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
135-
[1, 'test1']);
136-
await tx.execute(
137-
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
138-
[2, 'test2']);
139-
expect(await tx.getAutoCommit(), equals(false));
140-
try {
135+
var tp = db.writeTransaction((tx) async {
141136
await tx.execute(
142137
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
143-
[2, 'test3']);
144-
} catch (e) {
145-
// Ignore
146-
}
147-
148-
expect(await tx.getAutoCommit(), equals(true));
149-
expect(tx.closed, equals(false));
150-
151-
// Will not be executed because of the above rollback
152-
await tx.execute(
153-
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
154-
[4, 'test4']);
155-
});
156-
157-
// The error propagates up to the transaction
138+
[1, 'test1']);
139+
await tx.execute(
140+
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
141+
[2, 'test2']);
142+
expect(await tx.getAutoCommit(), equals(false));
143+
try {
144+
await tx.execute(
145+
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
146+
[2, 'test3']);
147+
} catch (e) {
148+
// Ignore
149+
}
150+
151+
expect(await tx.getAutoCommit(), equals(true));
152+
expect(tx.closed, equals(false));
153+
154+
// Will not be executed because of the above rollback
155+
await tx.execute(
156+
'INSERT OR ROLLBACK INTO test_data(id, description) VALUES(?, ?)',
157+
[4, 'test4']);
158+
});
159+
160+
// The error propagates up to the transaction
161+
await expectLater(
162+
tp,
163+
throwsA((e) =>
164+
e is SqliteException &&
165+
e.message
166+
.contains('Transaction rolled back by earlier statement')));
167+
168+
expect(await db.get('SELECT count() count FROM test_data'),
169+
equals({'count': 0}));
170+
171+
// Check that we can open another transaction afterwards
172+
await db.writeTransaction((tx) async {});
173+
},
174+
skip: _isDart2Wasm
175+
? 'Fails due to compiler bug, https://dartbug.com/59981'
176+
: null,
177+
);
178+
179+
test('reports exceptions as SqliteExceptions', () async {
180+
final db = await testUtils.setupDatabase(path: path);
158181
await expectLater(
159-
tp,
160-
throwsA((e) =>
161-
e is SqliteException &&
162-
e.message
163-
.contains('Transaction rolled back by earlier statement')));
164-
165-
expect(await db.get('SELECT count() count FROM test_data'),
166-
equals({'count': 0}));
167-
168-
// Check that we can open another transaction afterwards
169-
await db.writeTransaction((tx) async {});
182+
db.get('SELECT invalid_statement;'),
183+
throwsA(
184+
isA<SqliteException>()
185+
.having((e) => e.causingStatement, 'causingStatement',
186+
'SELECT invalid_statement;')
187+
.having((e) => e.extendedResultCode, 'extendedResultCode', 1),
188+
),
189+
);
170190
});
171191
});
172192
}

‎packages/sqlite_async/test/close_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:io';
35

46
import 'package:sqlite_async/sqlite_async.dart';

‎packages/sqlite_async/test/isolate_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:isolate';
35

46
import 'package:test/test.dart';

‎packages/sqlite_async/test/native/basic_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:async';
35
import 'dart:math';
46

‎packages/sqlite_async/test/native/native_mutex_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:isolate';
35

46
import 'package:sqlite_async/src/native/native_isolate_mutex.dart';

‎packages/sqlite_async/test/native/schema_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:async';
35

46
import 'package:sqlite_async/sqlite_async.dart';

‎packages/sqlite_async/test/native/watch_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('!browser')
2+
library;
3+
24
import 'dart:async';
35
import 'dart:isolate';
46
import 'dart:math';

‎packages/sqlite_async/test/server/worker_server.dart

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import 'dart:io';
22

3-
import 'package:dcli/dcli.dart';
43
import 'package:path/path.dart' as p;
54
import 'package:shelf/shelf.dart';
65
import 'package:shelf/shelf_io.dart' as io;
@@ -10,8 +9,7 @@ import 'package:stream_channel/stream_channel.dart';
109
import 'asset_server.dart';
1110

1211
Future<void> hybridMain(StreamChannel<Object?> channel) async {
13-
final directory = p.normalize(
14-
p.join(DartScript.self.pathToScriptDirectory, '../../../../assets'));
12+
final directory = p.normalize('../../assets');
1513

1614
final sqliteOutputPath = p.join(directory, 'sqlite3.wasm');
1715

‎packages/sqlite_async/test/utils/abstract_test_utils.dart

+1-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'package:sqlite_async/sqlite_async.dart';
2-
import 'package:test_api/src/backend/invoker.dart';
32

43
class TestDefaultSqliteOpenFactory extends DefaultSqliteOpenFactory {
54
final String sqlitePath;
@@ -9,14 +8,7 @@ class TestDefaultSqliteOpenFactory extends DefaultSqliteOpenFactory {
98
}
109

1110
abstract class AbstractTestUtils {
12-
String dbPath() {
13-
final test = Invoker.current!.liveTest;
14-
var testName = test.test.name;
15-
var testShortName =
16-
testName.replaceAll(RegExp(r'[\s\./]'), '_').toLowerCase();
17-
var dbName = "test-db/$testShortName.db";
18-
return dbName;
19-
}
11+
String dbPath();
2012

2113
/// Generates a test open factory
2214
Future<TestDefaultSqliteOpenFactory> testFactory(

‎packages/sqlite_async/test/utils/native_test_utils.dart

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import 'package:glob/list_local_fs.dart';
88
import 'package:sqlite_async/sqlite3_common.dart';
99
import 'package:sqlite_async/sqlite_async.dart';
1010
import 'package:sqlite3/open.dart' as sqlite_open;
11+
import 'package:test_descriptor/test_descriptor.dart' as d;
1112

1213
import 'abstract_test_utils.dart';
1314

@@ -52,8 +53,7 @@ class TestSqliteOpenFactory extends TestDefaultSqliteOpenFactory {
5253
class TestUtils extends AbstractTestUtils {
5354
@override
5455
String dbPath() {
55-
Directory("test-db").createSync(recursive: false);
56-
return super.dbPath();
56+
return d.path('test.db');
5757
}
5858

5959
@override

‎packages/sqlite_async/test/utils/stub_test_utils.dart

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import 'abstract_test_utils.dart';
22

33
class TestUtils extends AbstractTestUtils {
4+
@override
5+
String dbPath() {
6+
throw UnimplementedError();
7+
}
8+
49
@override
510
Future<void> cleanDb({required String path}) {
611
throw UnimplementedError();

‎packages/sqlite_async/test/utils/web_test_utils.dart

+19-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import 'dart:async';
22
import 'dart:js_interop';
3+
import 'dart:math';
34

45
import 'package:sqlite_async/sqlite_async.dart';
56
import 'package:test/test.dart';
@@ -9,6 +10,8 @@ import 'abstract_test_utils.dart';
910
@JS('URL.createObjectURL')
1011
external String _createObjectURL(Blob blob);
1112

13+
String? _dbPath;
14+
1215
class TestUtils extends AbstractTestUtils {
1316
late Future<void> _isInitialized;
1417
late final SqliteOptions webOptions;
@@ -19,7 +22,7 @@ class TestUtils extends AbstractTestUtils {
1922

2023
Future<void> _init() async {
2124
final channel = spawnHybridUri('/test/server/worker_server.dart');
22-
final port = await channel.stream.first as int;
25+
final port = (await channel.stream.first as num).toInt();
2326
final sqliteWasmUri = 'http://localhost:$port/sqlite3.wasm';
2427
// Cross origin workers are not supported, but we can supply a Blob
2528
var sqliteUri = 'http://localhost:$port/db_worker.js';
@@ -33,6 +36,21 @@ class TestUtils extends AbstractTestUtils {
3336
wasmUri: sqliteWasmUri.toString(), workerUri: sqliteUri));
3437
}
3538

39+
@override
40+
String dbPath() {
41+
if (_dbPath case final path?) {
42+
return path;
43+
}
44+
45+
final created = _dbPath = 'test-db/${Random().nextInt(1 << 31)}/test.db';
46+
addTearDown(() {
47+
// Pick a new path for the next test.
48+
_dbPath = null;
49+
});
50+
51+
return created;
52+
}
53+
3654
@override
3755
Future<void> cleanDb({required String path}) async {}
3856

‎packages/sqlite_async/test/web/watch_test.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
@TestOn('browser')
2+
library;
3+
24
import 'package:sqlite_async/sqlite_async.dart';
35
import 'package:test/test.dart';
46

‎scripts/sqlite3_wasm_download.dart

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
/// Downloads sqlite3.wasm
2+
library;
3+
24
import 'dart:io';
35

46
final sqliteUrl =

0 commit comments

Comments
 (0)
Please sign in to comment.