UNIVERSAL AUTO SYNC GUIDE
Ecosistema completo para organización y gestión de contenido con interfaces espaciales
🔄 Universal Auto-Sync Implementation Guide
Date: November 18, 2025
Purpose: Enable automatic MongoDB sync for ALL data changes
✅ Step 1: Initialize Universal Auto-Sync (ONE TIME SETUP)
Add to your main.ts or app initialization:
// apps/gograb-space/src/main.ts
import { UniversalAutoSyncService } from '@libs-foundational/core-angular';
// ... in your bootstrap function ...
const universalAutoSync = injector.get(UniversalAutoSyncService);
await universalAutoSync.initialize();
console.log('✅ Universal Auto-Sync enabled - ALL storage changes will sync to MongoDB!');
That's it! Every storage.put() and storage.remove() call will now automatically sync to MongoDB.
✅ Step 2: Verify It's Working
Test 1: Save Universe Layout
- Open Universe Builder
- Make changes to layout
- Click "Save"
- Watch console:
[UniversalAutoSync] 🔍 Detected write on universe: universe_1763427157418
[UniversalAutoSync] 🔄 Syncing universe: universe_1763427157418
[SyncEngine] 📤 Calling SpaceApiService.updateUniverse
✅ Universe synced to backend
Test 2: Check MongoDB
# Query MongoDB
db.space_YOUR_SPACE_ID.universes.findOne({ _id: "universe_1763427157418" })
# Should show updated layout
{
_id: "universe_1763427157418",
name: "...",
layout: { ... }, // ← Updated!
updatedAt: "2025-11-18T..."
}
🎯 How It Works
Architecture
User clicks "Save"
↓
Component calls storage.put(key, data)
↓
UniversalAutoSync intercepts the call
↓
Detects entity type from key (universe_, space_, page_, etc.)
↓
Debounces for 1 second (batches rapid changes)
↓
Queues sync operation
↓
SyncEngine syncs to MongoDB
↓
✅ Done! (User never waits)
Key Features
✅ Zero Configuration: No code changes needed in components
✅ Automatic Detection: Knows what entity type from storage key
✅ Smart Batching: Combines rapid changes
✅ Debouncing: Waits 1s before syncing (configurable)
✅ Offline-First: Local save happens immediately
✅ Background Sync: MongoDB update doesn't block UI
🔧 Configuration (Optional)
Change Debounce Time
// Make sync faster (500ms) or slower (2000ms)
universalAutoSync.updateConfig({
debounceTime: 500 // milliseconds
});
Exclude Certain Keys
universalAutoSync.updateConfig({
excludeKeys: ['temp_', 'cache_', 'draft_'] // Never sync these
});
Add Custom Entity Patterns
universalAutoSync.updateConfig({
entityPatterns: {
space: /^space_/,
universe: /^universe_/,
page: /^page_/,
galaxy: /^galaxy_/, // ← Custom entity
section: /^section_/ // ← Custom entity
}
});
📊 Monitoring
Check Sync Stats
// In console
const autoSync = injector.get(UniversalAutoSyncService);
console.log(autoSync.stats());
// Output:
{
totalDetected: 45, // Total changes detected
totalSynced: 42, // Successfully synced
totalSkipped: 3, // Excluded keys
lastSync: Date(...) // Last sync time
}
Flush Pending Syncs
// Force immediate sync of all pending changes
await autoSync.flushPendingSyncs();
console.log('✅ All changes synced immediately!');
🎨 Alternative: Directive Approach (More Explicit)
If you want explicit control per button:
Option A: Simple Button Sync
<!-- universe-builder.component.html -->
<button class="btn-secondary"
(click)="saveLayout()"
ggAutoSync
[syncEntity]="'universe'"
[syncData]="currentLayout()"
[syncId]="universeId()">
<i class="fas fa-save"></i>
Save
</button>
Import the directive:
import { AutoSyncDirective } from '@libs-foundational/core-angular';
@Component({
imports: [CommonModule, AutoSyncDirective, ...], // ← Add here
// ...
})
Option B: Debounced Input Sync
<input [(ngModel)]="universeName"
ggAutoSync
[syncEntity]="'universe'"
[syncProperty]="'name'"
[syncId]="universeId()"
[syncDebounce]="1000"
[syncTrigger]="'change'">
🚀 Service-Level Auto-Sync (Decorator)
For service methods:
import { AutoSync } from '@libs-foundational/core-angular';
@Injectable()
export class UniverseService {
private syncEngine = inject(SyncEngineService); // ← Required for decorator
private logger = inject(LoggerService); // ← Required for decorator
@AutoSync({ entity: 'universe', operation: 'update' })
async updateUniverse(universe: Universe): Promise<Universe> {
// Save locally (offline-first)
await this.storage.put(`universe_${universe.id}`, universe);
// Return triggers auto-sync ✨
return universe;
}
@AutoSync({ entity: 'universe', operation: 'create' })
async createUniverse(universe: Universe): Promise<Universe> {
await this.storage.put(`universe_${universe.id}`, universe);
return universe; // ← Auto-synced!
}
@AutoSync({
entity: 'universe',
operation: 'delete',
extractId: (result, universeId) => universeId
})
async deleteUniverse(universeId: string): Promise<void> {
await this.storage.remove(`universe_${universeId}`);
// ← Auto-synced with ID from parameter
}
}
🎯 Recommendation
Use Universal Auto-Sync (Option 1) because:
✅ Works everywhere automatically
✅ No code changes needed
✅ Can't forget to add sync
✅ Consistent behavior
✅ Easy to maintain
Use Directive/Decorator (Options 2-3) when you need:
⚙️ Explicit control
⚙️ Different sync behavior per action
⚙️ Special sync timing
📝 Summary
Before (Your Current Code)
async saveLayout(): Promise<void> {
this.logger.info('Layout saved successfully');
// Already auto-saves in canvas
}
Problem: Saves to local storage only, doesn't sync to MongoDB ❌
After (With Universal Auto-Sync)
NO CODE CHANGES NEEDED! ✨
Just initialize once in main.ts:
await injector.get(UniversalAutoSyncService).initialize();
Now EVERY storage operation syncs automatically:
- ✅ Universe changes
- ✅ Space changes
- ✅ Page changes
- ✅ Module changes
- ✅ Widget changes
- ✅ Everything!
🧪 Testing Checklist
- Initialize Universal Auto-Sync in
main.ts - Click "Save" in Universe Builder
- Check console for sync logs
- Check MongoDB for updated data
- Open in another browser
- Verify changes appear within 10 seconds
Status: Ready to implement! 🚀
Effort: 5 minutes (just add initialization)
Impact: Universal auto-sync for everything!