lorehub
Version:
Capture and surface the collective wisdom of your codebase
110 lines • 3.9 kB
JavaScript
import { GitSyncAdapter } from './git-sync-adapter.js';
export class ChangeTracker {
static instance = null;
syncAdapters = new Map();
enabled = false;
db = null;
constructor() { }
static getInstance() {
if (!ChangeTracker.instance) {
ChangeTracker.instance = new ChangeTracker();
}
return ChangeTracker.instance;
}
initialize(db) {
this.db = db;
this.enabled = true;
}
disable() {
this.enabled = false;
}
enable() {
this.enabled = true;
}
async recordChange(change, realmId) {
if (!this.enabled || !this.db)
return;
try {
// Get workspaces associated with this realm (if realmId provided)
let workspaces = [];
if (realmId) {
workspaces = this.db.getRealmWorkspaces(realmId);
}
else if (change.metadata?.workspaceId) {
const workspace = this.db.findWorkspace(change.metadata.workspaceId);
if (workspace)
workspaces = [workspace];
}
// If no workspaces found, try default workspace
if (workspaces.length === 0) {
const defaultWorkspace = this.db.getDefaultWorkspace();
if (defaultWorkspace)
workspaces = [defaultWorkspace];
}
// Record change in each workspace that has sync enabled
for (const workspace of workspaces) {
if (!workspace.syncEnabled)
continue;
// Get or create sync adapter for this workspace
let adapter = this.syncAdapters.get(workspace.id);
if (!adapter) {
adapter = new GitSyncAdapter(workspace, this.db);
await adapter.initialize();
this.syncAdapters.set(workspace.id, adapter);
}
// Record the change
await adapter.recordChange({
...change,
metadata: {
...change.metadata,
workspaceId: workspace.id,
realmId
}
});
// If auto-sync is enabled and we have a remote, push immediately
if (workspace.autoSync && workspace.syncRepo) {
// Don't await this - let it happen in the background
adapter.push().catch(err => {
console.error(`Auto-sync failed for workspace ${workspace.name}:`, err);
});
}
}
}
catch (error) {
console.error('Failed to record change:', error);
// Don't throw - we don't want change tracking to break operations
}
}
// Helper methods for specific entity types
async recordLoreChange(operation, loreId, realmId, data) {
await this.recordChange({
operation,
entity: 'lore',
entityId: loreId,
data,
metadata: { realmId }
}, realmId);
}
async recordRealmChange(operation, realmId, data) {
await this.recordChange({
operation,
entity: 'realm',
entityId: realmId,
data
}, realmId);
}
async recordRelationChange(operation, fromLoreId, toLoreId, type, realmId, data) {
await this.recordChange({
operation,
entity: 'relation',
entityId: `${fromLoreId}-${toLoreId}-${type}`,
data: data || { fromLoreId, toLoreId, type },
metadata: { realmId }
}, realmId);
}
// Clean up sync adapters
async cleanup() {
this.syncAdapters.clear();
}
}
//# sourceMappingURL=change-tracker.js.map