API Reference

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

📘 Complete API Reference

Complete API documentation for the GoGrab Storage System.


🎯 Core Storage Operations

Basic Methods

class StorageService {
  // Save data
  put<T>(key: string, value: T, options?: PutOptions): Promise<boolean>;
  
  // Load data
  get<T>(key: string, options?: GetOptions): Promise<T | null>;
  
  // Check existence
  has(key: string): Promise<boolean>;
  
  // Remove data
  remove(key: string): Promise<boolean>;
  
  // List keys
  list(options?: ListOptions): Promise<string[]>;
  
  // Clear data
  clear(prefix?: string): Promise<void>;
  
  // Pre-load keys
  prewarm(keys: string[]): Promise<void>;
}

Method Details

put<T>(key, value, options?)

Save data to storage with optional configuration.

Parameters:

Returns: Promise<boolean> - Success status

Example:

// Simple save
await storage.put('user-profile', {name: 'John', email: '[email protected]'});

// With options
await storage.put('temp-data', data, {
  ttlMs: 3600000,  // 1 hour TTL
  overwrite: true
});

Options:

interface PutOptions {
  ttlMs?: number;       // Time-to-live in milliseconds
  overwrite?: boolean;  // Force overwrite existing data
  priority?: 'low' | 'normal' | 'high'; // Migration priority
  cacheable?: boolean;  // Enable micro-cache
}

get<T>(key, options?)

Retrieve data from storage.

Parameters:

Returns: Promise<T | null> - Data or null if not found

Example:

const user = await storage.get<UserProfile>('user-profile');
if (user) {
  console.log(user.name);
}

// Cache-only read (skip storage)
const cached = await storage.get('hot-data', { cacheOnly: true });

Options:

interface GetOptions {
  cacheOnly?: boolean;  // Only read from cache, don't hit storage
}

has(key)

Check if a key exists.

Parameters:

Returns: Promise<boolean> - True if exists

Example:

if (await storage.has('user-profile')) {
  console.log('Profile exists');
}

remove(key)

Delete data by key.

Parameters:

Returns: Promise<boolean> - Success status

Example:

await storage.remove('temp-data');

list(options?)

List all keys or filtered keys.

Parameters:

Returns: Promise<string[]> - Array of keys

Example:

// All keys
const allKeys = await storage.list();

// Filter by prefix
const userKeys = await storage.list({ prefix: 'user/' });

// With limit
const recentKeys = await storage.list({ limit: 10 });

Options:

interface ListOptions {
  prefix?: string;  // Filter by prefix
  limit?: number;   // Maximum number of keys
}

clear(prefix?)

Clear all data or data with prefix.

Parameters:

Returns: Promise<void>

Example:

// Clear everything
await storage.clear();

// Clear only cache data
await storage.clear('cache/');

prewarm(keys)

Pre-load keys into cache for fast access.

Parameters:

Returns: Promise<void>

Example:

// Pre-load frequently accessed data
await storage.prewarm([
  'user-profile',
  'user-settings',
  'app-config'
]);

⚡ Flash Persistence API

autoFlashState()

Create an automatically persisted signal backed by IndexedDB.

function autoFlashState<T>(
  key: string,
  defaultValue: T,
  options?: AutoFlashStateOptions<T>
): AutoFlashSignal<T>

Parameters:

Returns: AutoFlashSignal<T> - Auto-persistent signal with hydration status

AutoFlashSignal<T> (Session 172)

Extends WritableSignal<T> with hydration status. Backward compatible — all existing WritableSignal<T> call sites work. .hydrated is opt-in.

type AutoFlashSignal<T> = WritableSignal<T> & {
  /** True when IndexedDB data has been loaded into this signal */
  readonly hydrated: Signal<boolean>;
};

Basic Example:

const theme = autoFlashState('theme', { color: 'blue', mode: 'dark' });

// Read
console.log(theme().color);

// Write (automatically saved to IndexedDB)
theme.set({ color: 'green', mode: 'light' });

// Update (automatically saved)
theme.update(t => ({ ...t, color: 'red' }));

Backend Sync Example (Session 172 cache pattern):

private readonly state = autoFlashState<MyState>('my-key', defaultState, config);

constructor() {
  effect(() => {
    // Gate backend loading on IndexedDB hydration
    if (!this.state.hydrated()) return;
    const userId = this._userId();
    if (!userId) return;
    if (this.loaded) return;
    this.loaded = true;

    // Load from backend, write INTO autoFlashState (atomic, no flash)
    this.http.get<BackendData>(url).subscribe(data => {
      this.state.update(s => ({ ...s, items: merge(s.items, data) }));
    });
  });
}

Options:

interface AutoFlashStateOptions<T> {
  debounceMs?: number;  // Debounce writes (default: 250ms). Session 172: now functional.
  versioning?: StateVersioningConfig<T>; // State version + migrations
  database?: string;    // IndexedDB database namespace
  collection?: string;  // Collection namespace
  namespace?: string;   // Custom namespace (default: 'flash')
  priority?: 'low' | 'normal' | 'high' | 'critical'; // Sync priority
  ttl?: number;         // Time-to-live in milliseconds
}

FlashStateHydratorService

Pre-load and hydrate flash states.

@Injectable({ providedIn: 'root' })
class FlashStateHydratorService {
  // Pre-load states for 0ms hydration
  preloadCriticalState(keys: string[], options?): Promise<void>;

  // Get instant state from cache
  getInstantState<T>(key: string): T | null;

  // Check global hydration status
  isHydrated(): Signal<boolean>;

  // Clear states
  clearStatesByPrefix(prefix: string): Promise<void>;

  // Flush pending writes immediately
  flushPendingPersistence(): Promise<void>;

  // Session 172: Per-key debounce override
  setDebounceMs(key: string, debounceMs: number): void;
}

Example:

// Pre-load in app initializer
export const appConfig: ApplicationConfig = {
  providers: [
    provideAppInitializer(() => {
      const hydrator = inject(FlashStateHydratorService);
      return () => hydrator.preloadStates(['user-profile', 'app-settings']);
    })
  ]
};

// Then in components - instant access (no await needed)
const profile = hydrator.getInstantState<UserProfile>('user-profile');

🧠 Intelligence & Strategy API

Strategy Management

type StorageStrategy = 'speed' | 'balanced' | 'durable';

// Set storage strategy
setStrategy(strategy: StorageStrategy): void;

// Get current strategy
getStrategy(): StorageStrategy;

Strategies:

Example:

// Switch to speed mode
storage.setStrategy('speed');

// Check current strategy
const current = storage.getStrategy(); // 'speed'

Capabilities Detection

getCapabilities(): StorageCapabilities;

interface StorageCapabilities {
  opfs: boolean;        // OPFS support
  indexedDB: boolean;   // IndexedDB support
  localStorage: boolean; // localStorage support
  worker: boolean;      // Web Worker support
}

Example:

const caps = storage.getCapabilities();
console.log('OPFS available:', caps.opfs);
console.log('IndexedDB available:', caps.indexedDB);

Performance Monitoring

// Get performance statistics
getPerformanceStats(): PerformanceStats | undefined;

// Get detailed report
getPerformanceReport(): string | null;

// Clear metrics
clearPerformanceMetrics(): void;

// Get micro-cache stats
getMicroCacheStats(): MicroCacheStats;

Interfaces:

interface PerformanceStats {
  cacheHitRate: number;    // Cache hit rate (0-1)
  avgDuration: number;     // Average operation time (ms)
  totalOperations: number; // Total operations
  adapterUsage: Record<string, number>; // Adapter distribution
}

interface MicroCacheStats {
  size: number;      // Current cache size (bytes)
  budget: number;    // Total cache budget (bytes)
  hitRate: number;   // Cache hit rate (0-1)
  entries: number;   // Number of cached entries
  evictions: number; // Number of evictions
}

Example:

const stats = storage.getPerformanceStats();
if (stats) {
  console.log('Cache hit rate:', stats.cacheHitRate);
  console.log('Avg operation time:', stats.avgDuration, 'ms');
}

const cacheStats = storage.getMicroCacheStats();
console.log('Cache usage:', cacheStats.size, '/', cacheStats.budget);

Adapter Management

// Get current adapter
getAdapterKind(): 'opfs' | 'dexie' | 'localStorage';

