Models & ORM
Zintrust features a powerful, zero-dependency ORM that provides a clean, ActiveRecord-like interface for interacting with your database.
Defining Models
Models are typically stored in the app/Models directory. You can generate a new model using the CLI:
zin add model UserA basic model looks like this:
import { IModel, Model } from '@orm/Model';
export const User = Model.define(
{
connection: 'default',
table: 'users',
fillable: ['name', 'email', 'password'],
hidden: ['password'],
timestamps: true,
casts: {
is_admin: 'boolean',
metadata: 'json',
},
},
{
isAdmin(model: IModel) {
return model.getAttribute('is_admin') === true;
},
}
);Using Models in Controllers & Services
You can import models using static imports (at module level) or dynamic imports (in async functions):
// ✅ Static import (preferred for top-level code)
import { User } from '@app/Models/User';
export const UserController = {
async index(req, res) {
const users = await User.all();
res.json({ data: users });
},
};// ✅ Dynamic import (preferred in async functions, error handlers)
async function fetchUser(id) {
const { User } = await import('@app/Models/User');
return await User.find(id);
}Both patterns work. Choose based on your context: use static imports for cleaner module-level code, dynamic imports for conditional or error-handling paths.
Multi-Database Support
Zintrust supports multiple database connections. You can specify which connection a model should use by setting connection in Model.define(...).
import { Model } from '@orm/Model';
export const ExternalUser = Model.define({
connection: 'external_db',
table: 'users',
fillable: [],
hidden: [],
timestamps: false,
casts: {},
});You can initialize connections in your application bootstrap:
import { useDatabase } from '@orm/Database';
useDatabase(
{
driver: 'mysql',
host: 'remote-host',
// ...
},
'external_db'
);Querying
The ORM uses a fluent QueryBuilder to construct SQL queries safely.
Basic Queries
// Get all users
const users = await User.query().get();
// Find by ID
const user = await User.query().find(1);
// Where clauses
const activeUsers = await User.query().where('is_active', true).where('age', '>', 18).get();Relationships
Zintrust supports standard relationships: HasOne, HasMany, BelongsTo, and BelongsToMany.
HasMany
import { Post } from '@app/Models/Post';
import { IModel, Model } from '@orm/Model';
export const User = Model.define(
{
table: 'users',
fillable: [],
hidden: [],
timestamps: true,
casts: {},
},
{
posts(model: IModel) {
return model.hasMany(Post);
},
}
);BelongsToMany (Pivot Tables)
import { Tag } from '@app/Models/Tag';
import { IModel, Model } from '@orm/Model';
export const Post = Model.define(
{
table: 'posts',
fillable: [],
hidden: [],
timestamps: true,
casts: {},
},
{
tags(model: IModel) {
return model.belongsToMany(Tag);
},
}
);By default, Zintrust will look for a pivot table named by joining the two table names in alphabetical order (e.g., posts_tags).
Persistence
// Create
const user = User.create({ name: 'John' });
await user.save();
// Update
user.setAttribute('name', 'Jane');
await user.save();
// Delete
await user.delete();