You are viewing the Akan.js v1 docs.Go to the latest v2 docs

model.constant.ts

The constant file defines the data shape (schema) of your domain. It ensures consistency between database storage, API communication, and frontend usage by creating a single source of truth.
📐Type Safety
Schema definitions are shared across backend and frontend, ensuring type consistency throughout your application.
🔄Auto Generation
From your constant definitions, the framework auto-generates MongoDB schemas, GraphQL types, REST APIs, and client-side types.

Class Hierarchy Pattern

Akan.js uses a hierarchical class pattern to organize schema definitions. Each layer has a specific purpose and builds upon the previous one.
1
Input
Fields required to create a new document (user-provided data)
2
Object
Input + system-generated fields (status, timestamps, computed values)
3
Light
Lightweight version with selected fields for list queries (prevents overfetching)
4
Full (Model)
Complete model with all fields and static/instance utility methods
5
Insight
Statistical aggregation fields for analytics (count, sum, avg)

Defining Enums with enumOf()

Before defining your model classes, you typically need to define enums for status fields and other categorical values. The enumOf() function creates type-safe enum classes.
product.constant.ts
Key points about enumOf():
as const
Required for TypeScript to infer literal types instead of string[]
First argument
The enum name used in dictionary translations
Generated type
Access values via ProductStatus["value"] type (e.g., "active" | "soldOut" | ...)

Input Class - Creation Fields

The Input class defines fields required when creating a new document. These are the values a user or system must provide.
product.constant.ts
Understanding the via() pattern:
via((field) => ({...}))
Creates a new class with the specified fields. The field() function takes a type and optional options.
field(Type, options?)
Type can be: String, Int, Float, Boolean, Date, JSON, ID, [Array], custom classes, or enums.
.optional()
Chain .optional() to make a field nullable. The field can then be omitted or set to null.
💡Usage in Code
Input fields are used in: fetch.createProduct(input), st.do.setNameOnProduct(value), productForm state

Object Class

The Object class extends Input and adds fields that are automatically set by the system. These fields are typically modified through service methods, not through direct user input.
product.constant.ts
Common Object fields:
status
Document lifecycle state, controlled by service methods
stock
Inventory count, default to 0, modified by sell operations
soldCount
Accumulated sales count for analytics

Light Class - Optimized for Lists

The Light class picks only necessary fields from Object for list views. This prevents overfetching when displaying multiple items in tables or cards.
product.constant.ts
Performance Benefits
When fetching 100 products for a list, Light ensures only essential fields are transferred, reducing payload size and database load.
Field Selection
Choose fields that appear in list UIs: identifiers, status, key metadata. Exclude: content, files, detailed nested objects.
Resolve Function
The (resolve) => ({}) function can add computed/virtual fields that are calculated server-side but not stored in DB.

Full Model - Complete with Methods

The Full model (often named after the domain like 'Product') combines Object and Light, and adds static utility methods for data manipulation.
product.constant.ts
Static Methods
Static methods operate on arrays of items. Use for filtering, grouping, or computing derived data from lists.
Usage Example
const activeProducts = cnst.Product.getActiveList(productList);

Insight Class

The Insight class defines aggregation fields for analytics. When querying, the framework calculates these statistics using MongoDB aggregation pipeline.
product.constant.ts
Understanding the accumulate option:
{ $sum: 1 }
Simple count - adds 1 for each matching document
{ $sum: "$fieldName" }
Sum of field values across all matching documents
{ $cond: [...] }
Conditional aggregation - count only documents matching a condition
Usage in code:
Using Insight

Scalar - Embedded Objects

Scalars are embedded objects that don't have their own collection. They're stored within the parent document and defined using via() without the full class hierarchy.
milestone.constant.ts
Using scalars in parent models:
bizContract.constant.ts
When to use Scalars
Data that belongs to a single parent (1:N embedded). No need for separate queries or references. Data always accessed with parent document.
Scalar Location
Scalars are typically placed in __scalar/ directory to indicate they're embedded types, not standalone collections.

Relation Patterns

There are three main ways to establish relationships between models in Akan.js, following MongoDB schema design principles.
Scalar Embedding
Embed scalar objects directly in the document. Best for 1:N relationships where child data is always accessed with parent.
Reference by ID
Store only the ObjectID of related document. Best when you need to query the referenced collection separately.
Light Model Reference
Embed a Light version of another model. Best when you need key fields without full population.

Field Options Reference

The field() function accepts various options to configure validation, defaults, database behavior, and more. Here's the complete reference:
defaultany | (() => any)
Default value when no value is provided. Can be a static value or a function for dynamic defaults.
nullablebooleandefault false
If true, the field can be null or omitted. Equivalent to using .optional() chain method.
refstring
Reference collection name for ID fields. Used for MongoDB population.
refPathstring
Dynamic reference path - uses another field's value to determine the referenced collection.
refType"child" | "parent" | "relation"
Type of reference relationship. Affects how population and cascading operations work.
type"email" | "password" | "url"
Preset type that applies default validation and example values for common patterns.
fieldType"property" | "hidden" | "resolve"default "property"
property: normal field, hidden: backend-only (not sent to frontend), resolve: computed field (not stored in DB).
immutablebooleandefault false
If true, field cannot be modified after document creation. Only set during create.
minnumber
Minimum value constraint for Int or Float fields. Validation runs on save.
maxnumber
Maximum value constraint for Int or Float fields. Validation runs on save.
minlengthnumber
Minimum string length constraint for String fields.
maxlengthnumber
Maximum string length constraint for String fields.
enumEnumClass
Restrict field values to enum values. Typically used with enumOf() defined classes.
selectbooleandefault true
If false, field is excluded from default queries. Use for sensitive or large fields.
accumulateobject
MongoDB aggregation expression for Insight fields. Calculates statistics across matched documents.
exampleany
Example value for API documentation generation (Swagger/OpenAPI).
ofType
Value type for Map fields. The key is always string, value type is specified by 'of'.
validate(value, model) => boolean
Custom validation function. Receives the field value and full model, returns boolean.
text"search" | "filter"
Enable text indexing for full-text search (search) or filtering (filter) capabilities.
metaobject
Custom metadata object for additional field information used by UI components or plugins.
fieldType Options
property
Normal field - stored in DB, sent to frontend
hidden
Backend only - stored in DB but never sent to frontend (e.g., OTP codes)
resolve
Virtual field - computed on query, not stored in DB (e.g., view count from other collection)
refType Options
parent
This document belongs to the referenced document
child
Referenced document belongs to this document
relation
Many-to-many relationship without ownership
Common field patterns:
Common Field Patterns

Constant Best Practices

Class Ordering
Define in order: Enums → Input → Object → Light → Full → Insight. This prevents forward reference issues.
Light Field Selection
Include: id, status, key identifiers, timestamps. Exclude: large content fields, files, detailed nested objects.
Default Values
Always provide defaults for Object fields. Use functions for dynamic values like dates: () => dayjs()
Static Methods
Add static utility methods to Full class for filtering/grouping logic. Keep them pure (no side effects).
Import Paths
Always use direct file imports for other constants to avoid circular references. Never import from barrel files.

Released under the MIT License

Connect your AI to these docs

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js All rights reserved.System managed bybassman