import { CommandBus } from '@application/handlers/CommandBus'; import { QueryBus } from '@application/handlers/QueryBus'; import { EventBus } from '@domain/events/EventBus'; import { LocalStorageRepository } from '@infrastructure/persistence/LocalStorageRepository'; import { ElectronNotification } from '@infrastructure/notifications/ElectronNotification'; import { WebAudioAlarm } from '@infrastructure/alarm/WebAudioAlarm'; import { UIState } from '@presentation/state/UIState'; import { App } from '@presentation/components/App'; import type { AppState } from '@domain/ports/StateRepository'; // Command handler factories import { createStartTimerHandler } from '@application/commands/StartTimer'; import { createStopTimerHandler } from '@application/commands/StopTimer'; import { createCreateEnclosHandler } from '@application/commands/CreateEnclos'; import { createDeleteEnclosHandler } from '@application/commands/DeleteEnclos'; import { createAddDragodindeHandler } from '@application/commands/AddDragodinde'; import { createRemoveDragodindeHandler } from '@application/commands/RemoveDragodinde'; import { createToggleGaugeHandler, createUpdateGaugeLevelHandler } from '@application/commands/UpdateGauge'; import { createRegisterAccouplementHandler } from '@application/commands/RegisterAccouplement'; import { createUpdateSettingsHandler } from '@application/commands/UpdateSettings'; import { createResetStatsHandler } from '@application/commands/ResetStats'; import { createReorderEnclosHandler } from '@application/commands/ReorderEnclos'; import { createUpdateWorkflowHandler } from '@application/commands/UpdateWorkflow'; import { createDeleteWorkflowHandler } from '@application/commands/DeleteWorkflow'; import { createSaveWorkflowHandler } from '@application/commands/SaveWorkflow'; import { createImportWorkflowsHandler } from '@application/commands/ImportWorkflows'; import { createClearEnclosHandler, createRenameEnclosHandler, createResetTimerHandler, createNouvelleFourneeHandler } from '@application/commands/EnclosActions'; import { createRechargeGaugeHandler } from '@application/commands/RechargeGauge'; import { createCompleteTimerHandler } from '@application/commands/CompleteTimer'; import { createRenameDragodindeHandler, createUpdateDdStatHandler, createUpdateDdSerenTargetHandler, createUpdateDdLevelTargetHandler, createReorderDragodindeHandler } from '@application/commands/DragodindeActions'; // Query handler factories import { createGetDashboardHandler } from '@application/queries/GetDashboard'; import { createGetEnclosDetailHandler } from '@application/queries/GetEnclosDetail'; import { createGetTimerStateHandler } from '@application/queries/GetTimerState'; import { createGetBreedingOptionsHandler } from '@application/queries/GetBreedingOptions'; import { createGetReapproTreeHandler } from '@application/queries/GetReapproTree'; import { createGetInventaireHandler } from '@application/queries/GetInventaire'; import { createGetSettingsHandler } from '@application/queries/GetSettings'; import { createGetWorkflowsHandler } from '@application/queries/GetWorkflows'; import { createGetStatisticsHandler } from '@application/queries/GetStatistics'; async function bootstrap(): Promise { // Infrastructure const repo = new LocalStorageRepository(); const notifications = new ElectronNotification(); const alarm = new WebAudioAlarm(); const events = new EventBus(); // Load state const defaultState: AppState = { enclos: [], activeId: 'dashboard', nextEnclosId: 1, alarmSound: 'arpege', notifsEnabled: true, ntfyTopic: '', archivedStats: [], inventaire: {}, workflows: [], accouplements: [], }; const state: AppState = (await repo.load()) ?? defaultState; // Command Bus const commandBus = new CommandBus(); commandBus.register('start-timer', createStartTimerHandler(state, repo)); commandBus.register('stop-timer', createStopTimerHandler(state, repo)); commandBus.register('create-enclos', createCreateEnclosHandler(state, repo)); commandBus.register('delete-enclos', createDeleteEnclosHandler(state, repo, events)); commandBus.register('add-dragodinde', createAddDragodindeHandler(state, repo)); commandBus.register('remove-dragodinde', createRemoveDragodindeHandler(state, repo)); commandBus.register('toggle-gauge', createToggleGaugeHandler(state, repo)); commandBus.register('update-gauge-level', createUpdateGaugeLevelHandler(state, repo)); commandBus.register('register-accouplement', createRegisterAccouplementHandler(state, repo, events)); commandBus.register('update-settings', createUpdateSettingsHandler(state, repo)); commandBus.register('reset-stats', createResetStatsHandler(state, repo)); commandBus.register('reorder-enclos', createReorderEnclosHandler(state, repo)); commandBus.register('update-workflow', createUpdateWorkflowHandler(state, repo)); commandBus.register('delete-workflow', createDeleteWorkflowHandler(state, repo)); commandBus.register('save-workflow', createSaveWorkflowHandler(state, repo)); commandBus.register('import-workflows', createImportWorkflowsHandler(state, repo)); commandBus.register('complete-timer', createCompleteTimerHandler(state, repo, events)); commandBus.register('recharge-gauge', createRechargeGaugeHandler(state, repo)); commandBus.register('clear-enclos', createClearEnclosHandler(state, repo)); commandBus.register('rename-enclos', createRenameEnclosHandler(state, repo)); commandBus.register('reset-timer', createResetTimerHandler(state, repo)); commandBus.register('nouvelle-fournee', createNouvelleFourneeHandler(state, repo)); commandBus.register('rename-dragodinde', createRenameDragodindeHandler(state, repo)); commandBus.register('update-dd-stat', createUpdateDdStatHandler(state, repo)); commandBus.register('update-dd-seren-target', createUpdateDdSerenTargetHandler(state, repo)); commandBus.register('update-dd-level-target', createUpdateDdLevelTargetHandler(state, repo)); commandBus.register('reorder-dragodinde', createReorderDragodindeHandler(state, repo)); // Query Bus const queryBus = new QueryBus(); queryBus.register('get-dashboard', createGetDashboardHandler(state)); queryBus.register('get-enclos-detail', createGetEnclosDetailHandler(state)); queryBus.register('get-timer-state', createGetTimerStateHandler(state)); queryBus.register('get-breeding-options', createGetBreedingOptionsHandler()); queryBus.register('get-reappro-tree', createGetReapproTreeHandler()); queryBus.register('get-inventaire', createGetInventaireHandler(state)); queryBus.register('get-settings', createGetSettingsHandler(state)); queryBus.register('get-workflows', createGetWorkflowsHandler(state)); queryBus.register('get-statistics', createGetStatisticsHandler(state)); // Event handlers events.on('timer-completed', (event) => { const enclosName = (event as any).enclosName ?? 'Enclos'; if (state.notifsEnabled) { notifications.showNotification('Dragodindes prêtes !', `${enclosName} — Toutes les cibles atteintes !`); } alarm.play(state.alarmSound); if (state.ntfyTopic) { const url = `https://ntfy.mickael-pol.fr/${state.ntfyTopic}`; notifications.sendMobileNotification(url, 'Dragodindes prêtes !', `${enclosName} — Toutes les cibles atteintes !`); } }); // Presentation const uiState = new UIState(); uiState.activeView = state.activeId ?? 'dashboard'; const rootEl = document.getElementById('app'); if (!rootEl) throw new Error('Root element #app not found'); const app = new App(commandBus, queryBus, uiState, rootEl, (name: string) => alarm.play(name)); app.render(); } bootstrap().catch(console.error);