
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Modern, feature-rich JSON database module for Node.js with encryption, compression, transactions, and more
Modern, feature-rich and secure JSON database module for Node.js.
user.settings.theme)npm install datara
or
yarn add datara
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();
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 }
}
});
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 }
// 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');
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
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'
// 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();
// 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 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');
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
// 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-15T10-30-00-000Z', ...]
// Restore from backup
db.restore(backupPath);
// 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', () => {});
// 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
// Enable gzip compression
const db = new Datara('./compressed.json', {
compression: true
});
// Data is automatically compressed/decompressed
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
// 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 set
await db.setAsync('key', 'value');
// Async get
const value = await db.getAsync('key');
// Async save
await db.saveAsync();
// 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();
// ES Modules
import Datara from 'datara';
// Or import specific classes
import { Datara, DataraError, ValidationError } from 'datara';
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');
}
}
| 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 |
MIT © devraikou
Contributions, issues and feature requests are welcome!
Give a ⭐️ if this project helped you!
FAQs
Modern, feature-rich JSON database module for Node.js with encryption, compression, transactions, and more
The npm package datara receives a total of 3 weekly downloads. As such, datara popularity was classified as not popular.
We found that datara demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.