Scalar Constant Implementation Guide

Scalar constants serve as foundational building blocks for complex data modeling in Akan.js applications. They define reusable value objects that can be embedded in other models without creating separate database collections.
File Structure and Location
Scalar constants follow strict naming conventions and directory structure:

# File location convention
{app,lib}/
└── */lib/__scalar/
    └── <scalarName>/               # camelCase directory
        └── <scalarName>.constant.ts  # scalar definition file
        
ElementConventionExample
Directory
1camelCase
1geoLocation
File
1<scalarName>.constant.ts
1geoLocation.constant.ts
Class
1PascalCase
1GeoLocation
Enum Values
1camelCase
1active, pendingApproval
Model Definition
Scalar models follow a strict single-responsibility pattern with essential decorators:
1
2import { Field, Model } from "@akanjs/constant";
3
4@Model.Scalar("ScalarName") // Must match class name exactly
5export class ScalarName {
6  @Field.Prop(() => FieldType, { ...options })
7  fieldName: FieldType;
8}
9        
Critical: The string passed to @Model.Scalar() must match the class name exactly
Field Definitions
Field definitions support various types with configurable validation options:
1
2// Basic field types
3@Field.Prop(() => String)
4name: string;
5
6@Field.Prop(() => Int)
7quantity: number;
8
9@Field.Prop(() => Float)
10percentage: number;
11
12@Field.Prop(() => Boolean)
13isActive: boolean;
14
15@Field.Prop(() => Date)
16timestamp: Dayjs;  // Always use Dayjs for dates
17
18// Special field types
19@Field.Hidden(() => String)
20internalCode: string;
21
22@Field.Secret(() => String)
23apiKey: string;
24
25@Field.Resolve(() => Int)
26get total(): number {
27  return this.items.length;
28}
29        
Field Options
default:Any:undefined

Default field value

1{ default: 0 }
nullable:Boolean:false

Allows null values

1{ nullable: true }
enum:Enum:-

Restricts to enum values

1{ enum: Status }
min:Number:-

Minimum numeric value

1{ min: 0 }
max:Number:-

Maximum numeric value

1{ max: 100 }
minlength:Number:-

Minimum string length

1{ minlength: 3 }
maxlength:Number:-

Maximum string length

1{ maxlength: 255 }
example:Any:-

Example value for documentation

1{ example: [0,0] }
validate:Function:-

Custom validation function

1{ validate: (v) => v > 0 }
immutable:Boolean:false

Prevents modification after creation

1{ immutable: true }
select:Boolean:true

Includes in query results by default

1{ select: false }
text:String:-

Enables text search capabilities

1{ text: 'search' }
Complex Field Types
Scalar constants support advanced field types for complex data structures:
1
2// Array fields
3@Field.Prop(() => [String])
4tags: string[];
5
6@Field.Prop(() => [[Int]])
7matrix: number[][];
8
9@Field.Prop(() => [OtherScalar])
10items: OtherScalar[];
11
12// Map fields
13@Field.Prop(() => Map, {
14  of: String,  // Must specify value type
15  default: new Map()
16})
17metadata: Map<string, string>;
18
19// Enum implementation (camelCase values)
20export const Status = enumOf(["active", "inactive"] as const);
21export type Status = enumOf<typeof Status>;
22
23@Field.Prop(() => String, {
24  enum: Status,
25  default: "active"
26})
27status: Status;
28        
Static Methods
Add utility methods directly to scalar classes for domain-specific operations:
1
2@Model.Scalar("Coordinate")
3export class Coordinate {
4  @Field.Prop(() => [Float], { default: [0, 0] })
5  coordinates: number[];
6
7  // Calculate distance between coordinates
8  static getDistanceKm(loc1: Coordinate, loc2: Coordinate) {
9    const [lon1, lat1] = loc1.coordinates;
10    const [lon2, lat2] = loc2.coordinates;
11    // Distance calculation logic
12    return distance;
13  }
14}
15        
Common Mistakes
IssueWrongCorrect
Incorrect Enum Case
1enumOf(['ACTIVE', 'INACTIVE'])
1enumOf(['active', 'inactive'])
Incorrect Array Syntax
1() => Array<Int>
1() => [Int]
Missing Nullable Type
1description: string;
1description: string | null;
Improper Enum Implementation
1const Status = enumOf(['active'])
1export const Status = enumOf(['active'])
Multiple Models
1Multiple @Model.Scalar per file
1Single scalar per file
Incorrect Date Handling
1createdAt: Date;
1createdAt: Dayjs;
Full Examples
Practical implementations demonstrating various scalar patterns:
1
2// Basic scalar example
3@Model.Scalar("Amount")
4export class Amount {
5  @Field.Prop(() => Float, { min: 0, default: 0 })
6  value: number;
7
8  @Field.Prop(() => String, { default: "USD" })
9  currency: string;
10}
11
12// Complex scalar with enums
13@Model.Scalar("GeoLocation")
14export class GeoLocation {
15  @Field.Prop(() => Float, { min: -90, max: 90 })
16  latitude: number;
17  
18  @Field.Prop(() => Float, { min: -180, max: 180 })
19  longitude: number;
20  
21  @Field.Prop(() => String, { 
22    enum: AccuracyLevel,
23    default: "medium" 
24  })
25  accuracy: AccuracyLevel;
26}
27
28// Scalar with nested objects
29@Model.Scalar("ProductSpec")
30export class ProductSpec {
31  @Field.Prop(() => String)
32  sku: string;
33  
34  @Field.Prop(() => [String], { default: [] })
35  colors: string[];
36  
37  @Field.Prop(() => Dimension)
38  size: Dimension;
39}
40        
Implementation Checklist
  • Location: __scalar/<camelCase>/<camelCase>.constant.ts
  • Structure: Single @Model.Scalar class per file
  • Naming: Class name = PascalCase directory name
  • Decorator: @Model.Scalar('ClassName') with exact match
  • Enum Values: Always camelCase (active, not ACTIVE)
  • Fields: Use @Field.Prop with arrow function types
  • Arrays: Wrap in [] (e.g., [Int])
  • Enums: Export with enumOf and derived type
  • Dates: Always use Dayjs type with Date decorator
  • Nullability: Use | null with { nullable: true }
  • Validation: Implement field-level constraints
Tip: Scalar constants are value objects - they should not contain ID or timestamp fields
Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman