Package Exports
- @sinkingsheep/jsondb
- @sinkingsheep/jsondb/dist/JsonDB.js
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@sinkingsheep/jsondb) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
JsonDB
A powerful, MongoDB-like JSON database for Node.js with TypeScript support. JsonDB provides rich querying capabilities, transactions, indexing, and more, while maintaining data in simple JSON files.
Features
- 💪 Strong TypeScript support
- 🔍 Rich query API (MongoDB-like operators)
- 📑 Multiple collection support
- 🔄 Transaction support with rollback
- 📇 Indexing with unique and sparse options
- 🔗 Collection joins
- ✅ Schema validation
- 💾 Automatic saving
- 🎯 Event system
- ⛓️ Chain syntax for queries
Installation
npm install @sinkingsheep/jsondb
# or
yarn add @sinkingsheep/jsondbQuick Start
import JsonDB from '@sinkingsheep/jsondb';
interface User {
id?: string;
name: string;
age: number;
email: string;
}
async function main() {
// Initialize database
const db = new JsonDB({
directory: './data',
autoSave: true,
saveInterval: 1000
});
await db.init();
// Insert a document
const user = await db.insert<User>('users', {
name: 'John Doe',
age: 30,
email: 'john@example.com'
});
// Query documents
const users = await db.find('users', {
age: { $gt: 25 }
});
// Close database
await db.close();
}Database Operations
Initialization
interface DBOptions {
directory: string;
autoSave?: boolean;
saveInterval?: number;
prettyPrint?: boolean;
}
const db = new JsonDB({
directory: './data',
autoSave: true,
saveInterval: 1000,
prettyPrint: true
});
await db.init();Basic CRUD Operations
Insert
// Single insert
const user = await db.insert<User>('users', {
name: 'John',
age: 30
});
// Bulk insert
const users = await db.insertMany<User>('users', [
{ name: 'Alice', age: 25 },
{ name: 'Bob', age: 30 }
]);Find
// Find all matching documents
const users = await db.find('users', {
age: { $gt: 25 }
});
// Find one document
const user = await db.findOne('users', {
name: 'John'
});
// Chain syntax
const results = await db
.chain('users')
.where({ status: 'active' })
.sort({ age: -1 })
.limit(10)
.find();Update
// Update multiple documents
const updateCount = await db.update('users',
{ status: 'inactive' },
{ status: 'active' }
);
// Update single document
const updated = await db.updateOne('users',
{ id: 'user123' },
{ status: 'active' }
);Delete
const deleteCount = await db.delete('users', {
status: 'inactive'
});Query Operators
Comparison Operators
// Equal to
{ age: { $eq: 30 } }
// Greater than
{ age: { $gt: 25 } }
// Less than or equal to
{ age: { $lte: 40 } }
// In array
{ status: { $in: ['active', 'pending'] } }
// Not in array
{ status: { $nin: ['deleted', 'banned'] } }Logical Operators
// AND
{
$and: [
{ status: 'active' },
{ age: { $gt: 25 } }
]
}
// OR
{
$or: [
{ status: 'admin' },
{ role: 'moderator' }
]
}
// NOT
{
status: { $not: { $eq: 'inactive' } }
}Array Operators
// Array contains all elements
{ scores: { $all: [80, 85] } }
// Array size
{ scores: { $size: 3 } }
// Element match
{ scores: { $elemMatch: { $gte: 90 } } }Indexing
// Create unique index
await db.createIndex('users', 'email', { unique: true });
// Create sparse index
await db.createIndex('users', 'optional_field', { sparse: true });Transactions
// Begin transaction
const transactionId = await db.beginTransaction();
try {
await db.insert('accounts', { id: '1', balance: 100 });
await db.update('accounts', { id: '1' }, { balance: 50 });
await db.commitTransaction(transactionId);
} catch (error) {
await db.rollbackTransaction(transactionId);
throw error;
}Joins
const results = await db.findWithJoin('orders',
{ status: 'pending' },
{
joins: [{
collection: 'users',
localField: 'userId',
foreignField: 'id',
as: 'user'
}]
}
);Schema Validation
const userSchema = defineSchema({
name: 'string',
age: 'number',
email: 'string'
});
const isValid = validateDocument(userSchema, document);Events
db.on('save', (collectionName) => {
console.log(`Collection ${collectionName} was saved`);
});
db.on('update', (collectionName, document) => {
console.log(`Document updated in ${collectionName}`);
});
db.on('delete', (collectionName, documentId) => {
console.log(`Document ${documentId} deleted from ${collectionName}`);
});Chain Syntax
JsonDB provides a fluent chain syntax for building queries:
const results = await db
.chain('users')
.where({ status: 'active' })
.sort({ age: -1 })
.skip(10)
.limit(5)
.find();
const user = await db
.chain('users')
.where({ age: { $gt: 30 } })
.findOne();Performance Considerations
- Collections are loaded lazily on first access
- Each collection is stored in a separate file
- Indexes improve query performance for indexed fields
- Auto-save interval is configurable
- In-memory caching of loaded collections
Error Handling
try {
await db.insert('users', { email: 'duplicate@email.com' });
} catch (error) {
if (error.message.includes('Unique constraint violation')) {
// Handle unique constraint violation
}
throw error;
}TypeScript Support
JsonDB is written in TypeScript and provides full type support:
interface User {
id?: string;
name: string;
age: number;
email: string;
}
const user = await db.insert<User>('users', {
name: 'John',
age: 30,
email: 'john@example.com'
});Best Practices
Collection Management
- Use separate collections for different types of data
- Consider collection joins for related data
- Drop unused collections to free up resources
Indexing
- Create indexes for frequently queried fields
- Use sparse indexes for optional fields
- Be mindful of index overhead for write operations
Transactions
- Use transactions for operations that need to be atomic
- Always handle transaction errors and rollbacks
- Keep transactions as short as possible
Performance
- Use specific queries instead of loading all documents
- Implement pagination for large result sets
- Configure auto-save interval based on your needs
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT
Credits
Created and maintained by sinkingsheep