Adds audit logging and sync management infrastructure
Introduces comprehensive audit trail system with: - AuditService to track entity changes - SyncManager for background sync of audit entries - New CoreEvents for entity and audit tracking - Simplified sync architecture with event-driven approach Prepares system for enhanced compliance and change tracking
This commit is contained in:
parent
dcd76836bd
commit
9ea98e3a04
18 changed files with 469 additions and 414 deletions
|
|
@ -2,6 +2,9 @@ import { ISync, EntityType, SyncStatus } from '../types/CalendarTypes';
|
|||
import { IEntityService } from './IEntityService';
|
||||
import { SyncPlugin } from './SyncPlugin';
|
||||
import { IndexedDBContext } from './IndexedDBContext';
|
||||
import { IEventBus } from '../types/CalendarTypes';
|
||||
import { CoreEvents } from '../constants/CoreEvents';
|
||||
import { diff } from 'json-diff-ts';
|
||||
|
||||
/**
|
||||
* BaseEntityService<T extends ISync> - Abstract base class for all entity services
|
||||
|
|
@ -42,11 +45,16 @@ export abstract class BaseEntityService<T extends ISync> implements IEntityServi
|
|||
// IndexedDB context - provides database connection
|
||||
private context: IndexedDBContext;
|
||||
|
||||
// EventBus for emitting entity events
|
||||
protected eventBus: IEventBus;
|
||||
|
||||
/**
|
||||
* @param context - IndexedDBContext instance (injected dependency)
|
||||
* @param eventBus - EventBus for emitting entity events
|
||||
*/
|
||||
constructor(context: IndexedDBContext) {
|
||||
constructor(context: IndexedDBContext, eventBus: IEventBus) {
|
||||
this.context = context;
|
||||
this.eventBus = eventBus;
|
||||
this.syncPlugin = new SyncPlugin<T>(this);
|
||||
}
|
||||
|
||||
|
|
@ -132,10 +140,28 @@ export abstract class BaseEntityService<T extends ISync> implements IEntityServi
|
|||
|
||||
/**
|
||||
* Save an entity (create or update)
|
||||
* Emits ENTITY_SAVED event with operation type and changes
|
||||
*
|
||||
* @param entity - Entity to save
|
||||
*/
|
||||
async save(entity: T): Promise<void> {
|
||||
const entityId = (entity as any).id;
|
||||
|
||||
// Check if entity exists to determine create vs update
|
||||
const existingEntity = await this.get(entityId);
|
||||
const isCreate = existingEntity === null;
|
||||
|
||||
// Calculate changes: full entity for create, diff for update
|
||||
let changes: any;
|
||||
if (isCreate) {
|
||||
changes = entity;
|
||||
} else {
|
||||
// Calculate diff between existing and new entity
|
||||
const existingSerialized = this.serialize(existingEntity);
|
||||
const newSerialized = this.serialize(entity);
|
||||
changes = diff(existingSerialized, newSerialized);
|
||||
}
|
||||
|
||||
const serialized = this.serialize(entity);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
|
@ -144,17 +170,26 @@ export abstract class BaseEntityService<T extends ISync> implements IEntityServi
|
|||
const request = store.put(serialized);
|
||||
|
||||
request.onsuccess = () => {
|
||||
// Emit ENTITY_SAVED event
|
||||
this.eventBus.emit(CoreEvents.ENTITY_SAVED, {
|
||||
entityType: this.entityType,
|
||||
entityId,
|
||||
operation: isCreate ? 'create' : 'update',
|
||||
changes,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
resolve();
|
||||
};
|
||||
|
||||
request.onerror = () => {
|
||||
reject(new Error(`Failed to save ${this.entityType} ${(entity as any).id}: ${request.error}`));
|
||||
reject(new Error(`Failed to save ${this.entityType} ${entityId}: ${request.error}`));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an entity
|
||||
* Emits ENTITY_DELETED event
|
||||
*
|
||||
* @param id - Entity ID to delete
|
||||
*/
|
||||
|
|
@ -165,6 +200,13 @@ export abstract class BaseEntityService<T extends ISync> implements IEntityServi
|
|||
const request = store.delete(id);
|
||||
|
||||
request.onsuccess = () => {
|
||||
// Emit ENTITY_DELETED event
|
||||
this.eventBus.emit(CoreEvents.ENTITY_DELETED, {
|
||||
entityType: this.entityType,
|
||||
entityId: id,
|
||||
operation: 'delete',
|
||||
timestamp: Date.now()
|
||||
});
|
||||
resolve();
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue