A lightweight, flexible data modeling and storage library for Node.js applications. Stormflow enables you to define data schemas, manage collections, and perform CRUD operations easily, without the overhead of a full database system.
- Schema Definition: Strict or flexible schemas for data consistency.
- Data Collections: Full CRUD support for collections.
- Middleware: Pre- and post-operation hooks for custom logic.
- Query Engine: Advanced queries with comparison and logical operators.
- File Persistence: Data is persisted to disk with optional backups.
- References: Seamless handling of document references.
- Universal Compatibility: Works with CommonJS, ES modules, and TypeScript.
Install via npm or yarn:
npm install stormflow
# or
yarn add stormflow
import db from 'stormflow';
await db.start({
strict: false, // Enforce strict schema validation
defaultFields: true, // Auto add _created/_updated timestamps
verbose: false, // Verbose logging
});
const userSchema = db.Schema({
name: { type: 'string', required: true },
email: { type: 'string', required: true, unique: true },
age: { type: 'number', default: 0 },
friends: [{ type: 'string', $ref: 'user' }],
});
const User = db.model('users', userSchema);
const newUser = await User.insertOne({ name: 'John Doe', email: 'john@example.com', age: 30 });
const adults = await User.find({ age: { $gte: 18 } });
const updatedUser = await User.findByIdAndUpdate(newUser._id, { age: 31 });
await User.findByIdAndDelete(newUser._id);
Method | Description |
---|---|
insertOne(item) |
Insert a single document. |
insertMany(items) |
Insert multiple documents. |
find(query) |
Find all documents matching the query. |
findById(id) |
Find a document by its unique ID. |
findOne(query) |
Find the first document matching the query. |
findByIdAndReplace(id, replacement) |
Replace a document by ID. |
findByIdAndUpdate(id, updates) |
Update fields of a document by ID. |
findByIdAndDelete(id) |
Delete a document by its ID. |
updateOne(query, updates) |
Update one document matching the query. |
updateMany(query, updates) |
Update multiple documents matching the query. |
replaceOne(query, replacement) |
Replace one document matching the query. |
replaceMany(query, replacement) |
Replace multiple documents matching the query. |
deleteOne(query) |
Delete one document matching the query. |
deleteMany(query) |
Delete multiple documents matching the query. |
count(query) |
Count documents matching the query. |
exists(query) |
Check if at least one document matches. |
pre(method, fn) |
Register middleware before the given action. |
post(method, fn) |
Register middleware after the given action. |
Register middleware for operations (wildcard *
is supported only for method):
User.pre('*', async (doc) => {
// Before any operation
});
User.post('update', async (doc) => {
// After updating user
});
Supported methods: 'create' | 'read' | 'update' | 'replace' | 'delete' | '*'
.
Stormflow supports rich queries with comparison and logical operators.
Operator | Description |
---|---|
$eq |
Equal |
$ne |
Not equal |
$lt |
Less than |
$lte |
Less than or equal |
$gt |
Greater than |
$gte |
Greater than or equal |
$in |
Value in array |
$nin |
Value not in array |
$regex |
Matches regular expression |
Operator | Description |
---|---|
$and |
Logical AND |
$or |
Logical OR |
$not |
Logical NOT |
$nor |
Logical NOR |
const result = await User.find({
$or: [{ age: { $lt: 20 } }, { age: { $gt: 60 } }],
});
Stormflow uses a pluggable storage adapter system. The default file-based storage is implemented via a storage adapter, but you can provide your own adapter for custom persistence.
The file storage adapter persists collections in a specified directory. You can configure the location and behavior via options.
Example usage:
import fileStorageAdapter from 'stormflow/adapters/fileStorageAdapter';
const adapter = fileStorageAdapter({
dataFolder: './data', // default: './data'
throttle: 100, // ms, default: 100
verbose: false, // logging
});
For automatic backups, use the file backup adapter:
import fileBackupAdapter from 'stormflow/adapters/fileBackupAdapter';
const backup = fileBackupAdapter({
backupFolder: './data/backup', // default
backupInterval: 60, // minutes
maxBackups: 5, // how many to keep
verbose: false,
});
See the
src/storage/fileStorageAdapter.d.ts
andfileBackupAdapter.d.ts
for full API details.
import db from 'stormflow';
import fileStorageAdapter from 'stormflow/adapters/fileStorageAdapter';
import fileBackupAdapter from 'stormflow/adapters/fileBackupAdapter';
const storage = fileStorageAdapter({
dataFolder: './data',
throttle: 100,
verbose: false,
});
const backup = fileBackupAdapter({
backupFolder: './data/backup',
backupInterval: 60,
maxBackups: 5,
verbose: false,
});
await db.start({}, storage, backup);
-
start(options?: Options, storageAdapter?: any, backupAdapter?: any): Promise<void>
— Start Stormflow with configuration. -
setConfig(options: Options): void
— Update configuration at runtime. -
getConfig(): Options
— Get current configuration. -
Schema(definition: SchemaDefinition): SchemaDefinition
— Create a schema. -
model(name: string, schema?: SchemaDefinition): StormflowModel
— Create or get a model.
See Code of Conduct, Contributing, and Security Policy.
MIT License © 2022–2024 Zsolt Tövis
If you find this project useful, please consider sponsoring me on GitHub, PayPal, or give the repo a star.