Initial project
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user