@pixagram/lacerta-db 0.6.0 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/readme.md CHANGED
@@ -1,1238 +1,1364 @@
1
- # LacertaDB 0.6.0
1
+ # LacertaDB 0.6.2
2
2
  ![](https://github.com/pixagram-blockchain/LacertaDB/blob/main/logo.webp?raw=true)
3
3
 
4
4
  > 🦎 **LacertaDB** - A powerful, feature-rich browser-based document database with encryption, compression, and advanced querying capabilities.
5
5
 
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![Version](https://img.shields.io/badge/version-4.0.3-blue.svg)]()
7
+ [![Version](https://img.shields.io/badge/version-0.6.2-blue.svg)]()
8
8
  [![Browser Compatible](https://img.shields.io/badge/browser-compatible-green.svg)]()
9
+ [![npm downloads](https://img.shields.io/npm/dm/lacertadb.svg)](https://www.npmjs.com/package/lacertadb)
10
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/lacertadb)](https://bundlephobia.com/package/lacertadb)
9
11
 
10
- ## 📚 Table of Contents
11
-
12
- - [✨ Features](#-features)
13
- - [🚀 Quick Start](#-quick-start)
14
- - [📦 Installation](#-installation)
15
- - [🎯 Basic Usage](#-basic-usage)
16
- - [🔧 Core Concepts](#-core-concepts)
17
- - [Database](#database)
18
- - [Collections](#collections)
19
- - [Documents](#documents)
20
- - [🔍 Querying](#-querying)
21
- - [Basic Queries](#basic-queries)
22
- - [Advanced Queries](#advanced-queries)
23
- - [Aggregation Pipeline](#aggregation-pipeline)
24
- - [🔐 Security Features](#-security-features)
25
- - [Encryption](#encryption)
26
- - [Password Protection](#password-protection)
27
- - [📎 Attachments](#-attachments)
28
- - [⚡ Performance](#-performance)
29
- - [Compression](#compression)
30
- - [Performance Monitoring](#performance-monitoring)
31
- - [Query Caching](#query-caching)
32
- - [🔄 Data Migration](#-data-migration)
33
- - [💾 Backup & Restore](#-backup--restore)
34
- - [🛠️ Advanced Features](#️-advanced-features)
35
- - [Batch Operations](#batch-operations)
36
- - [Event System](#event-system)
37
- - [Quick Store](#quick-store)
38
- - [📊 Storage Management](#-storage-management)
39
- - [🎨 API Reference](#-api-reference)
40
- - [💡 Examples](#-examples)
41
- - [🐛 Error Handling](#-error-handling)
42
- - [📝 Best Practices](#-best-practices)
43
- - [🤝 Contributing](#-contributing)
44
-
45
- ## ✨ Features
46
-
47
- 🎯 **Core Features**
48
- - 📁 **Document-based storage** using IndexedDB
49
- - 🔍 **MongoDB-like query syntax** for familiar operations
50
- - 🔐 **AES-256-GCM encryption** with PBKDF2 key derivation
51
- - 🗜️ **Built-in compression** using CompressionStream API
52
- - 📎 **File attachments** via Origin Private File System (OPFS)
53
- - ⚡ **High performance** with async operations and caching
54
-
55
- 🚀 **Advanced Capabilities**
56
- - 📊 **Aggregation pipeline** for complex data processing
57
- - 🔄 **Schema migration system** for version management
58
- - 📈 **Performance monitoring** with real-time metrics
59
- - 🎭 **Event-driven architecture** with hooks
60
- - 💾 **Import/Export functionality** with encryption support
61
- - 🔧 **Batch operations** for efficient bulk processing
62
-
63
- ## 🚀 Quick Start
12
+ [**🎮 PLAYGROUND**](https://codepen.io/Matias-Affolter/pen/ogjrQdB)
64
13
 
65
- ```javascript
66
- import * AS LACERTA from './lacertadb.js';
14
+ ---
67
15
 
68
- // Initialize LacertaDB
69
- const lacerta = new LACERTA.LacertaDB();
16
+ ## 📖 Table of Contents
17
+
18
+ 1. [Introduction](#introduction)
19
+ 2. [Browser Compatibility](#browser-compatibility)
20
+ 3. [Quick Start](#quick-start)
21
+ 4. [Installation](#installation)
22
+ 5. [Core Concepts](#core-concepts)
23
+ 6. [API Reference](#api-reference)
24
+ - [LacertaDB Class](#lacertadb-class)
25
+ - [Database Class](#database-class)
26
+ - [Collection Class](#collection-class)
27
+ - [Document Class](#document-class)
28
+ - [Index Management](#index-management)
29
+ - [Encryption](#encryption)
30
+ 7. [Advanced Features](#advanced-features)
31
+ 8. [Real-World Examples](#real-world-examples)
32
+ 9. [Performance Optimization](#performance-optimization)
33
+ 10. [Migration Guide](#migration-guide)
34
+ 11. [Troubleshooting](#troubleshooting)
35
+ 12. [Error Handling](#error-handling)
36
+ 13. [Comparison](#comparison)
37
+ 14. [Contributing](#contributing)
38
+ 15. [Changelog](#changelog)
70
39
 
71
- // Get or create a database
72
- const db = await lacerta.getDatabase('myApp');
40
+ ---
73
41
 
74
- // Create a collection
75
- const users = await db.createCollection('users');
42
+ ## Introduction
76
43
 
77
- // Add a document
78
- const userId = await users.add({
79
- name: 'Alice Johnson',
80
- email: 'alice@example.com',
81
- age: 28,
82
- tags: ['developer', 'javascript']
83
- });
44
+ LacertaDB is a high-performance, browser-based NoSQL database built on IndexedDB. It provides MongoDB-like query capabilities, automatic compression, encryption support, and advanced indexing strategies - all running entirely in the browser with zero backend dependencies.
84
45
 
85
- // Query documents
86
- const results = await users.query({
87
- age: { $gte: 25 },
88
- tags: { $in: ['developer'] }
89
- });
46
+ ### Key Features
90
47
 
91
- console.log('Found users:', results);
92
- ```
48
+ - 🔐 **Database-level encryption** with AES-GCM-256
49
+ - 🗜️ **Automatic compression** using native browser APIs (60-80% size reduction)
50
+ - 🔍 **Multiple index types** (B-Tree, Hash, Text, Geo)
51
+ - ⚡ **Smart caching strategies** (LRU, LFU, TTL)
52
+ - 📊 **Aggregation pipeline** for complex queries
53
+ - 🔄 **Atomic batch operations**
54
+ - 📈 **Built-in performance monitoring**
55
+ - 💾 **OPFS support** for attachments
56
+ - 🌐 **Works offline** - no server required
57
+ - 📦 **Small bundle size** (~45KB gzipped)
93
58
 
94
- ## 📦 Installation
59
+ ### 🎯 Use Cases
95
60
 
96
- ### NPM/Yarn Installation
61
+ - **PWAs & Offline-First Apps** - Full database functionality without connectivity
62
+ - **Client-Side Encryption** - Secure sensitive data before any network transmission
63
+ - **Local Data Processing** - Complex queries and aggregations without server round-trips
64
+ - **Browser Extensions** - Persistent storage with advanced querying
65
+ - **Prototyping** - Rapid development without backend setup
97
66
 
98
- ```bash
99
- npm install @pixagram/lacertadb
100
- # or
101
- yarn add @pixagram/lacertadb
102
- ```
67
+ ---
103
68
 
104
- ### Browser Module
69
+ ## Browser Compatibility
105
70
 
106
- ```html
107
- <script type="module">
108
- import { LacertaDB } from './lacertadb.js';
109
- const lacerta = new LacertaDB();
110
- </script>
111
- ```
71
+ | Browser | Minimum Version | Notes |
72
+ |---------|----------------|--------|
73
+ | Chrome | 88+ | Full support including compression |
74
+ | Firefox | 90+ | Full support |
75
+ | Safari | 15.4+ | Full support |
76
+ | Edge | 88+ | Full support |
77
+ | Opera | 74+ | Full support |
78
+ | Chrome Mobile | 88+ | Full support |
79
+ | Safari iOS | 15.4+ | Storage limits may apply |
112
80
 
113
- ### Dependencies
81
+ ### Required Browser APIs
82
+ - IndexedDB API
83
+ - Web Crypto API
84
+ - CompressionStream API (optional, falls back gracefully)
85
+ - Origin Private File System (optional, for attachments)
114
86
 
115
- LacertaDB requires:
116
- - `@pixagram/turboserial` - High-performance serialization
117
- - `@pixagram/turbobase64` - Optimized Base64 encoding
87
+ ---
118
88
 
119
- ## 🎯 Basic Usage
89
+ ## Quick Start
120
90
 
121
- ### Creating a Database and Collection
91
+ ### 🚀 5-Minute Setup
122
92
 
123
93
  ```javascript
94
+ import { LacertaDB } from 'lacertadb';
95
+
96
+ // 1. Initialize LacertaDB
124
97
  const lacerta = new LacertaDB();
125
98
 
126
- // Create or get a database
127
- const db = await lacerta.getDatabase('myDatabase');
99
+ // 2. Get a database
100
+ const db = await lacerta.getDatabase('my-app');
128
101
 
129
- // Create a collection with options
130
- const products = await db.createCollection('products', {
131
- compressed: true, // Enable compression by default
132
- encrypted: false // Encryption disabled by default
133
- });
134
- ```
102
+ // 3. Create a collection
103
+ const users = await db.createCollection('users');
135
104
 
136
- ### Adding Documents
105
+ // 4. Add documents
106
+ await users.add({
107
+ name: 'John Doe',
108
+ email: 'john@example.com',
109
+ age: 30,
110
+ tags: ['developer', 'javascript']
111
+ });
137
112
 
138
- ```javascript
139
- // Simple document
140
- await products.add({
141
- name: 'Laptop',
142
- price: 999.99,
143
- inStock: true
113
+ // 5. Query documents
114
+ const developers = await users.query({
115
+ tags: { $in: ['developer'] },
116
+ age: { $gte: 25 }
144
117
  });
145
118
 
146
- // Document with options
147
- await products.add(
148
- {
149
- name: 'Secure Document',
150
- data: 'sensitive information'
151
- },
152
- {
153
- id: 'custom-id-123', // Custom ID
154
- encrypted: true, // Encrypt this document
155
- password: 'secretPassword', // Encryption password
156
- compressed: true, // Compress the document
157
- permanent: true // Mark as permanent (won't be auto-deleted)
158
- }
159
- );
119
+ // 6. Use aggregation
120
+ const stats = await users.aggregate([
121
+ { $match: { age: { $gte: 18 } } },
122
+ { $group: {
123
+ _id: null,
124
+ avgAge: { $avg: '$age' },
125
+ total: { $count: {} }
126
+ }}
127
+ ]);
160
128
  ```
161
129
 
162
- ### Retrieving Documents
130
+ ### 🔐 Encrypted Database Setup
163
131
 
164
132
  ```javascript
165
- // Get by ID
166
- const product = await products.get('custom-id-123', {
167
- password: 'secretPassword' // Required for encrypted documents
168
- });
169
-
170
- // Get all documents
171
- const allProducts = await products.getAll();
133
+ // Create an encrypted database
134
+ const secureDb = await lacerta.getSecureDatabase(
135
+ 'secure-app',
136
+ 'user-pin-123456' // User's PIN
137
+ );
172
138
 
173
- // Get with attachments
174
- const withFiles = await products.get('doc-id', {
175
- includeAttachments: true
176
- });
139
+ // All operations are automatically encrypted
140
+ const secrets = await secureDb.createCollection('secrets');
141
+ await secrets.add({ apiKey: 'sk_live_...' });
177
142
  ```
178
143
 
179
- ## 🔧 Core Concepts
180
-
181
- ### Database
182
-
183
- The database is the top-level container for your collections.
184
-
185
- ```javascript
186
- // Get existing or create new database
187
- const db = await lacerta.getDatabase('appDB');
144
+ ---
188
145
 
189
- // List all collections
190
- const collections = db.listCollections();
146
+ ## Installation
191
147
 
192
- // Get database statistics
193
- const stats = db.getStats();
194
- console.log(`Total size: ${stats.totalSizeKB} KB`);
195
- console.log(`Total documents: ${stats.totalDocuments}`);
148
+ ### NPM
149
+ ```bash
150
+ npm install lacertadb
151
+ ```
196
152
 
197
- // Configure database settings
198
- db.updateSettings({
199
- sizeLimitKB: 50000, // 50MB limit
200
- bufferLimitKB: 40000, // Start cleanup at 40MB
201
- freeSpaceEvery: 60000 // Run cleanup every minute
202
- });
153
+ ### Yarn
154
+ ```bash
155
+ yarn add lacertadb
203
156
  ```
204
157
 
205
- ### Collections
158
+ ### CDN
159
+ ```html
160
+ <script type="module">
161
+ import { LacertaDB } from 'https://cdn.jsdelivr.net/npm/lacertadb@latest/dist/index.min.js';
162
+ </script>
163
+ ```
206
164
 
207
- Collections are containers for documents of similar type.
165
+ ### Import Options
208
166
 
209
167
  ```javascript
210
- // Create collection
211
- const posts = await db.createCollection('posts');
168
+ // ES6 Modules
169
+ import { LacertaDB } from 'lacertadb';
170
+
171
+ // Import specific components
172
+ import {
173
+ LacertaDB,
174
+ SecureDatabaseEncryption,
175
+ PerformanceMonitor,
176
+ MigrationManager
177
+ } from 'lacertadb';
178
+
179
+ // CommonJS (Node.js)
180
+ const { LacertaDB } = require('lacertadb');
181
+ ```
212
182
 
213
- // Get existing collection
214
- const existingPosts = await db.getCollection('posts');
183
+ ---
215
184
 
216
- // Collection operations
217
- await posts.clear(); // Remove all documents
218
- await db.dropCollection('posts'); // Delete collection entirely
185
+ ## Core Concepts
186
+
187
+ ### Database Structure
219
188
 
220
- // Collection events
221
- posts.on('afterAdd', (doc) => {
222
- console.log('Document added:', doc._id);
223
- });
189
+ ```
190
+ LacertaDB Instance
191
+ ├── Database 1
192
+ │ ├── Collection A
193
+ │ │ ├── Document 1
194
+ │ │ ├── Document 2
195
+ │ │ └── Indexes
196
+ │ └── Collection B
197
+ └── Database 2
198
+ └── __private_keys__ (special collection for encrypted keys)
224
199
  ```
225
200
 
226
- ### Documents
201
+ ### Document Structure
227
202
 
228
- Documents are JavaScript objects with automatic metadata.
203
+ Every document automatically includes:
229
204
 
230
205
  ```javascript
231
- // Document structure
232
- const doc = {
233
- // User data
234
- title: 'My Post',
235
- content: 'Lorem ipsum...',
236
-
237
- // Automatic metadata (added by LacertaDB)
238
- _id: 'doc_1234567890_abc', // Auto-generated unique ID
239
- _created: 1704067200000, // Creation timestamp
240
- _modified: 1704067200000, // Last modification timestamp
241
- _permanent: false, // Deletion protection flag
242
- };
206
+ {
207
+ _id: "doc_1234567890_abc", // Auto-generated unique ID
208
+ _created: 1234567890, // Creation timestamp
209
+ _modified: 1234567890, // Last modified timestamp
210
+ _permanent: false, // Protection from auto-cleanup
211
+ ...yourData // Your document fields
212
+ }
243
213
  ```
244
214
 
245
- ## 🔍 Querying
215
+ ---
216
+
217
+ ## API Reference
218
+
219
+ ### 📦 LacertaDB Class
220
+
221
+ The main entry point for database operations.
246
222
 
247
- ### Basic Queries
223
+ | Method | Parameters | Returns | Description |
224
+ |--------|------------|---------|-------------|
225
+ | `getDatabase()` | `name: string`<br/>`options?: object` | `Promise<Database>` | Get or create a database |
226
+ | `getSecureDatabase()` | `name: string`<br/>`pin: string`<br/>`salt?: string`<br/>`config?: object` | `Promise<Database>` | Get encrypted database |
227
+ | `dropDatabase()` | `name: string` | `Promise<void>` | Delete a database |
228
+ | `listDatabases()` | - | `string[]` | List all databases |
229
+ | `createBackup()` | `password?: string` | `Promise<string>` | Create full backup |
230
+ | `restoreBackup()` | `data: string`<br/>`password?: string` | `Promise<object>` | Restore from backup |
231
+ | `destroy()` | - | `void` | Clean up all connections |
232
+
233
+ <details>
234
+ <summary><strong>Examples</strong></summary>
248
235
 
249
236
  ```javascript
250
- // Find all documents matching criteria
251
- const results = await users.query({
252
- age: 30, // Exact match
253
- 'address.city': 'New York' // Nested field
254
- });
237
+ // Initialize LacertaDB
238
+ const lacerta = new LacertaDB();
239
+
240
+ // Get a standard database
241
+ const db = await lacerta.getDatabase('myapp');
255
242
 
256
- // With options
257
- const paginatedResults = await users.query(
258
- { status: 'active' },
243
+ // Get an encrypted database with custom security
244
+ const secureDb = await lacerta.getSecureDatabase(
245
+ 'sensitive-data',
246
+ 'my-secure-pin-123456',
247
+ null, // Auto-generate salt
259
248
  {
260
- sort: { createdAt: -1 }, // Sort descending
261
- skip: 10, // Skip first 10
262
- limit: 20, // Limit to 20 results
263
- projection: { // Select fields
264
- name: 1,
265
- email: 1,
266
- _id: 0
267
- }
249
+ iterations: 200000, // Higher = more secure but slower
250
+ keyLength: 256
268
251
  }
269
252
  );
270
- ```
271
-
272
- ### Advanced Queries
273
253
 
274
- LacertaDB supports MongoDB-style query operators:
254
+ // Create a full backup
255
+ const backup = await lacerta.createBackup('backup-password');
256
+ // Save to file or cloud
257
+ await saveToCloud(backup);
275
258
 
276
- #### Comparison Operators
259
+ // Restore from backup
260
+ const backupData = await loadFromCloud();
261
+ const result = await lacerta.restoreBackup(backupData, 'backup-password');
262
+ console.log(`Restored: ${result.databases} databases, ${result.documents} documents`);
277
263
 
278
- ```javascript
279
- // $eq, $ne, $gt, $gte, $lt, $lte
280
- await products.query({
281
- price: { $gte: 100, $lte: 500 }
282
- });
264
+ // List all databases
265
+ const databases = lacerta.listDatabases();
266
+ console.log('Available databases:', databases);
283
267
 
284
- // $in, $nin
285
- await users.query({
286
- role: { $in: ['admin', 'moderator'] }
268
+ // Clean up when done (important for SPAs)
269
+ window.addEventListener('beforeunload', () => {
270
+ lacerta.destroy();
287
271
  });
288
272
  ```
289
273
 
290
- #### Logical Operators
274
+ </details>
291
275
 
292
- ```javascript
293
- // $and
294
- await products.query({
295
- $and: [
296
- { price: { $lt: 1000 } },
297
- { category: 'electronics' }
298
- ]
299
- });
276
+ ---
300
277
 
301
- // $or
302
- await users.query({
303
- $or: [
304
- { age: { $gte: 65 } },
305
- { status: 'premium' }
306
- ]
307
- });
278
+ ### 🗄️ Database Class
308
279
 
309
- // $not
310
- await products.query({
311
- discontinued: { $not: { $eq: true } }
312
- });
313
- ```
280
+ Manages collections and database-level operations.
314
281
 
315
- #### Array Operators
282
+ | Method | Parameters | Returns | Description |
283
+ |--------|------------|---------|-------------|
284
+ | `createCollection()` | `name: string`<br/>`options?: object` | `Promise<Collection>` | Create a new collection |
285
+ | `getCollection()` | `name: string` | `Promise<Collection>` | Get existing collection |
286
+ | `dropCollection()` | `name: string` | `Promise<void>` | Delete a collection |
287
+ | `listCollections()` | - | `string[]` | List all collections |
288
+ | `getStats()` | - | `object` | Get database statistics |
289
+ | `updateSettings()` | `settings: object` | `void` | Update database settings |
290
+ | `export()` | `format: 'json'│'encrypted'`<br/>`password?: string` | `Promise<string>` | Export database |
291
+ | `import()` | `data: string`<br/>`format: string`<br/>`password?: string` | `Promise<object>` | Import data |
292
+ | `storePrivateKey()` | `name: string`<br/>`key: string`<br/>`auth?: string` | `Promise<boolean>` | Store encrypted key |
293
+ | `getPrivateKey()` | `name: string`<br/>`auth?: string` | `Promise<string>` | Retrieve encrypted key |
294
+ | `clearAll()` | - | `Promise<void>` | Clear all collections |
295
+
296
+ #### Database Settings
297
+
298
+ | Setting | Type | Default | Description |
299
+ |---------|------|---------|-------------|
300
+ | `sizeLimitKB` | `number` | `Infinity` | Maximum database size |
301
+ | `bufferLimitKB` | `number` | `80% of limit` | Start cleanup threshold |
302
+ | `freeSpaceEvery` | `number` | `10000` | Cleanup interval (ms) |
303
+
304
+ <details>
305
+ <summary><strong>Examples</strong></summary>
316
306
 
317
307
  ```javascript
318
- // $all - Array contains all values
319
- await posts.query({
320
- tags: { $all: ['javascript', 'database'] }
308
+ // Create collections
309
+ const users = await db.createCollection('users');
310
+ const posts = await db.createCollection('posts', {
311
+ compressed: true
321
312
  });
322
313
 
323
- // $elemMatch - Element matching
324
- await orders.query({
325
- items: {
326
- $elemMatch: {
327
- product: 'laptop',
328
- quantity: { $gte: 2 }
329
- }
330
- }
314
+ // Configure database limits
315
+ db.updateSettings({
316
+ sizeLimitKB: 100000, // 100MB limit
317
+ bufferLimitKB: 80000, // Start cleanup at 80MB
318
+ freeSpaceEvery: 30000 // Check every 30 seconds
331
319
  });
332
320
 
333
- // $size - Array length
334
- await users.query({
335
- hobbies: { $size: 3 }
321
+ // Get database statistics
322
+ const stats = db.getStats();
323
+ console.log(`Database: ${stats.name}`);
324
+ console.log(`Size: ${(stats.totalSizeKB / 1024).toFixed(2)}MB`);
325
+ console.log(`Documents: ${stats.totalDocuments}`);
326
+ stats.collections.forEach(coll => {
327
+ console.log(` ${coll.name}: ${coll.documents} docs, ${coll.sizeKB}KB`);
336
328
  });
337
- ```
338
329
 
339
- #### Text Search
330
+ // Export/Import database
331
+ const exportData = await db.export('encrypted', 'export-password');
332
+ await saveToFile(exportData, 'backup.lacerta');
340
333
 
341
- ```javascript
342
- // $regex - Regular expression
343
- await users.query({
344
- email: { $regex: '@company\\.com$' }
345
- });
334
+ // Later...
335
+ const importData = await loadFromFile('backup.lacerta');
336
+ const result = await db.import(importData, 'encrypted', 'export-password');
346
337
 
347
- // $text - Case-insensitive text search
348
- await posts.query({
349
- content: { $text: 'javascript' }
350
- });
338
+ // Store private keys (requires encrypted database)
339
+ await secureDb.storePrivateKey(
340
+ 'stripe-api',
341
+ 'sk_live_abcd1234',
342
+ 'myapp.com' // Additional authentication
343
+ );
344
+
345
+ // Retrieve private key
346
+ const apiKey = await secureDb.getPrivateKey(
347
+ 'stripe-api',
348
+ 'myapp.com'
349
+ );
351
350
  ```
352
351
 
353
- ### Aggregation Pipeline
352
+ </details>
354
353
 
355
- Powerful data processing with aggregation stages:
354
+ ---
356
355
 
357
- ```javascript
358
- // Sales analysis pipeline
359
- const salesReport = await orders.aggregate([
360
- // Stage 1: Filter orders
361
- { $match: { status: 'completed' } },
362
-
363
- // Stage 2: Group by customer
364
- {
365
- $group: {
366
- _id: '$customerId',
367
- totalSpent: { $sum: '$amount' },
368
- orderCount: { $count: {} },
369
- avgOrderValue: { $avg: '$amount' }
370
- }
371
- },
372
-
373
- // Stage 3: Sort by total spent
374
- { $sort: { totalSpent: -1 } },
375
-
376
- // Stage 4: Limit to top 10
377
- { $limit: 10 },
378
-
379
- // Stage 5: Project final shape
380
- {
381
- $project: {
382
- customer: '$_id',
383
- metrics: {
384
- total: '$totalSpent',
385
- orders: '$orderCount',
386
- average: '$avgOrderValue'
387
- }
388
- }
389
- }
390
- ]);
391
- ```
356
+ ### 📁 Collection Class
392
357
 
393
- #### Lookup (Join) Operations
358
+ Manages documents within a collection.
394
359
 
395
- ```javascript
396
- // Join with another collection
397
- const ordersWithProducts = await orders.aggregate([
398
- {
399
- $lookup: {
400
- from: 'products', // Foreign collection
401
- localField: 'productId', // Field in orders
402
- foreignField: '_id', // Field in products
403
- as: 'productDetails' // Output array field
404
- }
405
- }
406
- ]);
407
- ```
360
+ #### Core Methods
408
361
 
409
- ## 🔐 Security Features
362
+ | Method | Parameters | Returns | Description |
363
+ |--------|------------|---------|-------------|
364
+ | `add()` | `data: object`<br/>`options?: object` | `Promise<string>` | Add a document |
365
+ | `get()` | `id: string`<br/>`options?: object` | `Promise<object>` | Get a document |
366
+ | `update()` | `id: string`<br/>`updates: object`<br/>`options?: object` | `Promise<string>` | Update a document |
367
+ | `delete()` | `id: string`<br/>`options?: object` | `Promise<void>` | Delete a document |
368
+ | `getAll()` | `options?: object` | `Promise<object[]>` | Get all documents |
369
+ | `clear()` | `options?: object` | `Promise<void>` | Clear collection |
370
+ | `count()` | `filter?: object` | `Promise<number>` | Count documents |
410
371
 
411
- ### Encryption
372
+ #### Query Methods
412
373
 
413
- Documents can be individually encrypted with AES-256-GCM:
374
+ | Method | Parameters | Returns | Description |
375
+ |--------|------------|---------|-------------|
376
+ | `query()` | `filter: object`<br/>`options?: object` | `Promise<object[]>` | Query documents |
377
+ | `aggregate()` | `pipeline: object[]` | `Promise<object[]>` | Run aggregation pipeline |
378
+ | `findOne()` | `filter: object` | `Promise<object│null>` | Find first matching document |
414
379
 
415
- ```javascript
416
- // Add encrypted document
417
- await users.add(
418
- {
419
- ssn: '123-45-6789',
420
- bankAccount: 'SECRET123',
421
- salary: 75000
422
- },
423
- {
424
- encrypted: true,
425
- password: 'strong-password-here',
426
- permanent: true // Protect from auto-deletion
427
- }
428
- );
380
+ #### Batch Operations
429
381
 
430
- // Retrieve encrypted document
431
- const userData = await users.get('user-id', {
432
- password: 'strong-password-here' // Required for decryption
433
- });
382
+ | Method | Parameters | Returns | Description |
383
+ |--------|------------|---------|-------------|
384
+ | `batchAdd()` | `documents: object[]`<br/>`options?: object` | `Promise<object[]>` | Add multiple documents |
385
+ | `batchUpdate()` | `updates: object[]`<br/>`options?: object` | `Promise<object[]>` | Update multiple documents |
386
+ | `batchDelete()` | `items: string[]│object[]` | `Promise<object[]>` | Delete multiple documents |
434
387
 
435
- // Update encrypted document
436
- await users.update('user-id',
437
- { salary: 80000 },
438
- {
439
- encrypted: true,
440
- password: 'strong-password-here'
441
- }
442
- );
443
- ```
388
+ #### Event Methods
444
389
 
445
- ### Password Protection
390
+ | Method | Parameters | Returns | Description |
391
+ |--------|------------|---------|-------------|
392
+ | `on()` | `event: string`<br/>`callback: function` | `void` | Add event listener |
393
+ | `off()` | `event: string`<br/>`callback: function` | `void` | Remove event listener |
446
394
 
447
- Secure your exports and backups:
395
+ #### Cache Methods
448
396
 
449
- ```javascript
450
- // Export with encryption
451
- const encryptedExport = await db.export('encrypted', 'export-password');
397
+ | Method | Parameters | Returns | Description |
398
+ |--------|------------|---------|-------------|
399
+ | `configureCacheStrategy()` | `config: object` | `void` | Configure caching |
400
+ | `clearCache()` | - | `void` | Clear query cache |
452
401
 
453
- // Import encrypted data
454
- await db.import(encryptedExport, 'encrypted', 'export-password');
402
+ #### Options Parameters
455
403
 
456
- // Create encrypted backup
457
- const backup = await lacerta.createBackup('backup-password');
404
+ | Option | Type | Default | Description |
405
+ |--------|------|---------|-------------|
406
+ | `id` | `string` | auto-generated | Custom document ID |
407
+ | `compressed` | `boolean` | `true` | Enable compression |
408
+ | `permanent` | `boolean` | `false` | Prevent auto-deletion |
409
+ | `includeAttachments` | `boolean` | `false` | Include file attachments |
410
+ | `attachments` | `Array` | `[]` | File attachments to store |
411
+ | `force` | `boolean` | `false` | Force delete permanent docs |
412
+ | `limit` | `number` | - | Limit results |
413
+ | `skip` | `number` | - | Skip results |
414
+ | `sort` | `object` | - | Sort criteria |
415
+ | `projection` | `object` | - | Field projection |
458
416
 
459
- // Restore from encrypted backup
460
- await lacerta.restoreBackup(backup, 'backup-password');
461
- ```
417
+ <details>
418
+ <summary><strong>Examples</strong></summary>
462
419
 
463
- ## 📎 Attachments
420
+ ```javascript
421
+ const users = await db.getCollection('users');
464
422
 
465
- Store files using the Origin Private File System:
423
+ // Add document with custom ID
424
+ const userId = await users.add({
425
+ name: 'John Doe',
426
+ email: 'john@example.com',
427
+ age: 30,
428
+ skills: ['JavaScript', 'TypeScript', 'React']
429
+ }, {
430
+ id: 'user_john_doe',
431
+ permanent: true // Protect from auto-cleanup
432
+ });
466
433
 
467
- ```javascript
468
- // Prepare files
469
- const file1 = new File(['content'], 'document.pdf', { type: 'application/pdf' });
470
- const file2 = new Blob(['image data'], { type: 'image/png' });
434
+ // Find one document
435
+ const john = await users.findOne({ email: 'john@example.com' });
471
436
 
472
- // Add document with attachments
473
- const docId = await documents.add(
474
- { title: 'Report with Files' },
475
- {
476
- attachments: [
477
- file1,
478
- file2,
479
- {
480
- name: 'custom.txt',
481
- type: 'text/plain',
482
- data: new TextEncoder().encode('Custom file content')
483
- }
484
- ]
437
+ // Query with multiple conditions
438
+ const seniorDevs = await users.query(
439
+ {
440
+ age: { $gte: 25, $lte: 45 },
441
+ skills: { $all: ['JavaScript', 'React'] }
442
+ },
443
+ {
444
+ sort: { age: -1 },
445
+ limit: 10,
446
+ projection: { name: 1, email: 1, skills: 1 }
485
447
  }
486
448
  );
487
449
 
488
- // Retrieve with attachments
489
- const docWithFiles = await documents.get(docId, {
490
- includeAttachments: true
491
- });
450
+ // Complex aggregation pipeline
451
+ const skillStats = await users.aggregate([
452
+ { $match: { age: { $gte: 18 } } },
453
+ { $project: { skills: 1 } },
454
+ { $unwind: '$skills' },
455
+ { $group: {
456
+ _id: '$skills',
457
+ count: { $count: {} },
458
+ users: { $push: '$_id' }
459
+ }
460
+ },
461
+ { $sort: { count: -1 } },
462
+ { $limit: 5 }
463
+ ]);
492
464
 
493
- // Access attachments
494
- docWithFiles._attachments.forEach(attachment => {
495
- console.log(`File: ${attachment.name} (${attachment.size} bytes)`);
496
- // attachment.data is Uint8Array
465
+ // Batch operations with error handling
466
+ const newUsers = [
467
+ { name: 'Alice', email: 'alice@example.com' },
468
+ { name: 'Bob', email: 'bob@example.com' }
469
+ ];
470
+
471
+ const results = await users.batchAdd(newUsers, {
472
+ compressed: true,
473
+ permanent: false
497
474
  });
498
- ```
499
475
 
500
- ## Performance
476
+ results.forEach(result => {
477
+ if (result.success) {
478
+ console.log(`Added user: ${result.id}`);
479
+ } else {
480
+ console.error(`Failed to add user: ${result.error}`);
481
+ }
482
+ });
501
483
 
502
- ### Compression
484
+ // Event listeners
485
+ users.on('beforeAdd', (data) => {
486
+ console.log('Adding document:', data);
487
+ });
503
488
 
504
- Reduce storage size with automatic compression:
489
+ users.on('afterDelete', (id) => {
490
+ console.log('Deleted document:', id);
491
+ });
505
492
 
506
- ```javascript
507
- // Enable compression for all documents in collection
508
- const compressedColl = await db.createCollection('largeDocs', {
509
- compressed: true
493
+ // Add with file attachments
494
+ const profile = await users.add({
495
+ name: 'User with Avatar'
496
+ }, {
497
+ attachments: [
498
+ await OPFSUtility.prepareAttachment(avatarFile, 'avatar.jpg'),
499
+ await OPFSUtility.prepareAttachment(resumeFile, 'resume.pdf')
500
+ ]
510
501
  });
511
502
 
512
- // Per-document compression
513
- await collection.add(largeData, {
514
- compressed: true // Uses DeflateStream compression
503
+ // Retrieve with attachments
504
+ const userWithFiles = await users.get(profile, {
505
+ includeAttachments: true
515
506
  });
507
+ // userWithFiles._attachments will contain the file data
516
508
  ```
517
509
 
518
- ### Performance Monitoring
510
+ </details>
519
511
 
520
- Track database performance metrics:
512
+ ---
521
513
 
522
- ```javascript
523
- // Start monitoring
524
- lacerta.performanceMonitor.startMonitoring();
514
+ ### 🔍 Index Management
525
515
 
526
- // Perform operations...
516
+ Create indexes for optimized queries.
527
517
 
528
- // Get performance stats
529
- const stats = lacerta.performanceMonitor.getStats();
530
- console.log(`Operations/sec: ${stats.opsPerSec}`);
531
- console.log(`Avg latency: ${stats.avgLatency}ms`);
532
- console.log(`Cache hit rate: ${stats.cacheHitRate}%`);
533
- console.log(`Memory usage: ${stats.memoryUsageMB}MB`);
518
+ | Method | Parameters | Returns | Description |
519
+ |--------|------------|---------|-------------|
520
+ | `createIndex()` | `field: string`<br/>`options: object` | `Promise<string>` | Create an index |
521
+ | `dropIndex()` | `name: string` | `Promise<void>` | Remove an index |
522
+ | `getIndexes()` | - | `Promise<object>` | Get index statistics |
523
+ | `verifyIndexes()` | - | `Promise<object>` | Verify and repair indexes |
524
+ | `reindexCollection()` | - | `Promise<void>` | Rebuild all indexes |
534
525
 
535
- // Get optimization tips
536
- const tips = lacerta.performanceMonitor.getOptimizationTips();
537
- tips.forEach(tip => console.log(`💡 ${tip}`));
526
+ #### Index Types and Use Cases
538
527
 
539
- // Stop monitoring
540
- lacerta.performanceMonitor.stopMonitoring();
541
- ```
528
+ | Type | Use Case | Query Performance | Space Overhead |
529
+ |------|----------|-------------------|----------------|
530
+ | `btree` | Range queries, sorting | O(log n) | Medium |
531
+ | `hash` | Exact match queries | O(1) | Low |
532
+ | `text` | Full-text search | O(n) for terms | High |
533
+ | `geo` | Spatial queries | O(n log n) | Medium |
534
+
535
+ #### Index Options
542
536
 
543
- ### Query Caching
537
+ | Option | Type | Default | Values | Description |
538
+ |--------|------|---------|--------|-------------|
539
+ | `type` | `string` | `'btree'` | `'btree'`, `'hash'`, `'text'`, `'geo'` | Index type |
540
+ | `unique` | `boolean` | `false` | - | Enforce uniqueness |
541
+ | `sparse` | `boolean` | `false` | - | Skip null values |
542
+ | `name` | `string` | field name | - | Custom index name |
543
+ | `collation` | `object` | null | - | Collation rules |
544
544
 
545
- Queries are automatically cached for 60 seconds:
545
+ <details>
546
+ <summary><strong>Examples</strong></summary>
546
547
 
547
548
  ```javascript
548
- // First query - hits database
549
- const results1 = await users.query({ status: 'active' });
549
+ // Create B-Tree index for range queries
550
+ await users.createIndex('age', {
551
+ type: 'btree',
552
+ name: 'age_index'
553
+ });
550
554
 
551
- // Second identical query - served from cache
552
- const results2 = await users.query({ status: 'active' });
555
+ // Create compound index (nested fields)
556
+ await users.createIndex('address.city', {
557
+ type: 'hash',
558
+ name: 'city_index'
559
+ });
553
560
 
554
- // Clear cache manually if needed
555
- users.clearCache();
556
- ```
561
+ // Create unique index on email
562
+ await users.createIndex('email', {
563
+ unique: true,
564
+ sparse: true // Allow multiple nulls
565
+ });
557
566
 
558
- ## 🔄 Data Migration
567
+ // Create text index for full-text search
568
+ await posts.createIndex('content', {
569
+ type: 'text',
570
+ name: 'content_search'
571
+ });
559
572
 
560
- Version your schema changes:
573
+ // Use text index
574
+ const searchResults = await posts.query({
575
+ content: { $text: 'javascript tutorial' }
576
+ });
561
577
 
562
- ```javascript
563
- const migrationManager = new MigrationManager(db);
578
+ // Create geo index for location queries
579
+ await stores.createIndex('location', {
580
+ type: 'geo'
581
+ });
564
582
 
565
- // Define migrations
566
- migrationManager.addMigration({
567
- version: '2.0.0',
568
- name: 'Add user roles',
569
- up: async (doc) => {
570
- if (doc.type === 'user' && !doc.role) {
571
- return { ...doc, role: 'standard' };
583
+ // Query using geo index - find nearby
584
+ const nearbyStores = await stores.query({
585
+ location: {
586
+ $near: {
587
+ coordinates: { lat: 40.7128, lng: -74.0060 },
588
+ maxDistance: 5000 // 5km in meters
572
589
  }
573
- return doc;
574
- },
575
- down: async (doc) => {
576
- if (doc.type === 'user') {
577
- const { role, ...rest } = doc;
578
- return rest;
590
+ }
591
+ });
592
+
593
+ // Query using geo index - find within bounds
594
+ const storesInArea = await stores.query({
595
+ location: {
596
+ $within: {
597
+ minLat: 40.7,
598
+ maxLat: 40.8,
599
+ minLng: -74.1,
600
+ maxLng: -74.0
579
601
  }
580
- return doc;
581
602
  }
582
603
  });
583
604
 
584
- // Run migrations
585
- await migrationManager.runMigrations('2.0.0');
605
+ // Get index statistics
606
+ const indexes = await users.getIndexes();
607
+ Object.entries(indexes).forEach(([name, info]) => {
608
+ console.log(`Index: ${name}`);
609
+ console.log(` Type: ${info.type}`);
610
+ console.log(` Size: ${info.size} entries`);
611
+ console.log(` Memory: ~${info.memoryUsage} bytes`);
612
+ });
586
613
 
587
- // Rollback if needed
588
- await migrationManager.rollback('1.0.0');
614
+ // Verify and auto-repair indexes
615
+ const report = await users.verifyIndexes();
616
+ if (!report.healthy) {
617
+ console.log('Indexes repaired:', report.repaired);
618
+ }
589
619
  ```
590
620
 
591
- ## 💾 Backup & Restore
621
+ </details>
592
622
 
593
- ### Database Export/Import
623
+ ---
594
624
 
595
- ```javascript
596
- // Export single database
597
- const exportData = await db.export('json');
598
- // Save exportData to file or send to server
625
+ ### 🔐 Encryption
599
626
 
600
- // Import data
601
- const importResult = await db.import(exportData, 'json');
602
- console.log(`Imported ${importResult.documents} documents`);
627
+ Database-level encryption configuration.
603
628
 
604
- // Export with encryption
605
- const secureExport = await db.export('encrypted', 'password123');
606
- ```
629
+ | Method | Parameters | Returns | Description |
630
+ |--------|------------|---------|-------------|
631
+ | `initialize()` | `pin: string`<br/>`salt?: Uint8Array` | `Promise<string>` | Initialize encryption |
632
+ | `changePin()` | `oldPin: string`<br/>`newPin: string` | `Promise<string>` | Change encryption PIN |
633
+ | `destroy()` | - | `void` | Clear encryption keys |
634
+ | `exportMetadata()` | - | `object` | Export encryption config |
635
+ | `importMetadata()` | `metadata: object` | `boolean` | Import encryption config |
607
636
 
608
- ### Full System Backup
637
+ #### Encryption Configuration
609
638
 
610
- ```javascript
611
- // Backup all databases
612
- const systemBackup = await lacerta.createBackup();
613
- // Optional: encrypt the backup
614
- const encryptedBackup = await lacerta.createBackup('backup-password');
615
-
616
- // Restore from backup
617
- const restoreResult = await lacerta.restoreBackup(systemBackup);
618
- console.log(`Restored: ${restoreResult.databases} databases`);
619
- console.log(`Total documents: ${restoreResult.documents}`);
620
- ```
639
+ | Option | Type | Default | Range | Description |
640
+ |--------|------|---------|-------|-------------|
641
+ | `iterations` | `number` | `100000` | 10000-1000000 | PBKDF2 iterations |
642
+ | `hashAlgorithm` | `string` | `'SHA-256'` | SHA-256/SHA-512 | Hash algorithm |
643
+ | `keyLength` | `number` | `256` | 128/192/256 | Key length in bits |
644
+ | `saltLength` | `number` | `32` | 16-64 | Salt length in bytes |
621
645
 
622
- ## 🛠️ Advanced Features
646
+ #### Static Methods
623
647
 
624
- ### Batch Operations
648
+ | Method | Parameters | Returns | Description |
649
+ |--------|------------|---------|-------------|
650
+ | `generateSecurePIN()` | `length: number` | `string` | Generate random PIN |
625
651
 
626
- Efficient bulk operations with transaction support:
652
+ <details>
653
+ <summary><strong>Examples</strong></summary>
627
654
 
628
655
  ```javascript
629
- // Batch insert
630
- const documents = [
631
- { name: 'Doc 1', value: 100 },
632
- { name: 'Doc 2', value: 200 },
633
- { name: 'Doc 3', value: 300 }
634
- ];
656
+ // Initialize encrypted database with custom config
657
+ const secureDb = await lacerta.getSecureDatabase(
658
+ 'secure-app',
659
+ 'user-pin-123456',
660
+ null, // Auto-generate salt
661
+ {
662
+ iterations: 200000, // Higher = more secure but slower
663
+ keyLength: 256,
664
+ hashAlgorithm: 'SHA-512'
665
+ }
666
+ );
635
667
 
636
- const results = await collection.batchAdd(documents, {
637
- compressed: true,
638
- encrypted: false
639
- });
668
+ // Change PIN
669
+ const newSalt = await secureDb.changePin(
670
+ 'old-pin-123456',
671
+ 'new-pin-789012'
672
+ );
673
+ console.log('New salt (store securely):', newSalt);
640
674
 
641
- // Check results
642
- results.forEach(result => {
643
- if (result.success) {
644
- console.log(`✅ Added: ${result.id}`);
645
- } else {
646
- console.log(`❌ Failed: ${result.error}`);
647
- }
648
- });
675
+ // Generate secure PIN
676
+ const securePin = SecureDatabaseEncryption.generateSecurePIN(8);
677
+ console.log('Generated PIN:', securePin);
649
678
 
650
- // Batch update
651
- const updates = [
652
- { id: 'doc1', data: { status: 'active' } },
653
- { id: 'doc2', data: { status: 'inactive' } }
654
- ];
655
- await collection.batchUpdate(updates);
679
+ // Export encryption metadata (for backup)
680
+ const encryptionMeta = secureDb.encryption.exportMetadata();
681
+ // Store this securely with your backups
656
682
 
657
- // Batch delete
658
- const idsToDelete = ['doc3', 'doc4', 'doc5'];
659
- await collection.batchDelete(idsToDelete);
683
+ // Restore encryption with same config
684
+ const restoredDb = await lacerta.getSecureDatabase(
685
+ 'secure-app',
686
+ userPin,
687
+ encryptionMeta.salt // Use stored salt
688
+ );
660
689
  ```
661
690
 
662
- ### Event System
691
+ </details>
663
692
 
664
- React to database operations:
693
+ ---
665
694
 
666
- ```javascript
667
- // Collection-level events
668
- collection.on('beforeAdd', async (data) => {
669
- console.log('Validating document...');
670
- // Perform validation
671
- });
695
+ ## Advanced Features
672
696
 
673
- collection.on('afterAdd', async (doc) => {
674
- console.log(`Document ${doc._id} added`);
675
- // Send notification, update cache, etc.
676
- });
697
+ ### 🎯 Query Operators
677
698
 
678
- collection.on('beforeUpdate', async ({ docId, updates }) => {
679
- console.log(`Updating ${docId}`);
680
- });
699
+ #### Comparison Operators
681
700
 
682
- collection.on('afterDelete', async (docId) => {
683
- console.log(`Document ${docId} deleted`);
684
- // Cleanup related data
685
- });
701
+ | Operator | Description | Example |
702
+ |----------|-------------|---------|
703
+ | `$eq` | Equals | `{ age: { $eq: 25 } }` |
704
+ | `$ne` | Not equals | `{ status: { $ne: 'deleted' } }` |
705
+ | `$gt` | Greater than | `{ price: { $gt: 100 } }` |
706
+ | `$gte` | Greater than or equal | `{ age: { $gte: 18 } }` |
707
+ | `$lt` | Less than | `{ score: { $lt: 50 } }` |
708
+ | `$lte` | Less than or equal | `{ age: { $lte: 65 } }` |
686
709
 
687
- // Remove event listener
688
- const handler = (doc) => console.log(doc);
689
- collection.on('afterAdd', handler);
690
- collection.off('afterAdd', handler);
691
- ```
710
+ #### Array Operators
692
711
 
693
- ### Quick Store
712
+ | Operator | Description | Example |
713
+ |----------|-------------|---------|
714
+ | `$in` | Value in array | `{ category: { $in: ['A', 'B'] } }` |
715
+ | `$nin` | Value not in array | `{ status: { $nin: ['banned'] } }` |
716
+ | `$all` | Array contains all | `{ tags: { $all: ['js', 'node'] } }` |
717
+ | `$elemMatch` | Array element match | `{ scores: { $elemMatch: { $gt: 80 } } }` |
718
+ | `$size` | Array size | `{ items: { $size: 3 } }` |
719
+
720
+ #### Logical Operators
694
721
 
695
- Fast localStorage-based storage for small data:
722
+ | Operator | Description | Example |
723
+ |----------|-------------|---------|
724
+ | `$and` | Logical AND | `{ $and: [{ age: { $gte: 18 } }, { active: true }] }` |
725
+ | `$or` | Logical OR | `{ $or: [{ role: 'admin' }, { role: 'moderator' }] }` |
726
+ | `$not` | Logical NOT | `{ age: { $not: { $lt: 18 } } }` |
727
+ | `$nor` | Logical NOR | `{ $nor: [{ expired: true }, { deleted: true }] }` |
728
+
729
+ #### Element Operators
730
+
731
+ | Operator | Description | Example |
732
+ |----------|-------------|---------|
733
+ | `$exists` | Field exists | `{ email: { $exists: true } }` |
734
+ | `$type` | Field type | `{ age: { $type: 'number' } }` |
735
+
736
+ #### String Operators
737
+
738
+ | Operator | Description | Example |
739
+ |----------|-------------|---------|
740
+ | `$regex` | Regular expression | `{ name: { $regex: '^John' } }` |
741
+ | `$text` | Text search | `{ bio: { $text: 'developer' } }` |
742
+
743
+ ### 📊 Aggregation Pipeline Stages
744
+
745
+ | Stage | Description | Example |
746
+ |-------|-------------|---------|
747
+ | `$match` | Filter documents | `{ $match: { age: { $gte: 18 } } }` |
748
+ | `$group` | Group by field | `{ $group: { _id: '$category', count: { $count: {} } } }` |
749
+ | `$sort` | Sort results | `{ $sort: { createdAt: -1 } }` |
750
+ | `$limit` | Limit results | `{ $limit: 10 }` |
751
+ | `$skip` | Skip results | `{ $skip: 20 }` |
752
+ | `$project` | Project fields | `{ $project: { name: 1, email: 1 } }` |
753
+ | `$lookup` | Join collections | `{ $lookup: { from: 'posts', localField: '_id', foreignField: 'userId', as: 'userPosts' } }` |
754
+
755
+ #### Aggregation Accumulator Operators
756
+
757
+ | Operator | Description | Example |
758
+ |----------|-------------|---------|
759
+ | `$sum` | Sum values | `{ total: { $sum: '$amount' } }` |
760
+ | `$avg` | Average values | `{ avgAge: { $avg: '$age' } }` |
761
+ | `$min` | Minimum value | `{ minPrice: { $min: '$price' } }` |
762
+ | `$max` | Maximum value | `{ maxScore: { $max: '$score' } }` |
763
+ | `$count` | Count documents | `{ total: { $count: {} } }` |
764
+
765
+ ### 💾 Cache Strategies
766
+
767
+ | Strategy | Description | Best For | Configuration |
768
+ |----------|-------------|----------|---------------|
769
+ | `lru` | Least Recently Used | General purpose | `maxSize`, `ttl` |
770
+ | `lfu` | Least Frequently Used | Repeated queries | `maxSize`, `ttl` |
771
+ | `ttl` | Time To Live | Time-sensitive data | `ttl` |
772
+ | `none` | No caching | Real-time data | - |
773
+
774
+ <details>
775
+ <summary><strong>Examples</strong></summary>
696
776
 
697
777
  ```javascript
698
- // Access QuickStore
699
- const quickStore = db.quickStore;
700
-
701
- // Store data
702
- quickStore.add('user-prefs', {
703
- theme: 'dark',
704
- language: 'en',
705
- notifications: true
778
+ // Configure LRU cache with TTL
779
+ users.configureCacheStrategy({
780
+ type: 'lru',
781
+ maxSize: 200, // Max 200 cached queries
782
+ ttl: 60000, // Expire after 1 minute
783
+ enabled: true
706
784
  });
707
785
 
708
- // Retrieve data
709
- const prefs = quickStore.get('user-prefs');
710
-
711
- // Update
712
- quickStore.update('user-prefs', { theme: 'light' });
713
-
714
- // Get all stored items
715
- const allItems = quickStore.getAll();
716
-
717
- // Clear QuickStore
718
- quickStore.clear();
719
- ```
720
-
721
- ## 📊 Storage Management
722
-
723
- ### Size Limits and Auto-Cleanup
724
-
725
- ```javascript
726
- // Configure storage limits
727
- db.updateSettings({
728
- sizeLimitKB: 100000, // 100MB total limit
729
- bufferLimitKB: 80000, // Start cleanup at 80MB
730
- freeSpaceEvery: 30000 // Check every 30 seconds
786
+ // Configure LFU for frequently accessed data
787
+ products.configureCacheStrategy({
788
+ type: 'lfu',
789
+ maxSize: 500,
790
+ ttl: 300000 // 5 minutes
731
791
  });
732
792
 
733
- // Manual cleanup
734
- await collection.freeSpace();
793
+ // TTL-only for session data
794
+ sessions.configureCacheStrategy({
795
+ type: 'ttl',
796
+ ttl: 900000 // 15 minutes
797
+ });
735
798
 
736
- // Mark documents as permanent
737
- await collection.add(importantData, {
738
- permanent: true // Won't be deleted during cleanup
799
+ // Disable caching for real-time data
800
+ liveData.configureCacheStrategy({
801
+ type: 'none'
739
802
  });
740
803
 
741
- // Check collection size
742
- const stats = collection.metadata;
743
- console.log(`Collection size: ${stats.sizeKB} KB`);
744
- console.log(`Document count: ${stats.length}`);
804
+ // Manual cache control
805
+ users.clearCache(); // Clear all cached queries
745
806
  ```
746
807
 
747
- ### Storage Information
808
+ </details>
748
809
 
749
- ```javascript
750
- // Database statistics
751
- const dbStats = db.getStats();
752
- console.log(dbStats);
753
- /* Output:
754
- {
755
- name: 'myDatabase',
756
- totalSizeKB: 2457.3,
757
- totalDocuments: 1250,
758
- collections: [
759
- {
760
- name: 'users',
761
- sizeKB: 1024.5,
762
- documents: 500,
763
- createdAt: '2024-01-01T00:00:00.000Z',
764
- modifiedAt: '2024-01-15T10:30:00.000Z'
765
- }
766
- ]
767
- }
768
- */
810
+ ---
769
811
 
770
- // List all databases
771
- const allDatabases = lacerta.listDatabases();
772
- console.log('Available databases:', allDatabases);
773
- ```
812
+ ## Real-World Examples
774
813
 
775
- ## 🎨 API Reference
776
-
777
- ### LacertaDB Class
778
-
779
- | Method | Description | Returns |
780
- |--------|-------------|---------|
781
- | `getDatabase(name)` | Get or create a database | `Promise<Database>` |
782
- | `dropDatabase(name)` | Delete a database | `Promise<void>` |
783
- | `listDatabases()` | List all database names | `Array<string>` |
784
- | `createBackup(password?)` | Create full system backup | `Promise<string>` |
785
- | `restoreBackup(data, password?)` | Restore from backup | `Promise<Object>` |
786
-
787
- ### Database Class
788
-
789
- | Method | Description | Returns |
790
- |--------|-------------|---------|
791
- | `createCollection(name, options?)` | Create new collection | `Promise<Collection>` |
792
- | `getCollection(name)` | Get existing collection | `Promise<Collection>` |
793
- | `dropCollection(name)` | Delete collection | `Promise<void>` |
794
- | `listCollections()` | Get collection names | `Array<string>` |
795
- | `getStats()` | Get database statistics | `Object` |
796
- | `updateSettings(settings)` | Update configuration | `void` |
797
- | `export(format, password?)` | Export database | `Promise<string>` |
798
- | `import(data, format, password?)` | Import data | `Promise<Object>` |
799
- | `clearAll()` | Delete all collections | `Promise<void>` |
800
-
801
- ### Collection Class
802
-
803
- | Method | Description | Returns |
804
- |--------|-------------|---------|
805
- | `add(data, options?)` | Add document | `Promise<string>` |
806
- | `get(id, options?)` | Get document by ID | `Promise<Object>` |
807
- | `getAll(options?)` | Get all documents | `Promise<Array>` |
808
- | `update(id, updates, options?)` | Update document | `Promise<string>` |
809
- | `delete(id)` | Delete document | `Promise<void>` |
810
- | `query(filter, options?)` | Query documents | `Promise<Array>` |
811
- | `aggregate(pipeline)` | Run aggregation | `Promise<Array>` |
812
- | `batchAdd(documents, options?)` | Add multiple documents | `Promise<Array>` |
813
- | `batchUpdate(updates, options?)` | Update multiple documents | `Promise<Array>` |
814
- | `batchDelete(ids)` | Delete multiple documents | `Promise<Array>` |
815
- | `clear()` | Remove all documents | `Promise<void>` |
816
- | `on(event, callback)` | Add event listener | `void` |
817
- | `off(event, callback)` | Remove event listener | `void` |
818
- | `clearCache()` | Clear query cache | `void` |
819
-
820
- ## 💡 Examples
821
-
822
- ### Todo Application
814
+ ### 💬 Chat Application
823
815
 
824
816
  ```javascript
825
- // Initialize
817
+ // Initialize encrypted database for chat
826
818
  const lacerta = new LacertaDB();
827
- const db = await lacerta.getDatabase('todoApp');
828
- const todos = await db.createCollection('todos');
829
-
830
- // Add todos
831
- await todos.add({
832
- title: 'Learn LacertaDB',
833
- completed: false,
834
- priority: 'high',
835
- tags: ['learning', 'database'],
836
- createdAt: Date.now()
837
- });
838
-
839
- // Query incomplete high-priority todos
840
- const urgentTodos = await todos.query({
841
- completed: false,
842
- priority: 'high'
819
+ const db = await lacerta.getSecureDatabase('chat-app', userPin);
820
+
821
+ // Create collections
822
+ const messages = await db.createCollection('messages');
823
+ const conversations = await db.createCollection('conversations');
824
+
825
+ // Create indexes for performance
826
+ await messages.createIndex('conversationId', { type: 'hash' });
827
+ await messages.createIndex('timestamp', { type: 'btree' });
828
+ await messages.createIndex('content', { type: 'text' });
829
+
830
+ // Store message with attachment
831
+ const messageId = await messages.add({
832
+ conversationId: 'conv_123',
833
+ userId: 'user_456',
834
+ content: 'Check out this photo!',
835
+ timestamp: Date.now(),
836
+ read: false
843
837
  }, {
844
- sort: { createdAt: -1 }
838
+ attachments: [imageFile],
839
+ permanent: false
845
840
  });
846
841
 
847
- // Mark as complete
848
- await todos.update(todoId, {
849
- completed: true,
850
- completedAt: Date.now()
842
+ // Get recent messages with pagination
843
+ const recentMessages = await messages.query(
844
+ { conversationId: 'conv_123' },
845
+ {
846
+ sort: { timestamp: -1 },
847
+ limit: 20,
848
+ skip: 0
849
+ }
850
+ );
851
+
852
+ // Search messages
853
+ const searchResults = await messages.query({
854
+ content: { $text: 'photo' }
851
855
  });
852
856
 
853
- // Get statistics
854
- const stats = await todos.aggregate([
855
- {
856
- $group: {
857
- _id: '$priority',
858
- count: { $count: {} },
859
- completed: {
860
- $sum: { $cond: ['$completed', 1, 0] }
861
- }
862
- }
863
- }
864
- ]);
857
+ // Mark messages as read
858
+ await messages.batchUpdate(
859
+ unreadMessages.map(msg => ({
860
+ id: msg._id,
861
+ data: { read: true }
862
+ }))
863
+ );
865
864
  ```
866
865
 
867
- ### E-Commerce Inventory
866
+ ### 🛒 E-Commerce Cart
868
867
 
869
868
  ```javascript
870
- // Setup
869
+ // Shopping cart with product management
871
870
  const db = await lacerta.getDatabase('shop');
871
+ const cart = await db.createCollection('cart');
872
872
  const products = await db.createCollection('products');
873
- const orders = await db.createCollection('orders');
874
-
875
- // Product with images
876
- const productId = await products.add(
877
- {
878
- name: 'Wireless Mouse',
879
- price: 29.99,
880
- stock: 150,
881
- category: 'electronics'
882
- },
883
- {
884
- attachments: [productImage1, productImage2]
885
- }
886
- );
887
873
 
888
- // Complex inventory query
889
- const lowStock = await products.query({
890
- $and: [
891
- { stock: { $lt: 20 } },
892
- { category: { $in: ['electronics', 'accessories'] } }
893
- ]
894
- }, {
895
- projection: { name: 1, stock: 1, price: 1 }
874
+ // Add product to cart
875
+ await cart.add({
876
+ productId: 'prod_123',
877
+ quantity: 2,
878
+ price: 29.99,
879
+ addedAt: Date.now()
896
880
  });
897
881
 
898
- // Sales report with joins
899
- const salesReport = await orders.aggregate([
900
- { $match: { status: 'completed' } },
901
- {
902
- $lookup: {
882
+ // Calculate cart total with aggregation
883
+ const cartTotal = await cart.aggregate([
884
+ { $lookup: {
903
885
  from: 'products',
904
886
  localField: 'productId',
905
887
  foreignField: '_id',
906
888
  as: 'product'
907
889
  }
908
890
  },
909
- {
910
- $group: {
911
- _id: '$product.category',
912
- revenue: { $sum: '$total' },
913
- orderCount: { $count: {} }
891
+ { $project: {
892
+ quantity: 1,
893
+ price: 1,
894
+ total: { $multiply: ['$quantity', '$price'] }
914
895
  }
915
896
  },
916
- { $sort: { revenue: -1 } }
897
+ { $group: {
898
+ _id: null,
899
+ subtotal: { $sum: '$total' },
900
+ items: { $sum: '$quantity' }
901
+ }
902
+ }
917
903
  ]);
904
+
905
+ // Clear old cart items
906
+ const oneWeekAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);
907
+ await cart.query(
908
+ { addedAt: { $lt: oneWeekAgo } }
909
+ ).then(oldItems =>
910
+ cart.batchDelete(oldItems.map(item => item._id))
911
+ );
918
912
  ```
919
913
 
920
- ### User Session Management
914
+ ### 📝 Note-Taking App
921
915
 
922
916
  ```javascript
923
- // Encrypted session storage
924
- const sessions = await db.createCollection('sessions');
925
-
926
- // Store session with encryption
927
- await sessions.add(
928
- {
929
- userId: 'user123',
930
- token: 'secret-session-token',
931
- ipAddress: '192.168.1.1',
932
- userAgent: navigator.userAgent,
933
- expiresAt: Date.now() + (24 * 60 * 60 * 1000)
934
- },
935
- {
936
- encrypted: true,
937
- password: process.env.SESSION_KEY,
938
- permanent: false
917
+ // Note app with full-text search
918
+ const db = await lacerta.getDatabase('notes');
919
+ const notes = await db.createCollection('notes');
920
+
921
+ // Create search index
922
+ await notes.createIndex('content', { type: 'text' });
923
+ await notes.createIndex('tags', { type: 'hash' });
924
+
925
+ // Save note with auto-save
926
+ let noteId;
927
+ const autoSave = async (content) => {
928
+ if (noteId) {
929
+ await notes.update(noteId, {
930
+ content,
931
+ lastModified: Date.now()
932
+ });
933
+ } else {
934
+ noteId = await notes.add({
935
+ title: 'New Note',
936
+ content,
937
+ tags: [],
938
+ createdAt: Date.now()
939
+ }, { permanent: true });
939
940
  }
940
- );
941
-
942
- // Cleanup expired sessions
943
- const now = Date.now();
944
- const expired = await sessions.query({
945
- expiresAt: { $lt: now }
946
- });
941
+ };
947
942
 
948
- await sessions.batchDelete(expired.map(s => s._id));
943
+ // Search notes
944
+ const searchNotes = async (query) => {
945
+ return await notes.query({
946
+ $or: [
947
+ { content: { $text: query } },
948
+ { title: { $regex: query } },
949
+ { tags: { $in: [query] } }
950
+ ]
951
+ });
952
+ };
949
953
  ```
950
954
 
951
- ## 🐛 Error Handling
955
+ ---
956
+
957
+ ## Performance Optimization
952
958
 
953
- LacertaDB provides detailed error information:
959
+ ### 📈 Performance Monitoring
954
960
 
955
961
  ```javascript
956
- try {
957
- await collection.get('non-existent-id');
958
- } catch (error) {
959
- if (error instanceof LacertaDBError) {
960
- console.error('Error:', error.message);
961
- console.error('Code:', error.code);
962
- console.error('Timestamp:', error.timestamp);
963
-
964
- // Handle specific error codes
965
- switch(error.code) {
966
- case 'DOCUMENT_NOT_FOUND':
967
- // Handle missing document
968
- break;
969
- case 'ENCRYPTION_FAILED':
970
- // Handle encryption error
971
- break;
972
- case 'QUOTA_EXCEEDED':
973
- // Handle storage limit
974
- break;
975
- }
976
- }
977
- }
978
- ```
962
+ // Enable performance monitoring
963
+ lacerta.performanceMonitor.startMonitoring();
964
+
965
+ // Get real-time statistics
966
+ const stats = lacerta.performanceMonitor.getStats();
967
+ console.log(`Operations/sec: ${stats.opsPerSec}`);
968
+ console.log(`Avg latency: ${stats.avgLatency}ms`);
969
+ console.log(`Cache hit rate: ${stats.cacheHitRate}%`);
970
+ console.log(`Memory usage: ${stats.memoryUsageMB}MB`);
979
971
 
980
- ### Common Error Codes
972
+ // Get optimization recommendations
973
+ const tips = lacerta.performanceMonitor.getOptimizationTips();
974
+ tips.forEach(tip => console.log('💡', tip));
981
975
 
982
- | Code | Description | Solution |
983
- |------|-------------|----------|
984
- | `DOCUMENT_NOT_FOUND` | Document ID doesn't exist | Check ID or use query |
985
- | `COLLECTION_NOT_FOUND` | Collection doesn't exist | Create collection first |
986
- | `ENCRYPTION_FAILED` | Encryption/decryption error | Check password |
987
- | `COMPRESSION_FAILED` | Compression error | Check data format |
988
- | `QUOTA_EXCEEDED` | Storage limit reached | Increase limit or cleanup |
989
- | `INVALID_OPERATION` | Operation not allowed | Check document flags |
990
- | `TRANSACTION_FAILED` | Database transaction error | Retry operation |
976
+ // Monitor specific operations
977
+ const startTime = performance.now();
978
+ await users.query({ age: { $gte: 18 } });
979
+ console.log(`Query took: ${performance.now() - startTime}ms`);
991
980
 
992
- ## 📝 Best Practices
981
+ // Stop monitoring
982
+ lacerta.performanceMonitor.stopMonitoring();
983
+ ```
993
984
 
994
- ### 1. Index Strategy
985
+ ### Best Practices
995
986
 
987
+ #### 1. **Indexing Strategy**
996
988
  ```javascript
997
- // Analyze query patterns first
998
- const queryPatterns = {
999
- byEmail: { email: 'user@example.com' }, // Hash index
1000
- byAgeRange: { age: { $gte: 25, $lte: 35 } }, // B-Tree index
1001
- byDescription: { $text: 'search terms' }, // Text index
1002
- byLocation: { $near: { lat: 0, lng: 0 } } // Geo index
1003
- };
989
+ // Index frequently queried fields
990
+ await users.createIndex('email', { unique: true });
991
+ await users.createIndex('createdAt', { type: 'btree' });
1004
992
 
1005
- // Create appropriate indexes
1006
- await users.createIndex('email', { type: 'hash', unique: true });
1007
- await users.createIndex('age', { type: 'btree' });
1008
- await users.createIndex('bio', { type: 'text' });
1009
- await users.createIndex('location', { type: 'geo' });
993
+ // Use compound indexes for complex queries
994
+ await orders.createIndex('userId', { type: 'hash' });
995
+ await orders.createIndex('status', { type: 'hash' });
1010
996
  ```
1011
997
 
1012
- ### 2. Cache Optimization
998
+ #### 2. **Compression Settings**
999
+ ```javascript
1000
+ // Enable compression for large documents
1001
+ await logs.add(largeLogData, { compressed: true });
1002
+
1003
+ // Disable for frequently accessed small docs
1004
+ await config.add(settings, { compressed: false });
1005
+ ```
1013
1006
 
1007
+ #### 3. **Batch Operations**
1014
1008
  ```javascript
1015
- // Match cache strategy to access patterns
1016
- const cacheStrategies = {
1017
- // Frequently changing data - LRU with short TTL
1018
- activeSessions: { type: 'lru', maxSize: 1000, ttl: 60000 },
1019
-
1020
- // Hot data - LFU for keeping popular items
1021
- trendingProducts: { type: 'lfu', maxSize: 500 },
1022
-
1023
- // Time-sensitive - TTL only
1024
- tempTokens: { type: 'ttl', ttl: 300000 },
1025
-
1026
- // Sensitive data - No cache
1027
- privateKeys: { type: 'none', enabled: false }
1028
- };
1009
+ // Good: Single batch operation
1010
+ await users.batchAdd(thousandUsers);
1011
+
1012
+ // Bad: Individual adds in loop
1013
+ for (const user of thousandUsers) {
1014
+ await users.add(user); // Slow!
1015
+ }
1029
1016
  ```
1030
1017
 
1031
- ### 3. Security Best Practices
1018
+ #### 4. **Memory Management**
1019
+ ```javascript
1020
+ // Configure size limits
1021
+ db.updateSettings({
1022
+ sizeLimitKB: 50000, // 50MB limit
1023
+ bufferLimitKB: 40000, // Start cleanup at 40MB
1024
+ freeSpaceEvery: 10000 // Check every 10 seconds
1025
+ });
1026
+
1027
+ // Mark important docs as permanent
1028
+ await users.add(adminUser, { permanent: true });
1029
+ ```
1032
1030
 
1031
+ #### 5. **Query Optimization**
1033
1032
  ```javascript
1034
- // For private keys and sensitive data
1035
- const secureDb = await lacerta.getSecureDatabase(
1036
- 'vault',
1037
- SecureDatabaseEncryption.generateSecurePIN(12) // 12-digit secure PIN
1033
+ // Use projection to reduce data transfer
1034
+ const names = await users.query(
1035
+ { active: true },
1036
+ { projection: { name: 1, email: 1 } }
1038
1037
  );
1039
1038
 
1040
- // Always use additional authentication
1041
- await secureDb.storePrivateKey('key-name', privateKey, userEmail);
1042
-
1043
- // Regular PIN rotation
1044
- const rotatePin = async () => {
1045
- const newPin = SecureDatabaseEncryption.generateSecurePIN(12);
1046
- await secureDb.changePin(currentPin, newPin);
1047
- // Securely store newPin
1048
- };
1039
+ // Use indexes for sorting
1040
+ await messages.createIndex('timestamp', { type: 'btree' });
1041
+ const recent = await messages.query({}, { sort: { timestamp: -1 } });
1049
1042
  ```
1050
1043
 
1051
- ### 4. Performance Optimization
1044
+ ---
1052
1045
 
1053
- ```javascript
1054
- // Enable monitoring during development
1055
- lacerta.performanceMonitor.startMonitoring();
1046
+ ## Migration Guide
1056
1047
 
1057
- // Test different strategies
1058
- const testPerformance = async () => {
1059
- // Test without index
1060
- const start1 = Date.now();
1061
- await collection.query({ field: 'value' });
1062
- console.log('Without index:', Date.now() - start1);
1063
-
1064
- // Create index
1065
- await collection.createIndex('field', { type: 'hash' });
1066
-
1067
- // Test with index
1068
- const start2 = Date.now();
1069
- await collection.query({ field: 'value' });
1070
- console.log('With index:', Date.now() - start2);
1071
- };
1048
+ ### Schema Migrations
1072
1049
 
1073
- // Get optimization suggestions
1074
- const tips = lacerta.performanceMonitor.getOptimizationTips();
1075
- ```
1050
+ ```javascript
1051
+ const migrationManager = new MigrationManager(db);
1076
1052
 
1077
- ### 5. Storage Management
1053
+ // Add a migration
1054
+ migrationManager.addMigration({
1055
+ version: '2.0.0',
1056
+ name: 'Add user roles',
1057
+ up: async (doc) => {
1058
+ if (doc.type === 'user' && !doc.role) {
1059
+ return { ...doc, role: 'member' };
1060
+ }
1061
+ return null;
1062
+ },
1063
+ down: async (doc) => {
1064
+ if (doc.type === 'user') {
1065
+ const { role, ...rest } = doc;
1066
+ return rest;
1067
+ }
1068
+ return null;
1069
+ }
1070
+ });
1078
1071
 
1079
- ```javascript
1080
- // Set appropriate limits
1081
- db.updateSettings({
1082
- sizeLimitKB: 100000, // 100MB total
1083
- bufferLimitKB: 80000, // Start cleanup at 80MB
1084
- freeSpaceEvery: 300000 // Check every 5 minutes
1072
+ // Add another migration
1073
+ migrationManager.addMigration({
1074
+ version: '2.1.0',
1075
+ name: 'Add timestamps',
1076
+ up: async (doc) => {
1077
+ if (!doc.updatedAt) {
1078
+ return { ...doc, updatedAt: doc._modified };
1079
+ }
1080
+ return null;
1081
+ }
1085
1082
  });
1086
1083
 
1087
- // Mark critical documents as permanent
1088
- await collection.add(importantData, { permanent: true });
1084
+ // Run all migrations up to version
1085
+ await migrationManager.runMigrations('2.1.0');
1089
1086
 
1090
- // Regular maintenance
1091
- const maintenance = async () => {
1092
- const stats = db.getStats();
1093
- if (stats.totalSizeKB > 90000) {
1094
- // Cleanup old non-permanent documents
1095
- await collection.freeSpace();
1096
- }
1097
- };
1087
+ // Rollback if needed
1088
+ await migrationManager.rollback('1.0.0');
1098
1089
  ```
1099
1090
 
1100
- ## 🔄 Migration from v4.x
1091
+ ### Upgrading from v0.5.x to v0.6.x
1092
+
1093
+ ```javascript
1094
+ // Export data from old version
1095
+ const oldDb = await getOldDatabase();
1096
+ const backup = await oldDb.export('json');
1097
+
1098
+ // Import to new version
1099
+ const newLacerta = new LacertaDB();
1100
+ const newDb = await newLacerta.getDatabase('upgraded-db');
1101
+ await newDb.import(backup, 'json');
1102
+
1103
+ // Update indexes for better performance
1104
+ const collections = newDb.listCollections();
1105
+ for (const collName of collections) {
1106
+ const coll = await newDb.getCollection(collName);
1107
+ await coll.verifyIndexes();
1108
+ }
1109
+ ```
1101
1110
 
1102
- ### Breaking Changes
1111
+ ---
1103
1112
 
1104
- None! LacertaDB v5.0.0 is fully backward compatible. All v4.x code continues to work without modifications.
1113
+ ## Troubleshooting
1105
1114
 
1106
- ### New Features to Adopt
1115
+ ### Common Issues and Solutions
1107
1116
 
1108
- ```javascript
1109
- // v4.x code (still works)
1110
- const collection = await db.createCollection('data');
1111
- const results = await collection.query({ status: 'active' });
1117
+ #### 🔴 **QuotaExceededError**
1112
1118
 
1113
- // v5.0.0 optimized code
1114
- const collection = await db.createCollection('data');
1119
+ **Problem:** Browser storage limit reached
1115
1120
 
1116
- // Add index for 50x faster queries
1117
- await collection.createIndex('status', { type: 'hash' });
1121
+ **Solutions:**
1122
+ ```javascript
1123
+ // 1. Check current usage
1124
+ const stats = db.getStats();
1125
+ console.log(`Using ${stats.totalSizeKB}KB`);
1118
1126
 
1119
- // Configure smart caching
1120
- await collection.configureCacheStrategy({
1121
- type: 'lru',
1122
- maxSize: 500,
1123
- ttl: 120000
1127
+ // 2. Clear old data
1128
+ await logs.clear();
1129
+
1130
+ // 3. Enable automatic cleanup
1131
+ db.updateSettings({
1132
+ sizeLimitKB: 45000,
1133
+ bufferLimitKB: 40000
1124
1134
  });
1125
1135
 
1126
- // Now queries are much faster
1127
- const results = await collection.query({ status: 'active' });
1136
+ // 4. Use compression
1137
+ await collection.add(data, { compressed: true });
1128
1138
  ```
1129
1139
 
1130
- ### Migration Checklist
1140
+ #### 🔴 **Slow Query Performance**
1131
1141
 
1132
- 1. **Add Indexes** to frequently queried fields
1133
- 2. **Configure Cache Strategies** based on access patterns
1134
- 3. **Enable PIN encryption** for databases with sensitive data
1135
- 4. **Update force delete** calls for permanent document management
1136
- 5. **Monitor performance** to identify optimization opportunities
1142
+ **Problem:** Queries taking too long
1137
1143
 
1144
+ **Solutions:**
1138
1145
  ```javascript
1139
- // Complete migration example
1140
- const migrate = async () => {
1141
- // 1. Get existing database
1142
- const db = await lacerta.getDatabase('myApp');
1143
-
1144
- // 2. Add indexes to collections
1145
- const users = await db.getCollection('users');
1146
- await users.createIndex('email', { type: 'hash', unique: true });
1147
- await users.createIndex('createdAt', { type: 'btree' });
1148
-
1149
- // 3. Configure caching
1150
- await users.configureCacheStrategy({
1151
- type: 'lru',
1152
- maxSize: 1000,
1153
- ttl: 300000
1154
- });
1155
-
1156
- // 4. For sensitive data, create new secure database
1157
- const secureDb = await lacerta.getSecureDatabase('secure', pin);
1158
- // Migrate sensitive data to secure database
1159
-
1160
- console.log('Migration complete!');
1161
- };
1146
+ // 1. Add appropriate indexes
1147
+ await collection.createIndex('fieldName', { type: 'btree' });
1148
+
1149
+ // 2. Use query projection
1150
+ const results = await collection.query(
1151
+ filter,
1152
+ { projection: { needed: 1, fields: 1 } }
1153
+ );
1154
+
1155
+ // 3. Enable caching
1156
+ collection.configureCacheStrategy({
1157
+ type: 'lru',
1158
+ maxSize: 100
1159
+ });
1160
+
1161
+ // 4. Check index health
1162
+ const report = await collection.verifyIndexes();
1162
1163
  ```
1163
1164
 
1164
- ## 🤝 Contributing
1165
+ #### 🔴 **Memory Leaks in SPAs**
1165
1166
 
1166
- We welcome contributions! Here's how you can help:
1167
+ **Problem:** Memory usage growing over time
1167
1168
 
1168
- 1. **Report Bugs**: Open an issue with reproduction steps
1169
- 2. **Suggest Features**: Share your ideas in discussions
1170
- 3. **Improve Docs**: Fix typos or add examples
1171
- 4. **Submit PRs**: Fork, code, test, and submit
1169
+ **Solutions:**
1170
+ ```javascript
1171
+ // 1. Clean up on component unmount
1172
+ componentWillUnmount() {
1173
+ this.collection.off('update', this.handleUpdate);
1174
+ this.db.destroy();
1175
+ }
1172
1176
 
1173
- ### Development Setup
1177
+ // 2. Use destroy method
1178
+ window.addEventListener('beforeunload', () => {
1179
+ lacerta.destroy();
1180
+ });
1174
1181
 
1175
- ```bash
1176
- # Clone repository
1177
- git clone https://github.com/pixagram-blockchain/LacertaDB.git
1178
- cd LacertaDB
1182
+ // 3. Clear caches periodically
1183
+ setInterval(() => {
1184
+ collection.clearCache();
1185
+ }, 300000); // Every 5 minutes
1186
+ ```
1187
+
1188
+ #### 🔴 **Encryption Issues**
1189
+
1190
+ **Problem:** Cannot access encrypted database
1179
1191
 
1180
- # Install dependencies
1181
- npm install
1192
+ **Solutions:**
1193
+ ```javascript
1194
+ // 1. Verify PIN is correct
1195
+ try {
1196
+ const db = await lacerta.getSecureDatabase('app', pin);
1197
+ } catch (error) {
1198
+ if (error.code === 'ENCRYPTION_FAILED') {
1199
+ console.error('Invalid PIN');
1200
+ }
1201
+ }
1182
1202
 
1183
- # Run tests
1184
- npm test
1203
+ // 2. Check if salt is preserved
1204
+ const metadata = db.encryption.exportMetadata();
1205
+ localStorage.setItem('app-salt', metadata.salt);
1185
1206
 
1186
- # Build
1187
- npm run build
1207
+ // 3. Use same encryption config
1208
+ const db = await lacerta.getSecureDatabase('app', pin, salt, {
1209
+ iterations: 100000, // Must match original
1210
+ keyLength: 256
1211
+ });
1188
1212
  ```
1189
1213
 
1190
- ### Testing
1214
+ ### Debug Mode
1191
1215
 
1192
1216
  ```javascript
1193
- // Test your changes
1194
- import { LacertaDB } from './lacertadb.js';
1217
+ // Enable debug logging
1218
+ window.LACERTA_DEBUG = true;
1219
+
1220
+ // Log all operations
1221
+ const originalAdd = collection.add;
1222
+ collection.add = async function(...args) {
1223
+ console.log('Adding document:', args);
1224
+ const result = await originalAdd.apply(this, args);
1225
+ console.log('Document added:', result);
1226
+ return result;
1227
+ };
1228
+ ```
1195
1229
 
1196
- const runTests = async () => {
1197
- const lacerta = new LacertaDB();
1198
- const db = await lacerta.getDatabase('test');
1199
-
1200
- // Test new features
1201
- const collection = await db.createCollection('test');
1202
- await collection.createIndex('field', { type: 'hash' });
1203
-
1204
- // Verify functionality
1205
- console.assert(collection.indexManager.indexes.size === 1);
1230
+ ---
1231
+
1232
+ ## Error Handling
1233
+
1234
+ ### Error Types
1235
+
1236
+ | Error Code | Description | Resolution |
1237
+ |------------|-------------|------------|
1238
+ | `DATABASE_OPEN_FAILED` | Cannot open database | Check browser support, clear browser data |
1239
+ | `DOCUMENT_NOT_FOUND` | Document doesn't exist | Verify document ID exists |
1240
+ | `COLLECTION_NOT_FOUND` | Collection doesn't exist | Create collection first |
1241
+ | `COLLECTION_EXISTS` | Collection already exists | Use getCollection instead |
1242
+ | `UNIQUE_CONSTRAINT` | Unique index violation | Use different value or update existing |
1243
+ | `QUOTA_EXCEEDED` | Storage limit reached | Clear old data or increase limit |
1244
+ | `ENCRYPTION_NOT_INITIALIZED` | Encryption required | Use getSecureDatabase |
1245
+ | `ENCRYPTION_FAILED` | Decryption failed | Check PIN and salt |
1246
+ | `PERMANENT_DOCUMENT_PROTECTION` | Cannot delete permanent | Use force: true option |
1247
+ | `TRANSACTION_FAILED` | Transaction aborted | Retry operation |
1248
+ | `INVALID_FORMAT` | Invalid data format | Check data structure |
1249
+
1250
+ <details>
1251
+ <summary><strong>Example Error Handling</strong></summary>
1252
+
1253
+ ```javascript
1254
+ // Comprehensive error handling
1255
+ class DatabaseService {
1256
+ async safeOperation(operation) {
1257
+ try {
1258
+ return await operation();
1259
+ } catch (error) {
1260
+ switch (error.code) {
1261
+ case 'UNIQUE_CONSTRAINT':
1262
+ console.error('Duplicate entry:', error.message);
1263
+ // Handle duplicate
1264
+ break;
1265
+
1266
+ case 'QUOTA_EXCEEDED':
1267
+ console.warn('Storage full, cleaning up...');
1268
+ await this.cleanup();
1269
+ // Retry operation
1270
+ return await operation();
1271
+
1272
+ case 'DOCUMENT_NOT_FOUND':
1273
+ console.error('Document not found');
1274
+ return null;
1275
+
1276
+ case 'ENCRYPTION_FAILED':
1277
+ console.error('Invalid credentials');
1278
+ throw new Error('Authentication failed');
1279
+
1280
+ default:
1281
+ console.error('Database error:', error);
1282
+ throw error;
1283
+ }
1284
+ }
1285
+ }
1206
1286
 
1207
- console.log('Tests passed!');
1208
- };
1287
+ async cleanup() {
1288
+ const logs = await db.getCollection('logs');
1289
+ const oldLogs = await logs.query({
1290
+ timestamp: { $lt: Date.now() - 86400000 }
1291
+ });
1292
+ await logs.batchDelete(oldLogs.map(log => log._id));
1293
+ }
1294
+ }
1295
+
1296
+ // Usage
1297
+ const service = new DatabaseService();
1298
+ const result = await service.safeOperation(async () => {
1299
+ return await users.add({ email: 'test@example.com' });
1300
+ });
1209
1301
  ```
1210
1302
 
1211
- ## 📄 License
1303
+ </details>
1212
1304
 
1213
- MIT License - See [LICENSE](LICENSE) file for details
1305
+ ---
1214
1306
 
1215
- ## 🙏 Acknowledgments
1307
+ ## Comparison
1308
+
1309
+ ### LacertaDB vs Alternatives
1310
+
1311
+ | Feature | LacertaDB | LocalStorage | IndexedDB (Raw) | PouchDB | Dexie.js |
1312
+ |---------|-----------|--------------|-----------------|---------|----------|
1313
+ | **Size Limit** | ~2GB* | 5-10MB | ~2GB* | ~2GB* | ~2GB* |
1314
+ | **Encryption** | ✅ Built-in | ❌ | ❌ | ⚠️ Plugin | ❌ |
1315
+ | **Compression** | ✅ Automatic | ❌ | ❌ | ❌ | ❌ |
1316
+ | **Query Language** | ✅ MongoDB-like | ❌ | ❌ | ✅ Map/Reduce | ⚠️ Limited |
1317
+ | **Indexes** | ✅ Multiple types | ❌ | ⚠️ Basic | ✅ | ✅ |
1318
+ | **Aggregation** | ✅ Full pipeline | ❌ | ❌ | ⚠️ Views | ❌ |
1319
+ | **File Attachments** | ✅ OPFS | ❌ | ❌ | ✅ | ❌ |
1320
+ | **Performance Monitor** | ✅ Built-in | ❌ | ❌ | ❌ | ❌ |
1321
+ | **Bundle Size** | ~45KB | 0KB | 0KB | ~140KB | ~90KB |
1322
+ | **TypeScript** | ✅ | ✅ | ✅ | ✅ | ✅ |
1323
+ | **Learning Curve** | Medium | Low | High | Medium | Low |
1324
+
1325
+ *Actual limit varies by browser and available disk space
1326
+
1327
+ ### When to Use LacertaDB
1328
+
1329
+ ✅ **Use LacertaDB when you need:**
1330
+ - Client-side encryption for sensitive data
1331
+ - Complex queries and aggregations
1332
+ - Automatic compression to save space
1333
+ - MongoDB-like query syntax
1334
+ - Built-in performance monitoring
1335
+ - File attachment support
1336
+
1337
+ ❌ **Consider alternatives when:**
1338
+ - You need < 1MB storage (use localStorage)
1339
+ - You need server synchronization (use PouchDB)
1340
+ - You need minimal bundle size (use raw IndexedDB)
1341
+ - You only need key-value storage (use localStorage)
1342
+
1343
+ ---
1344
+
1345
+ ## 📝 License
1216
1346
 
1217
- - Built with ❤️ by the Pixagram team
1218
- - Uses TurboSerial and TurboBase64 for high performance
1219
- - Inspired by MongoDB's query language
1220
- - Powered by modern browser APIs (IndexedDB, OPFS, Web Crypto)
1347
+ MIT © 2024 LacertaDB Contributors
1221
1348
 
1222
- ## 🎉 What's New in v5.0.0
1349
+ ---
1223
1350
 
1224
- - **Custom Indexing**: B-Tree, Hash, Text, and Geo indexes for 50x faster queries
1225
- - 🧠 **Smart Caching**: LRU, LFU, and TTL strategies with per-collection configuration
1226
- - 🔐 **Database Encryption**: PIN-based security with 1M PBKDF2 iterations for private keys
1227
- - 💪 **Force Delete**: Administrative control over permanent documents
1228
- - 📊 **Enhanced Monitoring**: Detailed performance metrics and optimization tips
1351
+ ## 🙏 Acknowledgments
1229
1352
 
1353
+ Special thanks to all contributors and the open-source community.
1354
+
1355
+ Built with ❤️ using:
1356
+ - [TurboSerial](https://github.com/pixagram/turboserial) for serialization
1357
+ - [TurboBase64](https://github.com/pixagram/turbobase64) for encoding
1358
+
1359
+ ---
1230
1360
  ---
1231
1361
 
1232
- <div align="center">
1233
- <strong>🦎 LacertaDB v0.6.0 - Fast, Secure, Browser-Native Database</strong>
1234
- <br>
1235
- <i>50x faster queries • Military-grade encryption • Smart caching</i>
1236
- <br><br>
1237
- Made with ❤️ by Pixagram Blockchain
1238
- </div>
1362
+ <p align="center">
1363
+ <strong>Star this repository if you find it helpful!</strong>
1364
+ </p>