JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 12
  • Score
    100M100P100Q56041F
  • License MIT

Lacerta-DB is a Javascript IndexedDB Database for Web Browsers. Simple, Fast, Secure.

Package Exports

  • @pixagram/lacerta-db
  • @pixagram/lacerta-db/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@pixagram/lacerta-db) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

LacertaDB 0.7.0

🦎 LacertaDB - A sophisticated, feature-rich browser-based document database with encryption, compression, QuickStore, and advanced querying capabilities.

License: MIT Version Browser Compatible npm downloads Bundle Size

🎮 PLAYGROUND


📖 Table of Contents

  1. Introduction
  2. Browser Compatibility
  3. Quick Start
  4. Installation
  5. Core Concepts
  6. API Reference
  7. Advanced Features
  8. Real-World Examples
  9. Performance Optimization
  10. Migration Guide
  11. Architecture Deep Dive
  12. Troubleshooting
  13. Error Handling
  14. Comparison
  15. Contributing
  16. Changelog

Introduction

LacertaDB v0.7.0 represents a paradigmatic evolution in browser-based data persistence, architecting a sophisticated NoSQL database atop IndexedDB foundations. This iteration introduces QuickStore for ephemeral caching, implements rigorous encapsulation through private property conventions, and establishes connection pooling mechanisms for optimal resource utilization.

✨ Key Features

  • 🚀 QuickStore - High-velocity localStorage-based caching with query capabilities
  • 🔐 Database-level encryption with AES-GCM-256 cryptographic primitives
  • 🗜️ Automatic compression leveraging native browser APIs (60-80% spatial reduction)
  • 🔍 Multiple index architectures (B-Tree, Hash, Text, Geo)
  • Sophisticated caching strategies (LRU, LFU, TTL)
  • 📊 Aggregation pipeline for complex analytical queries
  • 🔄 Atomic batch operations with transactional guarantees
  • 🔌 Connection pooling for optimized resource management
  • 🔒 Async mutex for concurrent operation synchronization
  • 📈 Built-in performance telemetry
  • 💾 OPFS support for binary attachment persistence
  • 🌐 Offline-first architecture - zero backend dependencies
  • 📦 Optimized bundle footprint (~48KB gzipped)

🎯 Architectural Use Cases

  • Progressive Web Applications - Complete database functionality in disconnected states
  • Client-Side Cryptography - Zero-knowledge encryption before network transmission
  • Edge Computing - Complex data processing at the browser periphery
  • Browser Extensions - Persistent storage with sophisticated querying semantics
  • Rapid Prototyping - Backend-agnostic development workflows
  • Ephemeral Caching - QuickStore for session-based data persistence

Browser Compatibility

Browser Minimum Version Architectural Notes
Chrome 88+ Full API surface including CompressionStream
Firefox 90+ Complete implementation
Safari 15.4+ Full support with OPFS
Edge 88+ Chromium-based implementation
Opera 74+ Complete feature parity
Chrome Mobile 88+ Mobile-optimized performance
Safari iOS 15.4+ Storage quotas may apply

Required Browser APIs

  • IndexedDB API - Primary persistence layer
  • Web Crypto API - Cryptographic operations
  • CompressionStream API - Optional compression (graceful degradation)
  • Origin Private File System - Binary attachment storage
  • LocalStorage API - QuickStore implementation

Quick Start

🚀 Rapid Initialization Sequence

import { LacertaDB } from 'lacertadb';

// 1. Instantiate LacertaDB orchestrator
const lacerta = new LacertaDB();

// 2. Acquire database instance
const db = await lacerta.getDatabase('application-nexus');

// 3. Initialize collection with QuickStore
const users = await db.createCollection('users');

// 4. Leverage QuickStore for ephemeral caching
db.quickStore.add('session', { userId: 'usr_123', token: 'xyz' });
const session = db.quickStore.get('session');

// 5. Persist documents with compression
await users.add({
  name: 'John Doe',
  email: 'john@example.com',
  metadata: { created: Date.now() }
});

// 6. Execute sophisticated queries
const results = await users.query({
  $and: [
    { 'metadata.created': { $gte: Date.now() - 86400000 } },
    { email: { $regex: '@example.com$' } }
  ]
});

🔐 Cryptographically Secured Database

// Initialize encrypted database with configurable parameters
const secureDb = await lacerta.getSecureDatabase(
  'classified-data',
  'user-pin-entropy',
  null,  // Auto-generate cryptographic salt
  {
    iterations: 200000,      // PBKDF2 iteration count
    hashAlgorithm: 'SHA-512' // Hashing algorithm selection
  }
);

// Encrypted operations maintain transparency
const secrets = await secureDb.createCollection('api-keys');
await secrets.add({ 
  service: 'stripe',
  key: await secureDb.encryption.encryptPrivateKey('sk_live_...', 'stripe.com')
});

Installation

Package Manager Installation

# NPM
npm install lacertadb

# Yarn
yarn add lacertadb

# PNPM
pnpm add lacertadb

CDN Integration

<script type="module">
  import { LacertaDB } from 'https://cdn.jsdelivr.net/npm/lacertadb@0.7.0/dist/index.min.js';
</script>

Import Paradigms

// ES6 Module Syntax
import { LacertaDB, QuickStore } from 'lacertadb';

// Selective Component Import
import { 
  LacertaDB, 
  SecureDatabaseEncryption,
  PerformanceMonitor,
  MigrationManager,
  QuickStore,
  BTreeIndex,
  AsyncMutex
} from 'lacertadb';

// CommonJS Pattern
const { LacertaDB } = require('lacertadb');

Core Concepts

Hierarchical Architecture

LacertaDB Instance
├── Connection Pool (Global)
│   └── Database Connections (Reusable)
├── Database 1
│   ├── QuickStore (LocalStorage Layer)
│   ├── Collection A
│   │   ├── Documents (IndexedDB)
│   │   ├── Indexes (B-Tree/Hash/Text/Geo)
│   │   └── Cache Strategy (LRU/LFU/TTL)
│   └── Collection B
└── Database 2
    ├── QuickStore Instance
    └── __private_keys__ (Encrypted Key Storage)

Document Metadata Schema

{
  _id: "doc_1234567890_abc",        // Unique identifier
  _created: 1234567890,              // Creation timestamp
  _modified: 1234567890,             // Modification timestamp
  _permanent: false,                 // Cleanup immunity flag
  _compressed: true,                 // Compression status
  _encrypted: false,                 // Encryption status
  _attachments: [],                  // OPFS attachment references
  ...userDefinedFields               // Application data
}

Private Property Convention

Version 0.7.0 implements systematic encapsulation through underscore-prefixed private properties and methods, establishing clear API boundaries while optimizing memory through lazy initialization patterns.


API Reference

📦 LacertaDB Class

Primary orchestrator for database lifecycle management.

Method Parameters Returns Description
getDatabase() name: string
options?: object
Promise<Database> Acquire database instance
getSecureDatabase() name: string
pin: string
salt?: string
config?: object
Promise<Database> Initialize encrypted database
dropDatabase() name: string Promise<void> Destroy database and QuickStore
listDatabases() - string[] Enumerate databases
createBackup() password?: string Promise<string> Generate comprehensive backup
restoreBackup() data: string
password?: string
Promise<object> Restore from backup
destroy() - void Release all connections
performanceMonitor - PerformanceMonitor Access performance telemetry
Implementation Examples
const lacerta = new LacertaDB();

// Connection pooling automatically manages resources
const db1 = await lacerta.getDatabase('app1');
const db2 = await lacerta.getDatabase('app2');
// Connections are pooled and reused efficiently

// Access performance monitoring
lacerta.performanceMonitor.startMonitoring();
const metrics = lacerta.performanceMonitor.getStats();

// Comprehensive backup including QuickStore
const backup = await lacerta.createBackup('encryption-key');
localStorage.setItem('backup', backup);

// Cleanup with connection pool release
window.addEventListener('beforeunload', () => {
  lacerta.destroy(); // Releases all pooled connections
});

🗄️ Database Class

Database-level operations with QuickStore integration.

Method Parameters Returns Description
createCollection() name: string
options?: object
Promise<Collection> Initialize collection
getCollection() name: string Promise<Collection> Retrieve collection (lazy init)
dropCollection() name: string Promise<void> Remove collection
listCollections() - string[] Enumerate collections
getStats() - object Database metrics
updateSettings() settings: object void Configure database
export() format: string
password?: string
Promise<string> Export database
import() data: string
format: string
password?: string
Promise<object> Import data
storePrivateKey() name: string
key: string
auth?: string
Promise<boolean> Secure key storage
getPrivateKey() name: string
auth?: string
Promise<string> Retrieve secured key
clearAll() - Promise<void> Purge all data

Database Properties (Getters)

