SQLMongoose
A SQLite ORM that works exactly like Mongoose, bringing the familiar MongoDB/Mongoose syntax to SQLite.
Support server: https://discord.gg/hzWuQH869R
Features
- 🎯 Mongoose-like Schema definitions
- 🚀 Simple and intuitive Model API
- 📦 TypeScript support out of the box
- 🛡️ Type safety for your database operations
- 🔍 Familiar query interface (find, findOne)
- 🎨 Clean and modern API design
- 🔄 Pre/Post Hooks for save and update operations
- 🤝 Relationship support with populate
- ⚡ Advanced querying (gt, lt, like, in, etc.)
- 📊 Index support
- 🔒 Transaction support
- ✨ Field validation
Installation
npm install sqlmongoose
Quick Start
const sqlmongoose = require('sqlmongoose');
await sqlmongoose.connect('database.db');
const userSchema = new Schema({
name: { type: 'STRING', required: true },
email: { type: 'STRING', unique: true },
balance: { type: 'NUMBER', default: 0 },
isActive: { type: 'BOOLEAN', default: true },
lastLogin: { type: 'DATE' }
});
const User = sqlmongoose.model('User', userSchema);
const user = await User.create({
name: 'John',
email: 'john@example.com'
});
Defining Schemas
const economySchema = new Schema({
userId: {
type: 'STRING',
required: true,
unique: true
},
money: {
type: 'NUMBER',
default: 0,
validate: value => value >= 0
},
inventory: {
type: 'STRING',
default: JSON.stringify({
items: [],
lastUpdated: new Date()
})
}
});
economySchema.pre('save', async function(data) {
if (typeof data.inventory === 'object') {
data.inventory = JSON.stringify(data.inventory);
}
});
economySchema.post('save', async function(data) {
if (typeof data.inventory === 'string') {
data.inventory = JSON.parse(data.inventory);
}
});
const Economy = sqlmongoose.model('Economy', economySchema);
module.exports = Economy;
Using Models
Creating Documents
const Economy = sqlmongoose.model('Economy');
async function createUser(userId) {
const economy = await Economy.create({
userId: userId,
money: 1000
});
return economy;
}
Finding Documents
const user = await Economy.findOne({ userId: '123' });
const richUsers = await Economy.find({
money: { gt: 10000 }
}, {
limit: 10,
orderBy: { money: 'DESC' }
});
const users = await Economy.find({
money: { gt: 1000, lte: 5000 },
lastLogin: { gt: new Date('2024-01-01') },
name: { like: 'John' }
});
Updating Documents
await Economy.update(
{ userId: '123' },
{ money: 5000 }
);
await Economy.update(
{ userId: '123' },
{ $inc: { money: 100 } }
);
await Economy.update(
{ userId: '123' },
{
$inc: { money: -50 },
$set: { lastTransaction: new Date() }
}
);
Using in Discord.js Commands
const { SlashCommandBuilder } = require('discord.js');
const Economy = require('../schemas/EconomySchema');
module.exports = {
data: new SlashCommandBuilder()
.setName('balance')
.setDescription('Check your balance'),
async execute(interaction) {
let user = await Economy.findOne({
userId: interaction.user.id
});
if (!user) {
user = await Economy.create({
userId: interaction.user.id,
money: 1000,
bank: 0
});
}
await interaction.reply(
`Balance: ${user.money}\nBank: ${user.bank}`
);
}
};
Transactions
const sqlmongoose = require('sqlmongoose');
async function transferMoney(fromId, toId, amount) {
await sqlmongoose.transaction(async () => {
const [from, to] = await Promise.all([
Economy.findOne({ userId: fromId }),
Economy.findOne({ userId: toId })
]);
if (from.money < amount) {
throw new Error('Insufficient funds');
}
await Economy.update(
{ userId: fromId },
{ $inc: { money: -amount } }
);
await Economy.update(
{ userId: toId },
{ $inc: { money: amount } }
);
});
}
Update Operators
SQLMongoose supports these MongoDB-like operators:
await Economy.update(
{ userId },
{ $inc: { money: 100, xp: 50 } }
);
await Economy.update(
{ userId },
{ $set: { lastLogin: new Date() } }
);
await Economy.update(
{ userId },
{ $unset: { temporaryBuff: 1 } }
);
Query Operators
eq: Equal
ne: Not Equal
gt: Greater Than
gte: Greater Than or Equal
lt: Less Than
lte: Less Than or Equal
in: In Array
like: Like (SQL LIKE)
await Economy.find({
level: { gte: 10 },
name: { like: 'John%' },
status: { in: ['active', 'premium'] }
});
TypeScript Support
interface UserDocument {
id?: number;
userId: string;
money: number;
bank: number;
inventory: string;
}
const User = sqlmongoose.model<UserDocument>('User', userSchema);
Schema Types
SQLite Schemas supports the following data types:
STRING (stored as TEXT)
NUMBER (stored as NUMERIC)
BOOLEAN (stored as INTEGER)
DATE (stored as TEXT)
Schema Configuration
interface SchemaField {
type: 'STRING' | 'NUMBER' | 'BOOLEAN' | 'DATE';
required?: boolean;
default?: any;
validate?: (value: any) => boolean | Promise<boolean>;
index?: boolean;
unique?: boolean;
ref?: string;
}
const userSchema = new Schema({
name: {
type: 'STRING',
required: true,
validate: (value) => value.length >= 2
},
email: {
type: 'STRING',
unique: true,
index: true
},
age: {
type: 'NUMBER',
validate: (value) => value >= 0
},
departmentId: {
type: 'NUMBER',
ref: 'departments'
}
});
Advanced Querying
const results = await UserModel.find({
age: { gt: 18, lte: 65 },
name: { like: 'John' },
status: { in: ['active', 'pending'] }
}, {
populate: ['departmentId'],
limit: 10,
offset: 0,
orderBy: {
name: 'ASC',
age: 'DESC'
}
});
await UserModel.update(
{ age: { lt: 18 } },
{ status: 'underage' }
);
await UserModel.delete({ status: 'inactive' });
Hooks
userSchema.pre('save', async function(data) {
data.createdAt = new Date();
data.password = await hashPassword(data.password);
});
userSchema.post('save', async function(data) {
await sendWelcomeEmail(data.email);
});
userSchema.pre('update', async function(data) {
data.updatedAt = new Date();
});
Transactions
const connection = createConnection('example.db');
await connection.transaction(async (db) => {
const UserModel = new Model(db, 'users', userSchema);
const OrderModel = new Model(db, 'orders', orderSchema);
const user = await UserModel.create({ });
const order = await OrderModel.create({
userId: user.id,
});
});
Relationships and Population
const departmentSchema = new Schema({
name: { type: 'STRING', required: true }
});
const userSchema = new Schema({
name: { type: 'STRING', required: true },
departmentId: { type: 'NUMBER', ref: 'departments' }
});
const users = await UserModel.find(
{ age: { gt: 25 } },
{ populate: ['departmentId'] }
);
Validation
const productSchema = new Schema({
name: {
type: 'STRING',
required: true,
validate: (value) => value.length >= 3
},
price: {
type: 'NUMBER',
validate: (value) => value > 0
},
sku: {
type: 'STRING',
unique: true,
validate: (value) => /^[A-Z]{2}-\d{6}$/.test(value)
}
});
try {
await ProductModel.create({
name: 'A',
price: -10
});
} catch (error) {
console.error('Validation failed:', error.message);
}
Indexing
const userSchema = new Schema({
email: {
type: 'STRING',
unique: true,
index: true
},
name: {
type: 'STRING',
index: true
}
});
API Reference
Schema
Constructor
new Schema(definition: SchemaDefinition)
Model
Constructor
new Model<T>(db: Database, tableName: string, schema: Schema)
Methods
find
find(query?: Partial<T>): Promise<T[]>
findOne
findOne(query: Partial<T>): Promise<T | null>
create
create(data: T): Promise<T>
Examples
Complete User Management Example
import { createConnection, Schema, Model } from 'sqlite-schemas';
interface User {
id?: number;
name: string;
email: string;
age: number;
active: boolean;
}
const db = createConnection('users.db');
const userSchema = new Schema({
name: { type: 'STRING', required: true },
email: { type: 'STRING', required: true },
age: { type: 'NUMBER', required: true },
active: { type: 'BOOLEAN', default: true }
});
const UserModel = new Model<User>(db, 'users', userSchema);
async function userExample() {
await UserModel.create({
name: 'John Doe',
email: 'john@example.com',
age: 25,
active: true
});
const activeUsers = await UserModel.find({ active: true });
const john = await UserModel.findOne({ email: 'john@example.com' });
}
JavaScript Examples
Basic Setup
const sqlmongoose = require('sqlmongoose');
async function init() {
await sqlmongoose.connect('database.db');
require('./schemas/UserSchema');
require('./schemas/EconomySchema');
}
init().catch(console.error);
Schema Definition
const sqlmongoose = require('sqlmongoose');
const { Schema } = sqlmongoose;
const economySchema = new Schema({
userId: {
type: 'STRING',
required: true,
unique: true
},
money: {
type: 'NUMBER',
default: 0,
validate: value => value >= 0
},
bank: {
type: 'NUMBER',
default: 0
},
inventory: {
type: 'STRING',
default: JSON.stringify({
items: [],
lastUpdated: new Date()
})
},
dailyStreak: {
type: 'NUMBER',
default: 0
},
lastDaily: {
type: 'DATE',
default: null
}
});
economySchema.pre('save', async function(data) {
if (typeof data.inventory === 'object') {
data.inventory = JSON.stringify(data.inventory);
}
});
economySchema.post('save', async function(data) {
if (typeof data.inventory === 'string') {
data.inventory = JSON.parse(data.inventory);
}
});
module.exports = sqlmongoose.model('Economy', economySchema);
Using in Commands (Discord.js Example)
const { SlashCommandBuilder } = require('discord.js');
const Economy = require('../schemas/EconomySchema');
module.exports = {
data: new SlashCommandBuilder()
.setName('balance')
.setDescription('Check your or someone else\'s balance')
.addUserOption(option =>
option.setName('user')
.setDescription('User to check')
.setRequired(false)),
async execute(interaction) {
const target = interaction.options.getUser('user') || interaction.user;
let userData = await Economy.findOne({ userId: target.id });
if (!userData) {
userData = await Economy.create({
userId: target.id,
money: 1000,
bank: 0
});
}
const embed = {
title: `💰 ${target.username}'s Balance`,
fields: [
{ name: 'Cash', value: `$${userData.money}`, inline: true },
{ name: 'Bank', value: `$${userData.bank}`, inline: true },
{ name: 'Total', value: `$${userData.money + userData.bank}` }
],
color: 0x0099FF
};
await interaction.reply({ embeds: [embed] });
}
};
const Economy = require('../schemas/EconomySchema');
const ONE_DAY = 24 * 60 * 60 * 1000;
module.exports = {
data: new SlashCommandBuilder()
.setName('daily')
.setDescription('Collect your daily reward'),
async execute(interaction) {
const user = await Economy.findOne({ userId: interaction.user.id });
const now = new Date();
if (user.lastDaily && (now - new Date(user.lastDaily)) < ONE_DAY) {
const timeLeft = ONE_DAY - (now - new Date(user.lastDaily));
const hoursLeft = Math.floor(timeLeft / (60 * 60 * 1000));
return interaction.reply(
`You can collect your daily reward in ${hoursLeft} hours!`
);
}
const reward = 100 * (user.dailyStreak + 1);
await Economy.update(
{ userId: interaction.user.id },
{
$inc: {
money: reward,
dailyStreak: 1
},
$set: { lastDaily: now }
}
);
await interaction.reply(
`You collected $${reward}! 🎉\nDaily streak: ${user.dailyStreak + 1}`
);
}
};
Advanced Examples
Economy System
const Economy = require('../schemas/EconomySchema');
async function transfer(fromId, toId, amount) {
return await sqlmongoose.transaction(async () => {
const [from, to] = await Promise.all([
Economy.findOne({ userId: fromId }),
Economy.findOne({ userId: toId })
]);
if (!from || !to) throw new Error('User not found');
if (from.money < amount) throw new Error('Insufficient funds');
await Promise.all([
Economy.update(
{ userId: fromId },
{ $inc: { money: -amount } }
),
Economy.update(
{ userId: toId },
{ $inc: { money: amount } }
)
]);
return { from, to, amount };
});
}
async function addItem(userId, item) {
const user = await Economy.findOne({ userId });
const inventory = JSON.parse(user.inventory);
inventory.items.push({
...item,
obtainedAt: new Date()
});
await Economy.update(
{ userId },
{
$set: {
inventory: JSON.stringify(inventory)
}
}
);
}
async function buyItem(userId, itemId) {
const user = await Economy.findOne({ userId });
const item = SHOP_ITEMS[itemId];
if (!item) throw new Error('Item not found');
if (user.money < item.price) throw new Error('Insufficient funds');
await Economy.update(
{ userId },
{ $inc: { money: -item.price } }
);
await addItem(userId, item);
return item;
}
Advanced Queries
async function getLeaderboard() {
return await Economy.find(
{
money: { gt: 0 },
lastDaily: {
gt: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)
}
},
{
orderBy: { money: 'DESC' },
limit: 10
}
);
}
async function getActiveUsers() {
return await Economy.find({
lastDaily: { gt: new Date(Date.now() - 24 * 60 * 60 * 1000) },
money: { gt: 1000 }
});
}
async function searchUsers(query) {
return await Economy.find({
$or: [
{ username: { like: `%${query}%` } },
{ userId: { eq: query } }
]
});
}
JavaScript Examples
CommonJS Usage
const { createConnection, Schema, Model } = require('sqlmongoose');
const db = createConnection('example.db');
const userSchema = new Schema({
name: { type: 'STRING', required: true },
email: { type: 'STRING', unique: true },
age: { type: 'NUMBER' },
isActive: { type: 'BOOLEAN', default: true }
});
const UserModel = new Model(db, 'users', userSchema);
UserModel.create({
name: 'John Doe',
email: 'john@example.com',
age: 30
})
.then(user => console.log('User created:', user))
.catch(err => console.error('Error:', err));
async function findUsers() {
try {
const users = await UserModel.find({
age: { gt: 18, lt: 65 },
isActive: true
}, {
limit: 10,
orderBy: { name: 'ASC' }
});
console.log('Active users:', users);
const updated = await UserModel.update(
{ age: { lt: 18 } },
{ isActive: false }
);
console.log('Updated records:', updated);
} catch (error) {
console.error('Error:', error);
}
}
async function createUserWithOrder() {
const connection = createConnection('store.db');
try {
await connection.transaction(async (db) => {
const UserModel = new Model(db, 'users', userSchema);
const OrderModel = new Model(db, 'orders', orderSchema);
const user = await UserModel.create({
name: 'Jane Doe',
email: 'jane@example.com'
});
await OrderModel.create({
userId: user.id,
total: 99.99,
status: 'pending'
});
});
console.log('Transaction completed successfully');
} catch (error) {
console.error('Transaction failed:', error);
}
}
userSchema.pre('save', async function(data) {
data.createdAt = new Date();
if (data.password) {
data.password = await bcrypt.hash(data.password, 10);
}
});
const orderSchema = new Schema({
userId: { type: 'NUMBER', ref: 'users' },
total: { type: 'NUMBER' }
});
OrderModel.find(
{ total: { gt: 100 } },
{ populate: ['userId'] }
)
.then(orders => {
orders.forEach(order => {
console.log(`Order total: ${order.total}`);
console.log(`Customer: ${order.userId.name}`);
});
});
ES Modules Usage
import { createConnection, Schema, Model } from 'sqlmongoose';
const db = createConnection('example.db');
const productSchema = new Schema({
name: {
type: 'STRING',
validate: value => value.length >= 3
},
price: {
type: 'NUMBER',
required: true
}
});
const ProductModel = new Model(db, 'products', productSchema);
try {
const product = await ProductModel.create({
name: 'Test Product',
price: 29.99
});
console.log('Product created:', product);
const products = await ProductModel.find({
price: { lt: 100 }
});
console.log('Affordable products:', products);
} catch (error) {
console.error('Error:', error);
}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - see the LICENSE file for details.