2025-12-17 23:54:25 +01:00
|
|
|
import { ISync, SyncStatus } from '../types/CalendarTypes';
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* SyncPlugin<T extends ISync> - Pluggable sync functionality for entity services
|
|
|
|
|
*
|
|
|
|
|
* COMPOSITION PATTERN:
|
|
|
|
|
* - Encapsulates all sync-related logic in separate class
|
|
|
|
|
* - Composed into BaseEntityService (not inheritance)
|
|
|
|
|
*/
|
|
|
|
|
export class SyncPlugin<T extends ISync> {
|
|
|
|
|
constructor(private service: any) {}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mark entity as successfully synced
|
|
|
|
|
*/
|
|
|
|
|
async markAsSynced(id: string): Promise<void> {
|
|
|
|
|
const entity = await this.service.get(id);
|
|
|
|
|
if (entity) {
|
|
|
|
|
entity.syncStatus = 'synced';
|
|
|
|
|
await this.service.save(entity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Mark entity as sync error
|
|
|
|
|
*/
|
|
|
|
|
async markAsError(id: string): Promise<void> {
|
|
|
|
|
const entity = await this.service.get(id);
|
|
|
|
|
if (entity) {
|
|
|
|
|
entity.syncStatus = 'error';
|
|
|
|
|
await this.service.save(entity);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get current sync status for an entity
|
|
|
|
|
*/
|
|
|
|
|
async getSyncStatus(id: string): Promise<SyncStatus | null> {
|
|
|
|
|
const entity = await this.service.get(id);
|
|
|
|
|
return entity ? entity.syncStatus : null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get entities by sync status using IndexedDB index
|
|
|
|
|
*/
|
|
|
|
|
async getBySyncStatus(syncStatus: string): Promise<T[]> {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const transaction = this.service.db.transaction([this.service.storeName], 'readonly');
|
|
|
|
|
const store = transaction.objectStore(this.service.storeName);
|
|
|
|
|
const index = store.index('syncStatus');
|
|
|
|
|
const request = index.getAll(syncStatus);
|
|
|
|
|
|
|
|
|
|
request.onsuccess = () => {
|
|
|
|
|
const data = request.result as unknown[];
|
|
|
|
|
const entities = data.map(item => this.service.deserialize(item));
|
|
|
|
|
resolve(entities);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
request.onerror = () => {
|
|
|
|
|
reject(new Error(`Failed to get by sync status ${syncStatus}: ${request.error}`));
|
|
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|