Property Type Description
quickStore QuickStore LocalStorage-based cache
collections Map<string, Collection> Collection registry
metadata DatabaseMetadata Database metadata
settings Settings Configuration parameters
encryption SecureDatabaseEncryption│null Encryption instance
isEncrypted boolean Encryption status
performanceMonitor PerformanceMonitor Performance telemetry
Advanced Usage Patterns
// Lazy collection initialization
const users = await db.getCollection('users');
// Collection is initialized only on first access

// QuickStore integration for session management
db.quickStore.add('user_session', {
  userId: 'usr_123',
  loginTime: Date.now(),
  permissions: ['read', 'write']
});

// Query QuickStore with same engine
const activeSessions = db.quickStore.query({
  loginTime: { $gte: Date.now() - 3600000 }
});

// Configure with size management
db.updateSettings({
  sizeLimitKB: 100000,
  bufferLimitKB: 80000,
  freeSpaceEvery: 30000
});

// Export with QuickStore data
const fullExport = await db.export('encrypted', 'password');

🚀 QuickStore

High-performance localStorage-based caching layer with query capabilities.

Method Parameters Returns Description
add() docId: string
data: object
boolean Store document
get() docId: string object│null Retrieve document
update() docId: string
data: object
boolean Update document
delete() docId: string void Remove document
getAll() - object[] Retrieve all documents
query() filter: object object[] Query documents
clear() - void Purge all data
size - number Document count

QuickStore Architecture

QuickStore leverages localStorage for ephemeral data persistence, providing:

  • Synchronous operations for immediate data access
  • Query engine integration using identical syntax as main collections
  • Automatic serialization with TurboSerial
  • Index management for efficient lookups
  • Size limitations based on localStorage quotas (5-10MB)
QuickStore Implementation Patterns
const db = await lacerta.getDatabase('app');
const quickStore = db.quickStore;

// Session management
quickStore.add('current_user', {
  id: 'usr_123',
  name: 'John Doe',
  loginTime: Date.now(),
  preferences: {
    theme: 'dark',
    language: 'en'
  }
});

// Shopping cart persistence
quickStore.add('cart', {
  items: [
    { productId: 'prod_1', quantity: 2, price: 29.99 },
    { productId: 'prod_2', quantity: 1, price: 49.99 }
  ],
  total: 109.97,
  updated: Date.now()
});

// Query capabilities with same syntax
const recentActivity = quickStore.query({
  loginTime: { $gte: Date.now() - 3600000 }
});

// Atomic updates
quickStore.update('current_user', {
  ...quickStore.get('current_user'),
  lastActivity: Date.now()
});

// Clear on logout
function logout() {
  quickStore.delete('current_user');
  quickStore.delete('cart');
}

// Full clear
quickStore.clear();

📁 Collection Class

Document management with advanced querying and indexing.

Core Methods

Method Parameters Returns Description
add() data: object
options?: object
Promise<string> Insert document
get() id: string
options?: object
Promise<object> Retrieve document
update() id: string
updates: object
options?: object
Promise<string> Modify document
delete() id: string
options?: object
Promise<void> Remove document
getAll() options?: object Promise<object[]> Retrieve all documents
clear() options?: object Promise<void> Purge collection

Query and Aggregation

Method Parameters Returns Description
query() filter: object
options?: object
Promise<object[]> Execute query
aggregate() pipeline: object[] Promise<object[]> Aggregation pipeline
findOne() filter: object Promise<object│null> First match
count() filter?: object Promise<number> Document count

Batch Operations

Method Parameters Returns Description
batchAdd() documents: object[]
options?: object
Promise<object[]> Bulk insert
batchUpdate() updates: object[]
options?: object
Promise<object[]> Bulk update
batchDelete() items: string[]│object[] Promise<object[]> Bulk delete

Event System

Method Parameters Returns Description
on() event: string
callback: function
void Register listener
off() event: string
callback: function
void Unregister listener

Collection Properties

Property Type Description
name string Collection identifier
database Database Parent database
settings Settings Configuration
metadata CollectionMetadata Collection metrics
initialized boolean Initialization status

🔐 Connection Management

IndexedDBConnectionPool

Global connection pool for optimized database connections.

Method Parameters Returns Description
getConnection() dbName: string
version: number
upgradeCallback?: function
Promise<IDBDatabase> Acquire connection
releaseConnection() dbName: string
version: number
void Release connection
closeAll() - void Close all connections

AsyncMutex

Synchronization primitive for concurrent operations.

Method Parameters Returns Description
acquire() - Promise<function> Acquire lock
release() - void Release lock
runExclusive() callback: function Promise<any> Execute exclusively
Concurrency Control Patterns
// Connection pooling is automatic
const db1 = await connectionPool.getConnection('db1', 1);
const db2 = await connectionPool.getConnection('db1', 1); // Reuses connection

