Refactors repository layer and IndexedDB architecture
Eliminates redundant repository abstraction layer by directly using EntityService methods Implements key improvements: - Removes unnecessary repository wrappers - Introduces polymorphic DataSeeder for mock data loading - Renames IndexedDBService to IndexedDBContext - Fixes database injection timing with lazy access pattern - Simplifies EventManager to use services directly Reduces code complexity and improves separation of concerns
This commit is contained in:
parent
5648c7c304
commit
dcd76836bd
10 changed files with 1260 additions and 574 deletions
|
|
@ -2,38 +2,39 @@ import { IEventBus, ICalendarEvent } from '../types/CalendarTypes';
|
|||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
import { Configuration } from '../configurations/CalendarConfig';
|
||||
import { DateService } from '../utils/DateService';
|
||||
import { IEventRepository } from '../repositories/IEventRepository';
|
||||
import { EventService } from '../storage/events/EventService';
|
||||
import { IEntityService } from '../storage/IEntityService';
|
||||
|
||||
/**
|
||||
* EventManager - Event lifecycle and CRUD operations
|
||||
* Delegates all data operations to IEventRepository
|
||||
* No longer maintains in-memory cache - repository is single source of truth
|
||||
* Delegates all data operations to EventService
|
||||
* EventService provides CRUD operations via BaseEntityService (save, delete, getAll)
|
||||
*/
|
||||
export class EventManager {
|
||||
|
||||
private dateService: DateService;
|
||||
private config: Configuration;
|
||||
private repository: IEventRepository;
|
||||
private eventService: EventService;
|
||||
|
||||
constructor(
|
||||
private eventBus: IEventBus,
|
||||
dateService: DateService,
|
||||
config: Configuration,
|
||||
repository: IEventRepository
|
||||
eventService: IEntityService<ICalendarEvent>
|
||||
) {
|
||||
this.dateService = dateService;
|
||||
this.config = config;
|
||||
this.repository = repository;
|
||||
this.eventService = eventService as EventService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load event data from repository
|
||||
* No longer caches - delegates to repository
|
||||
* Load event data from service
|
||||
* Ensures data is loaded (called during initialization)
|
||||
*/
|
||||
public async loadData(): Promise<void> {
|
||||
try {
|
||||
// Just ensure repository is ready - no caching
|
||||
await this.repository.loadEvents();
|
||||
// Just ensure service is ready - getAll() will return data
|
||||
await this.eventService.getAll();
|
||||
} catch (error) {
|
||||
console.error('Failed to load event data:', error);
|
||||
throw error;
|
||||
|
|
@ -41,19 +42,19 @@ export class EventManager {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all events from repository
|
||||
* Get all events from service
|
||||
*/
|
||||
public async getEvents(copy: boolean = false): Promise<ICalendarEvent[]> {
|
||||
const events = await this.repository.loadEvents();
|
||||
const events = await this.eventService.getAll();
|
||||
return copy ? [...events] : events;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event by ID from repository
|
||||
* Get event by ID from service
|
||||
*/
|
||||
public async getEventById(id: string): Promise<ICalendarEvent | undefined> {
|
||||
const events = await this.repository.loadEvents();
|
||||
return events.find(event => event.id === id);
|
||||
const event = await this.eventService.get(id);
|
||||
return event || undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -116,7 +117,7 @@ export class EventManager {
|
|||
* Get events that overlap with a given time period
|
||||
*/
|
||||
public async getEventsForPeriod(startDate: Date, endDate: Date): Promise<ICalendarEvent[]> {
|
||||
const events = await this.repository.loadEvents();
|
||||
const events = await this.eventService.getAll();
|
||||
// Event overlaps period if it starts before period ends AND ends after period starts
|
||||
return events.filter(event => {
|
||||
return event.start <= endDate && event.end >= startDate;
|
||||
|
|
@ -125,10 +126,19 @@ export class EventManager {
|
|||
|
||||
/**
|
||||
* Create a new event and add it to the calendar
|
||||
* Delegates to repository with source='local'
|
||||
* Generates ID and saves via EventService
|
||||
*/
|
||||
public async addEvent(event: Omit<ICalendarEvent, 'id'>): Promise<ICalendarEvent> {
|
||||
const newEvent = await this.repository.createEvent(event, 'local');
|
||||
// Generate unique ID
|
||||
const id = `event-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
||||
|
||||
const newEvent: ICalendarEvent = {
|
||||
...event,
|
||||
id,
|
||||
syncStatus: 'synced' // No queue yet, mark as synced
|
||||
};
|
||||
|
||||
await this.eventService.save(newEvent);
|
||||
|
||||
this.eventBus.emit(CoreEvents.EVENT_CREATED, {
|
||||
event: newEvent
|
||||
|
|
@ -139,11 +149,23 @@ export class EventManager {
|
|||
|
||||
/**
|
||||
* Update an existing event
|
||||
* Delegates to repository with source='local'
|
||||
* Merges updates with existing event and saves
|
||||
*/
|
||||
public async updateEvent(id: string, updates: Partial<ICalendarEvent>): Promise<ICalendarEvent | null> {
|
||||
try {
|
||||
const updatedEvent = await this.repository.updateEvent(id, updates, 'local');
|
||||
const existingEvent = await this.eventService.get(id);
|
||||
if (!existingEvent) {
|
||||
throw new Error(`Event with ID ${id} not found`);
|
||||
}
|
||||
|
||||
const updatedEvent: ICalendarEvent = {
|
||||
...existingEvent,
|
||||
...updates,
|
||||
id, // Ensure ID doesn't change
|
||||
syncStatus: 'synced' // No queue yet, mark as synced
|
||||
};
|
||||
|
||||
await this.eventService.save(updatedEvent);
|
||||
|
||||
this.eventBus.emit(CoreEvents.EVENT_UPDATED, {
|
||||
event: updatedEvent
|
||||
|
|
@ -158,11 +180,11 @@ export class EventManager {
|
|||
|
||||
/**
|
||||
* Delete an event
|
||||
* Delegates to repository with source='local'
|
||||
* Calls EventService.delete()
|
||||
*/
|
||||
public async deleteEvent(id: string): Promise<boolean> {
|
||||
try {
|
||||
await this.repository.deleteEvent(id, 'local');
|
||||
await this.eventService.delete(id);
|
||||
|
||||
this.eventBus.emit(CoreEvents.EVENT_DELETED, {
|
||||
eventId: id
|
||||
|
|
@ -177,18 +199,24 @@ export class EventManager {
|
|||
|
||||
/**
|
||||
* Handle remote update from SignalR
|
||||
* Delegates to repository with source='remote'
|
||||
* Saves remote event directly (no queue logic yet)
|
||||
*/
|
||||
public async handleRemoteUpdate(event: ICalendarEvent): Promise<void> {
|
||||
try {
|
||||
await this.repository.updateEvent(event.id, event, 'remote');
|
||||
// Mark as synced since it comes from remote
|
||||
const remoteEvent: ICalendarEvent = {
|
||||
...event,
|
||||
syncStatus: 'synced'
|
||||
};
|
||||
|
||||
await this.eventService.save(remoteEvent);
|
||||
|
||||
this.eventBus.emit(CoreEvents.REMOTE_UPDATE_RECEIVED, {
|
||||
event
|
||||
event: remoteEvent
|
||||
});
|
||||
|
||||
this.eventBus.emit(CoreEvents.EVENT_UPDATED, {
|
||||
event
|
||||
event: remoteEvent
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(`Failed to handle remote update for event ${event.id}:`, error);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue