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:
key: string- Unique identifier for the datavalue: T- Data to store (any JSON-serializable value)options?: PutOptions- Optional configuration
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:
key: string- Key to retrieveoptions?: GetOptions- Optional configuration
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:
key: string- Key to check
Returns: Promise<boolean> - True if exists
Example:
if (await storage.has('user-profile')) {
console.log('Profile exists');
}
remove(key)
Delete data by key.
Parameters:
key: string- Key to remove
Returns: Promise<boolean> - Success status
Example:
await storage.remove('temp-data');
list(options?)
List all keys or filtered keys.
Parameters:
options?: ListOptions- Optional filters
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:
prefix?: string- Optional prefix filter
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:
keys: string[]- Keys to pre-load
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:
key: string- Storage keydefaultValue: T- Initial/default valueoptions?: AutoFlashStateOptions<T>- Optional configuration
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:
'speed': Maximum performance (micro-cache + queued writes)'balanced': Optimal balance (recommended)'durable': Maximum reliability (redundancy + sync writes)
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
- Getting Started - 5-minute quick start
- Overview - Architecture and features
- BackendSyncEngine Guide - Fire-and-forget backend sync (Session 166.3)
- Common Mistakes - Anti-patterns and troubleshooting
- Flash Persistence + Conversation Genome - Chat persistence architecture
🔄 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