// Mutex for critical sections
const mutex = new AsyncMutex();

async function criticalOperation() {
  const release = await mutex.acquire();
  try {
    // Exclusive access guaranteed
    await performCriticalWork();
  } finally {
    release();
  }
}

// Or using runExclusive
await mutex.runExclusive(async () => {
  await performCriticalWork();
});

🔍 Index Management

Sophisticated indexing strategies for query optimization.

Index Methods

Method Parameters Returns Description
createIndex() field: string
options: object
Promise<string> Create index
dropIndex() name: string Promise<void> Remove index
getIndexes() - Promise<object> Index statistics
verifyIndexes() - Promise<object> Self-healing verification

Index Architectures

Type Algorithm Use Case Complexity Space
btree B-Tree Range queries, sorting O(log n) O(n)
hash Hash Table Exact match O(1) avg O(n)
text Inverted Index Full-text search O(m) O(n*m)
geo R-Tree variant Spatial queries O(log n) O(n)

Self-Healing Indexes

B-Tree indexes include automatic verification and repair mechanisms:

// Automatic verification during operations
const btreeIndex = new BTreeIndex();
btreeIndex.insert(key, value); // Triggers periodic verification

// Manual verification
const report = await collection.verifyIndexes();
// {
//   'age_index': { healthy: true, issues: [] },
//   'email_index': { healthy: false, issues: [...], repaired: 2 }
// }

🔐 Encryption

Cryptographic subsystem with configurable parameters.

SecureDatabaseEncryption Class

Method Parameters Returns Description
initialize() pin: string
salt?: Uint8Array
Promise<string> Initialize encryption
encrypt() data: any Promise<Uint8Array> Encrypt data
decrypt() data: Uint8Array Promise<Uint8Array> Decrypt data
encryptPrivateKey() key: string
auth?: string
Promise<string> Secure key encryption
decryptPrivateKey() encrypted: string
auth?: string
Promise<string> Key decryption
changePin() oldPin: string
newPin: string
Promise<string> Rotate PIN
destroy() - void Clear keys
exportMetadata() - object Export config
importMetadata() metadata: object boolean Import config

Encryption Properties (Getters)

Property Type Description
initialized boolean Initialization status

Cryptographic Parameters

Parameter Default Range Description
iterations 100000 10000-1000000 PBKDF2 iterations
hashAlgorithm SHA-256 SHA-256/512 Hash function
keyLength 256 128/192/256 AES key size
saltLength 32 16-64 Salt bytes

Advanced Features

🎯 Query Operators

Comparison Operators

Operator Semantic Example
$eq Equality { status: { $eq: 'active' } }
$ne Inequality { deleted: { $ne: true } }
$gt Greater than { score: { $gt: 90 } }
$gte Greater or equal { age: { $gte: 18 } }
$lt Less than { price: { $lt: 100 } }
$lte Less or equal { quantity: { $lte: 10 } }

Set Operations

Operator Semantic Example
$in Set membership { role: { $in: ['admin', 'mod'] } }
$nin Set exclusion { status: { $nin: ['deleted'] } }

Array Operations

Operator Semantic Example
$all Contains all { tags: { $all: ['js', 'ts'] } }
$elemMatch Element match { scores: { $elemMatch: { $gt: 80 } } }
$size Array length { items: { $size: 5 } }

Logical Operators

Operator Semantic Example
$and Conjunction { $and: [{ a: 1 }, { b: 2 }] }
$or Disjunction { $or: [{ a: 1 }, { b: 2 }] }
$not Negation { field: { $not: { $eq: 'value' } } }
$nor Joint denial { $nor: [{ a: 1 }, { b: 2 }] }

Type and Existence

Operator Semantic Example
$exists Field existence { optional: { $exists: false } }
$type Type checking { age: { $type: 'number' } }

Pattern Matching

Operator Semantic Example
$regex Regular expression { email: { $regex: '^[a-z]+@' } }
$text Text search { content: { $text: 'javascript' } }

📊 Aggregation Pipeline

Pipeline Stages

Stage Function Example
$match Filter documents { $match: { status: 'active' } }
$project Shape output { $project: { name: 1, age: 1 } }
$group Aggregate groups { $group: { _id: '$category', total: { $sum: 1 } } }
$sort Order results { $sort: { createdAt: -1 } }
$limit Limit count { $limit: 100 }
$skip Skip documents { $skip: 20 }
$lookup Join collections { $lookup: { from: 'orders', localField: 'userId', foreignField: '_id', as: 'orders' } }

