Api Reference

Ecosistema completo para organización y gestión de contenido con interfaces espaciales

Flash Persistence - API Reference

Complete API documentation for Flash Persistence.


Table of Contents

  1. autoFlashState()
  2. Flash State Builders
  3. FlashStateService
  4. FlashStateHydratorService
  5. Provider Functions
  6. Types & Interfaces

autoFlashState()

Create an auto-persistent signal.

Signature

function autoFlashState<T>(
  options: AutoFlashStateOptions<T>
): WritableSignal<T>

Parameters

AutoFlashStateOptions

interface AutoFlashStateOptions<T> {
  key: string;                    // Required: Unique storage key
  initialValue: T;                // Required: Default value
  database?: string;              // Optional: Database name
  collection?: string;            // Optional: Collection name
  namespace?: string;             // Optional: Namespace
  ttl?: number;                   // Optional: Time-to-live (ms)
  priority?: SyncPriority;        // Optional: Sync priority
  equal?: (a: T, b: T) => boolean; // Optional: Custom equality
}
Parameter Type Required Default Description
key string ✅ - Unique identifier for this state
initialValue T ✅ - Initial/default value
database string ❌ 'default' Database name for organization
collection string ❌ 'general' Collection name for grouping
namespace string ❌ '' Additional namespace for isolation
ttl number ❌ undefined Expiration time in milliseconds
priority SyncPriority ❌ undefined MongoDB sync priority
equal function ❌ === Custom equality function

Returns

WritableSignal<T> - A writable Angular signal with automatic persistence

Usage Examples

Basic Usage

const theme = autoFlashState({
  key: 'theme',
  initialValue: 'dark'
});

// Read
console.log(theme()); // 'dark'

// Write
theme.set('light'); // ✅ Persisted automatically

With Database Organization

const userProfile = autoFlashState({
  key: 'profile',
  database: 'user-data',
  collection: 'profiles',
  namespace: 'current-user',
  initialValue: { name: '', email: '' }
});
// Full key: user-data:current-user:profiles:profile

With TTL (Temporary Data)

const sessionData = autoFlashState({
  key: 'session',
  initialValue: null,
  ttl: 30 * 60 * 1000 // 30 minutes
});
// Automatically deleted after 30 minutes

With MongoDB Sync Priority

const sharedDocument = autoFlashState({
  key: 'doc-123',
  database: 'collaboration',
  collection: 'documents',
  initialValue: { content: '' },
  priority: 'high' // Sync every 5 minutes
});

With Custom Equality

interface ComplexObject {
  id: string;
  data: any[];
  timestamp: number;
}

const complexState = autoFlashState<ComplexObject>({
  key: 'complex',
  initialValue: { id: '', data: [], timestamp: 0 },
  equal: (a, b) => {
    // Only consider 'id' for equality
    return a.id === b.id;
  }
});

Flash State Builders

Convenience helpers for common patterns.

appFlashState()

Create state in the 'app-data' database.

function appFlashState<T>(options: {
  key: string;
  initialValue: T;
  collection?: string;
  ttl?: number;
  priority?: SyncPriority;
}): WritableSignal<T>

Example:

const appState = appFlashState({
  key: 'state',
  initialValue: { sidebarOpen: true },
  collection: 'ui-state'
});
// Stored in: app-data:ui-state:state

userFlashState()

Create state in the 'user-data' database.

function userFlashState<T>(options: {
  key: string;
  initialValue: T;
  collection?: string;
  ttl?: number;
  priority?: SyncPriority;
}): WritableSignal<T>

Example:

const preferences = userFlashState({
  key: 'preferences',
  initialValue: { theme: 'dark' },
  collection: 'settings',
  priority: 'high' // Sync to MongoDB
});
// Stored in: user-data:settings:preferences

cacheFlashState()

Create temporary cached state with TTL.

function cacheFlashState<T>(options: {
  key: string;
  initialValue: T;
  ttl?: number;
}): WritableSignal<T>

Example:

const apiCache = cacheFlashState({
  key: 'users-list',
  initialValue: [],
  ttl: 5 * 60 * 1000 // 5 minutes
});
// Automatically expires after 5 minutes

