Initial project
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
/// 管理每个用户对应的 SQLite 文件连接。
|
||||
///
|
||||
/// [databaseFactory] 由调用方(App 层)提供,负责把 [QueryExecutor]
|
||||
/// 包装成具体的 [GeneratedDatabase] 子类(含表定义和迁移策略)。
|
||||
///
|
||||
/// 这样 storage_sdk 只负责连接机制,不感知业务表结构。
|
||||
///
|
||||
/// 示例:
|
||||
/// ```dart
|
||||
/// final ds = DatabaseDataSource(
|
||||
/// databaseFactory: (executor) => AppDatabase(executor),
|
||||
/// );
|
||||
/// await ds.openDatabase(userId);
|
||||
/// ```
|
||||
class DatabaseDataSource {
|
||||
final GeneratedDatabase Function(QueryExecutor) _databaseFactory;
|
||||
|
||||
DatabaseDataSource({
|
||||
required GeneratedDatabase Function(QueryExecutor) databaseFactory,
|
||||
}) : _databaseFactory = databaseFactory;
|
||||
|
||||
GeneratedDatabase? _db;
|
||||
|
||||
/// 当前已打开的数据库实例;未开库时为 null。
|
||||
GeneratedDatabase? get current => _db;
|
||||
|
||||
/// 打开指定用户的数据库文件,若已有连接则先关闭。
|
||||
///
|
||||
/// 数据库文件路径:`<ApplicationSupport>/../databases/<uid>.sqlite`
|
||||
Future<GeneratedDatabase> openDatabase(int uid) async {
|
||||
await _db?.close();
|
||||
_db = null;
|
||||
|
||||
///TODO: iOS路径
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
final dbDir = Directory('${dir.parent.path}/databases');
|
||||
if (!dbDir.existsSync()) {
|
||||
dbDir.createSync(recursive: true);
|
||||
}
|
||||
|
||||
final file = File('${dbDir.path}/$uid.sqlite');
|
||||
_db = _databaseFactory(NativeDatabase(file));
|
||||
return _db!;
|
||||
}
|
||||
|
||||
/// 关闭当前数据库连接并清空引用。
|
||||
Future<void> closeDatabase() async {
|
||||
await _db?.close();
|
||||
_db = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../../domain/repositories/database_repository.dart';
|
||||
import '../local/datasources/database_datasource.dart';
|
||||
|
||||
/// [DatabaseRepository] 的 Drift 实现。
|
||||
///
|
||||
/// 通过 [DatabaseDataSource.current] 获取当前数据库实例。
|
||||
/// 数据库未打开(null)时所有方法静默返回,不抛异常。
|
||||
class DatabaseRepositoryImpl implements DatabaseRepository {
|
||||
final DatabaseDataSource _dataSource;
|
||||
|
||||
DatabaseRepositoryImpl(this._dataSource);
|
||||
|
||||
GeneratedDatabase? get _db => _dataSource.current;
|
||||
|
||||
// ── 插入 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> insertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await db.into(table).insertOnConflictUpdate(companion);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> insert<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await db.into(table).insert(companion, mode: InsertMode.insertOrIgnore);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> batchInsertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
List<Insertable<D>> companions,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await db.batch(
|
||||
(batch) => batch.insertAllOnConflictUpdate(table, companions),
|
||||
);
|
||||
}
|
||||
|
||||
// ── 更新 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> updateWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
Expression<bool> Function(T) filter,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await (db.update(table)..where(filter)).write(companion);
|
||||
}
|
||||
|
||||
// ── 删除 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> deleteWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await (db.delete(table)..where(filter)).go();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await db.delete(table).go();
|
||||
}
|
||||
|
||||
// ── 查询 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table) async {
|
||||
final db = _db;
|
||||
if (db == null) return [];
|
||||
return db.select(table).get();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<D>> selectWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return [];
|
||||
return (db.select(table)..where(filter)).get();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<D?> selectFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) async {
|
||||
final db = _db;
|
||||
if (db == null) return null;
|
||||
return (db.select(table)..where(filter)..limit(1)).getSingleOrNull();
|
||||
}
|
||||
|
||||
// ── 监听 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table) {
|
||||
final db = _db;
|
||||
if (db == null) return const Stream.empty();
|
||||
return db.select(table).watch();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<List<D>> watchWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) {
|
||||
final db = _db;
|
||||
if (db == null) return const Stream.empty();
|
||||
return (db.select(table)..where(filter)).watch();
|
||||
}
|
||||
|
||||
@override
|
||||
Stream<D?> watchFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) {
|
||||
final db = _db;
|
||||
if (db == null) return const Stream.empty();
|
||||
return (db.select(table)..where(filter)..limit(1)).watchSingleOrNull();
|
||||
}
|
||||
|
||||
// ── 原始 SQL ─────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<List<QueryRow>> rawQuery(
|
||||
String sql, [
|
||||
List<Object?> args = const [],
|
||||
]) async {
|
||||
final db = _db;
|
||||
if (db == null) return [];
|
||||
return db
|
||||
.customSelect(
|
||||
sql,
|
||||
variables: args.map((e) => Variable(e)).toList(),
|
||||
)
|
||||
.get();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> rawExecute(
|
||||
String sql, [
|
||||
List<Object?> args = const [],
|
||||
]) async {
|
||||
final db = _db;
|
||||
if (db == null) return;
|
||||
await db.customStatement(sql, args);
|
||||
}
|
||||
|
||||
// ── 统计 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<int> count<T extends Table, D>(
|
||||
TableInfo<T, D> table, {
|
||||
Expression<bool> Function(T)? filter,
|
||||
}) async {
|
||||
final db = _db;
|
||||
if (db == null) return 0;
|
||||
final countExpr = table.$columns.first.count();
|
||||
final query = db.selectOnly(table)..addColumns([countExpr]);
|
||||
if (filter != null) query.where(filter(table.asDslTable));
|
||||
final row = await query.getSingle();
|
||||
return row.read(countExpr) ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
/// 通用数据库 CRUD 接口。
|
||||
///
|
||||
/// 所有方法通过 Drift 的 [TableInfo]、[Insertable]、[Expression] 泛型操作,
|
||||
/// 与具体表定义解耦,App 层按需传入对应 Table 即可。
|
||||
///
|
||||
/// 示例:
|
||||
/// ```dart
|
||||
/// await repo.insertOrReplace(db.users, companion);
|
||||
/// final list = await repo.selectWhere(db.messages, (t) => t.chatId.equals(id));
|
||||
/// ```
|
||||
abstract class DatabaseRepository {
|
||||
// ── 插入 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 插入或替换(主键冲突时覆盖)。
|
||||
Future<void> insertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
);
|
||||
|
||||
/// 插入或忽略(主键冲突时跳过)。
|
||||
Future<void> insert<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
);
|
||||
|
||||
/// 批量插入或替换。
|
||||
Future<void> batchInsertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
List<Insertable<D>> companions,
|
||||
);
|
||||
|
||||
// ── 更新 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 按条件更新。
|
||||
Future<void> updateWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 删除 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 按条件删除。
|
||||
Future<void> deleteWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 清空整张表。
|
||||
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
// ── 查询 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 查询全部记录。
|
||||
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
/// 按条件查询。
|
||||
Future<List<D>> selectWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 查询第一条匹配记录。
|
||||
Future<D?> selectFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 监听 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 监听全部记录(实时流)。
|
||||
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
/// 按条件监听(实时流)。
|
||||
Stream<List<D>> watchWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 监听第一条匹配记录(实时流)。
|
||||
Stream<D?> watchFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 原始 SQL ─────────────────────────────────────────────────────────────
|
||||
|
||||
/// 执行原始查询,返回行数据。
|
||||
Future<List<QueryRow>> rawQuery(String sql, [List<Object?> args]);
|
||||
|
||||
/// 执行原始语句(无返回值)。
|
||||
Future<void> rawExecute(String sql, [List<Object?> args]);
|
||||
|
||||
// ── 统计 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 统计记录数。
|
||||
Future<int> count<T extends Table, D>(
|
||||
TableInfo<T, D> table, {
|
||||
Expression<bool> Function(T)? filter,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../wiring/storage_sdk_wiring.dart';
|
||||
|
||||
/// 本地数据库的统一公开接口。
|
||||
///
|
||||
/// 通过 [StorageSdkApi] 工厂方法获取实例,传入 App 侧的数据库工厂即可:
|
||||
///
|
||||
/// ```dart
|
||||
/// final api = StorageSdkApi(
|
||||
/// databaseFactory: (executor) => AppDatabase(executor),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ## 生命周期
|
||||
/// - 用户登录后调用 [openDatabase] 开库;
|
||||
/// - 用户登出时调用 [closeDatabase] 关库;
|
||||
/// - [isDatabaseOpen] 可查询当前状态。
|
||||
///
|
||||
/// 内部接口,仅供 App 层生命周期管理使用
|
||||
abstract class StorageSdkLifecycle {
|
||||
Future<void> openDatabase(int uid);
|
||||
Future<void> closeDatabase();
|
||||
bool get isDatabaseOpen;
|
||||
}
|
||||
///
|
||||
///
|
||||
/// ## CRUD
|
||||
/// 所有 CRUD 方法均为泛型,接受 Drift 的 [TableInfo],与具体业务表解耦。
|
||||
/// App 层传入自己定义的 Table 即可复用全部操作。
|
||||
abstract class StorageSdkApi {
|
||||
/// 创建 SDK 实例。
|
||||
///
|
||||
/// [databaseFactory] 由 App 层提供:接受 [QueryExecutor],
|
||||
/// 返回自定义的 [GeneratedDatabase] 子类(含表定义和迁移策略)。
|
||||
factory StorageSdkApi({
|
||||
required GeneratedDatabase Function(QueryExecutor) databaseFactory,
|
||||
}) =>
|
||||
StorageSdkWiring.build(databaseFactory: databaseFactory);
|
||||
|
||||
// ── 插入 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 插入或替换(主键冲突时覆盖)。
|
||||
Future<void> insertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
);
|
||||
|
||||
/// 插入或忽略(主键冲突时跳过)。
|
||||
Future<void> insert<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
);
|
||||
|
||||
/// 批量插入或替换。
|
||||
Future<void> batchInsertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
List<Insertable<D>> companions,
|
||||
);
|
||||
|
||||
// ── 更新 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 按条件更新。
|
||||
Future<void> updateWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 删除 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 按条件删除。
|
||||
Future<void> deleteWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 清空整张表。
|
||||
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
// ── 查询 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 查询全部记录。
|
||||
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
/// 按条件查询。
|
||||
Future<List<D>> selectWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 查询第一条匹配记录。
|
||||
Future<D?> selectFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 监听 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 监听全部记录(实时流)。
|
||||
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table);
|
||||
|
||||
/// 按条件监听(实时流)。
|
||||
Stream<List<D>> watchWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
/// 监听第一条匹配记录(实时流)。
|
||||
Stream<D?> watchFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
);
|
||||
|
||||
// ── 原始 SQL ─────────────────────────────────────────────────────────────
|
||||
|
||||
/// 执行原始查询,返回行数据。
|
||||
Future<List<QueryRow>> rawQuery(String sql, [List<Object?> args]);
|
||||
|
||||
/// 执行原始语句(无返回值)。
|
||||
Future<void> rawExecute(String sql, [List<Object?> args]);
|
||||
|
||||
// ── 统计 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
/// 统计记录数。
|
||||
Future<int> count<T extends Table, D>(
|
||||
TableInfo<T, D> table, {
|
||||
Expression<bool> Function(T)? filter,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../facade/storage_sdk_api.dart';
|
||||
import 'storage_sdk_core.dart';
|
||||
|
||||
/// [StorageSdkApi] 的实现,委托给 [StorageSdkCore]。
|
||||
class StorageSdkApiImpl implements StorageSdkApi, StorageSdkLifecycle {
|
||||
final StorageSdkCore _core;
|
||||
|
||||
StorageSdkApiImpl({required StorageSdkCore core}) : _core = core;
|
||||
|
||||
// ── 生命周期 ─────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> openDatabase(int uid) =>
|
||||
_core.dataSource.openDatabase(uid);
|
||||
|
||||
@override
|
||||
Future<void> closeDatabase() => _core.dataSource.closeDatabase();
|
||||
|
||||
@override
|
||||
bool get isDatabaseOpen => _core.dataSource.current != null;
|
||||
|
||||
// ── 插入 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> insertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
) =>
|
||||
_core.repo.insertOrReplace(table, companion);
|
||||
|
||||
@override
|
||||
Future<void> insert<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
) =>
|
||||
_core.repo.insert(table, companion);
|
||||
|
||||
@override
|
||||
Future<void> batchInsertOrReplace<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
List<Insertable<D>> companions,
|
||||
) =>
|
||||
_core.repo.batchInsertOrReplace(table, companions);
|
||||
|
||||
// ── 更新 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> updateWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Insertable<D> companion,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.updateWhere(table, companion, filter);
|
||||
|
||||
// ── 删除 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<void> deleteWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.deleteWhere(table, filter);
|
||||
|
||||
@override
|
||||
Future<void> deleteAll<T extends Table, D>(TableInfo<T, D> table) =>
|
||||
_core.repo.deleteAll(table);
|
||||
|
||||
// ── 查询 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<List<D>> selectAll<T extends Table, D>(TableInfo<T, D> table) =>
|
||||
_core.repo.selectAll(table);
|
||||
|
||||
@override
|
||||
Future<List<D>> selectWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.selectWhere(table, filter);
|
||||
|
||||
@override
|
||||
Future<D?> selectFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.selectFirst(table, filter);
|
||||
|
||||
// ── 监听 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Stream<List<D>> watchAll<T extends Table, D>(TableInfo<T, D> table) =>
|
||||
_core.repo.watchAll(table);
|
||||
|
||||
@override
|
||||
Stream<List<D>> watchWhere<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.watchWhere(table, filter);
|
||||
|
||||
@override
|
||||
Stream<D?> watchFirst<T extends Table, D>(
|
||||
TableInfo<T, D> table,
|
||||
Expression<bool> Function(T) filter,
|
||||
) =>
|
||||
_core.repo.watchFirst(table, filter);
|
||||
|
||||
// ── 原始 SQL ─────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<List<QueryRow>> rawQuery(String sql, [List<Object?> args = const []]) =>
|
||||
_core.repo.rawQuery(sql, args);
|
||||
|
||||
@override
|
||||
Future<void> rawExecute(String sql, [List<Object?> args = const []]) =>
|
||||
_core.repo.rawExecute(sql, args);
|
||||
|
||||
// ── 统计 ─────────────────────────────────────────────────────────────────
|
||||
|
||||
@override
|
||||
Future<int> count<T extends Table, D>(
|
||||
TableInfo<T, D> table, {
|
||||
Expression<bool> Function(T)? filter,
|
||||
}) =>
|
||||
_core.repo.count(table, filter: filter);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import '../../data/local/datasources/database_datasource.dart';
|
||||
import '../../domain/repositories/database_repository.dart';
|
||||
|
||||
/// SDK 核心依赖容器。
|
||||
class StorageSdkCore {
|
||||
final DatabaseDataSource dataSource;
|
||||
final DatabaseRepository repo;
|
||||
|
||||
const StorageSdkCore({
|
||||
required this.dataSource,
|
||||
required this.repo,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
import '../facade/storage_sdk_api.dart';
|
||||
import '../../data/local/datasources/database_datasource.dart';
|
||||
import '../../data/repositories/database_repository_impl.dart';
|
||||
import 'storage_sdk_core.dart';
|
||||
import 'storage_sdk_api_impl.dart';
|
||||
|
||||
/// SDK 依赖装配入口。
|
||||
///
|
||||
/// 调用方传入数据库工厂,SDK 负责连接生命周期和 CRUD 机制。
|
||||
///
|
||||
/// 示例(im_app 的 DI 层):
|
||||
/// ```dart
|
||||
/// StorageSdkWiring.build(
|
||||
/// databaseFactory: (executor) => AppDatabase(executor),
|
||||
/// );
|
||||
/// ```
|
||||
class StorageSdkWiring {
|
||||
StorageSdkWiring._();
|
||||
|
||||
static StorageSdkApi build({
|
||||
required GeneratedDatabase Function(QueryExecutor) databaseFactory,
|
||||
}) {
|
||||
final dataSource = DatabaseDataSource(databaseFactory: databaseFactory);
|
||||
final repo = DatabaseRepositoryImpl(dataSource);
|
||||
final core = StorageSdkCore(dataSource: dataSource, repo: repo);
|
||||
return StorageSdkApiImpl(core: core);
|
||||
}
|
||||
}
|
||||
2
packages/storage_sdk/lib/storage_sdk.dart
Normal file
2
packages/storage_sdk/lib/storage_sdk.dart
Normal file
@@ -0,0 +1,2 @@
|
||||
export 'src/presentation/facade/storage_sdk_api.dart';
|
||||
|
||||
Reference in New Issue
Block a user