Schema Definition
In ObjectQL, you do not write CREATE TABLE statements, nor do you define Mongoose Schemas or TypeORM Classes. Instead, you define Objects using a standard YAML (or JSON) protocol.
This Schema is the Single Source of Truth. It drives not only the Database structure but also the API validation, the UI generation, and the permission checking.
1. The Object Protocol
An Object in ObjectQL represents a business entity (e.g., Project, Invoice, Employee). It maps roughly to a table in a relational database or a collection in a document database.
Basic Structure
# src/objects/project.object.yml
name: project # Unique API identifier (snake_case)
label: Project # Human-readable label
table_name: projects # (Optional) Physical table name override
icon: standard:account # Icon for ObjectUI
description: A high-level container for tasks and resources.
hidden: false # If true, hidden from the API discovery
2. Fields
Fields define the columns and properties of the object. ObjectQL supports Enterprise Data Types out of the box, ensuring consistency across different underlying databases.
Core Data Types
| Type | Description | Maps to (Postgres) | Maps to (Mongo) |
|---|---|---|---|
text | Single line string | VARCHAR | String |
textarea | Multi-line text | TEXT | String |
html | Rich text | TEXT | String |
number | Double precision | NUMERIC | Number |
currency | High-precision money | DECIMAL(18, 2) | Decimal128 |
boolean | True/False | BOOLEAN | Boolean |
date | Date only | DATE | Date |
datetime | Date and Time | TIMESTAMP | Date |
select | Enum / Dropdown | VARCHAR | String |
Field Configuration
fields:
name:
type: text
label: Project Name
required: true
searchable: true # Creates a database index automatically
index: true
status:
type: select
options:
- label: Planning
value: planning
- label: In Progress
value: in_progress
- label: Completed
value: completed
default: planning
budget:
type: currency
scale: 2
precision: 18
3. Relationships
ObjectQL handles relationships by treating them as Field Types. The compiler automatically generates the necessary Foreign Keys and JOIN logic.
Lookup (Many-to-One)
The most common relationship. A task belongs to a project.
# src/objects/task.object.yml
fields:
project:
type: lookup
reference_to: project # Points to the 'name' of the target Object
required: true
- Database Effect: Creates a
projectcolumn (FK) in thetaskstable. - UI Effect: Renders a searchable dropdown or modal picker.
Master-Detail (Strong Ownership)
Similar to Lookup, but implies ownership. If the Master record is deleted, the Detail records are deleted (Cascade Delete).
# src/objects/invoice_line.object.yml
fields:
invoice:
type: master_detail
reference_to: invoice
write_requires_master_read: true # Security inheritance
Hierarchical (Self-Reference)
An object linking to itself (e.g., an Org Chart or Folder Tree).
fields:
parent_task:
type: lookup
reference_to: task
4. Virtual Fields (Computed)
This is where ObjectQL shines as a Compiler. You can define fields that do not exist in the database but are calculated on-the-fly during the query.
Formula Fields
Compiles to a SQL expression injected into the SELECT clause.
fields:
# Logic: (Total - Cost) / Total
margin_percentage:
type: formula
data_type: number
formula: "({amount} - {cost}) / {amount}"
scale: 2
Summary Fields (Rollups)
Compiles to a SQL Subquery or Aggregation.
# src/objects/project.object.yml
fields:
# Counts all tasks linked to this project where status = 'closed'
closed_task_count:
type: summary
summary_object: task
summary_type: count
summary_field: _id
filters: [["status", "=", "closed"]]
5. The Compilation Process
When you start the ObjectOS engine, it reads these YAML files and performs a Schema Diff:
- Parse: Convert YAML to AST.
- Compare: Check AST against current Database Information Schema.
- Migrate: Generate SQL DDL (
CREATE,ALTER) to synchronize the DB.
Example Output
For the YAML above, the Postgres driver might execute:
CREATE TABLE projects (
_id VARCHAR(50) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
status VARCHAR(50) DEFAULT 'planning',
budget DECIMAL(18, 2)
);
CREATE INDEX idx_projects_name ON projects(name);
:::info Database Agnostic Because the definition is in YAML, switching from PostgreSQL to MySQL requires zero changes to your schema files. You only change the Driver configuration. :::