// Switch adapter (development/debugging only)
switchAdapter(kind: 'opfs' | 'dexie' | 'localStorage'): boolean;

// Get current namespace
getNamespace(): string;

// Switch namespace
switchNamespace(namespace: string): boolean;

Example:

console.log('Current adapter:', storage.getAdapterKind());
console.log('Current namespace:', storage.getNamespace());

// Development only - force specific adapter
if (environment.development) {
  storage.switchAdapter('opfs');
}

🚀 Angular Integration API

StorageService

Complete service with reactive patterns.

@Injectable({ providedIn: 'root' })
export class StorageService {
  // All core operations
  get<T>(key: string, options?: GetOptions): Promise<T | null>;
  put<T>(key: string, value: T, options?: PutOptions): Promise<boolean>;
  remove(key: string): Promise<boolean>;
  has(key: string): Promise<boolean>;
  list(options?: ListOptions): Promise<string[]>;
  clear(prefix?: string): Promise<void>;
  
  // Reactive signals
  asSignal<T>(key: string, initial?: T | null): {
    value: WritableSignal<T | null>;
    refresh(): Promise<void>;
  };
  
  // Intelligence features
  setStrategy(strategy: StorageStrategy): void;
  getStrategy(): StorageStrategy;
  getCapabilities(): StorageCapabilities;
  getPerformanceStats(): PerformanceStats | undefined;
  getMicroCacheStats(): MicroCacheStats;
  
  // Properties
  readonly adapterKind: 'opfs' | 'dexie' | 'localStorage';
  readonly namespace: string;
  readonly config: GgStorageConfig;
}

Providers

// Basic provider
function provideGgStorage(config: GgStorageConfig): Provider[];

// MongoDB sync provider
function provideMongoDBSync(config: MongoDBSyncConfig): Provider[];

// Firebase sync provider
function provideFirebaseSync(config: FirebaseSyncConfig): Provider[];

Configuration:

interface GgStorageConfig {
  namespace: string;
  cache: { maxItems: number; ttlMs: number };
  strategy?: 'speed' | 'balanced' | 'durable';
  adapterPreference?: 'opfs' | 'dexie' | 'localStorage';
  performance?: {
    monitoring?: boolean;
    batchProcessing?: boolean;
    redundancy?: boolean;
    adaptiveStrategy?: boolean;
    microCacheBudget?: number;
  };
}

Example:

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideGgStorage({
      namespace: 'my-app',
      cache: { maxItems: 1000, ttlMs: 300000 },
      strategy: 'balanced',
      performance: {
        monitoring: true,
        redundancy: true,
        microCacheBudget: 100 * 1024
      }
    })
  ]
};

Reactive Signals

// Create reactive signal
const userProfile = storage.asSignal<UserProfile>('user/profile', null);

// Access value
console.log(userProfile.value());

// Refresh from storage
await userProfile.refresh();

☁️ Cloud Sync API

MongoDB Sync

interface MongoDBSyncConfig {
  connectionString: string;
  database: string;
  defaultStrategy?: {
    mode: 'offline-first' | 'online-first' | 'realtime';
    priority: 'low' | 'normal' | 'high' | 'critical';
    conflictResolution: 'last-write-wins' | 'merge' | 'manual';
  };
  enableRealtime?: boolean;
  autoInit?: boolean;
}

Example:

provideMongoDBSync({
  connectionString: environment.mongoDbUri,
  database: 'my-app',
  defaultStrategy: {
    mode: 'offline-first',
    priority: 'normal',
    conflictResolution: 'last-write-wins'
  },
  enableRealtime: true
})

Firebase/Firestore Sync

class FirestoreSyncAdapter {
  constructor(config: FirestoreSyncConfig);
  
  // Core sync operations
  push(changes: SyncChange[]): Promise<SyncResult>;
  pull(since: SyncCursor | null, limit?: number): Promise<PullResult>;
  getStatus(): Promise<SyncStatus>;
  
  // Real-time sync
  setupRealtimeSync(callback: (changes: SyncChange[]) => void): Promise<() => void>;
  
  // Database management
  switchDatabase(databaseId: string): Promise<void>;
  createCollection(name: string): Promise<void>;
}

Example:

