JexiDB is a high-performance, in-memory database with persistence capabilities. It provides advanced indexing, querying, and term mapping features for efficient data operations. Ideal for local Node.js projects as well as apps built with Electron or NW.js. Written in pure JavaScript, it requires no compilation and is compatible with both CommonJS and ESM modules.
Key Features:
- In-memory storage with optional persistence
- Advanced indexing and querying capabilities
- Term mapping for efficient storage and querying
- Bulk update operations with
iterate()method - Manual save functionality (auto-save removed for better control)
- Transaction support with operation queuing
- Recovery mechanisms for data integrity
To install JexiDB, you can use npm:
npm install EdenwareApps/jexidbTo create a new instance of the database, you need to provide a file path where the database will be stored and an optional configuration object for indexes.
// const { Database } = require('jexidb'); // commonjs
import { Database } from 'jexidb'; // ESM
const db = new Database('path/to/database.jdb', {
create: true, // Create file if doesn't exist (default: true)
clear: false, // Clear existing files before loading (default: false)
// REQUIRED - Define your schema structure
fields: {
id: 'number',
name: 'string',
email: 'string',
tags: 'array:string'
},
// OPTIONAL - Performance optimization (only fields you query frequently)
indexes: {
name: 'string', // β
Search by name
tags: 'array:string' // β
Search by tags
}
// termMapping is now auto-enabled for array:string fields
});-
create (boolean, default:
true): Controls whether the database file should be created if it doesn't exist.true: Creates the file if it doesn't exist (default behavior)false: Throws an error if the file doesn't exist
-
clear (boolean, default:
false): Controls whether to clear existing database files before loading.true: Deletes both the main database file (.jdb) and index file (.idx.jdb) if they exist, then starts with a clean databasefalse: Loads existing data from files (default behavior)
You can learn a bit more about these options at this link.
Before using the database, you need to initialize it. This will load the existing data and indexes from the file.
await db.init();Only the values ββspecified as indexes are kept in memory for faster queries. JexiDB will never load the entire file into memory.
You can insert data into the database by using the insert method. The data should be an object that contains the defined indexes. All object values will be saved into database.
await db.insert({ id: 1, name: 'John Doe' });
await db.insert({ id: 2, name: 'Jane Doe', anyArbitraryField: '1' });The query method allows you to retrieve data based on specific criteria. You can specify criteria for multiple fields.
const results = await db.query({ name: 'John Doe' }, { caseInsensitive: true });
console.log(results); // [{ id: 1, name: 'John Doe' }]Note: For now the query should be limited to using the fields specified as 'indexes' when instantiating the class.
You can use conditions to perform more complex queries:
const results = await db.query({ id: { '>': 1 } });
console.log(results); // [{ id: 2, name: 'Jane Doe' }]To update existing records, use the update method with the criteria to find the records and the new data.
await db.update({ id: 1 }, { name: 'John Smith' });You can delete records that match certain criteria using the delete method.
const deletedCount = await db.delete({ name: 'Jane Doe' });
console.log(`Deleted ${deletedCount} record(s).`);You can iterate through records in the database using the walk method, which returns an async generator.
for await (const record of db.walk()) {
console.log(record);
}After making any changes to the database, you need to save them using the save method. This will persist the changes to disk.
await db.save();JexiDB includes a comprehensive test suite built with Jest. To run the tests:
# Run all tests
npm test
# Run tests in watch mode (for development)
npm test:watch
# Run tests with coverage report
npm test:coverage
# Run legacy test suite (original Mortal Kombat themed tests)
npm run test:legacyThe test suite includes:
- Database Tests: Complete CRUD operations, querying, indexing, and persistence
- IndexManager Tests: Index creation, querying with various operators, and data management
- Serializer Tests: JSON serialization/deserialization with various data types
All database operations ensure that the _ property (position index) is always included in returned results.
The iterate() method provides high-performance bulk update capabilities with streaming support:
// Basic bulk update
for await (const entry of db.iterate({ category: 'fruits' })) {
entry.price = entry.price * 1.1 // 10% price increase
entry.lastUpdated = new Date().toISOString()
}
// Advanced options with progress tracking
for await (const entry of db.iterate(
{ status: 'active' },
{
chunkSize: 1000,
progressCallback: (progress) => {
console.log(`Processed: ${progress.processed}, Modified: ${progress.modified}`)
}
}
)) {
entry.processed = true
}Key Benefits:
- Streaming Performance: Process large datasets without loading everything into memory
- Bulk Updates: Modify multiple records in a single operation
- Automatic Change Detection: Automatically detects which records were modified
- Progress Tracking: Optional progress callbacks for long-running operations
Existing .jdb files from version 1.x.x will NOT work with version 2.1.0.
// In your 1.x.x application
const oldDb = new Database('old-database.jdb', {
indexes: { name: 'string', tags: 'array:string' }
})
await oldDb.init()
const allData = await oldDb.find({}) // Export all data
await oldDb.destroy()// β OLD (1.x.x)
const db = new Database('db.jdb', {
indexes: { name: 'string', tags: 'array:string' }
})
// β
NEW (2.1.0)
const db = new Database('db.jdb', {
fields: { // REQUIRED - Define schema
id: 'number',
name: 'string',
tags: 'array:string'
},
indexes: { // OPTIONAL - Performance optimization
name: 'string', // β
Search by name
tags: 'array:string' // β
Search by tags
}
})// In your 2.1.0 application
const newDb = new Database('new-database.jdb', {
fields: { /* your schema */ },
indexes: { /* your indexes */ }
})
await newDb.init()
// Import all data
for (const record of allData) {
await newDb.insert(record)
}
await newDb.save()| Feature | 1.x.x | 2.1.0 |
|---|---|---|
fields |
Optional | MANDATORY |
termMapping |
false (default) |
true (default) |
termMappingFields |
Manual config | Auto-detected |
| Database files | Compatible | NOT compatible |
| Performance | Basic | 77% size reduction |
For comprehensive documentation and examples:
- π Full Documentation - Complete documentation index
- π§ API Reference - Detailed API documentation
- π‘ Examples - Practical examples and use cases
- π Getting Started - Quick start guide
- Bulk Operations - High-performance
iterate()method - Term Mapping - Optimize storage for repetitive data
- Query Operators - Advanced querying capabilities
- Performance Tips - Optimization strategies
JexiDB provides a simple yet powerful way to store and manage data in JavaScript applications. With its indexing and querying features, you can build efficient data-driven applications.
Please, feel free to contribute to the project by opening a discussion under Issues section or sending your PR.
If you find this library useful, please consider making a donation of any amount via PayPal by clicking here to help the developer continue to dedicate himself to the project. β€
