A reactive adapter for SQLite using RxJS, providing a reactive programming model for SQLite databases. This project includes both a standalone RxJS-based SQLite adapter and an RxDB adapter for SQLite that works in Node.js environments.
This project is currently in alpha stage and has not been tested in a full production environment yet. While the core functionality is implemented and working, you may encounter bugs or limitations. Use at your own risk in production systems. We welcome feedback, bug reports, and contributions to help improve stability and feature completeness.
npm install rxjs-sqlite
The simplest way to use this adapter is with RxDB:
import { createRxDatabase } from 'rxdb';
import { getRxStorageSQLite } from 'rxjs-sqlite/rxdb-adapter';
// Create a database with the SQLite adapter
const db = await createRxDatabase({
name: 'mydb',
storage: getRxStorageSQLite(),
// Recommended for alpha release
ignoreDuplicate: true,
// Dev mode provides helpful warnings but requires validation strategy
// for nullable fields
devMode: true,
// Configure validation strategy to handle nullable fields properly
validationStrategy: {
validateBeforeInsert: true,
validateBeforeSave: false,
validateOnQuery: false
}
});
// Define a schema for your collection
const taskSchema = {
title: 'Task schema',
version: 0,
primaryKey: 'id',
type: 'object',
properties: {
id: { type: 'string' },
title: { type: 'string' },
completed: { type: 'boolean', default: false },
// Nullable field using multi-type array
dueDate: { type: ['string', 'null'], default: null },
// Another nullable field example
notes: { type: ['string', 'null'], default: null }
},
required: ['id', 'title']
};
// Add a collection
const tasks = await db.addCollection({
name: 'tasks',
schema: taskSchema
});
// Insert a document
await tasks.insert({
id: '1',
title: 'Complete project',
dueDate: '2023-12-31',
notes: null
});
// Query documents
const allTasks = await tasks.find().exec();
console.log('All tasks:', allTasks);
// Create a reactive query
const incompleteTasks$ = tasks.find({
selector: { completed: false }
}).$;
// Subscribe to changes
const subscription = incompleteTasks$.subscribe(tasks => {
console.log('Incomplete tasks updated:', tasks);
});
// Later, update a document
await tasks.findOne('1').update({ $set: { completed: true } });
// Clean up
subscription.unsubscribe();
await db.remove();
Important Note: The validation strategy shown above is recommended even if you're not using dev mode. It ensures proper handling of nullable fields and provides better error messages when validation fails. If you don't use nullable fields (with multi-type arrays like
{ type: ['string', 'null'] }
), you can omit the validation strategy configuration.
Once set up, the adapter is transparent - you use the standard RxDB API for all operations, and the SQLite storage is handled automatically.
- Reactive Queries: Get real-time updates when data changes
- RxJS Integration: Leverage the power of RxJS operators
- TypeScript Support: Full TypeScript support with type definitions
- High Performance: Built on top of better-sqlite3 for optimal performance
- Transaction Support: Full support for SQLite transactions
- Minimal Dependencies: Only depends on RxJS and better-sqlite3
- RxDB Compatibility: Can be used as a storage adapter for RxDB
When using nullable fields, use multi-type arrays and configure validation properly:
// Define nullable fields like this:
{
optionalField: {
type: ['string', 'null'],
default: null
}
}
// Always use a validation strategy (recommended even without dev mode)
validationStrategy: {
validateBeforeInsert: true, // Validate before inserting new documents
validateBeforeSave: false, // Skip validation on updates for better perf
validateOnQuery: false // Skip validation on queries for better perf
}
// If you don't need dev mode warnings, you can also disable it entirely
// devMode: false
The validation strategy is recommended even if you're not using dev mode. It provides better error messages and ensures proper handling of nullable fields. Without it, you might encounter cryptic errors or unexpected behavior when working with null values.
See README.validation.md for detailed explanation.
RxDB is incompatible with autoincrement primary keys. Use client-generated IDs like UUIDs instead.
See README.about.md for more details.
You can access the underlying SQLite database directly:
// Get the SQLite database instance
const sqliteDb = getRxStorageSQLite.getDBByName('mydb');
// Execute raw SQL queries
const results = sqliteDb.prepare(`
SELECT * FROM mydb_tasks WHERE completed = 0
`).all();
- API Reference - Detailed API documentation
- Database Management - How DB instances are managed
- Capabilities & Limitations - What's supported and what's not
- Examples - More usage examples
- Development Guide - For contributors
For a complete, real-world implementation, check out the included Recipe App:
- Recipe App Instructions - A fully functional recipe management application that demonstrates how to use the SQLite adapter in a practical scenario.
The Recipe App showcases:
- Using the SQLite adapter in a Node.js backend
- Implementing a REST API with Express
- Handling complex data relationships
- Implementing search functionality
- Managing nullable fields properly
This example follows the "dogfood principle" by using the adapter in a real application, proving its capabilities in a practical context.
MIT