npm package: @matteuccimarco/slim-db
Description: Embedded database with native SLIM storage - optimized for AI/LLM workloads
Author: Marco Matteucci
Latest version: 0.1.0

# slim-db

[![npm version](https://img.shields.io/npm/v/slim-db.svg)](https://www.npmjs.com/package/slim-db)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

**SLIM-DB** - Embedded document database with native SLIM storage. Part of the SLIM Protocol ecosystem.

## Why SLIM-DB?

- **Token-efficient storage**: Uses SLIM format (40-50% smaller than JSON)
- **Zero dependencies** (except slim-protocol-core)
- **MongoDB-like API**: Familiar query and update operators
- **Multiple index types**: B-tree, Hash, Bitmap, Inverted
- **Transactions**: Snapshot isolation with rollback support
- **TypeScript first**: Full type safety

## Installation

```bash
npm install slim-db
```

## Quick Start

```typescript
import { createDatabase } from 'slim-db';

// Create in-memory database
const db = createDatabase();

// Or with persistence
const db = createDatabase({ dataDir: './my-database' });

// Get a collection
const users = db.collection('users');

// Insert documents
users.insert({ name: 'Mario', age: 35, role: 'plumber' });
users.insertMany([
  { name: 'Luigi', age: 33, role: 'plumber' },
  { name: 'Peach', age: 30, role: 'princess' },
]);

// Find documents
const plumbers = await users.find({ role: 'plumber' }).toArray();
const mario = users.findOne({ name: 'Mario' });

// Update documents
users.updateOne({ name: 'Mario' }, { $set: { coins: 100 } });
users.updateMany({ role: 'plumber' }, { $inc: { coins: 10 } });

// Delete documents
users.deleteOne({ name: 'Bowser' });

// Save to disk (if using persistence)
db.save();
```

## Query Operators

### Comparison
```typescript
users.find({ age: { $gt: 30 } });      // Greater than
users.find({ age: { $gte: 30 } });     // Greater than or equal
users.find({ age: { $lt: 35 } });      // Less than
users.find({ age: { $lte: 35 } });     // Less than or equal
users.find({ age: { $ne: 30 } });      // Not equal
users.find({ name: { $in: ['Mario', 'Luigi'] } });   // In array
users.find({ name: { $nin: ['Bowser'] } });          // Not in array
```

### Logical
```typescript
users.find({ $and: [{ age: { $gt: 30 } }, { role: 'plumber' }] });
users.find({ $or: [{ name: 'Mario' }, { name: 'Luigi' }] });
users.find({ age: { $not: { $lt: 30 } } });
```

### Element
```typescript
users.find({ coins: { $exists: true } });
users.find({ role: { $type: 'string' } });
```

### String
```typescript
users.find({ name: { $regex: '^Mar' } });
users.find({ name: { $startsWith: 'Mar' } });
users.find({ name: { $endsWith: 'io' } });
```

### Array
```typescript
users.find({ items: { $contains: 'mushroom' } });
```

## Update Operators

```typescript
// Set fields
users.updateOne({ name: 'Mario' }, { $set: { level: 1 } });

// Unset fields
users.updateOne({ name: 'Mario' }, { $unset: { tempBonus: true } });

// Increment numbers
users.updateOne({ name: 'Mario' }, { $inc: { coins: 10 } });

// Array operations
users.updateOne({ name: 'Mario' }, { $push: { items: 'star' } });
users.updateOne({ name: 'Mario' }, { $pull: { items: 'mushroom' } });

// Min/Max (keep smaller/larger value)
users.updateOne({ name: 'Mario' }, { $min: { score: 50 } });
users.updateOne({ name: 'Mario' }, { $max: { score: 100 } });

// Rename field
users.updateOne({ name: 'Mario' }, { $rename: { hp: 'health' } });
```

## Cursor Operations

```typescript
const results = await users.find({ role: 'plumber' })
  .sort({ age: -1 })        // Sort descending
  .skip(10)                  // Skip first 10
  .limit(5)                  // Limit to 5
  .project(['name', 'age']) // Only these fields
  .toArray();

// Iteration
await users.find().forEach(doc => console.log(doc));
const names = await users.find().map(doc => doc.name);
const count = await users.find({ active: true }).count();
```

## Indexes

```typescript
// Create indexes
users.createIndex({ fields: ['email'], unique: true });
users.createIndex({ fields: ['age'], type: 'btree' });
users.createIndex({ fields: ['status'], type: 'bitmap' }); // Low cardinality
users.createIndex({ fields: ['tags'], type: 'inverted' }); // Arrays

// List indexes
const indexes = users.getIndexes();

// Drop index
users.dropIndex('email');
```

## Transactions

```typescript
const tx = db.beginTransaction();

try {
  tx.insert('users', { name: 'Toad', role: 'helper' });
  tx.updateOne('users', { name: 'Mario' }, { $inc: { coins: -50 } });
  tx.commit();
} catch (error) {
  tx.rollback();
}

// Or use withTransaction helper
await db.withTransaction(async (tx) => {
  // Operations here auto-commit on success, rollback on error
});
```

## SLIM Functions

SQL-style functions for querying SLIM data:

```typescript
import { slimFunctions } from 'slim-db';

const doc = { _id: '1', user: { name: 'Mario', items: ['star', 'mushroom'] } };

slimFunctions.slim_get(doc, 'user.name');        // 'Mario'
slimFunctions.slim_num(doc, 'user.age');         // null (not a number)
slimFunctions.slim_str(doc, 'user.name');        // 'Mario'
slimFunctions.slim_arr(doc, 'user.items');       // ['star', 'mushroom']
slimFunctions.slim_len(doc, 'user.items');       // 2
slimFunctions.slim_exists(doc, 'user.coins');    // false
slimFunctions.slim_type(doc, 'user.items');      // 'array'
slimFunctions.slim_match(doc, { 'user.name': 'Mario' }); // true
```

## Persistence

```typescript
// Create with file persistence
const db = createDatabase({ dataDir: './data' });

// Auto-save every 5 seconds
const db = createDatabase({
  dataDir: './data',
  autoSaveInterval: 5000
});

// Manual save
db.save();

// Check for unsaved changes
if (db.isDirty()) {
  db.save();
}
```

## Export/Import

```typescript
// Export entire database as SLIM
const slim = db.exportSLIM();

// Import into another database
const db2 = createDatabase();
db2.importSLIM(slim);

// Export single collection
const usersSlim = users.toSLIM();
const usersJson = users.toJSON();
```

## Collection Options

```typescript
const users = db.collection('users', {
  // Add createdAt/updatedAt timestamps
  timestamps: true,

  // Custom validation
  validator: (doc) => {
    if (!doc.email) return 'Email required';
    return true;
  },

  // Auto-create indexes
  indexes: [
    { fields: ['email'], unique: true },
    { fields: ['createdAt'] }
  ]
});
```

## API Reference

### Database

```typescript
createDatabase(options?: DatabaseOptions): SlimDB

interface DatabaseOptions {
  dataDir?: string | null;      // Directory for persistence
  autoSaveInterval?: number;    // Auto-save interval in ms
}

// Methods
db.collection(name, options?)   // Get/create collection
db.listCollections()            // List collection names
db.dropCollection(name)         // Drop a collection
db.beginTransaction()           // Start transaction
db.save()                       // Save to disk
db.stats()                      // Get statistics
db.exportSLIM()                 // Export as SLIM
db.importSLIM(slim)             // Import from SLIM
```

### Collection

```typescript
// CRUD
collection.insert(doc)
collection.insertMany(docs)
collection.find(filter?, options?)
collection.findOne(filter?)
collection.findById(id)
collection.updateOne(filter, update)
collection.updateMany(filter, update)
collection.updateById(id, update)
collection.replaceOne(filter, doc)
collection.deleteOne(filter)
collection.deleteMany(filter)
collection.deleteById(id)

// Utilities
collection.count(filter?)
collection.exists(filter)
collection.distinct(field, filter?)

// Indexes
collection.createIndex(spec)
collection.dropIndex(name)
collection.getIndexes()

// Export
collection.toSLIM()
collection.toJSON()
collection.stats()
```

## Test Coverage

- **103 tests** passing
- Full coverage of CRUD, queries, updates, indexes, transactions

## Requirements

- Node.js >= 18.0.0
- slim-protocol-core >= 0.1.0

## Related Packages

- [slim-protocol-core](https://www.npmjs.com/package/slim-protocol-core) - Core SLIM serialization

## License

MIT