Accumulator Operators

Operator Function Example
$sum Summation { total: { $sum: '$amount' } }
$avg Average { avgScore: { $avg: '$score' } }
$min Minimum { lowest: { $min: '$price' } }
$max Maximum { highest: { $max: '$price' } }
$count Count { count: { $count: {} } }

💾 Cache Strategies

Strategy Architectures

Strategy Algorithm Eviction Policy Configuration
lru Least Recently Used Temporal locality maxSize, ttl
lfu Least Frequently Used Access frequency maxSize, ttl
ttl Time To Live Temporal expiry ttl
none No caching Immediate -
Cache Strategy Implementation
// LRU with TTL for balanced performance
collection.configureCacheStrategy({
  type: 'lru',
  maxSize: 200,
  ttl: 60000,
  enabled: true
});

// LFU for hot data
hotCollection.configureCacheStrategy({
  type: 'lfu',
  maxSize: 500,
  ttl: 300000
});

// TTL-only for sessions
sessionCollection.configureCacheStrategy({
  type: 'ttl',
  ttl: 900000
});

// Memory optimization through lazy initialization
// Cache is created only when first accessed (getter pattern)
const strategy = new CacheStrategy({ type: 'lru' });
// Internal cache instantiated on first get() call

Architecture Deep Dive

Memory Optimization Patterns

Version 0.7.0 implements sophisticated memory management through:

  1. Lazy Initialization: Collections and caches instantiate on first access
  2. Getter/Setter Patterns: Document data uses accessors for memory efficiency
  3. Connection Pooling: Reuses database connections across operations
  4. Private Property Convention: Underscore prefix for encapsulation
class Document {
  constructor(data = {}) {
    this._data = null;  // Private storage
    // ... other initialization
  }
  
  // Lazy getter for memory optimization
  get data() {
    return this._data || {};
  }
  
  set data(value) {
    this._data = value;
  }
}

Concurrency Control

AsyncMutex ensures atomic operations:

class AsyncMutex {
  async runExclusive(callback) {
    const release = await this.acquire();
    try {
      return await callback();
    } finally {
      release();
    }
  }
}

Transaction Resilience

Automatic retry mechanisms with exponential backoff:

async performTransaction(db, storeNames, mode, callback, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await executeTransaction();
    } catch (error) {
      if (i < retries - 1) {
        await new Promise(r => setTimeout(r, (2 ** i) * 100));
      }
    }
  }
}

Real-World Examples

🏥 Healthcare Data Management

// HIPAA-compliant patient data storage
const lacerta = new LacertaDB();
const healthDb = await lacerta.getSecureDatabase(
  'patient-records',
  await SecureDatabaseEncryption.generateSecurePIN(12),
  null,
  { iterations: 500000 }  // Enhanced security
);

const patients = await healthDb.createCollection('patients');
const vitals = await healthDb.createCollection('vitals');

// QuickStore for current session
healthDb.quickStore.add('current_patient', {
  id: 'pat_123',
  name: 'John Doe',
  sessionStart: Date.now()
});

// Create indexes for efficient queries
await patients.createIndex('mrn', { unique: true });  // Medical Record Number
await vitals.createIndex('patientId', { type: 'hash' });
await vitals.createIndex('timestamp', { type: 'btree' });

// Store patient with encryption
await patients.add({
  mrn: 'MRN123456',
  name: 'John Doe',
  dob: '1980-01-15',
  allergies: ['penicillin'],
  conditions: ['hypertension']
}, { permanent: true });

// Record vitals
await vitals.add({
  patientId: 'pat_123',
  timestamp: Date.now(),
  bloodPressure: { systolic: 120, diastolic: 80 },
  heartRate: 72,
  temperature: 98.6
});

// Aggregate patient statistics
const stats = await vitals.aggregate([
  { $match: { patientId: 'pat_123' } },
  { $sort: { timestamp: -1 } },
  { $limit: 100 },
  { $group: {
    _id: '$patientId',
    avgHeartRate: { $avg: '$heartRate' },
    avgSystolic: { $avg: '$bloodPressure.systolic' },
    readingCount: { $count: {} }
  }}
]);

🎮 Real-Time Gaming State

// Game state management with QuickStore
const gameDb = await lacerta.getDatabase('game-state');
const quickStore = gameDb.quickStore;

// Immediate state updates via QuickStore
quickStore.add('player_state', {
  position: { x: 100, y: 200, z: 50 },
  health: 100,
  inventory: ['sword', 'potion'],
  score: 5000
});

