feat(bibliothèque): migration Drift v16, seed basket et seeding au démarrage (ticket #80)
Ajoute la migration Drift v16 (enum ExerciseCategory, champ isExample sur exercises/programs/workout_templates, table local_seed_metadata), le contenu seed basket déterministe (21 exercices, 1 programme, 1 séance- modèle) dans lib/application/starter_content/, les ports StarterSeedStateRepository/StarterContentRepository et le use case SeedStarterContentUseCase branché dans AppBootstrap.create(). Validé GO par QA/Main : dart analyze propre, suite complète 167 tests (4 échecs préexistants sans rapport avec ce lot), 4 nouveaux tests seed tous verts. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -2,9 +2,76 @@ import 'dart:convert';
|
||||
|
||||
import '../domain/domain.dart';
|
||||
import 'ports.dart';
|
||||
import 'starter_content/basket_starter_seed_v1.dart';
|
||||
import 'starter_content/starter_content.dart';
|
||||
|
||||
const Object _useCaseUnchanged = Object();
|
||||
|
||||
enum StarterSeedStatus { inserted, skippedAlreadyApplied, skippedNotEmpty }
|
||||
|
||||
final class StarterSeedResult {
|
||||
const StarterSeedResult({required this.status, required this.appliedVersion});
|
||||
|
||||
final StarterSeedStatus status;
|
||||
final int appliedVersion;
|
||||
}
|
||||
|
||||
final class SeedStarterContentUseCase {
|
||||
const SeedStarterContentUseCase({
|
||||
required this.seedStateRepository,
|
||||
required this.contentRepository,
|
||||
required this.clock,
|
||||
required this.originDeviceId,
|
||||
});
|
||||
|
||||
final StarterSeedStateRepository seedStateRepository;
|
||||
final StarterContentRepository contentRepository;
|
||||
final Clock clock;
|
||||
final String originDeviceId;
|
||||
|
||||
Future<StarterSeedResult> run() async {
|
||||
final appliedVersion = await seedStateRepository
|
||||
.readAppliedStarterSeedVersion();
|
||||
if (appliedVersion >= starterSeedVersion) {
|
||||
return const StarterSeedResult(
|
||||
status: StarterSeedStatus.skippedAlreadyApplied,
|
||||
appliedVersion: starterSeedVersion,
|
||||
);
|
||||
}
|
||||
|
||||
final now = clock.now();
|
||||
final isEmpty = await contentRepository.isLocalContentEmpty();
|
||||
if (!isEmpty) {
|
||||
await seedStateRepository.writeAppliedStarterSeedVersion(
|
||||
starterSeedVersion,
|
||||
now,
|
||||
);
|
||||
return const StarterSeedResult(
|
||||
status: StarterSeedStatus.skippedNotEmpty,
|
||||
appliedVersion: starterSeedVersion,
|
||||
);
|
||||
}
|
||||
|
||||
await contentRepository.insertStarterContent(
|
||||
buildStarterContent(
|
||||
exerciseSeeds: basketStarterExerciseSeedsV1,
|
||||
programSeed: basketStarterProgramSeedV1,
|
||||
templateSeed: basketStarterWorkoutTemplateSeedV1,
|
||||
now: now,
|
||||
originDeviceId: originDeviceId,
|
||||
),
|
||||
);
|
||||
await seedStateRepository.writeAppliedStarterSeedVersion(
|
||||
starterSeedVersion,
|
||||
now,
|
||||
);
|
||||
return const StarterSeedResult(
|
||||
status: StarterSeedStatus.inserted,
|
||||
appliedVersion: starterSeedVersion,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class AuthUseCases {
|
||||
const AuthUseCases({
|
||||
required this.tokenStore,
|
||||
|
||||
Reference in New Issue
Block a user