From 14c1d6f3f0e5ecab3bd0aa630f2eb099026dffda Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Wed, 6 Nov 2024 08:58:14 +0200 Subject: [PATCH 1/3] Fix migrations not running for drift_sqlite_async. --- .../drift_sqlite_async/example/main.g.dart | 131 ++++++++++++++++++ .../example/with_migrations.dart | 15 +- .../example/with_migrations.g.dart | 131 ++++++++++++++++++ .../drift_sqlite_async/lib/src/executor.dart | 6 +- .../test/generated/database.dart | 13 ++ .../test/generated/database.g.dart | 131 ++++++++++++++++++ .../test/migration_test.dart | 40 ++++++ 7 files changed, 457 insertions(+), 10 deletions(-) create mode 100644 packages/drift_sqlite_async/test/migration_test.dart diff --git a/packages/drift_sqlite_async/example/main.g.dart b/packages/drift_sqlite_async/example/main.g.dart index 576157c..0f4385e 100644 --- a/packages/drift_sqlite_async/example/main.g.dart +++ b/packages/drift_sqlite_async/example/main.g.dart @@ -109,6 +109,14 @@ class TodoItem extends DataClass implements Insertable { id: id ?? this.id, description: description ?? this.description, ); + TodoItem copyWithCompanion(TodoItemsCompanion data) { + return TodoItem( + id: data.id.present ? data.id.value : this.id, + description: + data.description.present ? data.description.value : this.description, + ); + } + @override String toString() { return (StringBuffer('TodoItem(') @@ -180,6 +188,7 @@ class TodoItemsCompanion extends UpdateCompanion { abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); late final $TodoItemsTable todoItems = $TodoItemsTable(this); @override Iterable> get allTables => @@ -187,3 +196,125 @@ abstract class _$AppDatabase extends GeneratedDatabase { @override List get allSchemaEntities => [todoItems]; } + +typedef $$TodoItemsTableCreateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + required String description, +}); +typedef $$TodoItemsTableUpdateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + Value description, +}); + +class $$TodoItemsTableFilterComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnFilters(column)); +} + +class $$TodoItemsTableOrderingComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnOrderings(column)); +} + +class $$TodoItemsTableAnnotationComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get description => $composableBuilder( + column: $table.description, builder: (column) => column); +} + +class $$TodoItemsTableTableManager extends RootTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()> { + $$TodoItemsTableTableManager(_$AppDatabase db, $TodoItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TodoItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TodoItemsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TodoItemsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value description = const Value.absent(), + }) => + TodoItemsCompanion( + id: id, + description: description, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String description, + }) => + TodoItemsCompanion.insert( + id: id, + description: description, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$TodoItemsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$TodoItemsTableTableManager get todoItems => + $$TodoItemsTableTableManager(_db, _db.todoItems); +} diff --git a/packages/drift_sqlite_async/example/with_migrations.dart b/packages/drift_sqlite_async/example/with_migrations.dart index 2bd4a87..7f8cb44 100644 --- a/packages/drift_sqlite_async/example/with_migrations.dart +++ b/packages/drift_sqlite_async/example/with_migrations.dart @@ -21,21 +21,18 @@ class AppDatabase extends _$AppDatabase { @override MigrationStrategy get migration { - return MigrationStrategy( - onCreate: (m) async { - // In this example, the schema is managed by Drift - await m.createAll(); - }, - ); + return MigrationStrategy(onCreate: (m) async { + // In this example, the schema is managed by Drift. + // For more options, see: + // https://drift.simonbinder.eu/migrations/#usage + await m.createAll(); + }); } } Future main() async { final db = SqliteDatabase(path: 'with_migrations.db'); - await db.execute( - 'CREATE TABLE IF NOT EXISTS todos(id integer primary key, description text)'); - final appdb = AppDatabase(db); // Watch a query on the Drift database diff --git a/packages/drift_sqlite_async/example/with_migrations.g.dart b/packages/drift_sqlite_async/example/with_migrations.g.dart index 67ce020..7c2afbd 100644 --- a/packages/drift_sqlite_async/example/with_migrations.g.dart +++ b/packages/drift_sqlite_async/example/with_migrations.g.dart @@ -109,6 +109,14 @@ class TodoItem extends DataClass implements Insertable { id: id ?? this.id, description: description ?? this.description, ); + TodoItem copyWithCompanion(TodoItemsCompanion data) { + return TodoItem( + id: data.id.present ? data.id.value : this.id, + description: + data.description.present ? data.description.value : this.description, + ); + } + @override String toString() { return (StringBuffer('TodoItem(') @@ -180,6 +188,7 @@ class TodoItemsCompanion extends UpdateCompanion { abstract class _$AppDatabase extends GeneratedDatabase { _$AppDatabase(QueryExecutor e) : super(e); + $AppDatabaseManager get managers => $AppDatabaseManager(this); late final $TodoItemsTable todoItems = $TodoItemsTable(this); @override Iterable> get allTables => @@ -187,3 +196,125 @@ abstract class _$AppDatabase extends GeneratedDatabase { @override List get allSchemaEntities => [todoItems]; } + +typedef $$TodoItemsTableCreateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + required String description, +}); +typedef $$TodoItemsTableUpdateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + Value description, +}); + +class $$TodoItemsTableFilterComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnFilters(column)); +} + +class $$TodoItemsTableOrderingComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnOrderings(column)); +} + +class $$TodoItemsTableAnnotationComposer + extends Composer<_$AppDatabase, $TodoItemsTable> { + $$TodoItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get description => $composableBuilder( + column: $table.description, builder: (column) => column); +} + +class $$TodoItemsTableTableManager extends RootTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()> { + $$TodoItemsTableTableManager(_$AppDatabase db, $TodoItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TodoItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TodoItemsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TodoItemsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value description = const Value.absent(), + }) => + TodoItemsCompanion( + id: id, + description: description, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String description, + }) => + TodoItemsCompanion.insert( + id: id, + description: description, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$TodoItemsTableProcessedTableManager = ProcessedTableManager< + _$AppDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$AppDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()>; + +class $AppDatabaseManager { + final _$AppDatabase _db; + $AppDatabaseManager(this._db); + $$TodoItemsTableTableManager get todoItems => + $$TodoItemsTableTableManager(_db, _db.todoItems); +} diff --git a/packages/drift_sqlite_async/lib/src/executor.dart b/packages/drift_sqlite_async/lib/src/executor.dart index 5d670c1..0727dd8 100644 --- a/packages/drift_sqlite_async/lib/src/executor.dart +++ b/packages/drift_sqlite_async/lib/src/executor.dart @@ -15,6 +15,7 @@ class _SqliteAsyncDelegate extends _SqliteAsyncQueryDelegate implements DatabaseDelegate { final SqliteConnection db; bool _closed = false; + bool _calledOpen = false; _SqliteAsyncDelegate(this.db) : super(db, db.writeLock); @@ -30,12 +31,15 @@ class _SqliteAsyncDelegate extends _SqliteAsyncQueryDelegate _SqliteAsyncTransactionDelegate(db); @override - bool get isOpen => !db.closed && !_closed; + bool get isOpen => !db.closed && !_closed && _calledOpen; @override Future open(QueryExecutorUser user) async { // Workaround - this ensures the db is open await db.get('SELECT 1'); + // We need to delay this until open() has been called, otherwise + // migrations don't run. + _calledOpen = true; } @override diff --git a/packages/drift_sqlite_async/test/generated/database.dart b/packages/drift_sqlite_async/test/generated/database.dart index e955c3d..7747be4 100644 --- a/packages/drift_sqlite_async/test/generated/database.dart +++ b/packages/drift_sqlite_async/test/generated/database.dart @@ -19,3 +19,16 @@ class TodoDatabase extends _$TodoDatabase { @override int get schemaVersion => 1; } + +class TodosMigrationDatabase extends TodoDatabase { + TodosMigrationDatabase(SqliteConnection db) : super(db); + + @override + MigrationStrategy get migration { + return MigrationStrategy( + onCreate: (m) async { + await m.createAll(); + }, + ); + } +} diff --git a/packages/drift_sqlite_async/test/generated/database.g.dart b/packages/drift_sqlite_async/test/generated/database.g.dart index 2572c32..fecba2b 100644 --- a/packages/drift_sqlite_async/test/generated/database.g.dart +++ b/packages/drift_sqlite_async/test/generated/database.g.dart @@ -109,6 +109,14 @@ class TodoItem extends DataClass implements Insertable { id: id ?? this.id, description: description ?? this.description, ); + TodoItem copyWithCompanion(TodoItemsCompanion data) { + return TodoItem( + id: data.id.present ? data.id.value : this.id, + description: + data.description.present ? data.description.value : this.description, + ); + } + @override String toString() { return (StringBuffer('TodoItem(') @@ -180,6 +188,7 @@ class TodoItemsCompanion extends UpdateCompanion { abstract class _$TodoDatabase extends GeneratedDatabase { _$TodoDatabase(QueryExecutor e) : super(e); + $TodoDatabaseManager get managers => $TodoDatabaseManager(this); late final $TodoItemsTable todoItems = $TodoItemsTable(this); @override Iterable> get allTables => @@ -187,3 +196,125 @@ abstract class _$TodoDatabase extends GeneratedDatabase { @override List get allSchemaEntities => [todoItems]; } + +typedef $$TodoItemsTableCreateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + required String description, +}); +typedef $$TodoItemsTableUpdateCompanionBuilder = TodoItemsCompanion Function({ + Value id, + Value description, +}); + +class $$TodoItemsTableFilterComposer + extends Composer<_$TodoDatabase, $TodoItemsTable> { + $$TodoItemsTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnFilters(column)); + + ColumnFilters get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnFilters(column)); +} + +class $$TodoItemsTableOrderingComposer + extends Composer<_$TodoDatabase, $TodoItemsTable> { + $$TodoItemsTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, builder: (column) => ColumnOrderings(column)); + + ColumnOrderings get description => $composableBuilder( + column: $table.description, builder: (column) => ColumnOrderings(column)); +} + +class $$TodoItemsTableAnnotationComposer + extends Composer<_$TodoDatabase, $TodoItemsTable> { + $$TodoItemsTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get description => $composableBuilder( + column: $table.description, builder: (column) => column); +} + +class $$TodoItemsTableTableManager extends RootTableManager< + _$TodoDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$TodoDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()> { + $$TodoItemsTableTableManager(_$TodoDatabase db, $TodoItemsTable table) + : super(TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TodoItemsTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TodoItemsTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TodoItemsTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: ({ + Value id = const Value.absent(), + Value description = const Value.absent(), + }) => + TodoItemsCompanion( + id: id, + description: description, + ), + createCompanionCallback: ({ + Value id = const Value.absent(), + required String description, + }) => + TodoItemsCompanion.insert( + id: id, + description: description, + ), + withReferenceMapper: (p0) => p0 + .map((e) => (e.readTable(table), BaseReferences(db, table, e))) + .toList(), + prefetchHooksCallback: null, + )); +} + +typedef $$TodoItemsTableProcessedTableManager = ProcessedTableManager< + _$TodoDatabase, + $TodoItemsTable, + TodoItem, + $$TodoItemsTableFilterComposer, + $$TodoItemsTableOrderingComposer, + $$TodoItemsTableAnnotationComposer, + $$TodoItemsTableCreateCompanionBuilder, + $$TodoItemsTableUpdateCompanionBuilder, + (TodoItem, BaseReferences<_$TodoDatabase, $TodoItemsTable, TodoItem>), + TodoItem, + PrefetchHooks Function()>; + +class $TodoDatabaseManager { + final _$TodoDatabase _db; + $TodoDatabaseManager(this._db); + $$TodoItemsTableTableManager get todoItems => + $$TodoItemsTableTableManager(_db, _db.todoItems); +} diff --git a/packages/drift_sqlite_async/test/migration_test.dart b/packages/drift_sqlite_async/test/migration_test.dart new file mode 100644 index 0000000..e05c212 --- /dev/null +++ b/packages/drift_sqlite_async/test/migration_test.dart @@ -0,0 +1,40 @@ +@TestOn('!browser') +import 'package:sqlite_async/sqlite_async.dart'; +import 'package:test/test.dart'; + +import './utils/test_utils.dart'; +import 'generated/database.dart'; + +void main() { + group('Migration tests', () { + late String path; + late SqliteDatabase db; + late TodoDatabase dbu; + + setUp(() async { + path = dbPath(); + await cleanDb(path: path); + + db = await setupDatabase(path: path); + dbu = TodosMigrationDatabase(db); + }); + + tearDown(() async { + await dbu.close(); + await db.close(); + + await cleanDb(path: path); + }); + + test('INSERT/SELECT', () async { + // This will fail if the migration didn't run + var insertRowId = await dbu + .into(dbu.todoItems) + .insert(TodoItemsCompanion.insert(description: 'Test 1')); + expect(insertRowId, greaterThanOrEqualTo(1)); + + final result = await dbu.select(dbu.todoItems).getSingle(); + expect(result.description, equals('Test 1')); + }); + }); +} From 195182085c7290c2b6760f3e749ffaf9336da07c Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Wed, 6 Nov 2024 09:09:10 +0200 Subject: [PATCH 2/3] Fix tests. --- packages/drift_sqlite_async/README.md | 1 + packages/drift_sqlite_async/test/db_test.dart | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/drift_sqlite_async/README.md b/packages/drift_sqlite_async/README.md index 977dbe1..e8810b1 100644 --- a/packages/drift_sqlite_async/README.md +++ b/packages/drift_sqlite_async/README.md @@ -8,6 +8,7 @@ Supported functionality: 2. Transactions and nested transactions. 3. Table updates are propagated between sqlite_async and Drift - watching queries works using either API. 4. Select queries can run concurrently with writes and other select statements. +5. Drift migrations are supported (optional). ## Usage diff --git a/packages/drift_sqlite_async/test/db_test.dart b/packages/drift_sqlite_async/test/db_test.dart index 6de575e..372f0fa 100644 --- a/packages/drift_sqlite_async/test/db_test.dart +++ b/packages/drift_sqlite_async/test/db_test.dart @@ -54,7 +54,7 @@ void main() { // Drift may or may not emit duplicate update notifications. // We use distinct() to ignore those. .distinct() - .skipWhile((e) => e.isEmpty) + .skipWhile((e) => e == '[]') .take(3) .toList(); @@ -83,7 +83,7 @@ void main() { var resultsPromise = stream .map((rows) => rows.toString()) .distinct() - .skipWhile((e) => e.isEmpty) + .skipWhile((e) => e == '[]') .take(3) .toList(); From efe6fa34e75c33ad8244dedb67c543da244ad6ff Mon Sep 17 00:00:00 2001 From: Ralf Kistner Date: Wed, 6 Nov 2024 09:30:18 +0200 Subject: [PATCH 3/3] chore(release): publish packages - drift_sqlite_async@0.2.0 --- CHANGELOG.md | 21 +++++++++++++++++++++ packages/drift_sqlite_async/CHANGELOG.md | 4 ++++ packages/drift_sqlite_async/pubspec.yaml | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5c9c0d..aba9311 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,27 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +## 2024-11-06 + +### Changes + +--- + +Packages with breaking changes: + + - There are no breaking changes in this release. + +Packages with other changes: + + - [`drift_sqlite_async` - `v0.2.0`](#drift_sqlite_async---v020) + +--- + +#### `drift_sqlite_async` - `v0.2.0` + + - Automatically run Drift migrations + + ## 2024-11-06 ### Changes diff --git a/packages/drift_sqlite_async/CHANGELOG.md b/packages/drift_sqlite_async/CHANGELOG.md index 23f501b..4c23e85 100644 --- a/packages/drift_sqlite_async/CHANGELOG.md +++ b/packages/drift_sqlite_async/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0 + + - Automatically run Drift migrations + ## 0.2.0-alpha.4 - Update a dependency to the latest release. diff --git a/packages/drift_sqlite_async/pubspec.yaml b/packages/drift_sqlite_async/pubspec.yaml index a2e8c99..f88dccb 100644 --- a/packages/drift_sqlite_async/pubspec.yaml +++ b/packages/drift_sqlite_async/pubspec.yaml @@ -1,5 +1,5 @@ name: drift_sqlite_async -version: 0.2.0-alpha.4 +version: 0.2.0 homepage: https://github.com/powersync-ja/sqlite_async.dart repository: https://github.com/powersync-ja/sqlite_async.dart description: Use Drift with a sqlite_async database, allowing both to be used in the same application.