HotCRM Logo

Data Layer Protocol (ObjectQL)

The core metadata protocol defining Objects, Fields, Validations, and Logic.

Data Layer Protocol (ObjectQL)

The HotCRM architecture is Metadata-Driven. All business entities, logic, and limitations are defined in declarative TypeScript files.

🟢 P0 Core Metadata

1.1 Object Definition

Location: packages/{pkg}/src/{entity}.object.ts

The foundational unit of the system. Represents a database table and its business rules.

interface ServiceObject {
  name: string;              // unique_snake_case (e.g., 'project_task')
  label: string;             // Human readable (e.g., 'Project Task')
  description?: string;
  fields: Record<string, Field>;
  
  // Functional Switches
  enable?: {                 
    trackHistory?: boolean;  // Audit Log
    apiEnabled?: boolean;    // REST/GraphQL API
    search?: boolean;        // Global Search Index
    activities?: boolean;    // Attach Tasks/Events
  };
}

1.2 Field Definition

Location: Inside ServiceObject.fields

We support 20+ field types to handle rich business data.

TypeDescriptionExample
textShort text (<255)Name, Code
textareaLong textDescription
numberInteger/FloatQty, Age
currencyMoneyPrice, Amount
percentPercentageDiscount Rate
date / datetimeTemporalDue Date
booleanTrue/FalseIs Active
selectDropdownStatus
multiselectMulti-TagsSkills
lookupReference-> Customer
master_detailStrong reference-> Order
formulaCalculationprice * qty
summaryRollup aggregationSUM(amount)

1.3 Validation Rules

Location: ServiceObject.validation

Server-side data integrity rules.

{
  name: 'valid_discount',
  errorMessage: 'Discount must be 0-100',
  formula: 'discount_rate >= 0 && discount_rate <= 100'
}

1.4 Query Protocol (ObjectQL)

Location: *.hook.ts or *.action.ts

Platform-agnostic data access layer.

Query Structure:

interface Query {
  object: string;
  fields?: string[];
  filters?: Filter;
  sort?: string[];
  limit?: number;
}

Filter Operators:

  • equals / =
  • not_equals / !=
  • contains (LIKE)
  • starts_with
  • greater_than / >
  • in (Array include)

1.5 Lifecycle Hooks

Location: packages/{pkg}/src/{entity}.hook.ts

Triggers that execute custom logic during record changes.

  • before_create / after_create
  • before_update / after_update
  • before_delete / after_delete

Example:

// Auto-number generation
{
  type: 'before_create',
  handler: async (context) => {
    context.record.code = await generateCode();
  }
}

On this page