Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

devRaikou/datara

Repository files navigation

πŸ—„οΈ Datara v2.0

Modern, feature-rich and secure JSON database module for Node.js.

License: MIT Node.js Version

✨ Features

Core Features

  • πŸš€ Simple & User-Friendly: Minimalist API for quick start
  • πŸ’Ύ Auto Save: Automatically saves on every operation (configurable)
  • πŸ”— Dot Notation: Easy access to nested objects (user.settings.theme)
  • πŸ“ TypeScript Support: Full TypeScript definitions included
  • 🎯 Zero Dependencies: No external dependencies required
  • ⚑ Lightweight: Minimal file size

New in v2.0

  • πŸ” AES-256 Encryption: Secure your database with password encryption
  • πŸ“¦ Gzip Compression: Reduce file size with compression
  • πŸ’Ό Transactions: Begin, commit, and rollback operations
  • πŸ” Query Builder: SQL-like queries on arrays
  • πŸ“ Collection API: MongoDB-like document collections
  • ⏰ TTL Support: Auto-expiring keys
  • πŸ‘€ Watch/Observe: Listen to data changes
  • πŸ“‘ Event Emitter: React to database events
  • βœ… Schema Validation: Validate data before saving
  • πŸ’Ύ Backup/Restore: Automatic backups with restore capability
  • πŸ”Œ Plugin System: Extend functionality with plugins
  • ⚑ Async/Await: Promise-based async operations
  • πŸ“¦ ESM Support: ES Modules support

πŸ“¦ Installation

npm install datara

or

yarn add datara

πŸš€ Quick Start

const Datara = require('datara');
// Create a database
const db = new Datara('./mydb.json');
// Save data
db.set('name', 'Datara');
db.set('version', '2.0.0');
// Read data
console.log(db.get('name')); // 'Datara'
// Nested objects
db.set('user.name', 'devraikou');
db.set('user.settings.theme', 'dark');
console.log(db.get('user')); // { name: 'devraikou', settings: { theme: 'dark' }}
// Clean up when done
db.close();

πŸ“– Documentation

Initialization

const Datara = require('datara');
// Basic usage
const db = new Datara('./database.json');
// With options
const db = new Datara('./database.json', {
 autoSave: true, // Auto-save on every operation (default: true)
 pretty: true, // Pretty print JSON (default: true)
 indentSize: 2, // Indentation size (default: 2)
 encryption: 'secret', // Encryption password (default: null)
 compression: true, // Enable gzip compression (default: false)
 backupInterval: 3600000, // Auto-backup interval in ms (default: null)
 maxBackups: 5, // Max backup files to keep (default: 5)
 timestamps: true, // Add timestamps to objects (default: false)
 schema: { // Schema validation rules (default: null)
 username: { type: 'string', required: true }
 }
});

Basic Operations

set(key, value)

Save data to the database.

db.set('username', 'devraikou');
db.set('score', 100);
db.set('active', true);
// Nested objects with dot notation
db.set('user.profile.name', 'Ali');
db.set('settings.theme.color', 'dark');

get(key, defaultValue)

Read data from the database.

const username = db.get('username'); // 'devraikou'
const score = db.get('score'); // 100
// With default value
const lang = db.get('language', 'en'); // 'en' (if not exists)
// Get all data
const allData = db.get(); // Entire database

has(key)

Check if a key exists.

db.has('username'); // true
db.has('nonexistent'); // false

delete(key)

Delete a key.

db.delete('username'); // true
db.delete('nonexistent'); // false

update(key, callback)

Update a value using a callback function.

db.set('counter', 10);
db.update('counter', val => val * 2); // 20

rename(oldKey, newKey)

Rename a key.

db.set('oldName', 'value');
db.rename('oldName', 'newName');

clone(sourceKey, destKey)

Clone a value to a new key.

db.set('original', { data: 'test' });
db.clone('original', 'copy');

type(key)

Get the type of a value.

db.type('name'); // 'string'
db.type('count'); // 'number'
db.type('items'); // 'array'
db.type('user'); // 'object'
db.type('missing'); // 'undefined'

merge(key, data)

Deep merge data into an existing object.

db.set('config', { a: 1, b: 2 });
db.merge('config', { b: 3, c: 4 });
// Result: { a: 1, b: 3, c: 4 }

Array Operations

