npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@sinkingsheep/jsondb

v1.0.7

Published

A lightweight JSON-based database for Node.js

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/jsondb

Quick 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: '[email protected]'
  });

  // 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: '[email protected]' });
} 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: '[email protected]'
});

Best Practices

  1. Collection Management

    • Use separate collections for different types of data
    • Consider collection joins for related data
    • Drop unused collections to free up resources
  2. Indexing

    • Create indexes for frequently queried fields
    • Use sparse indexes for optional fields
    • Be mindful of index overhead for write operations
  3. Transactions

    • Use transactions for operations that need to be atomic
    • Always handle transaction errors and rollbacks
    • Keep transactions as short as possible
  4. 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