Skip to main content
Sonamu supports various data types, and each type is appropriately mapped to PostgreSQL, TypeScript, and JSON.

Common Options

Options that apply to all field types.
OptionTypeDescriptionDefault
namestringField name (snake_case)required
typestringData typerequired
descstringField description-
nullablebooleanAllow NULLfalse
toFilterbooleanEnable search filteringfalse
dbDefaultstringDatabase default value-
generatedGeneratedColumnComputed column setting-

Generated Column

A column that automatically generates computed values.
{
  "name": "full_name",
  "type": "string",
  "generated": {
    "type": "STORED",
    "expression": "first_name || ' ' || last_name"
  }
}
Options:
  • type: STORED | VIRTUAL
    • STORED: Physically stored (can create indexes)
    • VIRTUAL: Calculated only on query (saves memory)
  • expression: SQL expression
  • VIRTUAL type cannot be used with array types, json, or vector
  • generated and dbDefault cannot be used together

Numeric Types

integer / integer[]

32-bit integer type.
{
  "name": "age",
  "type": "integer",
  "desc": "Age"
}
Mapping:
  • PostgreSQL: integer
  • TypeScript: number
  • JSON: number
Range: -2,147,483,648 ~ 2,147,483,647
Use cases: ID, count, age, order, year

bigInteger / bigInteger[]

64-bit integer type.
{
  "name": "transaction_id",
  "type": "bigInteger",
  "desc": "Transaction ID"
}
Mapping:
  • PostgreSQL: bigint
  • TypeScript: bigint
  • JSON: bigint (serialized as string)
Range: -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
Values exceeding JavaScript’s Number.MAX_SAFE_INTEGER (2^53 - 1) must use bigint to maintain accuracy.

number / number[]

Floating-point or fixed-point numeric type.
{
  "name": "price",
  "type": "number",
  "precision": 10,
  "scale": 2,
  "desc": "Price"
}
Mapping:
  • PostgreSQL: numeric(10, 2) (default)
  • TypeScript: number
  • JSON: number
Additional Options:
  • precision: Total digits (default: none = unlimited)
  • scale: Decimal places (default: 0)
  • numberType: numeric | real | double precision (default: numeric)
numberType Selection Guide:
TypePrecisionMemoryUse Cases
numericExact (recommended)HighMoney, currency
realApproximate (6 digits)4 bytesScientific data
double precisionApproximate (15 digits)8 bytesCoordinates, measurements
Money handling: Setting precision: 10, scale: 2 allows storing up to 99,999,999.99

numeric / numeric[]

High-precision numeric type. Processed as string in TypeScript.
{
  "name": "precise_amount",
  "type": "numeric",
  "precision": 20,
  "scale": 10,
  "desc": "High-precision amount"
}
Mapping:
  • PostgreSQL: numeric(20, 10)
  • TypeScript: string ⚠️
  • JSON: string
Additional Options:
  • precision: Total digits
  • scale: Decimal places
Difference between number and numeric:
  • number: number type in TypeScript (possible precision loss)
  • numeric: string type in TypeScript (maintains precision)
Use numeric when you need large numbers or very precise decimal calculations.

String Types

string / string[]

Variable-length string type.
{
  "name": "email",
  "type": "string",
  "length": 255,
  "zodFormat": "email",
  "desc": "Email"
}
Mapping:
  • PostgreSQL: varchar(255) (when length specified) or text
  • TypeScript: string
  • JSON: string
Additional Options:
  • length: Maximum length (uses text type when omitted)
  • zodFormat: Zod 4 String Format validation (see below)

zodFormat Option

