1.0.7 • Published 6 months ago

@sinkingsheep/jsondb v1.0.7

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

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: '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

  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

1.0.7

6 months ago

1.0.6

6 months ago

1.0.5

6 months ago

1.0.4

6 months ago

1.0.2

6 months ago

1.0.1

6 months ago

1.0.0

6 months ago