// Initialize array
db.set('items', []);
// Push - Add to end
db.push('items', 'first');
db.push('items', 'second');
// Pop - Remove from end
db.pop('items'); // Returns 'second'
// Shift - Remove from start
db.shift('items'); // Returns 'first'
// Unshift - Add to start
db.unshift('items', 'new first');
// Splice - Remove/replace elements
db.splice('items', 1, 2, 'replacement');
// Filter
const evens = db.filter('numbers', n => n % 2 === 0);
// Find
const user = db.find('users', u => u.id === 1);
// FindIndex
const index = db.findIndex('users', u => u.id === 1);
// Map
const names = db.map('users', u => u.name);
// Some - At least one matches
db.some('numbers', n => n > 10); // true/false
// Every - All match
db.every('numbers', n => n > 0); // true/false
// Reduce
const sum = db.reduce('numbers', (acc, n) => acc + n, 0);
// IndexOf
db.indexOf('items', 'value'); // Returns index or -1
// Includes
db.includes('items', 'value'); // true/false
// Sort
db.sort('numbers'); // Ascending
db.sort('numbers', (a, b) => b - a); // Descending
// Reverse
db.reverse('items');
// Flat - Flatten nested arrays
db.flat('nested', 2); // depth = 2
// Unique - Remove duplicates
db.unique('items');
// Pull - Remove specific value
db.pull('items', 'value');

Math Operations

db.set('score', 100);
// Increment/Decrement
db.increment('score'); // 101
db.increment('score', 5); // 106
db.decrement('score', 3); // 103
// Add/Subtract
db.add('score', 50); // 153
db.subtract('score', 30); // 123
// Multiply/Divide
db.multiply('score', 2); // 246
db.divide('score', 3); // 82
// Modulo
db.modulo('score', 10); // 2
// Power
db.power('score', 2); // 4
// Custom math operation
db.math('score', n => Math.sqrt(n)); // 2

Query Builder

db.set('users', [
 { name: 'Alice', age: 25, active: true },
 { name: 'Bob', age: 30, active: false },
 { name: 'Charlie', age: 35, active: true }
]);
// Simple query
const results = db.query('users')
 .where('age', '>', 25)
 .where('active', '==', true)
 .get();
// With ordering and limit
const top2 = db.query('users')
 .orderBy('age', 'desc')
 .limit(2)
 .get();
// Skip for pagination
const page2 = db.query('users')
 .skip(10)
 .limit(10)
 .get();
// Get first result
const first = db.query('users')
 .where('active', '==', true)
 .first();
// Count results
const count = db.query('users')
 .where('age', '>=', 30)
 .count();
// Available operators:
// '==' | '===' | '!=' | '!==' | '>' | '>=' | '<' | '<='
// 'includes' | 'startsWith' | 'endsWith' | 'in' | 'notIn' | 'regex'

Collection API (MongoDB-like)

// Get or create a collection
const users = db.collection('users');
// Insert documents
const user = users.insert({ name: 'John', email: 'john@test.com' });
// Returns: { _id: 'uuid', name: 'John', email: '...', _createdAt: '...', _updatedAt: '...' }
// Insert many
users.insertMany([
 { name: 'Alice', age: 25 },
 { name: 'Bob', age: 30 }
]);
// Find by ID
const found = users.findById('uuid');
// Find one by query
const alice = users.findOne({ name: 'Alice' });
// Find many with query operators
const adults = users.findMany({ age: { $gte: 18 } });
// Available operators:
// $eq, $ne, $gt, $gte, $lt, $lte, $in, $nin, $regex, $exists
// Update by ID
users.updateById('uuid', { age: 26 });
// Update one by query
users.updateOne({ name: 'Alice' }, { age: 27 });
// Update many
users.updateMany({ active: false }, { status: 'inactive' });
// Delete by ID
users.deleteById('uuid');
// Delete one by query
users.deleteOne({ name: 'Bob' });
// Delete many
const deletedCount = users.deleteMany({ active: false });
// Count
const count = users.count({ active: true });
// Drop collection
users.drop();

TTL (Time-To-Live)

// Set with TTL (expires in 5 seconds)
db.setWithTTL('session', { userId: 123 }, 5000);
// Check remaining TTL
const ttl = db.getTTL('session'); // milliseconds or null
// Make persistent (remove TTL)
db.persist('session');
// Listen to expiration
db.on('expire', (key) => {
 console.log(`Key "${key}" expired`);
});

Watch/Observer

// Watch for changes
const unwatch = db.watch('user.settings', (newValue, oldValue, key) => {
 console.log(`${key} changed from`, oldValue, 'to', newValue);
});
// Make changes
db.set('user.settings.theme', 'dark'); // Triggers watcher
// Stop watching
unwatch();
// Or unwatch all callbacks for a key
db.unwatch('user.settings');

Transactions

db.set('balance', 100);
// Begin transaction
db.beginTransaction();
try {
 db.set('balance', db.get('balance') - 50);
 db.set('transferred', 50);
 
 // Commit changes
 db.commit();
} catch (error) {
 // Rollback on error
 db.rollback();
}
// Check transaction state
db.inTransaction(); // true/false

