jdb-lite
Version:
A lightweight schema-based JSON database library with validation
497 lines (388 loc) ⢠11 kB
Markdown
# jdb-lite
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.
## ⨠Features
- š **Familiar API** - Mongoose-like interface that feels natural
- š **JSON File Storage** - Data stored in simple JSON files
- š§ **Schema Validation** - Define and validate your data structure
- š¦ **Multi-format Support** - Works with CommonJS, ES Modules, TypeScript, and JavaScript
- š **Full CRUD Operations** - Create, Read, Update, Delete with filtering and sorting
- šÆ **TypeScript Support** - Full type safety and IntelliSense
- ā” **Zero Dependencies** - Lightweight with no external dependencies
- š **Easy Setup** - Get started in minutes
## š¦ Installation
```bash
npm install jdb-lite
```
## š Quick Start
### JavaScript (CommonJS)
```javascript
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();
```
### JavaScript (ES Modules)
```javascript
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);
```
### TypeScript
```typescript
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
});
```
## š Complete Usage Guide
### 1. Connection
```javascript
// 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();
```
### 2. Schema Definition
```javascript
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)
});
```
### 3. Creating Documents
```javascript
// 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 }
]);
```
### 4. Reading Documents
```javascript
// 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 });
```
### 5. Updating Documents
```javascript
// 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 }
);
```
### 6. Deleting Documents
```javascript
// 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');
```
### 7. Instance Methods
```javascript
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();
```
## šļø Data Storage
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:
```json
[
{
"_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"
}
]
```
## š§ Advanced Features
### Custom Methods and Statics
```javascript
// 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');
```
### Schema Validation
```javascript
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;
}
}
});
```
## š± Module System Examples
### Node.js (CommonJS)
```javascript
// index.js
const JsonDB = require('jdb-lite');
async function main() {
await JsonDB.connect('./database');
// Your code here
}
```
### Node.js (ES Modules)
```javascript
// index.mjs or with "type": "module" in package.json
import JsonDB from 'jdb-lite';
await JsonDB.connect('./database');
// Your code here
```
### TypeScript
```typescript
// 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);
```
## š Query Examples
```javascript
// 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 });
```
## š ļø Error Handling
```javascript
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"
}
```
## š Performance Tips
1. **Use indexes for frequently queried fields** (planned feature)
2. **Limit results with `.limit()`** to avoid loading large datasets
3. **Use `.countDocuments()`** instead of `.find().length` for counting
4. **Close connections** with `JsonDB.disconnect()` when done
## š Migration from Other Libraries
### From Mongoose
```javascript
// Mongoose
const mongoose = require('mongoose');
const User = mongoose.model('User', userSchema);
// jdb-lite
const JsonDB = require('jdb-lite');
const User = JsonDB.model('User', userSchema);
```
### From Lowdb
```javascript
// Lowdb
const low = require('lowdb');
const db = low('db.json');
// jdb-lite
const JsonDB = require('jdb-lite');
await JsonDB.connect('./database');
```
## š¤ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
## š License
MIT License - see [LICENSE](LICENSE) file for details.
---
**Made with ā¤ļø for developers who need a simple, reliable JSON database solution.**