// Persistent game saves
const saves = await gameDb.createCollection('saves');
await saves.createIndex('timestamp', { type: 'btree' });

async function saveGame() {
  const state = quickStore.get('player_state');
  await saves.add({
    ...state,
    savePoint: 'checkpoint_3',
    timestamp: Date.now()
  }, { compressed: true });
}

// Load recent saves
const recentSaves = await saves.query(
  { timestamp: { $gte: Date.now() - 86400000 } },
  { sort: { timestamp: -1 }, limit: 10 }
);

📊 Analytics Dashboard

// Real-time analytics with caching strategies
const analyticsDb = await lacerta.getDatabase('analytics');
const events = await analyticsDb.createCollection('events');

// Configure aggressive caching for dashboards
events.configureCacheStrategy({
  type: 'lfu',  // Frequently accessed metrics
  maxSize: 1000,
  ttl: 300000  // 5-minute cache
});

// Create performance indexes
await events.createIndex('eventType', { type: 'hash' });
await events.createIndex('timestamp', { type: 'btree' });
await events.createIndex('userId', { type: 'hash' });

// Store events with batch operations
const eventBatch = Array.from({ length: 1000 }, (_, i) => ({
  eventType: ['click', 'view', 'purchase'][i % 3],
  userId: `user_${i % 100}`,
  timestamp: Date.now() - (i * 1000),
  metadata: { source: 'web', version: '2.0' }
}));

await events.batchAdd(eventBatch, { compressed: true });

// Complex analytics aggregation
const metrics = await events.aggregate([
  { $match: { 
    timestamp: { $gte: Date.now() - 3600000 }  // Last hour
  }},
  { $group: {
    _id: '$eventType',
    count: { $count: {} },
    uniqueUsers: { $addToSet: '$userId' }
  }},
  { $project: {
    eventType: '$_id',
    count: 1,
    uniqueUserCount: { $size: '$uniqueUsers' }
  }},
  { $sort: { count: -1 } }
]);

// Store computed metrics in QuickStore for instant access
analyticsDb.quickStore.add('dashboard_metrics', {
  computed: Date.now(),
  metrics,
  summary: {
    totalEvents: metrics.reduce((sum, m) => sum + m.count, 0),
    eventTypes: metrics.length
  }
});

Performance Optimization

📈 Advanced Performance Monitoring

// Initialize comprehensive monitoring
const monitor = lacerta.performanceMonitor;
monitor.startMonitoring();

// Custom performance tracking
class PerformanceTracker {
  constructor(monitor) {
    this.monitor = monitor;
    this.thresholds = {
      query: 50,      // ms
      write: 100,     // ms
      aggregate: 200  // ms
    };
  }
  
  async track(operation, type) {
    const start = performance.now();
    try {
      const result = await operation();
      const duration = performance.now() - start;
      
      this.monitor.recordOperation(type, duration);
      
      if (duration > this.thresholds[type]) {
        console.warn(`Slow ${type}: ${duration}ms`);
      }
      
      return result;
    } catch (error) {
      this.monitor.recordOperation(`${type}_error`, 0);
      throw error;
    }
  }
}

const tracker = new PerformanceTracker(monitor);

// Track operations
const results = await tracker.track(
  () => users.query({ age: { $gte: 18 } }),
  'query'
);

// Optimization recommendations
const tips = monitor.getOptimizationTips();
// Analyzes cache hit rates, latency patterns, memory trends

⚡ Optimization Strategies

1. Index Architecture Selection

// B-Tree for range queries and sorting
await orders.createIndex('createdAt', { type: 'btree' });
await products.createIndex('price', { type: 'btree' });

// Hash for exact matches
await users.createIndex('email', { type: 'hash', unique: true });
await sessions.createIndex('token', { type: 'hash' });

// Text index for search
await articles.createIndex('content', { type: 'text' });

// Geo index for spatial queries
await stores.createIndex('location', { type: 'geo' });

2. QuickStore vs Collection Strategy

// QuickStore for ephemeral, frequently accessed data
db.quickStore.add('ui_state', { theme: 'dark', sidebar: true });
db.quickStore.add('form_draft', { title: 'Unsaved', content: '...' });

// Collections for persistent, structured data
await documents.add({ title: 'Report', content: '...' });

3. Connection Pool Optimization

// Connections are automatically pooled and reused
const db1 = await lacerta.getDatabase('app');  // New connection
const db2 = await lacerta.getDatabase('app');  // Reuses connection

// Manual cleanup when necessary
connectionPool.releaseConnection('app');

4. Memory-Conscious Patterns

