Entity is a core component of Sonamu projects, defining both database tables and TypeScript types together.
What is an Entity?
An Entity is a data model definition that includes:
Database Schema - Table structure, columns, indexes
TypeScript Types - Type definitions for type safety
Relations - Connections with other Entities
Subsets - Field combinations for API responses
Enums - Enumeration types and labels
How to Define an Entity
It’s recommended to visually define Entities in Sonamu UI
(http://localhost:34900/sonamu-ui). Sonamu UI provides auto-completion, validation, and
real-time preview features.
entity.json File Structure
Entities are saved as entity.json files with the following structure:
{
"id" : "User" ,
"table" : "users" ,
"title" : "User" ,
"props" : [ ... ],
"indexes" : [ ... ],
"subsets" : { ... },
"enums" : { ... }
}
File Location : api/src/application/{entity}/{entity}.entity.json
Required Fields
The unique identifier for the Entity. Written in PascalCase .
Used for Entity class names and type names - Example: UserModel, User, UserBaseSchema
table
The database table name. Written in snake_case .
If the table name is omitted, it’s auto-generated based on the Entity ID: - User → users -
BlogPost → blog_posts
title
The display name for the Entity.
props
An array of Entity properties (columns). Each property defines its type and options.
{
"props" : [
{ "name" : "id" , "type" : "integer" , "desc" : "ID" },
{ "name" : "email" , "type" : "string" , "length" : 255 , "desc" : "Email" },
{ "name" : "created_at" , "type" : "date" , "dbDefault" : "CURRENT_TIMESTAMP" }
]
}
Basic Property Options :
Option Type Description Default namestring Property name (snake_case) required typestring Data type required descstring Description - nullableboolean Allow NULL falsedbDefaultstring DB default value -
Optional Fields
parentId
Used when inheriting from another Entity.
{
"id" : "Admin" ,
"parentId" : "User" ,
"title" : "Administrator"
}
Using parentId inherits all props from the parent Entity. Use carefully.
indexes
Defines database indexes.
{
"indexes" : [
{
"type" : "unique" ,
"name" : "users_email_unique" ,
"columns" : [{ "name" : "email" }]
},
{
"type" : "index" ,
"name" : "users_created_at_idx" ,
"columns" : [{ "name" : "created_at" }]
}
]
}
Index Types :
index - Regular index (improves search performance)
unique - Unique index (prevents duplicates)
hnsw - HNSW index for Vector search
ivfflat - IVFFlat index for Vector search
subsets
Defines field combinations for API responses.
{
"subsets" : {
"A" : [ "id" , "email" , "username" , "created_at" ],
"P" : [ "id" , "email" , "username" , "role" ],
"SS" : [ "id" , "email" ]
}
}
Subset Usage :
Usage in Model
Type Inference
async findAll (): Promise < UserSubsetA [] > {
return this.puri()
.select<UserSubsetA>( "A" )
.many();
}
Including Relation Fields :
{
"subsets" : {
"P" : [ "id" , "username" , "employee.id" , "employee.department.name" ]
}
}
Using dot notation in Subsets, you can include fields from related Entities. Sonamu automatically
generates JOINs.
enums
Defines enumeration types and labels.
{
"enums" : {
"UserRole" : {
"normal" : "Normal" ,
"admin" : "Administrator"
},
"UserOrderBy" : {
"id-desc" : "ID Newest First" ,
"created_at-desc" : "Created At Newest First"
},
"UserSearchField" : {
"email" : "Email" ,
"username" : "Name"
}
}
}
Enum Usage :
// Auto-generated Zod schema and TypeScript type
import { UserRole } from "./user.types" ;
// "normal" | "admin"
type Role = z . infer < typeof UserRole >;
// Usage in API
async updateRole ( userId : number , role : Role ) {
// ...
}
Practical Examples
Basic Entity Example
{
"id" : "User" ,
"table" : "users" ,
"title" : "User" ,
"props" : [
{ "name" : "id" , "type" : "integer" , "desc" : "ID" },
{
"name" : "created_at" ,
"type" : "date" ,
"desc" : "Created At" ,
"dbDefault" : "CURRENT_TIMESTAMP"
},
{ "name" : "email" , "type" : "string" , "length" : 255 , "desc" : "Email" },
{ "name" : "username" , "type" : "string" , "length" : 255 , "desc" : "Name" },
{ "name" : "password" , "type" : "string" , "length" : 255 , "desc" : "Password" },
{ "name" : "birth_date" , "type" : "date" , "nullable" : true , "desc" : "Birth Date" },
{ "name" : "role" , "type" : "enum" , "id" : "UserRole" , "desc" : "Role" },
{ "name" : "is_verified" , "type" : "boolean" , "desc" : "Verified" , "dbDefault" : "false" },
{ "name" : "deleted_at" , "type" : "date" , "nullable" : true , "desc" : "Deleted At" }
],
"indexes" : [{ "type" : "unique" , "name" : "users_email_unique" , "columns" : [{ "name" : "email" }] }],
"subsets" : {
"A" : [ "id" , "email" , "username" , "role" , "created_at" ],
"P" : [ "id" , "email" , "username" , "role" ]
},
"enums" : {
"UserRole" : { "normal" : "Normal" , "admin" : "Administrator" },
"UserOrderBy" : { "id-desc" : "ID Newest First" }
}
}
Example with Relations
{
"id" : "Employee" ,
"table" : "employees" ,
"title" : "Employee" ,
"props" : [
{ "name" : "id" , "type" : "integer" , "desc" : "ID" },
{
"name" : "created_at" ,
"type" : "date" ,
"desc" : "Created At" ,
"dbDefault" : "CURRENT_TIMESTAMP"
},
{
"type" : "relation" ,
"name" : "user" ,
"with" : "User" ,
"desc" : "User" ,
"relationType" : "OneToOne" ,
"hasJoinColumn" : true ,
"onDelete" : "CASCADE"
},
{
"type" : "relation" ,
"name" : "department" ,
"with" : "Department" ,
"nullable" : true ,
"desc" : "Department" ,
"relationType" : "BelongsToOne" ,
"onDelete" : "SET NULL"
},
{ "name" : "employee_number" , "type" : "string" , "length" : 32 , "desc" : "Employee Number" },
{
"name" : "salary" ,
"type" : "numeric" ,
"precision" : 10 ,
"scale" : 2 ,
"nullable" : true ,
"desc" : "Salary"
},
{ "name" : "hire_date" , "type" : "date" , "nullable" : true , "desc" : "Hire Date" }
],
"indexes" : [
{
"type" : "unique" ,
"name" : "employees_user_id_unique" ,
"columns" : [{ "name" : "user_id" }]
}
],
"subsets" : {
"A" : [
"id" ,
"created_at" ,
"user.username" ,
"department.name" ,
"employee_number" ,
"salary" ,
"hire_date"
]
},
"enums" : {
"EmployeeOrderBy" : { "id-desc" : "ID Newest First" }
}
}
Defining Entities in Sonamu UI
Access Sonamu UI
# After running API server
http://localhost:34900/sonamu-ui
Create Entity
Click “Entities” tab
Click “Create Entity” button
Enter Entity ID, table name, Title
Add Properties (Props)
Click “Add Property” button to add new properties
Select type and configure options
Change order with drag and drop
Define Subsets
Add subset keys in “Subsets” tab
Select fields to include with checkboxes
Relation fields expand as a tree structure
Save and Generate
Click “Save” button
Entity file auto-generated
Migration auto-generated
What Gets Auto-Generated After Entity Definition
When you define and save an Entity, Sonamu automatically generates the following:
TypeScript Types Types and Zod schemas generated in {entity}.types.ts file
Database Migration Migration file generated with table creation SQL
Base Schemas Base schemas and Enums added to sonamu.generated.ts
Model Scaffold {entity}.model.ts template generated (when selected)
Cautions
Be Careful When Modifying Entity Definitions - Be cautious when deleting columns or changing
types on deployed tables - Recommend making changes gradually through migrations - Consider
referential integrity when changing Relations
Entity Design Tips - Always start IDs with integer type - Include created_at, updated_at
fields - Explicitly specify indexes for fields requiring unique constraints - Add indexes to
frequently searched fields
Next Steps
After completing Entity definition, learn the following topics:
Using Sonamu UI Learn all Sonamu UI features and shortcuts
Field Types Learn all available field types and options
Relations Learn how to define Entity relationships
Enums Learn how to define and use Enum types