The zodFormat option automatically applies Zod’s string format validation when generating BaseSchema. Usage Example:
{
  "name": "user_email",
  "type": "string",
  "zodFormat": "email",
  "desc": "User email"
}
Supported Formats:
CategoryFormatDescription
BasicemailEmail address format
uuidUUID format
urlURL format
httpUrlHTTP/HTTPS URL format
hostnameHostname format
emojiEmoji format
jwtJWT token format
Encodingbase64Base64 encoding
base64urlURL-safe Base64 encoding
hexHexadecimal string
IDnanoidNanoID format
cuidCUID format
cuid2CUID2 format
ulidULID format
Networkipv4IPv4 address
ipv6IPv6 address
macMAC address
cidrv4IPv4 CIDR notation
cidrv6IPv6 CIDR notation
HashhashMd5MD5 hash
hashSha1SHA-1 hash
hashSha256SHA-256 hash
hashSha384SHA-384 hash
hashSha512SHA-512 hash
ISOisoDateISO 8601 date (YYYY-MM-DD)
isoTimeISO 8601 time (HH:MM:SS)
isoDatetimeISO 8601 datetime
isoDurationISO 8601 duration
length Setting Guide:
  • Short text (name, email): 255
  • Long text (description, content): omit (text type)
  • Fixed length (zip code, phone number): specify exact length
Difference between zodFormat and uuid type:
  • type: "uuid": Uses PostgreSQL’s native uuid column type, enabling UUID-specific indexes and functions
  • type: "string" + zodFormat: "uuid": Uses PostgreSQL’s text/varchar column while validating UUID format only at the API level

enum / enum[]

Enumeration type. Only values defined in the Entity’s enums are allowed.
{
  "name": "role",
  "type": "enum",
  "id": "UserRole",
  "desc": "User role"
}
Mapping:
  • PostgreSQL: text
  • TypeScript: "admin" | "normal" (Union of Enum keys)
  • JSON: string
Additional Options:
  • id: Enum type ID (must be defined in Entity’s enums)
  • length: String max length (optional)
Enum Definition Example:
{
  "props": [
    {
      "name": "role",
      "type": "enum",
      "id": "UserRole"
    }
  ],
  "enums": {
    "UserRole": {
      "admin": "Administrator",
      "normal": "Normal User"
    }
  }
}
Learn More
  • Enums - Detailed Enum guide

Boolean Type

boolean / boolean[]

Type for storing true/false values.
{
  "name": "is_active",
  "type": "boolean",
  "dbDefault": "true",
  "desc": "Active status"
}
Mapping:
  • PostgreSQL: boolean
  • TypeScript: boolean
  • JSON: boolean
Default value setting: dbDefault: "true" or dbDefault: "false"

Date/Time Types

date / date[]

Type for storing date and time.
{
  "name": "created_at",
  "type": "date",
  "dbDefault": "CURRENT_TIMESTAMP",
  "desc": "Created at"
}
Mapping:
  • PostgreSQL: timestamptz (with timezone)
  • TypeScript: Date
  • JSON: string (ISO 8601 format)
Commonly used default values:
  • CURRENT_TIMESTAMP: Current time
  • CURRENT_DATE: Current date (time 00:00:00)

UUID Type

uuid / uuid[]

Universally Unique Identifier (UUID) type.
{
  "name": "session_id",
  "type": "uuid",
  "dbDefault": "gen_random_uuid()",
  "desc": "Session ID"
}
Mapping:
  • PostgreSQL: uuid
  • TypeScript: string
  • JSON: string
UUID Generation: Using PostgreSQL’s gen_random_uuid() function as dbDefault enables auto-generation.

Structured Data Types

json

Type for storing structured data in JSON format.
{
  "name": "metadata",
  "type": "json",
  "id": "ProductMetadata",
  "nullable": true,
  "desc": "Product metadata"
}
Mapping:
  • PostgreSQL: json
  • TypeScript: User-defined type (ProductMetadata)
  • JSON: any
Additional Options:
  • id: TypeScript type ID (defined in .types.ts)
Type Definition Example:
{
  "name": "metadata",
  "type": "json",
  "id": "ProductMetadata"
}
JSON types can be difficult to index and may have lower performance. It’s recommended to separate frequently searched fields into separate columns.

virtual