// Use projection to minimize memory footprint
const summaries = await posts.query(
  { published: true },
  { 
    projection: { title: 1, excerpt: 1 },  // Only needed fields
    limit: 100
  }
);

// Clear caches periodically
setInterval(() => {
  posts.clearCache();
}, 300000);  // Every 5 minutes

// Configure appropriate cache sizes
posts.configureCacheStrategy({
  type: 'lru',
  maxSize: 50  // Limit cache entries
});

Migration Guide

Version 0.6.x to 0.7.0

// 1. Export existing data
const oldDb = await getOldDatabase();
const backup = await oldDb.export('json');

// 2. Initialize new version
const newLacerta = new LacertaDB();
const newDb = await newLacerta.getDatabase('migrated');

// 3. Import with QuickStore preservation
await newDb.import(backup, 'json');

// 4. Migrate to QuickStore where appropriate
const sessions = await newDb.getCollection('sessions');
const allSessions = await sessions.getAll();

// Move active sessions to QuickStore
for (const session of allSessions) {
  if (session.active) {
    newDb.quickStore.add(`session_${session.userId}`, session);
    await sessions.delete(session._id);
  }
}

// 5. Update indexes for new architecture
const collections = newDb.listCollections();
for (const name of collections) {
  const coll = await newDb.getCollection(name);
  await coll.verifyIndexes();  // Self-healing verification
}

Schema Evolution with Migrations

const migrationManager = new MigrationManager(db);

// Migration to add QuickStore references
migrationManager.addMigration({
  version: '0.7.0',
  name: 'Add QuickStore support',
  up: async (doc) => {
    if (doc.sessionId && !doc.quickStoreKey) {
      // Move session data to QuickStore
      db.quickStore.add(`session_${doc.sessionId}`, {
        userId: doc.userId,
        created: doc._created
      });
      return { ...doc, quickStoreKey: `session_${doc.sessionId}` };
    }
    return null;
  },
  down: async (doc) => {
    if (doc.quickStoreKey) {
      db.quickStore.delete(doc.quickStoreKey);
      const { quickStoreKey, ...rest } = doc;
      return rest;
    }
    return null;
  }
});

await migrationManager.runMigrations('0.7.0');

Troubleshooting

Common Issues and Solutions

🔴 QuickStore Quota Exceeded

Problem: LocalStorage limit reached (5-10MB)

Solutions:

// 1. Monitor QuickStore usage
console.log(`QuickStore entries: ${db.quickStore.size}`);

// 2. Implement rotation policy
function rotateQuickStore(maxEntries = 100) {
  const all = db.quickStore.getAll();
  if (all.length > maxEntries) {
    const toDelete = all
      .sort((a, b) => a._modified - b._modified)
      .slice(0, all.length - maxEntries);
    
    toDelete.forEach(doc => db.quickStore.delete(doc._id));
  }
}

// 3. Move to collections for larger data
if (data.length > 1000) {  // Large dataset
  await collection.add(data);
} else {
  db.quickStore.add('small_data', data);
}

🔴 Connection Pool Exhaustion

Problem: Too many concurrent database operations

Solutions:

// 1. Use batch operations
await users.batchAdd(documents);  // Single transaction

// 2. Implement operation queuing
class OperationQueue {
  constructor(concurrency = 10) {
    this.queue = [];
    this.running = 0;
    this.concurrency = concurrency;
  }
  
  async add(operation) {
    if (this.running >= this.concurrency) {
      await new Promise(resolve => this.queue.push(resolve));
    }
    this.running++;
    try {
      return await operation();
    } finally {
      this.running--;
      if (this.queue.length > 0) {
        this.queue.shift()();
      }
    }
  }
}

🔴 Memory Leaks with Private Properties

Problem: References to private properties preventing garbage collection

Solutions:

// 1. Proper cleanup in destroy methods
class Collection {
  destroy() {
    clearInterval(this._cleanupInterval);
    this._events.clear();
    this._cacheStrategy = null;
    this._indexManager = null;
    // Release connection
    if (this._db) {
      connectionPool.releaseConnection(this.database.name);
    }
  }
}

// 2. WeakMap for external references
const privateData = new WeakMap();
privateData.set(instance, { sensitive: 'data' });

Error Handling

Comprehensive Error Taxonomy

