
Research
/Security News
Coruna Respawned: Compromised art-template npm Package Leads to iOS Browser Exploit Kit
Compromised npm package art-template delivered a Coruna-like iOS Safari exploit framework through a watering-hole attack.
A lightweight, zero-dependency JSON database for Node.js with a familiar API. Perfect for small projects, prototyping, or when you need a simple file-based database without the complexity of traditional databases.
npm install jdb-lite
const JsonDB = require('jdb-lite');
const { Schema } = require('jdb-lite');
// Define a schema
const userSchema = new Schema({
name: { type: 'String', required: true },
email: { type: 'String', required: true },
age: { type: 'Number', required: true },
isActive: { type: 'Boolean', default: true }
});
// Connect and create model
async function main() {
await JsonDB.connect('./my-database');
const User = JsonDB.model('User', userSchema);
// Create a user
const user = new User({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
await user.save();
console.log('User saved!', user);
}
main();
import JsonDB, { Schema } from 'jdb-lite';
const userSchema = new Schema({
name: { type: 'String', required: true },
email: { type: 'String', required: true },
age: { type: 'Number', required: true }
});
await JsonDB.connect('./my-database');
const User = JsonDB.model('User', userSchema);
const user = await User.create({
name: 'Jane Doe',
email: 'jane@example.com',
age: 25
});
console.log('User created!', user);
import JsonDB, { Schema, Document } from 'jdb-lite';
// Define interface
interface IUser extends Document {
name: string;
email: string;
age: number;
isActive?: boolean;
}
// Create schema with type safety
const userSchema = new Schema<IUser>({
name: { type: 'String', required: true },
email: { type: 'String', required: true },
age: { type: 'Number', required: true },
isActive: { type: 'Boolean', default: true }
});
await JsonDB.connect('./my-database');
const User = JsonDB.model<IUser>('User', userSchema);
// Type-safe operations
const user: IUser = await User.create({
name: 'Alice Smith',
email: 'alice@example.com',
age: 28
});
// Connect to database (creates folder if doesn't exist)
await JsonDB.connect('./my-database');
// Or specify a different path
await JsonDB.connect('/path/to/database');
// Disconnect when done
await JsonDB.disconnect();
const userSchema = new Schema({
// String field
name: {
type: 'String',
required: true,
default: 'Anonymous'
},
// Number field
age: {
type: 'Number',
required: true,
validate: (value) => value >= 0 // Custom validation
},
// Boolean field
isActive: {
type: 'Boolean',
default: true
},
// Date field
createdAt: {
type: 'Date',
default: Date.now
},
// Array field
tags: {
type: 'Array',
default: []
},
// Object field
settings: {
type: 'Object',
default: {}
}
}, {
timestamps: true, // Adds createdAt and updatedAt automatically
collection: 'users' // Custom collection name (optional)
});
// Method 1: Constructor + save
const user = new User({
name: 'John Doe',
email: 'john@example.com',
age: 30
});
await user.save();
// Method 2: Direct creation
const user = await User.create({
name: 'Jane Doe',
email: 'jane@example.com',
age: 25
});
// Method 3: Create multiple
const users = await User.insertMany([
{ name: 'User 1', email: 'user1@example.com', age: 20 },
{ name: 'User 2', email: 'user2@example.com', age: 30 }
]);
// Find all documents
const allUsers = await User.find();
// Find with conditions
const adults = await User.find({ age: { $gte: 18 } });
const activeUsers = await User.find({ isActive: true });
// Find one document
const user = await User.findOne({ email: 'john@example.com' });
// Find by ID
const user = await User.findById('507f1f77bcf86cd799439011');
// Advanced querying
const users = await User.find({ age: { $gte: 25 } })
.sort({ age: -1 }) // Sort by age descending
.limit(10) // Limit to 10 results
.skip(5); // Skip first 5 results
// Count documents
const count = await User.countDocuments({ isActive: true });
// Update one document
await User.updateOne(
{ email: 'john@example.com' }, // Filter
{ age: 31 } // Update
);
// Update multiple documents
await User.updateMany(
{ isActive: false }, // Filter
{ isActive: true } // Update
);
// Find and update (returns updated document)
const updatedUser = await User.findOneAndUpdate(
{ email: 'john@example.com' },
{ age: 32 },
{ new: true } // Return updated document
);
// Find by ID and update
const user = await User.findByIdAndUpdate(
'507f1f77bcf86cd799439011',
{ name: 'John Smith' },
{ new: true }
);
// Delete one document
await User.deleteOne({ email: 'john@example.com' });
// Delete multiple documents
await User.deleteMany({ isActive: false });
// Find and delete (returns deleted document)
const deletedUser = await User.findOneAndDelete({ email: 'john@example.com' });
// Find by ID and delete
const user = await User.findByIdAndDelete('507f1f77bcf86cd799439011');
const user = await User.findOne({ email: 'john@example.com' });
// Check if document is new (not saved yet)
console.log(user.isNew); // false
// Check if field was modified
user.age = 32;
console.log(user.isModified('age')); // true
// Convert to plain object
const plainObject = user.toObject();
// Convert to JSON
const jsonString = JSON.stringify(user.toJSON());
// Validate document
await user.validate();
// Save changes
await user.save();
// Remove document
await user.remove();
Your data is stored in JSON files within the specified database folder:
my-database/
├── users.json # User collection
├── posts.json # Post collection
└── comments.json # Comment collection
Each collection is a JSON array of documents:
[
{
"_id": "507f1f77bcf86cd799439011",
"name": "John Doe",
"email": "john@example.com",
"age": 30,
"isActive": true,
"createdAt": "2023-01-01T00:00:00.000Z",
"updatedAt": "2023-01-01T00:00:00.000Z"
}
]
// Add instance methods
userSchema.methods.getDisplayName = function() {
return this.name.toUpperCase();
};
// Add static methods
userSchema.statics.findByEmail = function(email) {
return this.findOne({ email });
};
// Usage
const user = await User.findOne({ name: 'John' });
console.log(user.getDisplayName()); // "JOHN"
const user = await User.findByEmail('john@example.com');
const userSchema = new Schema({
email: {
type: 'String',
required: true,
validate: (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
throw new Error('Invalid email format');
}
return true;
}
},
age: {
type: 'Number',
required: true,
validate: (age) => {
if (age < 0 || age > 150) {
throw new Error('Age must be between 0 and 150');
}
return true;
}
}
});
// index.js
const JsonDB = require('jdb-lite');
async function main() {
await JsonDB.connect('./database');
// Your code here
}
// index.mjs or with "type": "module" in package.json
import JsonDB from 'jdb-lite';
await JsonDB.connect('./database');
// Your code here
// index.ts
import JsonDB, { Schema, Document } from 'jdb-lite';
interface User extends Document {
name: string;
email: string;
}
const userSchema = new Schema<User>({
name: { type: 'String', required: true },
email: { type: 'String', required: true }
});
await JsonDB.connect('./database');
const UserModel = JsonDB.model<User>('User', userSchema);
// Basic queries
const users = await User.find({ age: 25 });
const user = await User.findOne({ email: 'john@example.com' });
// Comparison operators
const adults = await User.find({ age: { $gte: 18 } });
const seniors = await User.find({ age: { $gt: 65 } });
const young = await User.find({ age: { $lt: 30 } });
// Sorting and limiting
const newest = await User.find().sort({ createdAt: -1 }).limit(5);
const oldest = await User.find().sort({ createdAt: 1 }).limit(5);
// Pagination
const page2 = await User.find().skip(10).limit(10);
// Counting
const totalUsers = await User.countDocuments();
const activeUsers = await User.countDocuments({ isActive: true });
try {
const user = new User({
name: 'John',
// Missing required email field
age: 30
});
await user.save();
} catch (error) {
console.error('Validation error:', error.message);
// "Field 'email' is required"
}
.limit() to avoid loading large datasets.countDocuments() instead of .find().length for countingJsonDB.disconnect() when done// Mongoose
const mongoose = require('mongoose');
const User = mongoose.model('User', userSchema);
// jdb-lite
const JsonDB = require('jdb-lite');
const User = JsonDB.model('User', userSchema);
// Lowdb
const low = require('lowdb');
const db = low('db.json');
// jdb-lite
const JsonDB = require('jdb-lite');
await JsonDB.connect('./database');
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE file for details.
Made with ❤️ for developers who need a simple, reliable JSON database solution.
FAQs
A lightweight schema-based JSON database library with validation
The npm package jdb-lite receives a total of 4 weekly downloads. As such, jdb-lite popularity was classified as not popular.
We found that jdb-lite 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.

Research
/Security News
Compromised npm package art-template delivered a Coruna-like iOS Safari exploit framework through a watering-hole attack.

Company News
As AI accelerates how code is written and shipped, Socket is scaling to protect the software supply chain from the growing wave of attacks targeting open source dependencies.

Company News
Socket is scaling to defend open source against supply chain attacks as AI accelerates software development.