Virtual fields not stored in the database.
{
  "name": "full_name",
  "type": "virtual",
  "id": "string",
  "virtualType": "code",
  "desc": "Full name"
}
Mapping:
  • PostgreSQL: Not stored
  • TypeScript: User-defined type (or string, number, etc.)
  • JSON: Included (after calculation)
Additional Options:
  • id: TypeScript type ID
  • virtualType: code | query (default: code)
    • code: Calculated with TypeScript code
    • query: Calculated with SQL appendSelect
virtualType Comparison:
Calculated with TypeScript code in Model.
// {entity}.model.ts
enhanceRow(row: User): User {
  return {
    ...row,
    full_name: `${row.first_name} ${row.last_name}`
  };
}
Pros: Can implement complex logic, can call external APIs Cons: Cannot filter/sort at database level
virtualType Selection Guide:
  • Simple string concatenation, arithmetic calculations → query
  • Complex business logic, external API calls → code

Vector Types

vector / vector[]

Type for storing vector embeddings. Requires pgvector extension.
{
  "name": "embedding",
  "type": "vector",
  "dimensions": 1536,
  "desc": "Text embedding"
}
Mapping:
  • PostgreSQL: vector(1536) (pgvector extension)
  • TypeScript: number[]
  • JSON: number[]
Additional Options:
  • dimensions: Vector dimensions (required, e.g., 1536)
Vector Search Example:
// Search by cosine similarity
async searchSimilar(queryEmbedding: number[]) {
  return this.puri()
    .whereRaw("embedding <=> ?", [JSON.stringify(queryEmbedding)])
    .orderByRaw("embedding <=> ?", [JSON.stringify(queryEmbedding)])
    .limit(10)
    .many();
}
Vector Index:
{
  "indexes": [
    {
      "type": "hnsw",
      "name": "posts_embedding_idx",
      "columns": [
        {
          "name": "embedding",
          "vectorOps": "vector_cosine_ops"
        }
      ],
      "m": 16,
      "efConstruction": 64
    }
  ]
}
Learn More

tsvector

Type for PostgreSQL Full-Text Search.
{
  "name": "search_vector",
  "type": "tsvector",
  "generated": {
    "type": "STORED",
    "expression": "to_tsvector('english', title || ' ' || content)"
  }
}
Mapping:
  • PostgreSQL: tsvector
  • TypeScript: string
  • JSON: string
Full-Text Search Index:
{
  "indexes": [
    {
      "type": "index",
      "name": "posts_search_vector_idx",
      "columns": [{ "name": "search_vector" }],
      "using": "gin"
    }
  ]
}
Full-Text Search: A type optimized for keyword searching in natural language text. Supports morphological analysis, stemming, etc.

Relation Type

Type for defining relationships with other Entities.
{
  "type": "relation",
  "name": "user",
  "with": "User",
  "relationType": "BelongsToOne",
  "desc": "Author"
}
Relation Types:
  • BelongsToOne: N:1 relationship
  • OneToOne: 1:1 relationship
  • HasMany: 1:N relationship
  • ManyToMany: N:M relationship
Learn More

Type Selection Guide

Storing Numbers

DataTypeReason
ID, age, countintegerCommon integers
Large ID, timestampbigIntegerLarge range needed
Money, pricenumber (precision, scale)Precise decimals
Scientific measurementsnumber (numberType: real)Approximate values allowed
High-precision calculationsnumericPrevent precision loss

Storing Strings

DataTypeReason
Name, emailstring (length: 255)Common text
Description, contentstring (omit length)Long text
Status, roleenumLimited value list
UUID, tokenuuidUnique identifier

Storing Date/Time

DataTypeSetting
Created atdatedbDefault: "CURRENT_TIMESTAMP"
Updated atdateUpdate trigger needed
Date onlydateTime is 00:00:00

Complex Data

DataTypeReason
Settings, metadatajsonStructured data
Computed fieldsvirtualNo storage needed
Text embeddingsvectorAI search
Full-text searchtsvectorKeyword search

Next Steps