2025-08-12 11:25:42 +00:00
# @push.rocks/smartdata 🚀
2025-02-03 14:03:03 +01:00
[](https://www.npmjs.com/package/@push .rocks/smartdata)
2025-08-18 11:50:37 +00:00
**The ultimate TypeScript-first MongoDB wrapper** that turns your database into a type-safe powerhouse. Built for modern applications that demand real-time performance, distributed coordination, and rock-solid reliability.
2025-02-03 14:03:03 +01:00
2025-08-12 11:25:42 +00:00
## 🌟 Why SmartData?
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
SmartData isn't just another MongoDB wrapper - it's a complete paradigm shift in how you work with databases:
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
- 🔒 **100% Type-Safe** : Full TypeScript with decorators, generics, and compile-time query validation
- ⚡ **Lightning Fast** : Connection pooling, cursor streaming, and intelligent indexing
- 🔄 **Real-time Ready** : MongoDB Change Streams with RxJS for reactive applications
- 🌍 **Distributed Systems** : Built-in leader election and task coordination
- 🛡️ **Security First** : NoSQL injection prevention, automatic sanitization, and secure defaults
- 🎯 **Developer Experience** : Intuitive API, powerful search, and IntelliSense that just works
2025-02-03 14:03:03 +01:00
2025-08-12 11:25:42 +00:00
## 📦 Installation
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
```bash
2025-08-12 11:25:42 +00:00
# Using pnpm (recommended)
2025-03-10 23:55:44 +00:00
pnpm add @push .rocks/smartdata
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
# Using npm
npm install @push .rocks/smartdata
2025-08-12 11:25:42 +00:00
# Using yarn
yarn add @push .rocks/smartdata
2025-03-10 23:55:44 +00:00
```
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
## 🚦 Requirements
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
- **Node.js** >= 16.x
- **MongoDB** >= 4.4
- **TypeScript** >= 4.x (for development)
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
## 🎯 Quick Start
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
### 1️ ⃣ Connect to Your Database
2020-06-11 23:05:45 +00:00
```typescript
2024-04-14 04:00:56 +02:00
import { SmartdataDb } from '@push .rocks/smartdata';
2025-08-12 11:25:42 +00:00
// Create a database instance with smart defaults
2024-04-14 04:00:56 +02:00
const db = new SmartdataDb({
2025-08-12 11:25:42 +00:00
mongoDbUrl: 'mongodb://localhost:27017/myapp',
mongoDbName: 'myapp',
mongoDbUser: 'username',
mongoDbPass: 'password',
2025-08-18 11:50:37 +00:00
// Optional: Advanced connection pooling
maxPoolSize: 100, // Max connections in pool
maxIdleTimeMS: 300000, // Max idle time before connection close
serverSelectionTimeoutMS: 30000 // Connection timeout
2020-06-11 23:05:45 +00:00
});
2025-08-18 11:50:37 +00:00
// Initialize with automatic retry and health monitoring
2024-04-14 04:00:56 +02:00
await db.init();
2020-06-11 23:05:45 +00:00
```
2025-08-12 11:25:42 +00:00
### 2️ ⃣ Define Your Data Models
2020-06-11 23:05:45 +00:00
```typescript
2025-04-06 18:18:39 +00:00
import {
SmartDataDbDoc,
Collection,
unI,
svDb,
index,
searchable,
} from '@push .rocks/smartdata';
2025-03-10 23:55:44 +00:00
import { ObjectId } from 'mongodb';
2024-04-14 04:00:56 +02:00
2025-08-12 11:25:42 +00:00
@Collection (() => db)
2024-04-14 04:00:56 +02:00
class User extends SmartDataDbDoc< User , User > {
@unI ()
2025-08-18 11:50:37 +00:00
public id: string; // Unique index with automatic ID generation
2025-08-12 11:25:42 +00:00
2024-04-14 04:00:56 +02:00
@svDb ()
2025-08-18 11:50:37 +00:00
@searchable () // Enable Lucene-style searching
2025-08-12 11:25:42 +00:00
public username: string;
2024-04-14 04:00:56 +02:00
@svDb ()
2025-08-12 11:25:42 +00:00
@searchable ()
2025-08-18 11:50:37 +00:00
@index ({ unique: false }) // Performance index
2025-08-12 11:25:42 +00:00
public email: string;
2025-03-10 23:55:44 +00:00
@svDb ()
2025-08-18 11:50:37 +00:00
public status: 'active' | 'inactive' | 'pending'; // Full union type support
2025-08-12 11:25:42 +00:00
2025-03-10 23:55:44 +00:00
@svDb ()
2025-08-18 11:50:37 +00:00
public organizationId: ObjectId; // Native MongoDB types
@svDb ()
public profilePicture: Buffer; // Binary data support
2025-08-12 11:25:42 +00:00
2025-04-06 18:18:39 +00:00
@svDb ({
2025-08-12 11:25:42 +00:00
// Custom serialization for complex objects
serialize: (data) => JSON.stringify(data),
deserialize: (data) => JSON.parse(data),
2025-03-10 23:55:44 +00:00
})
public preferences: Record< string , any > ;
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
@svDb ()
public tags: string[]; // Array support with operators
2025-08-12 11:25:42 +00:00
@svDb ()
public createdAt: Date = new Date();
2024-04-14 04:00:56 +02:00
constructor(username: string, email: string) {
super();
this.username = username;
this.email = email;
2025-08-18 11:50:37 +00:00
this.id = User.getNewId();
2020-06-11 23:05:45 +00:00
}
}
2024-04-14 04:00:56 +02:00
```
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
### 3️ ⃣ Perform CRUD Operations
2025-04-06 18:18:39 +00:00
2024-04-14 04:00:56 +02:00
```typescript
2025-08-12 11:25:42 +00:00
// ✨ Create
const user = new User('johndoe', 'john@example .com');
2025-08-18 11:50:37 +00:00
user.status = 'active';
user.tags = ['developer', 'typescript'];
2025-08-12 11:25:42 +00:00
await user.save();
2020-06-11 23:05:45 +00:00
2025-08-18 11:50:37 +00:00
// 🔍 Read - with full type safety
2025-08-12 11:25:42 +00:00
const foundUser = await User.getInstance({ username: 'johndoe' });
2025-08-18 11:50:37 +00:00
const activeUsers = await User.getInstances({ status: 'active' });
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
// ✏️ Update
foundUser.email = 'newemail@example .com';
2025-08-18 11:50:37 +00:00
foundUser.tags.push('mongodb');
2025-08-12 11:25:42 +00:00
await foundUser.save();
2025-03-10 23:55:44 +00:00
2025-08-12 11:25:42 +00:00
// 🗑️ Delete
await foundUser.delete();
2024-04-14 04:00:56 +02:00
```
2020-06-11 23:05:45 +00:00
2025-08-18 11:50:37 +00:00
## 🔥 Advanced Features
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
2025-08-18 11:50:37 +00:00
### 🎯 Type-Safe Query Filters
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
2025-08-18 11:50:37 +00:00
SmartData provides the most advanced type-safe filtering system for MongoDB, supporting all operators while maintaining full IntelliSense:
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
```typescript
2025-08-18 11:50:37 +00:00
// Union types work perfectly
const users = await User.getInstances({
status: { $in: ['active', 'pending'] } // TypeScript validates these values!
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
});
2025-08-18 11:50:37 +00:00
// Comparison operators with type checking
const adults = await User.getInstances({
age: { $gte: 18, $lt: 65 } // Type-safe numeric comparisons
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
});
2025-08-18 11:50:37 +00:00
// Array operations with full type safety
const experts = await User.getInstances({
tags: { $all: ['typescript', 'mongodb'] }, // Must have all tags
skills: { $size: 5 } // Exactly 5 skills
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
});
2025-08-18 11:50:37 +00:00
// Complex nested queries
const results = await Order.getInstances({
$and: [
{ status: { $in: ['pending', 'processing'] } },
{ 'items.price': { $gte: 100 } }, // Dot notation for nested fields
{
items: {
$elemMatch: { // Array element matching
product: 'laptop',
quantity: { $gte: 2 }
}
}
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
}
2025-08-18 11:50:37 +00:00
]
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
});
2025-08-18 11:50:37 +00:00
// Logical operators
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
const urgentOrHighValue = await Order.getInstances({
$or: [
{ priority: 'urgent' },
{ totalAmount: { $gte: 1000 } }
]
});
2025-08-18 11:50:37 +00:00
// Security: $where is automatically blocked
// await User.getInstances({ $where: '...' }); // ❌ Throws security error
feat: Add comprehensive query filters guide and enhance type safety for MongoDB queries
- Introduced a detailed guide on query filters in the README, covering basic filtering, comparison operators, array operators, logical operators, element operators, and advanced filtering patterns.
- Implemented a type-safe filtering system in `classes.doc.ts` with `MongoFilterCondition` and `MongoFilter` types to support MongoDB operators while maintaining nested type safety.
- Enhanced error handling for invalid operators and conditions in the filtering logic.
- Added extensive tests for various filtering scenarios, including basic, comparison, array, logical, and complex filters, ensuring robust functionality and performance.
- Implemented security measures to prevent the use of dangerous operators like `$where` and validate operator usage.
2025-08-18 11:29:15 +00:00
```
2025-08-12 11:25:42 +00:00
### 🔎 Powerful Search Engine
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
Built-in Lucene-style search with automatic indexing:
2025-04-06 18:18:39 +00:00
2024-04-14 04:00:56 +02:00
```typescript
2025-04-06 18:14:46 +00:00
@Collection (() => db)
class Product extends SmartDataDbDoc< Product , Product > {
2025-08-12 11:25:42 +00:00
@unI () public id: string;
2025-04-21 15:27:55 +00:00
@svDb () @searchable () public name: string;
@svDb () @searchable () public description: string;
@svDb () @searchable () public category: string;
@svDb () public price: number;
}
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
// Simple text search across all searchable fields
const results = await Product.search('laptop');
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
// Field-specific search
const electronics = await Product.search('category:Electronics');
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
// Wildcard searches
const matches = await Product.search('Mac*');
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
// Boolean operators
const query = await Product.search('laptop AND NOT gaming');
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
// Phrase search
const exact = await Product.search('"MacBook Pro 16"');
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
// Combined with filters for powerful queries
const affordable = await Product.search('laptop', {
filter: { price: { $lte: 1500 } },
validate: async (p) => p.inStock === true
2025-08-12 11:25:42 +00:00
});
2025-04-06 18:14:46 +00:00
```
2025-08-12 11:25:42 +00:00
### 💾 EasyStore - Type-Safe Key-Value Storage
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
Perfect for configuration, caching, and session management:
2025-02-03 14:03:03 +01:00
```typescript
2025-08-12 11:25:42 +00:00
interface AppConfig {
2025-03-10 23:55:44 +00:00
apiKey: string;
2025-08-12 11:25:42 +00:00
features: {
darkMode: boolean;
2025-03-10 23:55:44 +00:00
notifications: boolean;
};
2025-08-12 11:25:42 +00:00
limits: {
maxUsers: number;
maxStorage: number;
};
2025-03-10 23:55:44 +00:00
}
2025-02-03 14:03:03 +01:00
2025-08-12 11:25:42 +00:00
// Create a type-safe store
const config = await db.createEasyStore< AppConfig > ('app-config');
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
// Write with full type checking
2025-08-12 11:25:42 +00:00
await config.writeKey('features', {
darkMode: true,
notifications: false
});
2025-03-10 23:55:44 +00:00
2025-08-12 11:25:42 +00:00
// Read with guaranteed types
const features = await config.readKey('features');
2025-08-18 11:50:37 +00:00
// TypeScript knows: features.darkMode is boolean ✅
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
// Atomic updates
await config.updateKey('limits', (current) => ({
...current,
maxUsers: current.maxUsers + 100
}));
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
// Delete keys
2025-08-12 11:25:42 +00:00
await config.deleteKey('features');
2025-08-18 11:50:37 +00:00
// Clear entire store
2025-08-12 11:25:42 +00:00
await config.wipe();
2025-02-03 14:03:03 +01:00
```
2025-08-18 11:50:37 +00:00
### 📡 Real-Time Change Streams
React to database changes instantly with RxJS integration:
```typescript
// Watch for changes with automatic reconnection
const watcher = await User.watch(
{ status: 'active' }, // Filter which documents to watch
{
fullDocument: 'updateLookup', // Get full document on updates
bufferTimeMs: 100 // Buffer changes for efficiency
}
);
// Subscribe to changes with RxJS
watcher.changeSubject.subscribe({
next: (change) => {
console.log('User changed:', change.fullDocument);
switch(change.operationType) {
case 'insert':
console.log('New user created');
break;
case 'update':
console.log('User updated');
break;
case 'delete':
console.log('User deleted');
break;
}
},
error: (err) => console.error('Watch error:', err)
});
// Advanced: Watch with aggregation pipeline
const complexWatcher = await Order.watch(
{ status: 'pending' },
{
pipeline: [
{ $match: { 'fullDocument.totalAmount': { $gte: 1000 } } },
{ $addFields: { isHighValue: true } }
]
}
);
// Clean up when done
await watcher.close();
```
2025-08-12 11:25:42 +00:00
### 🌐 Distributed Coordination
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
Build resilient distributed systems with automatic leader election:
2025-02-03 14:03:03 +01:00
```typescript
2025-08-18 11:50:37 +00:00
import { SmartdataDistributedCoordinator } from '@push .rocks/smartdata';
2025-02-03 14:03:03 +01:00
const coordinator = new SmartdataDistributedCoordinator(db);
2025-08-12 11:25:42 +00:00
// Start coordination with automatic heartbeat
2025-02-03 14:03:03 +01:00
await coordinator.start();
2025-08-18 11:50:37 +00:00
// Leader election happens automatically
coordinator.asyncExecutionScheduler.addJobHandler('maintenance', async () => {
// This code only runs on the leader instance
console.log('🎖️ Running maintenance as leader');
await performDatabaseCleanup();
});
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
// Check leadership status
const isLeader = coordinator.isLeader;
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
// Fire distributed tasks (integrates with @push .rocks/taskbuffer)
2025-08-12 11:25:42 +00:00
const result = await coordinator.fireDistributedTaskRequest({
2025-08-18 11:50:37 +00:00
taskName: 'process-payments',
2025-08-12 11:25:42 +00:00
taskExecutionTime: Date.now(),
requestResponseId: 'unique-id'
2025-03-10 23:55:44 +00:00
});
2025-08-18 11:50:37 +00:00
// Graceful shutdown with leadership handoff
2025-03-10 23:55:44 +00:00
await coordinator.stop();
2025-02-03 14:03:03 +01:00
```
2025-08-18 11:50:37 +00:00
### 🔄 Cursor Streaming for Large Datasets
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
Process millions of documents without memory issues:
2025-03-10 23:55:44 +00:00
```typescript
2025-08-18 11:50:37 +00:00
// Get a cursor for memory-efficient iteration
2025-08-12 11:25:42 +00:00
const cursor = await User.getCursor(
2025-08-18 11:50:37 +00:00
{ status: 'active' },
{
// Optional: Use MongoDB native cursor modifiers
2025-08-12 11:25:42 +00:00
modifier: (cursor) => cursor
.sort({ createdAt: -1 })
2025-08-18 11:50:37 +00:00
.limit(10000)
.project({ email: 1, username: 1 })
2025-08-12 11:25:42 +00:00
}
);
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
// Process one at a time
2025-08-12 11:25:42 +00:00
await cursor.forEach(async (user) => {
2025-08-18 11:50:37 +00:00
await sendEmail(user.email);
// Each document is loaded individually
2025-08-12 11:25:42 +00:00
});
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
// Or use async iteration
for await (const user of cursor) {
if (shouldStop(user)) break;
await processUser(user);
2025-03-10 23:55:44 +00:00
}
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
// Always clean up
await cursor.close();
2025-03-10 23:55:44 +00:00
```
2025-08-12 11:25:42 +00:00
### 🔐 Transaction Support
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
Ensure data consistency with MongoDB transactions:
2025-03-10 23:55:44 +00:00
```typescript
2025-04-23 17:28:49 +00:00
const session = db.startSession();
2025-08-12 11:25:42 +00:00
2025-03-10 23:55:44 +00:00
try {
await session.withTransaction(async () => {
2025-08-12 11:25:42 +00:00
// All operations in this block are atomic
const sender = await User.getInstance(
{ id: 'user-1' },
2025-08-18 11:50:37 +00:00
{ session } // Pass session to all operations
2025-08-12 11:25:42 +00:00
);
2025-08-18 11:50:37 +00:00
2025-08-12 11:25:42 +00:00
sender.balance -= 100;
await sender.save({ session });
const receiver = await User.getInstance(
{ id: 'user-2' },
2025-08-18 11:50:37 +00:00
{ session }
2025-08-12 11:25:42 +00:00
);
2025-08-18 11:50:37 +00:00
2025-08-12 11:25:42 +00:00
receiver.balance += 100;
await receiver.save({ session });
// If anything fails, everything rolls back
if (sender.balance < 0 ) {
throw new Error('Insufficient funds!');
}
2025-03-10 23:55:44 +00:00
});
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
console.log('✅ Transaction completed');
2025-03-10 23:55:44 +00:00
} finally {
await session.endSession();
}
```
2025-08-12 11:25:42 +00:00
### 🎨 Custom Serialization
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
Handle complex data types with custom serializers:
2025-03-10 23:55:44 +00:00
```typescript
2025-08-12 11:25:42 +00:00
class Document extends SmartDataDbDoc< Document , Document > {
@svDb ({
// Encrypt sensitive data before storing
2025-08-18 11:50:37 +00:00
serialize: async (value) => await encrypt(value),
deserialize: async (value) => await decrypt(value)
2025-08-12 11:25:42 +00:00
})
public sensitiveData: string;
@svDb ({
// Compress large JSON objects
serialize: (value) => compress(JSON.stringify(value)),
deserialize: (value) => JSON.parse(decompress(value))
})
public largePayload: any;
@svDb ({
2025-08-18 11:50:37 +00:00
// Store Sets as arrays
2025-08-12 11:25:42 +00:00
serialize: (set) => Array.from(set),
deserialize: (arr) => new Set(arr)
})
public tags: Set< string > ;
2025-08-18 11:50:37 +00:00
@svDb ({
// Handle custom date formats
serialize: (date) => date?.toISOString(),
deserialize: (str) => str ? new Date(str) : null
})
public scheduledAt: Date | null;
2025-03-10 23:55:44 +00:00
}
```
2025-08-12 11:25:42 +00:00
### 🎣 Lifecycle Hooks
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
Add custom logic at any point in the document lifecycle:
2025-03-10 23:55:44 +00:00
```typescript
@Collection (() => db)
class Order extends SmartDataDbDoc< Order , Order > {
2025-08-12 11:25:42 +00:00
@unI () public id: string;
2025-08-18 11:50:37 +00:00
@svDb () public items: Array< { product: string; quantity: number }>;
@svDb () public totalAmount: number;
@svDb () public status: string;
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
// Called before saving (create or update)
2025-03-10 23:55:44 +00:00
async beforeSave() {
2025-08-18 11:50:37 +00:00
// Recalculate total
this.totalAmount = this.items.reduce((sum, item) =>
2025-08-12 11:25:42 +00:00
sum + (item.price * item.quantity), 0
);
2025-08-18 11:50:37 +00:00
// Validate
if (this.totalAmount < 0 ) {
throw new Error('Invalid order total');
2025-03-10 23:55:44 +00:00
}
}
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
// Called after successful save
2025-03-10 23:55:44 +00:00
async afterSave() {
2025-08-18 11:50:37 +00:00
// Send notifications
await notificationService.orderUpdated(this.id);
// Update cache
await cache.set(`order:${this.id}` , this);
2025-03-10 23:55:44 +00:00
}
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
// Called before deletion
2025-03-10 23:55:44 +00:00
async beforeDelete() {
2025-08-18 11:50:37 +00:00
// Archive order
await archive.store(this);
// Check if deletion is allowed
if (this.status === 'completed') {
throw new Error('Cannot delete completed orders');
2025-03-10 23:55:44 +00:00
}
}
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
// Called after successful deletion
2025-04-23 17:28:49 +00:00
async afterDelete() {
2025-08-18 11:50:37 +00:00
// Clean up related data
await cache.delete(`order:${this.id}` );
// Log deletion
console.log(`Order ${this.id} deleted at ${new Date()}` );
2025-04-23 17:28:49 +00:00
}
2025-03-10 23:55:44 +00:00
}
```
2025-08-18 11:50:37 +00:00
### 🚀 Performance Optimization
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
#### Intelligent Indexing
2025-04-06 18:18:39 +00:00
2025-08-12 11:25:42 +00:00
```typescript
@Collection (() => db)
2025-08-18 11:50:37 +00:00
class HighPerformanceDoc extends SmartDataDbDoc< HighPerformanceDoc , HighPerformanceDoc > {
@unI () // Unique index
public id: string;
@index () // Single field index
public userId: string;
@index ({ sparse: true }) // Sparse index for optional fields
public deletedAt?: Date;
@index ({
unique: false,
background: true, // Non-blocking index creation
expireAfterSeconds: 86400 // TTL index
})
public sessionToken: string;
// Compound indexes for complex queries
static async createIndexes() {
await this.collection.createIndex(
{ userId: 1, createdAt: -1 }, // Compound index
{ name: 'user_activity_idx' }
);
// Text index for search
await this.collection.createIndex(
{ title: 'text', content: 'text' },
{ weights: { title: 10, content: 5 } }
);
}
2025-08-12 11:25:42 +00:00
}
2025-08-18 11:50:37 +00:00
```
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
#### Connection Pool Management
```typescript
const db = new SmartdataDb({
mongoDbUrl: 'mongodb://localhost:27017',
mongoDbName: 'myapp',
// Connection pool optimization
maxPoolSize: 100, // Maximum connections
minPoolSize: 10, // Minimum connections to maintain
maxIdleTimeMS: 300000, // Close idle connections after 5 minutes
waitQueueTimeoutMS: 5000, // Max time to wait for available connection
// Server selection
serverSelectionTimeoutMS: 30000, // Timeout for selecting a server
heartbeatFrequencyMS: 10000, // How often to check server status
// Socket settings
socketTimeoutMS: 360000, // Socket timeout (6 minutes)
family: 4, // Force IPv4
2025-08-12 11:25:42 +00:00
});
```
2025-08-18 11:50:37 +00:00
## 🎯 Best Practices
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
### 1. Always Use TypeScript
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
SmartData is built for TypeScript. Using JavaScript means missing out on:
- Compile-time query validation
- IntelliSense for MongoDB operators
- Type-safe document updates
- Automatic refactoring support
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
### 2. Design Your Indexes Thoughtfully
2025-08-12 11:25:42 +00:00
```typescript
2025-08-18 11:50:37 +00:00
// ✅ Good: Index fields you query frequently
@index () public userId: string;
@index () public status: string;
// ❌ Bad: Over-indexing
@index () public everyField: string; // Don't index everything!
```
2025-04-06 18:14:46 +00:00
2025-08-18 11:50:37 +00:00
### 3. Use Transactions for Critical Operations
```typescript
// ✅ Good: Atomic operations for financial transactions
await session.withTransaction(async () => {
await debitAccount(fromAccount, amount, { session });
await creditAccount(toAccount, amount, { session });
2025-08-12 11:25:42 +00:00
});
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
// ❌ Bad: Multiple operations without transactions
await debitAccount(fromAccount, amount); // What if this fails?
await creditAccount(toAccount, amount);
2025-08-12 11:25:42 +00:00
```
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
### 4. Leverage Cursors for Large Datasets
2025-08-12 11:25:42 +00:00
```typescript
2025-08-18 11:50:37 +00:00
// ✅ Good: Stream processing
2025-08-12 11:25:42 +00:00
const cursor = await LargeCollection.getCursor({});
await cursor.forEach(async (doc) => {
2025-08-18 11:50:37 +00:00
await processOne(doc);
2025-08-12 11:25:42 +00:00
});
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
// ❌ Bad: Loading everything into memory
const allDocs = await LargeCollection.getInstances({}); // Could OOM!
```
2025-03-10 23:55:44 +00:00
2025-08-18 11:50:37 +00:00
### 5. Implement Proper Error Handling
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
```typescript
// ✅ Good: Graceful error handling
try {
const user = await User.getInstance({ id: userId });
if (!user) {
throw new Error('User not found');
}
await processUser(user);
} catch (error) {
logger.error('Failed to process user:', error);
await notificationService.alertAdmin(error);
}
// ❌ Bad: Ignoring errors
const user = await User.getInstance({ id: userId });
await processUser(user); // What if user is null?
2025-08-12 11:25:42 +00:00
```
2020-06-11 23:05:45 +00:00
2025-08-18 11:50:37 +00:00
## 🔧 Troubleshooting
### Connection Issues
2025-08-12 11:25:42 +00:00
```typescript
2025-08-18 11:50:37 +00:00
// Enable debug logging
const db = new SmartdataDb({
mongoDbUrl: 'mongodb://localhost:27017',
mongoDbName: 'myapp',
// Add connection event handlers
});
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
db.mongoClient.on('error', (err) => {
console.error('MongoDB connection error:', err);
});
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
db.mongoClient.on('timeout', () => {
console.error('MongoDB connection timeout');
});
2025-08-12 11:25:42 +00:00
2025-08-18 11:50:37 +00:00
// Check connection status
const isConnected = db.status === 'connected';
2025-08-12 11:25:42 +00:00
```
2025-08-18 11:50:37 +00:00
### Memory Leaks
Always clean up resources:
```typescript
// Watchers
const watcher = await User.watch({});
// ... use watcher
await watcher.close(); // Always close!
// Cursors
const cursor = await User.getCursor({});
// ... use cursor
await cursor.close(); // Always close!
// Sessions
const session = db.startSession();
// ... use session
await session.endSession(); // Always end!
```
### Performance Issues
```typescript
// Profile slow queries
await db.mongoDb.setProfilingLevel('all');
// Check query execution
const stats = await User.collection.mongoDbCollection
.find({ complex: 'query' })
.explain('executionStats');
console.log('Query execution time:', stats.executionTimeMillis);
console.log('Documents examined:', stats.totalDocsExamined);
console.log('Index used:', stats.executionStats.executionStages.indexName);
```
## 📚 API Reference
### Core Classes
- `SmartdataDb` - Database connection and management
- `SmartDataDbDoc` - Base class for all documents
- `SmartdataCollection` - Collection management
- `SmartdataDbCursor` - Cursor for streaming operations
- `SmartdataDbWatcher` - Change stream watcher
- `SmartdataDistributedCoordinator` - Distributed coordination
### Decorators
2025-04-06 18:18:39 +00:00
2025-08-18 11:50:37 +00:00
- `@Collection(dbGetter)` - Define collection for a document class
- `@unI()` - Create unique index
- `@index(options)` - Create regular index
- `@svDb(options)` - Mark field as saveable with optional serialization
- `@searchable()` - Enable text search on field
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
### Key Methods
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
- `getInstances(filter)` - Find multiple documents
- `getInstance(filter)` - Find single document
- `getCursor(filter)` - Get cursor for streaming
- `watch(filter, options)` - Watch for changes
- `search(query, options)` - Lucene-style search
- `save(options)` - Save document
- `delete(options)` - Delete document
- `updateFromDb()` - Refresh from database
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
## 🌍 Community & Support
2025-02-03 14:03:03 +01:00
2025-08-18 11:50:37 +00:00
- 📖 **Documentation** : [https://code.foss.global/push.rocks/smartdata ](https://code.foss.global/push.rocks/smartdata )
- 💬 **Issues** : [GitLab Issues ](https://code.foss.global/push.rocks/smartdata/issues )
- 📧 **Email** : hello@task .vc
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
## License and Legal Information
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license ](license ) file within this repository.
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
### Trademarks
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
2020-06-11 23:05:45 +00:00
2024-04-14 04:00:56 +02:00
### Company Information
2020-06-12 05:59:07 +00:00
2024-04-14 04:00:56 +02:00
Task Venture Capital GmbH
Registered at District court Bremen HRB 35230 HB, Germany
2020-06-12 05:59:07 +00:00
2024-04-14 04:00:56 +02:00
For any legal inquiries or if you require further information, please contact us via email at hello@task .vc.
2020-06-11 23:05:45 +00:00
2025-08-12 11:25:42 +00:00
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.