Error Code Semantic Context Resolution Strategy
DATABASE_OPEN_FAILED IndexedDB initialization failure Verify browser compatibility, clear data
DOCUMENT_NOT_FOUND Non-existent document reference Validate document existence
COLLECTION_NOT_FOUND Undefined collection Initialize collection first
COLLECTION_EXISTS Duplicate collection Use getCollection()
UNIQUE_CONSTRAINT Index uniqueness violation Modify value or update
QUOTA_EXCEEDED Storage capacity exceeded Implement cleanup strategy
ENCRYPTION_NOT_INITIALIZED Missing encryption context Use getSecureDatabase()
ENCRYPTION_FAILED Cryptographic operation failure Verify credentials
PERMANENT_DOCUMENT_PROTECTION Protected document deletion Apply force option
TRANSACTION_FAILED Transaction abort Retry with backoff
QUICKSTORE_QUOTA_EXCEEDED LocalStorage limit Rotate QuickStore data
Error Handling Patterns
class ResilientDatabaseService {
  constructor(lacerta) {
    this.lacerta = lacerta;
    this.mutex = new AsyncMutex();
  }
  
  async executeWithRetry(operation, maxRetries = 3) {
    return this.mutex.runExclusive(async () => {
      let lastError;
      
      for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
          return await operation();
        } catch (error) {
          lastError = error;
          
          // Categorize and handle errors
          switch (error.code) {
            case 'QUOTA_EXCEEDED':
              await this.handleQuotaExceeded();
              break;
              
            case 'TRANSACTION_FAILED':
              await this.delay((2 ** attempt) * 100);
              break;
              
            case 'ENCRYPTION_FAILED':
              throw new Error('Authentication required');
              
            default:
              if (attempt === maxRetries - 1) throw error;
          }
        }
      }
      
      throw lastError;
    });
  }
  
  async handleQuotaExceeded() {
    // Clear QuickStore
    const db = await this.lacerta.getDatabase('app');
    db.quickStore.clear();
    
    // Clear old collection data
    const collections = db.listCollections();
    for (const name of collections) {
      const coll = await db.getCollection(name);
      const oldDocs = await coll.query({
        _modified: { $lt: Date.now() - 86400000 }
      });
      await coll.batchDelete(oldDocs.map(d => d._id));
    }
  }
  
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

Comparison

LacertaDB v0.7.0 vs Alternatives

Feature LacertaDB 0.7 LocalStorage IndexedDB PouchDB Dexie.js LokiJS
Storage Limit ~2GB + 10MB* 5-10MB ~2GB ~2GB ~2GB Memory/5MB
QuickStore ✅ Built-in
Encryption ✅ AES-GCM ⚠️ Plugin
Compression ✅ Native
Connection Pool N/A
Query Language ✅ MongoDB ✅ MapReduce ⚠️ Limited
Indexes ✅ 4 types ⚠️ Basic
Aggregation ✅ Pipeline ⚠️ Views ⚠️
Self-Healing
Bundle Size ~48KB 0KB 0KB ~140KB ~90KB ~70KB
Concurrency ✅ Mutex ⚠️ ⚠️ ⚠️

*IndexedDB (2GB) + QuickStore LocalStorage (10MB)

Architectural Selection Criteria

Deploy LacertaDB when requiring:

  • Dual-layer storage (persistent + ephemeral)
  • Zero-knowledge client-side encryption
  • Self-healing index structures
  • Connection pooling for scalability
  • MongoDB-compatible query semantics
  • Integrated performance telemetry

Consider alternatives for:

  • Minimal storage needs (< 1MB): LocalStorage
  • Server synchronization priority: PouchDB/CouchDB
  • Memory-only operations: LokiJS
  • Simple key-value patterns: LocalStorage/SessionStorage

Changelog

Version 0.7.0 (Latest)

  • Added: QuickStore for localStorage-based ephemeral caching
  • Added: Connection pooling for optimized resource management
  • Added: AsyncMutex for concurrent operation synchronization
  • Improved: Private property conventions with underscore prefix
  • Improved: Memory optimization through lazy initialization
  • Improved: Self-healing B-Tree indexes with automatic verification
  • Enhanced: Export/import includes QuickStore data
  • Fixed: Connection leaks in collection destruction
  • Fixed: Memory optimization in Document class

Version 0.6.2

  • Database-level encryption
  • Compression support
  • Multiple index types
  • Aggregation pipeline
  • Performance monitoring

Contributing

LacertaDB embraces collaborative development. Contribution vectors include:

  1. Architecture Enhancement: Propose algorithmic improvements
  2. Index Strategies: Implement novel index structures
  3. Performance Optimization: Profile and optimize critical paths
  4. Documentation: Expand architectural documentation
  5. Test Coverage: Strengthen test suites

📝 License

MIT © 2024 LacertaDB Contributors