criticalFlashState()

Create critical state with immediate sync.

function criticalFlashState<T>(options: {
  key: string;
  initialValue: T;
  database?: string;
  collection?: string;
}): WritableSignal<T>

Example:

const authToken = criticalFlashState({
  key: 'auth-token',
  database: 'security',
  initialValue: null
});
// Syncs immediately to MongoDB (if configured)

FlashStateService

Injectable service for component-scoped state.

Constructor

@Injectable()
export class FlashStateService {
  createState<T>(options: AutoFlashStateOptions<T>): WritableSignal<T>
  createAppState<T>(options: {...}): WritableSignal<T>
  createUserState<T>(options: {...}): WritableSignal<T>
  createCacheState<T>(options: {...}): WritableSignal<T>
}

Usage

import { Component, inject } from '@angular/core';
import { FlashStateService } from '@storage-system';

@Component({
  selector: 'app-settings',
  standalone: true,
  providers: [FlashStateService]
})
export class SettingsComponent {
  private flashState = inject(FlashStateService);
  
  // Component-scoped persistent state
  localSettings = this.flashState.createState({
    key: 'component-settings',
    initialValue: { expanded: false }
  });
  
  toggleExpanded() {
    this.localSettings.update(s => ({ expanded: !s.expanded }));
  }
}

FlashStateHydratorService

Core service managing state hydration and persistence.

Methods

updateState()

Manually trigger state persistence.

updateState(key: string, value: any): void

Example:

import { inject } from '@angular/core';
import { FlashStateHydratorService } from '@storage-system';

const hydrator = inject(FlashStateHydratorService);
hydrator.updateState('my-key', { data: 'value' });

getInstantState()

Get cached state without async.

getInstantState<T>(key: string): T | undefined

Example:

const cachedValue = hydrator.getInstantState('theme');
console.log(cachedValue); // Instant access

clearState()

Clear a specific state.

clearState(key: string): Promise<void>

Example:

await hydrator.clearState('draft');

clearAllStates()

Clear all persisted states.

clearAllStates(): Promise<void>

Example:

await hydrator.clearAllStates();

flush()

Force immediate persistence of pending changes.

flush(): Promise<void>

Example:

// Before navigation
await hydrator.flush();
router.navigate(['/next-page']);

Provider Functions

provideFlashPersistence()

Setup Flash Persistence in your app.

function provideFlashPersistence(
  config?: FlashPersistenceConfig
): EnvironmentProviders

FlashPersistenceConfig

interface FlashPersistenceConfig {
  debounceMs?: number;              // Debounce time (default: 300ms)
  enableMongoDBSync?: boolean;      // Enable MongoDB sync
  preloadKeys?: string[];           // Keys to pre-load
  flushBeforeNavigation?: boolean;  // Flush on route change
  storageConfig?: {
    namespace?: string;
    cache?: { maxItems: number; ttlMs: number };
  };
}

Example:

import { ApplicationConfig } from '@angular/core';
import { provideFlashPersistence } from '@storage-system';

export const appConfig: ApplicationConfig = {
  providers: [
    provideFlashPersistence({
      debounceMs: 500,              // Wait 500ms before saving
      enableMongoDBSync: true,      // Enable cloud sync
      preloadKeys: ['theme', 'preferences'],
      flushBeforeNavigation: true,  // Auto-flush on navigation
      storageConfig: {
        namespace: 'my-app',
        cache: { maxItems: 1000, ttlMs: 600_000 }
      }
    })
  ]
};

Types & Interfaces

SyncPriority

type SyncPriority = 'critical' | 'high' | 'normal' | 'low';

Usage:

FlashPerformanceMetrics

interface FlashPerformanceMetrics {
  totalStates: number;
  cacheHitRate: number;
  avgReadTime: number;
  avgWriteTime: number;
  totalReads: number;
  totalWrites: number;
}

Access:

const hydrator = inject(FlashStateHydratorService);
const metrics = hydrator.getPerformanceMetrics();
console.log(`Cache hit rate: ${metrics.cacheHitRate}%`);

AutoDiscoveredState

interface AutoDiscoveredState {
  fullKey: string;
  database: string;
  collection: string;
  namespace: string;
  key: string;
  priority?: SyncPriority;
  ttl?: number;
}

Access:

import { AUTO_DISCOVERED_STATES } from '@storage-system';

console.log('All Flash states:', AUTO_DISCOVERED_STATES);

Advanced Usage

Computed Signals with Flash Persistence

const cart = autoFlashState<CartItem[]>({
  key: 'cart',
  initialValue: []
});

// Computed from persistent state
const itemCount = computed(() => 
  cart().reduce((sum, item) => sum + item.quantity, 0)
);

const total = computed(() =>
  cart().reduce((sum, item) => sum + (item.price * item.quantity), 0)
);

Effects with Flash Persistence

const theme = autoFlashState({
  key: 'theme',
  initialValue: 'dark'
});

// React to theme changes
effect(() => {
  const currentTheme = theme();
  document.body.classList.toggle('dark-theme', currentTheme === 'dark');
}, { allowSignalWrites: true });

Migration from NGXS

// Before (NGXS)
@Select(PreferencesState.theme) theme$!: Observable<string>;

constructor(private store: Store) {}

setTheme(theme: string) {
  this.store.dispatch(new SetTheme(theme));
}

// After (Flash Persistence)
theme = autoFlashState({
  key: 'theme',
  initialValue: 'dark'
});

setTheme(newTheme: string) {
  this.theme.set(newTheme); // That's it!
}

Custom Serialization

For complex types that need special serialization:

class CustomDate {
  constructor(public value: Date) {}
  
  toJSON() {
    return this.value.toISOString();
  }
  
  static fromJSON(json: string) {
    return new CustomDate(new Date(json));
  }
}

const dateState = autoFlashState({
  key: 'date',
  initialValue: new CustomDate(new Date())
});

// Serialization/deserialization handled automatically via toJSON

Performance Tips

1. Use Computed for Derived Values

// ❌ Bad - Recomputes every time
function getTotal() {
  return cart().reduce((sum, item) => sum + item.price, 0);
}

// ✅ Good - Computed once
const total = computed(() => 
  cart().reduce((sum, item) => sum + item.price, 0)
);

2. Batch Updates

// ❌ Bad - Multiple writes
items.forEach(item => cart.update(c => [...c, item]));

// ✅ Good - Single write
cart.update(c => [...c, ...items]);

3. Use TTL for Temporary Data

// ✅ Automatic cleanup
const tempCache = autoFlashState({
  key: 'temp-data',
  initialValue: null,
  ttl: 60 * 1000 // 1 minute
});

4. Optimize Large Objects

// ❌ Bad - Stores entire object
const largeState = autoFlashState({
  key: 'large',
  initialValue: { ...hugeObject }
});

// ✅ Good - Store only needed fields
const essentialState = autoFlashState({
  key: 'essential',
  initialValue: { id: hugeObject.id, name: hugeObject.name }
});

Error Handling

Flash Persistence handles errors gracefully:

const state = autoFlashState({
  key: 'data',
  initialValue: { value: 0 }
});

try {
  state.set({ value: 1 });
} catch (error) {
  // Errors are logged but don't throw
  // State update succeeds, persistence may be queued for retry
  console.error('Persistence error:', error);
}

Storage Quota Exceeded

When storage quota is exceeded:

  1. Least recently used items are evicted
  2. Write is retried
  3. If still fails, error is logged
  4. In-memory state is maintained

Debugging

Enable Debug Logging

// In development
if (!environment.production) {
  localStorage.setItem('DEBUG_FLASH_PERSISTENCE', 'true');
}

View Auto-Discovered States

import { AUTO_DISCOVERED_STATES } from '@storage-system';

console.table(AUTO_DISCOVERED_STATES);

Check Performance Metrics

const hydrator = inject(FlashStateHydratorService);
console.log(hydrator.getPerformanceMetrics());

Next Steps


Questions? Check GitHub Discussions or open an issue.