Backup/Restore

// Create backup
const backupPath = db.backup();
// Or with custom path
const backupPath = db.backup('./backups/mydb-backup.json');
// List available backups
const backups = db.listBackups();
// ['./mydb.json.backup-2024εΉ΄01月15ζ—₯T10-30-00-000Z', ...]
// Restore from backup
db.restore(backupPath);

Events

// Available events
db.on('set', (key, value, oldValue) => {});
db.on('delete', (key, oldValue) => {});
db.on('clear', (oldData) => {});
db.on('save', (data) => {});
db.on('reload', (data) => {});
db.on('import', (data, merge) => {});
db.on('expire', (key) => {});
db.on('backup', (path) => {});
db.on('restore', (path) => {});
db.on('close', () => {});
db.on('transactionBegin', () => {});
db.on('transactionCommit', () => {});
db.on('transactionRollback', () => {});

Encryption

// Create encrypted database
const db = new Datara('./secure.json', {
 encryption: 'my-secret-password'
});
// Data is automatically encrypted on save
db.set('secret', 'classified information');
// And decrypted on load
console.log(db.get('secret')); // 'classified information'
// File content is encrypted with AES-256-GCM

Compression

// Enable gzip compression
const db = new Datara('./compressed.json', {
 compression: true
});
// Data is automatically compressed/decompressed

Schema Validation

const db = new Datara('./validated.json', {
 schema: {
 username: {
 type: 'string',
 required: true,
 minLength: 3,
 maxLength: 20
 },
 age: {
 type: 'number',
 min: 0,
 max: 150
 },
 email: {
 type: 'string',
 pattern: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
 },
 role: {
 type: 'string',
 enum: ['admin', 'user', 'guest']
 },
 score: {
 type: 'number',
 custom: (value) => value >= 0 || 'Score must be positive'
 }
 }
});
// Valid data
db.set('username', 'john'); // OK
db.set('age', 25); // OK
// Invalid data throws ValidationError
db.set('username', 'ab'); // Error: minLength
db.set('age', 200); // Error: max

Plugin System

// Create a plugin
const timestampPlugin = {
 install(datara) {
 // Add new methods
 datara.setWithTimestamp = function(key, value) {
 return this.set(key, {
 value,
 createdAt: new Date().toISOString()
 });
 };
 }
};
// Use the plugin
db.use(timestampPlugin);
// Use new methods
db.setWithTimestamp('item', 'data');
// { value: 'data', createdAt: '2024-01-15T10:30:00.000Z' }

Async Operations

// Async set
await db.setAsync('key', 'value');
// Async get
const value = await db.getAsync('key');
// Async save
await db.saveAsync();

Utility Methods

// Get all keys
db.keys(); // ['key1', 'key2', ...]
db.keys('user'); // Keys starting with 'user'
// Get all values
db.values(); // [value1, value2, ...]
// Get all entries
db.entries(); // [['key1', value1], ['key2', value2], ...]
// Iterate
db.forEach((value, key) => {
 console.log(key, value);
});
// Size
db.size(); // Number of top-level keys
// Count array items
db.count('items'); // Array length
db.count('items', item => item.active); // Count with filter
// Clear all data
db.clear();
// Export database
const data = db.export();
// Import data
db.import(data);
db.import(data, true); // Merge with existing
// Reload from file
db.reload();
// Close database (cleanup)
db.close();

ESM Support

// ES Modules
import Datara from 'datara';
// Or import specific classes
import { Datara, DataraError, ValidationError } from 'datara';

Error Classes

const { 
 DataraError, 
 ValidationError, 
 EncryptionError, 
 TransactionError 
} = require('datara');
try {
 db.set('invalid', value);
} catch (error) {
 if (error instanceof ValidationError) {
 console.log('Validation failed:', error.key, error.value);
 } else if (error instanceof EncryptionError) {
 console.log('Encryption failed');
 }
}

πŸ”§ Configuration Options

Option Type Default Description
autoSave boolean true Automatically save after each operation
pretty boolean true Pretty print JSON with indentation
indentSize number 2 Indentation size for pretty print
encryption string null Password for AES-256-GCM encryption
compression boolean false Enable gzip compression
backupInterval number null Auto-backup interval in milliseconds
maxBackups number 5 Maximum backup files to keep
timestamps boolean false Add _createdAt/_updatedAt to objects
schema object null Schema validation rules

πŸ“„ License

MIT Β© devraikou

🀝 Contributing

Contributions, issues and feature requests are welcome!

⭐ Show your support

Give a ⭐️ if this project helped you!

About

Modern, feature-rich JSON database module for Node.js with encryption, compression, transactions, MongoDB-like collections, query builder, TTL, events, schema validation, and plugin system.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

Contributors

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /