Documentation

Complete reference for `json-database-st`.
Everything you need to store data safely in Node.js.

Installation

npm install json-database-st lodash proper-lockfile

Initialization

const JSONDatabase = require('json-database-st');
const path = require('path');

const db = new JSONDatabase(path.join(__dirname, 'db.json'), {
    // Optional Configuration
    encryptionKey: process.env.KEY, // 32-byte hex string
    prettyPrint: true,              // Format JSON for readability
    saveDelay: 50,                  // Debounce writes (ms)
    indices: [                      // Speed up lookups
        { name: 'email', path: 'users', field: 'email' }
    ]
});

Basic Operations

set(path, value)

Writes data to the path. Creates nested objects if they don't exist.

await db.set('app.name', 'My App');
await db.set('users.1', { name: 'John', age: 25 });

get(path, defaultValue)

Retrieves data. Returns `defaultValue` if the path is missing.

const name = await db.get('users.1.name');
const role = await db.get('users.1.role', 'guest'); // default to guest

has(path)

Checks if a key exists in the database.

if (await db.has('users.1')) {
    console.log('User exists!');
}

Deletion

delete(path)

Removes a key or object from the database permanently.

// Remove a specific field
await db.delete('users.1.age');

// Remove an entire object
await db.delete('users.1');

Array Methods

push(path, ...items)

Adds items to an array. Deeply checks for duplicates before adding.

await db.push('admins', 'user1', 'user2');
// Won't add 'user1' again if it exists

pull(path, ...items)

Removes items from an array using deep comparison.

await db.pull('admins', 'user2');

Atomic Math

Atomic calculations. Safer than read-modify-write loops.

await db.set('visits', 100);

// Atomic Increment
await db.add('visits', 1);

// Atomic Decrement
await db.subtract('visits', 10);

Find (Scan)

find(path, predicate)

Scans an array or object to find a matching element. Uses Lodash syntax.

// Find user where age is 25
const user = await db.find('users', { age: 25 });

// Find using a function
const active = await db.find('users', u => u.isActive === true);

Find By Index (O1)

For large datasets, use this instead of `find`. It uses a Hash Map for instant results.

// 1. Setup
const db = new JSONDatabase('db.json', {
    indices: [{ name: 'user_email', path: 'users', field: 'email' }]
});

// 2. Fast Lookup
const user = await db.findByIndex('user_email', 'john@example.com');

Pagination v2

Retrieve data in chunks. Essential for large lists or API endpoints.

// Fetch Page 1 (10 items per page)
const result = await db.paginate('users', 1, 10);

console.log(result.data); // Array of users
console.log(result.meta); 
/* 
{ 
  total: 50, 
  page: 1, 
  limit: 10, 
  totalPages: 5, 
  hasNext: true 
} 
*/

Middleware Hooks

Intercept operations. Supported hooks: `before`, `after`. Supported methods: `set`, `delete`, `push`, `pull`.

// Add timestamp before saving any user
db.before('set', 'users.*', (context) => {
    context.value.updatedAt = Date.now();
    return context; // Must return context
});

Schema Validation

const { z } = require('zod');

const db = new JSONDatabase('db.json', { 
    schema: z.object({
        // your zod schema here
    }) 
});

Events

The database extends NodeJS EventEmitter.

db.on('ready', () => console.log('Database loaded!'));

db.on('change', (data) => {
    console.log('Data changed:', data);
});

db.on('write', () => console.log('Data saved to disk.'));

Backups (Snapshots)

Create a manual copy of the database file instantly.

const path = await db.createSnapshot('daily-backup');
console.log(`Backup saved to: ${path}`);