const adapter = new FirestoreSyncAdapter({
  databaseId: 'g-space-db-standard',
  collection: 'app-data'
});

storage.setSyncAdapter(adapter);

📊 Events & Reactivity

Storage Events

// Listen for storage events
onEvent(listener: (event: StorageEvent) => void): () => void;

interface StorageEvent {
  type: 'put' | 'remove' | 'clear';
  key?: string;
  value?: any;
  timestamp: number;
}

Example:

const unsubscribe = storage.onEvent((event) => {
  console.log('Storage event:', event.type, event.key);
});

// Cleanup
unsubscribe();

🔧 Configuration Examples

Minimal Setup

provideGgStorage({
  namespace: 'my-app',
  cache: { maxItems: 500, ttlMs: 300000 }
})

Production Setup

provideGgStorage({
  namespace: 'my-app',
  cache: { maxItems: 2000, ttlMs: 600000 },
  strategy: 'balanced',
  performance: {
    monitoring: true,
    redundancy: true,
    adaptiveStrategy: true,
    microCacheBudget: 150 * 1024
  }
})

With MongoDB Sync

providers: [
  provideGgStorage({ namespace: 'my-app' }),
  provideMongoDBSync({
    connectionString: 'mongodb+srv://...',
    database: 'my-app',
    defaultStrategy: {
      mode: 'offline-first',
      priority: 'normal'
    }
  })
]

🗄️ Repository Pattern API (NEW!)

BaseRepository

Complete CRUD + Query + Batch operations with L1 + L2 caching.

import { BaseRepository, BaseEntity } from '@gograb-space/storage-system';

class UserRepository extends BaseRepository<User> {
  protected readonly entityName = 'User';
  protected readonly baseUrl = '/api/users';
  
  constructor() {
    super(storage, {
      cache: {
        maxEntries: 100,      // L1 cache size
        ttl: 300000,          // 5 minutes
        enableStats: true
      },
      enableEvents: true
    });
  }
}

Basic CRUD

// Find by ID (with L1 + L2 caching)
findById(id: string): Observable<T | null>

// Find all with filters/pagination/sorting
findAll(options?: QueryOptions<T>): Observable<T[]>

// Create entity
create(entity: Partial<T>): Observable<T>

// Update entity
update(id: string, entity: Partial<T>): Observable<T>

// Delete entity
delete(id: string): Observable<boolean>

Batch Operations (10x faster!)

// Create multiple entities
createMany(entities: Partial<T>[]): Observable<T[]>

// Update multiple entities
updateMany(updates: Array<{ id: string; data: Partial<T> }>): Observable<T[]>

// Delete multiple entities
deleteMany(ids: string[]): Observable<boolean>

Query Options

interface QueryOptions<T> {
  filter?: QueryFilter<T>;      // Field-level filtering
  pagination?: PaginationOptions; // Page + pageSize
  sort?: SortOptions<T>;         // Field + direction
}

// Filter operators
interface QueryFilter<T> {
  field?: value | QueryOperator;
}

// Operators: $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $contains, $startsWith, $endsWith

Utility Methods

// Count entities matching filter
count(filter?: QueryFilter<T>): Observable<number>

// Check if entity exists
exists(id: string): Observable<boolean>

// Find with pagination
findPaginated(options: QueryOptions<T>): Observable<PaginatedResponse<T>>

Cache Management

// Clear L1 cache
clearCache(): void

// Invalidate specific entry
invalidateCache(id: string): void

// Get statistics
getCacheStats(): { hits, misses, size, hitRate }

// Cache signals
readonly cacheHits: Signal<number>
readonly cacheMisses: Signal<number>
readonly cacheSize: Signal<number>
readonly cacheHitRate: Signal<number>  // Computed %

Example Usage

const userRepo = inject(UserRepository);

// Find with query
const activeUsers = await firstValueFrom(
  userRepo.findAll({
    filter: { status: 'active', role: { $in: ['admin', 'user'] } },
    pagination: { page: 1, pageSize: 10 },
    sort: { field: 'createdAt', direction: 'desc' }
  })
);

// Batch create
const created = await firstValueFrom(
  userRepo.createMany([user1, user2, user3])
);

// Check stats
const stats = userRepo.getCacheStats();
console.log('Cache hit rate:', stats.hitRate, '%');

📦 Modular Storage API (ENHANCED!)

ModularStorageService

Module-specific storage isolation with custom strategies.

import { ModularStorageService, ModuleStorageConfig } from '@gograb-space/storage-system';

const modularStorage = inject(ModularStorageService);

// Get module storage
const spaceStorage = modularStorage.getModuleStorage({
  moduleId: 'space-map',
  storage: {
    primary: 'offline-first',
    collections: {
      'universes': {
        sync: 'immediate',
        cache: 'aggressive',
        conflict: 'local-wins'
      }
    }
  }
});

ModuleStorage Methods

// Get from collection
async get<T>(collection: string, key: string): Promise<T | null>

// Set in collection
async set<T>(collection: string, key: string, value: T): Promise<void>

// Delete from collection
async delete(collection: string, key: string): Promise<void>

// ✅ NEW: Query entire collection
async query<T>(collection: string): Promise<T[]>

// ✅ NEW: Clear entire collection
async clearCollection(collection: string): Promise<void>

ModularStorageService Methods

// Get module storage instance
getModuleStorage(config: ModuleStorageConfig): ModuleStorage

// Check if module registered
hasModuleStorage(moduleId: string): boolean

// Get all registered modules
getRegisteredModules(): string[]

// ✅ NEW: Clear module storage
async clearModuleStorage(moduleId: string): Promise<void>

// ✅ NEW: Get statistics
async getStats(): Promise<{ moduleId, itemCount, sizeMB }[]>

📚 Related Documentation


🔄 Backend Sync Engine API (NEW! Session 166.3)

BackendSyncEngine

Generic fire-and-forget backend sync with persistent retry queue.

@Injectable({ providedIn: 'root' })
class BackendSyncEngine {
  // Register a sync descriptor for a feature
  register<T>(descriptor: SyncDescriptor<T>): void;

  // Fire-and-forget sync (queues on failure, drains on reconnect)
  sync<T>(descriptorKey: string, data: T, contextId?: string): void;

  // Drain retry queue manually
  drainRetryQueue(): Promise<void>;

  // Clear pending items
  clearQueue(descriptorKey?: string): void;

  // Reactive state
  readonly syncState: Signal<BackendSyncState>;
  readonly queueSize: Signal<number>;
  readonly canSync: Signal<boolean>;
}

SyncDescriptor

Define how to sync any data type to a backend endpoint:

interface SyncDescriptor<T> {
  key: string;                                     // Unique identifier
  method: 'POST' | 'PUT' | 'PATCH' | 'DELETE';    // HTTP method
  buildUrl: (op: PendingSyncItem<T>) => string;    // Dynamic URL builder
  toPayload: (op: PendingSyncItem<T>) => object;   // Request body builder
  dedupKey: (data: T) => string | null;            // Dedup strategy
  priority?: 'critical' | 'high' | 'normal' | 'low';
}

syncToBackend()

Watch a signal and automatically sync changes:

function syncToBackend<T>(
  signalRef: WritableSignal<T>,
  options: {
    descriptorKey: string;
    contextId?: string;
    debounceMs?: number;         // Default: 500
    shouldSync?: (v: T) => boolean;
    transform?: (v: T) => unknown;
  }
): void;

StorageObservabilityService

Client-side storage metrics:

@Injectable({ providedIn: 'root' })
class StorageObservabilityService {
  readonly metrics: Signal<StorageObservabilityMetrics>;
  readonly alerts: Signal<string[]>;
  readonly hasAlerts: Signal<boolean>;

  collect(): Promise<StorageObservabilityMetrics>;
  startPeriodicCollection(intervalMs?: number): void;
  stopPeriodicCollection(): void;
  toPrometheusText(): string;
  setThresholds(thresholds: Partial<StorageAlertThresholds>): void;
}

Providers

// Provide the engine (optional config)
provideBackendSync(config?: BackendSyncEngineConfig): EnvironmentProviders;

// Bridge HttpClient to engine (required for HTTP calls)
provideBackendSyncTransport(): Provider;

Complete, current, and production-ready API documentation.

Last Updated: March 3, 2026 (Session 166.3) — Added BackendSyncEngine, syncToBackend(), StorageObservabilityService