jexidb 2.0.1 → 2.0.3
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/CHANGELOG.md +109 -0
- package/README.md +142 -27
- package/dist/JSONLDatabase.js +240 -101
- package/dist/index.js +13 -4
- package/docs/API.md +390 -0
- package/docs/EXAMPLES.md +177 -0
- package/docs/MIGRATION.md +295 -0
- package/docs/README.md +184 -0
- package/examples/auto-save-example.js +158 -0
- package/examples/cjs-usage.cjs +82 -0
- package/examples/close-vs-delete-example.js +71 -0
- package/examples/esm-usage.js +113 -0
- package/examples/example-columns.idx.jdb +0 -0
- package/examples/example-columns.jdb +9 -0
- package/examples/example-options.idx.jdb +0 -0
- package/examples/example-options.jdb +0 -0
- package/examples/example-users.idx.jdb +0 -0
- package/examples/example-users.jdb +5 -0
- package/examples/simple-test.js +55 -0
- package/package.json +5 -2
- package/src/JSONLDatabase.js +245 -102
- package/src/index.js +7 -3
package/docs/API.md
ADDED
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
# JexiDB API Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
JexiDB is a high-performance, local JSONL database with intelligent optimizations, real compression, and comprehensive error handling.
|
|
6
|
+
|
|
7
|
+
## Core Classes
|
|
8
|
+
|
|
9
|
+
### Database
|
|
10
|
+
|
|
11
|
+
The main database class that provides CRUD operations with intelligent optimizations.
|
|
12
|
+
|
|
13
|
+
#### Constructor
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
new Database(filePath, options = {})
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Parameters:**
|
|
20
|
+
- `filePath` (string): Path to the database file
|
|
21
|
+
- `options` (object): Configuration options
|
|
22
|
+
- `indexes` (object): Index configuration
|
|
23
|
+
- `markDeleted` (boolean): Mark records as deleted instead of physical removal
|
|
24
|
+
- `create` (boolean): Create database if it doesn't exist (default: true)
|
|
25
|
+
- `clear` (boolean): Clear database on load if not empty (default: false)
|
|
26
|
+
|
|
27
|
+
**Auto-Save Configuration:**
|
|
28
|
+
- `autoSave` (boolean): Enable intelligent auto-save (default: true)
|
|
29
|
+
- `autoSaveThreshold` (number): Flush buffer when it reaches this many records (default: 50)
|
|
30
|
+
- `autoSaveInterval` (number): Flush buffer every N milliseconds (default: 5000)
|
|
31
|
+
- `forceSaveOnClose` (boolean): Always save when closing database (default: true)
|
|
32
|
+
|
|
33
|
+
**Performance Configuration:**
|
|
34
|
+
- `batchSize` (number): Batch size for inserts (default: 50)
|
|
35
|
+
- `adaptiveBatchSize` (boolean): Adjust batch size based on usage (default: true)
|
|
36
|
+
- `minBatchSize` (number): Minimum batch size for flush (default: 10)
|
|
37
|
+
- `maxBatchSize` (number): Maximum batch size for performance (default: 200)
|
|
38
|
+
|
|
39
|
+
**Memory Management:**
|
|
40
|
+
- `maxMemoryUsage` (string|number): Memory limit ('auto' or bytes, default: 'auto')
|
|
41
|
+
- `maxFlushChunkBytes` (number): Maximum chunk size for flush operations (default: 8MB)
|
|
42
|
+
|
|
43
|
+
#### Methods
|
|
44
|
+
|
|
45
|
+
##### init()
|
|
46
|
+
Initializes the database and loads existing data.
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
await db.init()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
##### insert(data)
|
|
53
|
+
Inserts a single record with adaptive optimization.
|
|
54
|
+
|
|
55
|
+
```javascript
|
|
56
|
+
const record = await db.insert({ id: '1', name: 'John' })
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
##### insertMany(dataArray)
|
|
60
|
+
Inserts multiple records with bulk optimization.
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
const records = await db.insertMany([
|
|
64
|
+
{ id: '1', name: 'John' },
|
|
65
|
+
{ id: '2', name: 'Jane' }
|
|
66
|
+
])
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
##### find(criteria, options)
|
|
70
|
+
Finds records matching criteria with query optimization.
|
|
71
|
+
|
|
72
|
+
```javascript
|
|
73
|
+
const results = await db.find(
|
|
74
|
+
{ age: { $gte: 25 } },
|
|
75
|
+
{ limit: 10, sort: { name: 1 } }
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
##### findOne(criteria, options)
|
|
80
|
+
Finds a single record matching criteria.
|
|
81
|
+
|
|
82
|
+
```javascript
|
|
83
|
+
const user = await db.findOne({ id: '1' })
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
##### update(criteria, updates, options)
|
|
87
|
+
Updates records matching criteria.
|
|
88
|
+
|
|
89
|
+
```javascript
|
|
90
|
+
const updated = await db.update(
|
|
91
|
+
{ id: '1' },
|
|
92
|
+
{ name: 'John Updated', age: 30 }
|
|
93
|
+
)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
##### delete(criteria, options)
|
|
97
|
+
Deletes records matching criteria.
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
const deleted = await db.delete({ id: '1' })
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
##### count(criteria)
|
|
104
|
+
Counts records matching criteria.
|
|
105
|
+
|
|
106
|
+
```javascript
|
|
107
|
+
const count = await db.count({ active: true })
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
##### save()
|
|
111
|
+
Saves pending changes to disk.
|
|
112
|
+
|
|
113
|
+
```javascript
|
|
114
|
+
await db.save()
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
##### flush()
|
|
118
|
+
Flushes the insertion buffer to disk immediately.
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
const flushedCount = await db.flush()
|
|
122
|
+
// Returns: number of records flushed
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
##### forceSave()
|
|
126
|
+
Forces a save operation regardless of buffer size.
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
await db.forceSave()
|
|
130
|
+
// Always saves, even with just 1 record in buffer
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
##### getBufferStatus()
|
|
134
|
+
Gets information about the current buffer state.
|
|
135
|
+
|
|
136
|
+
```javascript
|
|
137
|
+
const status = db.getBufferStatus()
|
|
138
|
+
// Returns: {
|
|
139
|
+
// pendingCount: 15,
|
|
140
|
+
// bufferSize: 50,
|
|
141
|
+
// lastFlush: 1640995200000,
|
|
142
|
+
// lastAutoSave: 1640995200000,
|
|
143
|
+
// shouldFlush: false,
|
|
144
|
+
// autoSaveEnabled: true,
|
|
145
|
+
// autoSaveTimer: 'active'
|
|
146
|
+
// }
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
##### configurePerformance(settings)
|
|
150
|
+
Dynamically configures performance settings.
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
db.configurePerformance({
|
|
154
|
+
batchSize: 25,
|
|
155
|
+
autoSaveThreshold: 30,
|
|
156
|
+
autoSaveInterval: 4000
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
##### getPerformanceConfig()
|
|
161
|
+
Gets current performance configuration.
|
|
162
|
+
|
|
163
|
+
```javascript
|
|
164
|
+
const config = db.getPerformanceConfig()
|
|
165
|
+
// Returns: {
|
|
166
|
+
// batchSize: 25,
|
|
167
|
+
// autoSaveThreshold: 30,
|
|
168
|
+
// autoSaveInterval: 4000,
|
|
169
|
+
// adaptiveBatchSize: true,
|
|
170
|
+
// minBatchSize: 10,
|
|
171
|
+
// maxBatchSize: 200
|
|
172
|
+
// }
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
##### validateIntegrity(options)
|
|
176
|
+
Validates database integrity.
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
const integrity = await db.validateIntegrity({ verbose: true })
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
##### getStats()
|
|
183
|
+
Gets comprehensive database statistics.
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
const stats = await db.getStats()
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
##### readColumnIndex(column)
|
|
190
|
+
Gets unique values from a specific column (indexed columns only).
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const categories = db.readColumnIndex('category')
|
|
194
|
+
// Returns: Set(['Electronics', 'Books', 'Clothing'])
|
|
195
|
+
// Throws error for non-indexed columns
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
##### close()
|
|
199
|
+
Closes the database instance and saves pending changes.
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
await db.close()
|
|
203
|
+
// Saves data and closes instance, but keeps the database file
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
##### destroy()
|
|
207
|
+
Closes the database instance and saves pending changes (equivalent to close()).
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
await db.destroy()
|
|
211
|
+
// Same as: await db.close()
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
##### deleteDatabase()
|
|
215
|
+
**⚠️ WARNING: This permanently deletes the database file!**
|
|
216
|
+
|
|
217
|
+
Deletes the database file from disk and closes the instance.
|
|
218
|
+
|
|
219
|
+
```javascript
|
|
220
|
+
await db.deleteDatabase() // Deletes the database file permanently
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
##### removeDatabase()
|
|
224
|
+
Removes the database file from disk (alias for deleteDatabase).
|
|
225
|
+
|
|
226
|
+
```javascript
|
|
227
|
+
await db.removeDatabase() // Same as: await db.deleteDatabase()
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### Properties
|
|
231
|
+
|
|
232
|
+
- `length`: Number of records in the database
|
|
233
|
+
- `indexStats`: Statistics about database indexes
|
|
234
|
+
|
|
235
|
+
#### Events
|
|
236
|
+
|
|
237
|
+
- `init`: Emitted when database is initialized
|
|
238
|
+
- `insert`: Emitted when a record is inserted
|
|
239
|
+
- `update`: Emitted when records are updated
|
|
240
|
+
- `delete`: Emitted when records are deleted
|
|
241
|
+
- `save`: Emitted when database is saved
|
|
242
|
+
- `before-save`: Emitted before database is saved
|
|
243
|
+
|
|
244
|
+
**Auto-Save Events:**
|
|
245
|
+
- `buffer-flush`: Emitted when buffer is flushed (count parameter)
|
|
246
|
+
- `buffer-full`: Emitted when buffer reaches threshold
|
|
247
|
+
- `auto-save-timer`: Emitted when time-based auto-save triggers
|
|
248
|
+
- `save-complete`: Emitted when save operation completes
|
|
249
|
+
- `close-save-complete`: Emitted when database closes with final save
|
|
250
|
+
- `close`: Emitted when database is closed
|
|
251
|
+
- `performance-configured`: Emitted when performance settings are changed
|
|
252
|
+
|
|
253
|
+
### Query Operators
|
|
254
|
+
|
|
255
|
+
The database supports MongoDB-style query operators:
|
|
256
|
+
|
|
257
|
+
- `$eq`: Equal to
|
|
258
|
+
- `$ne`: Not equal to
|
|
259
|
+
- `$gt`: Greater than
|
|
260
|
+
- `$gte`: Greater than or equal to
|
|
261
|
+
- `$lt`: Less than
|
|
262
|
+
- `$lte`: Less than or equal to
|
|
263
|
+
- `$in`: In array
|
|
264
|
+
- `$nin`: Not in array
|
|
265
|
+
- `$regex`: Regular expression match
|
|
266
|
+
|
|
267
|
+
### Nested Field Queries
|
|
268
|
+
|
|
269
|
+
You can query nested fields using dot notation:
|
|
270
|
+
|
|
271
|
+
```javascript
|
|
272
|
+
const results = await db.find({
|
|
273
|
+
'metadata.preferences.theme': 'dark',
|
|
274
|
+
'metadata.loginCount': { $gt: 10 }
|
|
275
|
+
})
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Query Options
|
|
279
|
+
|
|
280
|
+
- `limit`: Limit number of results
|
|
281
|
+
- `skip`: Skip number of results
|
|
282
|
+
- `sort`: Sort results by field
|
|
283
|
+
- `caseInsensitive`: Case-insensitive string matching
|
|
284
|
+
|
|
285
|
+
## Auto-Save Intelligence
|
|
286
|
+
|
|
287
|
+
JexiDB features intelligent auto-save capabilities that automatically manage data persistence without manual intervention.
|
|
288
|
+
|
|
289
|
+
### Auto-Save Modes
|
|
290
|
+
|
|
291
|
+
**Intelligent Auto-Save (Default):**
|
|
292
|
+
- Automatically flushes buffer when it reaches the threshold (default: 50 records)
|
|
293
|
+
- Automatically flushes buffer every N milliseconds (default: 5000ms)
|
|
294
|
+
- Always saves when closing the database
|
|
295
|
+
- Provides real-time feedback through events
|
|
296
|
+
|
|
297
|
+
**Manual Mode:**
|
|
298
|
+
- Disable auto-save with `autoSave: false`
|
|
299
|
+
- Manually call `flush()` and `save()` when needed
|
|
300
|
+
- Useful for applications requiring precise control over persistence timing
|
|
301
|
+
|
|
302
|
+
### Auto-Save Configuration
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
const db = new Database('data.jdb', {
|
|
306
|
+
// Enable intelligent auto-save
|
|
307
|
+
autoSave: true,
|
|
308
|
+
autoSaveThreshold: 50, // Flush every 50 records
|
|
309
|
+
autoSaveInterval: 5000, // Flush every 5 seconds
|
|
310
|
+
forceSaveOnClose: true, // Always save on close
|
|
311
|
+
|
|
312
|
+
// Performance tuning
|
|
313
|
+
batchSize: 50, // Reduced for faster response
|
|
314
|
+
adaptiveBatchSize: true, // Adjust based on usage
|
|
315
|
+
minBatchSize: 10, // Minimum flush size
|
|
316
|
+
maxBatchSize: 200 // Maximum flush size
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Event-Driven Monitoring
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
// Monitor auto-save operations
|
|
324
|
+
db.on('buffer-flush', (count) => {
|
|
325
|
+
console.log(`Flushed ${count} records`);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
db.on('buffer-full', () => {
|
|
329
|
+
console.log('Buffer reached threshold');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
db.on('auto-save-timer', () => {
|
|
333
|
+
console.log('Time-based auto-save triggered');
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
db.on('save-complete', () => {
|
|
337
|
+
console.log('Database saved successfully');
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Buffer Status Monitoring
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
// Check buffer status anytime
|
|
345
|
+
const status = db.getBufferStatus();
|
|
346
|
+
console.log(`Pending: ${status.pendingCount}/${status.bufferSize}`);
|
|
347
|
+
console.log(`Should flush: ${status.shouldFlush}`);
|
|
348
|
+
console.log(`Auto-save enabled: ${status.autoSaveEnabled}`);
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
## Optimization Features
|
|
352
|
+
|
|
353
|
+
### Adaptive Mode Switching
|
|
354
|
+
|
|
355
|
+
JexiDB automatically switches between insertion and query optimization modes based on usage patterns.
|
|
356
|
+
|
|
357
|
+
### Real Compression
|
|
358
|
+
|
|
359
|
+
- **LZ4**: Fast compression for warm data
|
|
360
|
+
- **Gzip**: High compression for cold data
|
|
361
|
+
- **Automatic fallback**: Graceful degradation if compression fails
|
|
362
|
+
|
|
363
|
+
### Intelligent Caching
|
|
364
|
+
|
|
365
|
+
- **Query result caching**: Caches frequently accessed query results
|
|
366
|
+
- **Index caching**: Caches index data for faster lookups
|
|
367
|
+
- **Adaptive eviction**: Automatically manages cache size
|
|
368
|
+
|
|
369
|
+
### Background Maintenance
|
|
370
|
+
|
|
371
|
+
- **Automatic compression**: Compresses old data in the background
|
|
372
|
+
- **Index optimization**: Optimizes indexes during idle time
|
|
373
|
+
- **Integrity checks**: Performs periodic integrity validation
|
|
374
|
+
|
|
375
|
+
## Error Handling
|
|
376
|
+
|
|
377
|
+
Comprehensive error handling with automatic recovery:
|
|
378
|
+
|
|
379
|
+
- **File corruption recovery**: Repairs corrupted files
|
|
380
|
+
- **Index rebuilding**: Automatically rebuilds corrupted indexes
|
|
381
|
+
- **Memory pressure management**: Handles memory pressure gracefully
|
|
382
|
+
- **Compression fallback**: Falls back to no compression if needed
|
|
383
|
+
|
|
384
|
+
## Performance Characteristics
|
|
385
|
+
|
|
386
|
+
- **Insert**: ~10,000 ops/sec (bulk), ~1,000 ops/sec (single)
|
|
387
|
+
- **Query**: ~5,000 ops/sec (indexed), ~500 ops/sec (unindexed)
|
|
388
|
+
- **Update**: ~1,000 ops/sec
|
|
389
|
+
- **Delete**: ~1,000 ops/sec
|
|
390
|
+
- **Compression**: 20-80% size reduction depending on data type
|
package/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Database Usage Examples
|
|
2
|
+
|
|
3
|
+
## Basic Usage
|
|
4
|
+
|
|
5
|
+
### Simple Database
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
const Database = require('jexidb');
|
|
9
|
+
|
|
10
|
+
// Create database
|
|
11
|
+
const db = new Database('./data/users.jsonl');
|
|
12
|
+
|
|
13
|
+
// Initialize
|
|
14
|
+
await db.init();
|
|
15
|
+
|
|
16
|
+
// Insert data
|
|
17
|
+
await db.insert({ id: '1', name: 'John', age: 30 });
|
|
18
|
+
await db.insert({ id: '2', name: 'Jane', age: 25 });
|
|
19
|
+
|
|
20
|
+
// Find data
|
|
21
|
+
const users = await db.find({ age: { $gte: 25 } });
|
|
22
|
+
const user = await db.findOne({ id: '1' });
|
|
23
|
+
|
|
24
|
+
// Update data
|
|
25
|
+
await db.update({ id: '1' }, { age: 31 });
|
|
26
|
+
|
|
27
|
+
// Delete data
|
|
28
|
+
await db.delete({ id: '2' });
|
|
29
|
+
|
|
30
|
+
// Save changes
|
|
31
|
+
await db.save();
|
|
32
|
+
|
|
33
|
+
// Clean up
|
|
34
|
+
await db.destroy();
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### With Indexes
|
|
38
|
+
|
|
39
|
+
```javascript
|
|
40
|
+
const db = new Database('./data/products.jsonl', {
|
|
41
|
+
indexes: {
|
|
42
|
+
id: true,
|
|
43
|
+
category: true,
|
|
44
|
+
price: true
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
await db.init();
|
|
49
|
+
|
|
50
|
+
// Fast indexed queries
|
|
51
|
+
const expensiveProducts = await db.find({ price: { $gt: 100 } });
|
|
52
|
+
const electronics = await db.find({ category: 'electronics' });
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Complex Queries
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// Nested field queries
|
|
59
|
+
const activeUsers = await db.find({
|
|
60
|
+
'metadata.active': true,
|
|
61
|
+
'preferences.theme': 'dark',
|
|
62
|
+
age: { $gte: 18, $lte: 65 }
|
|
63
|
+
}, {
|
|
64
|
+
limit: 50,
|
|
65
|
+
sort: { 'metadata.lastLogin': -1 }
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// Array queries
|
|
69
|
+
const taggedPosts = await db.find({
|
|
70
|
+
tags: { $in: ['javascript', 'database'] }
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Regular expressions
|
|
74
|
+
const emailUsers = await db.find({
|
|
75
|
+
email: { $regex: /@gmail\.com$/ }
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Bulk Operations
|
|
80
|
+
|
|
81
|
+
```javascript
|
|
82
|
+
// Bulk insert
|
|
83
|
+
const users = Array.from({ length: 1000 }, (_, i) => ({
|
|
84
|
+
id: `user_${i}`,
|
|
85
|
+
name: `User ${i}`,
|
|
86
|
+
email: `user${i}@example.com`,
|
|
87
|
+
age: Math.floor(Math.random() * 50) + 18
|
|
88
|
+
}));
|
|
89
|
+
|
|
90
|
+
await db.insertMany(users);
|
|
91
|
+
|
|
92
|
+
// Bulk update
|
|
93
|
+
await db.update(
|
|
94
|
+
{ age: { $lt: 18 } },
|
|
95
|
+
{ status: 'minor' }
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// Bulk delete
|
|
99
|
+
await db.delete({ status: 'inactive' });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Event Handling
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
db.on('insert', (record, index) => {
|
|
106
|
+
console.log(`Inserted record at index ${index}`);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
db.on('update', (records) => {
|
|
110
|
+
console.log(`Updated ${records.length} records`);
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
db.on('delete', (records) => {
|
|
114
|
+
console.log(`Deleted ${records.length} records`);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
db.on('save', () => {
|
|
118
|
+
console.log('Database saved');
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Error Handling
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
try {
|
|
126
|
+
await db.insert(invalidData);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error.name === 'JexiDBError[JSON_PARSE_ERROR]') {
|
|
129
|
+
console.log('Invalid JSON data');
|
|
130
|
+
} else if (error.name === 'JexiDBError[FILE_CORRUPTION]') {
|
|
131
|
+
console.log('File corruption detected, attempting recovery...');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Performance Monitoring
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
// Get database statistics
|
|
140
|
+
const stats = await db.getStats();
|
|
141
|
+
console.log(`Records: ${stats.recordCount}`);
|
|
142
|
+
console.log(`File size: ${stats.fileSize} bytes`);
|
|
143
|
+
console.log(`Cache hit rate: ${stats.cacheStats.hitRate}%`);
|
|
144
|
+
|
|
145
|
+
// Get optimization recommendations
|
|
146
|
+
const recommendations = db.getOptimizationRecommendations();
|
|
147
|
+
console.log('Optimization tips:', recommendations);
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Advanced Configuration
|
|
151
|
+
|
|
152
|
+
```javascript
|
|
153
|
+
const db = new Database('./data/advanced.jsonl', {
|
|
154
|
+
indexes: {
|
|
155
|
+
id: true,
|
|
156
|
+
email: true,
|
|
157
|
+
'metadata.created': true
|
|
158
|
+
},
|
|
159
|
+
markDeleted: false, // Physical deletion
|
|
160
|
+
autoSave: true,
|
|
161
|
+
validateOnInit: true,
|
|
162
|
+
backgroundMaintenance: true,
|
|
163
|
+
cache: {
|
|
164
|
+
maxSize: 1000,
|
|
165
|
+
ttl: 300000 // 5 minutes
|
|
166
|
+
},
|
|
167
|
+
compression: {
|
|
168
|
+
hot: { type: 'none', threshold: 7 },
|
|
169
|
+
warm: { type: 'lz4', threshold: 30 },
|
|
170
|
+
cold: { type: 'gzip', threshold: Infinity }
|
|
171
|
+
},
|
|
172
|
+
errorHandler: {
|
|
173
|
+
logLevel: 'info',
|
|
174
|
+
enableRecovery: true
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
```
|