Interact with your databasein a simple, graceful way.
Sutando brings the elegance of Laravel's Eloquent to Node.js — a fluent query builder, expressive models and relationships, transactions, migrations and more, with first-class TypeScript support.
$ npm install sutando$ yarn add sutando$ pnpm add sutandoimport { Model } from 'sutando';
class User extends Model {
declare id: number;
declare name: string;
}
const user = new User();
user.name = 'John';
await user.save();
const users = await User.query()
.where('age', '>', 18)
.get();Supports
- MySQL
- PostgreSQL
- SQLite
- MariaDB
- SQL Server
- Oracle
An ORM that stays out of your way
Write less SQL, keep full control — and reach for raw expressions whenever you need them.
A query builder you already know
Chain methods to build queries that read like the SQL you meant to write, with parameter binding handled for you.
- where, whereIn, join and orderBy constraints
- Aggregates with count() and exists()
- Pagination with paginate(), large results with chunk()
- Raw SQL through db.raw(), with parameter binding
import { sutando } from 'sutando';
const db = sutando.connection();
const users = await db.table('users')
.where('votes', '>', 100)
.whereIn('status', ['active', 'pending'])
.orderBy('name')
.take(10)
.get();Models and relationships
Define a model in a few lines, then describe how your tables relate. Loading related records never turns into an N+1.
- hasOne, hasMany, belongsTo and belongsToMany
- Eager loading with with() — two queries instead of N+1
- Accessors, mutators, casts and query scopes
- Soft deletes with restore() and forceDelete()
import { Model } from 'sutando';
class User extends Model {
declare id: number;
declare name: string;
relationPosts() {
return this.hasMany(Post);
}
}
// two queries, not N+1
const user = await User.query().with('posts').find(1);
user.posts.count();Schema you can version
Define your schema with the migration builder, commit it, and let every environment catch up the same way.
- Fluent schema builder: createTable, columns, indexes and foreign keys
- Reversible up and down migrations
- npx sutando migrate:run, and migrate:status to check
- Works with MySQL, PostgreSQL, SQLite, MariaDB and SQL Server
const { Migration } = require('sutando');
module.exports = class extends Migration {
async up(schema) {
await schema.createTable('users', (table) => {
table.increments('id');
table.string('name');
table.string('email').unique();
table.timestamps();
});
}
async down(schema) {
await schema.dropTableIfExists('users');
}
};Everything you need, nothing you don't
A complete toolkit for everyday database work — from raw queries to full model relationships.
Query Builder
Build SQL with a fluent, chainable API — where, joins, aggregations, subqueries and pagination.
Model Relationships
hasMany, belongsTo, belongsToMany and more — express your schema in plain, readable code.
Transactions
Wrap your work in transactions with a simple, promise-based API that keeps your data consistent.
Migrations
Version-control your schema and evolve it safely with your team.
Hooks & Soft Deletes
Act on every model lifecycle event, and keep deleted records around until you really need them gone.
Plugins & TypeScript
First-class type definitions and a growing plugin ecosystem.
Ready to get started?
Install Sutando and run your first query in under a minute.