Type System
Complete reference for ObjectQL field types - Scalars, relationships, computed fields, and advanced types
ObjectQL provides 20+ specialized field types that encode business semantics, not just data storage primitives. Each type understands its purpose and automatically configures database schemas, UI renderers, validation rules, and API serialization.
Type Philosophy
Traditional databases:
-- Just stores data
CREATE TABLE customer (
revenue DECIMAL(18,2) -- Is this USD? EUR? Monthly? Annual?
);ObjectQL:
# Encodes business meaning
revenue:
type: currency
label: Annual Revenue
scale: 2
precision: 18
# Automatically knows:
# - Store amount + currency code
# - UI shows currency symbol
# - Validate numeric precision
# - Format for display ($1,234.56)Type Categories
Scalar Types
Primitive values: text, numbers, dates, booleans
Relationship Types
Lookups, master-detail, hierarchical (tree) references
Computed Types
Formulas, rollup summaries, auto-numbers
Complex Types
JSON, tags, geolocation, file attachments
1. Scalar Types
Text Types
text
Single-line text field.
company_name:
type: text
label: Company Name
maxLength: 255
required: true
searchable: trueDatabase mapping:
- PostgreSQL:
VARCHAR(maxLength)orTEXT - MongoDB:
String - Redis:
String
UI rendering:
<input type="text" maxlength="255" required />Use cases:
- Names, titles, identifiers
- Email addresses, phone numbers
- Short descriptions
textarea
Multi-line plain text.
description:
type: textarea
label: Description
maxLength: 5000Database mapping:
- PostgreSQL:
TEXT - MongoDB:
String
UI rendering:
<textarea rows="10" maxlength="5000"></textarea>Use cases:
- Comments, notes
- Descriptions
- Plain text content
html
Rich text with HTML markup.
bio:
type: html
label: BiographyDatabase mapping:
- PostgreSQL:
TEXT - MongoDB:
String
UI rendering:
<!-- Rich text editor (TinyMCE, Quill, etc.) -->
<div class="rich-text-editor"></div>Use cases:
- Blog posts, articles
- Product descriptions
- Email templates
email
Email address with validation.
email:
type: email
label: Email Address
required: true
unique: true
index: trueValidation:
- RFC 5322 compliant regex
- Lowercase normalization
- Domain validation (optional DNS check)
Database mapping:
- PostgreSQL:
VARCHAR(255) - MongoDB:
String
Use cases:
- User emails
- Contact information
- Notification addresses
url
URL with protocol validation.
website:
type: url
label: WebsiteValidation:
- Must include protocol (
http://,https://) - Valid domain format
- Optional reachability check
Use cases:
- Company websites
- Social media links
- API endpoints
phone
Phone number with international format.
phone:
type: phone
label: Phone Number
format: international # E.164 formatStorage format: E.164 (+12025551234)
Display format: (202) 555-1234
Validation:
- Valid phone number format
- Country code verification
- Optional SMS capability check
Numeric Types
number
General-purpose numeric field.
quantity:
type: number
label: Quantity
min: 0
max: 9999
scale: 0 # Integer
defaultValue: 1Configuration:
scale: Decimal places (0 = integer)precision: Total digitsmin/max: Range validation
Database mapping:
- PostgreSQL:
NUMERIC(precision, scale) - MongoDB:
NumberorDecimal128
Use cases:
- Quantities, counts
- Ratings, scores
- General measurements
currency
Money amount with currency code.
annual_revenue:
type: currency
label: Annual Revenue
currencyConfig:
precision: 2
currencyMode: fixed
defaultCurrency: USDStorage:
{
"value": 1234.56,
"currency": "USD"
}Features:
- Multi-currency support
- Automatic formatting ($1,234.56)
- Exchange rate conversion (optional)
- ISO 4217 currency codes
Database mapping:
- PostgreSQL:
NUMERIC(18,2)+VARCHAR(3)orJSONB - MongoDB:
{ value: Decimal128, currency: String }
percent
Percentage value (0-100).
discount_rate:
type: percent
label: Discount
scale: 2
min: 0
max: 100Display: 25.5% (automatically adds % symbol)
Storage: As decimal (0.255 for 25.5%)
Use cases:
- Discounts, margins
- Completion rates
- Tax rates
Date/Time Types
date
Calendar date (no time component).
birth_date:
type: date
label: Date of BirthStorage format: ISO 8601 (2024-01-15)
Database mapping:
- PostgreSQL:
DATE - MongoDB:
Date(time set to 00:00:00 UTC)
Use cases:
- Birthdays, anniversaries
- Contract dates
- Deadlines
datetime
Date and time with timezone.
meeting_time:
type: datetime
label: Meeting TimeStorage format: ISO 8601 with timezone (2024-01-15T14:30:00Z)
Database mapping:
- PostgreSQL:
TIMESTAMP WITH TIME ZONE - MongoDB:
Date
time
Time of day (no date component).
business_hours_start:
type: time
label: Business Hours Start
defaultValue: "09:00:00"Storage format: HH:MM:SS — input accepts HH:MM or HH:MM:SS (with an optional fractional part and Z/offset). A time is a wall-clock value, not an instant: it is validated as a time-of-day, not parsed as a date.
Use cases:
- Business hours
- Recurring event times
- Time-based triggers
Boolean Types
boolean
True/false value.
is_active:
type: boolean
label: Active
defaultValue: trueStorage:
- PostgreSQL:
BOOLEAN - MongoDB:
Boolean - Redis:
1or0
UI rendering:
<input type="checkbox" />
<!-- or -->
<select>
<option value="true">Yes</option>
<option value="false">No</option>
</select>toggle
Boolean displayed as a toggle switch.
email_opt_in:
type: toggle
label: Subscribe to Newsletter
defaultValue: falseDifference from boolean:
- Always renders as a toggle switch (not a dropdown)
- Typically used for consent, preferences, on/off settings
Selection Types
select
Dropdown/picklist from predefined options.
priority:
type: select
label: Priority
options:
- value: low
label: Low
color: green
- value: medium
label: Medium
color: yellow
- value: high
label: High
color: orange
- value: critical
label: Critical
color: red
defaultValue: medium
required: trueStorage: Stores value (not label)
Database mapping:
- PostgreSQL:
VARCHARorENUM - MongoDB:
String
Use cases:
- Status, stage, priority
- Categories, types
- Fixed value lists
multiselect
Multiple selection from options.
tags:
type: multiselect
label: Tags
options:
- { value: customer, label: Customer }
- { value: partner, label: Partner }
- { value: vendor, label: Vendor }
# multiple: true # Implied by typeStorage:
- PostgreSQL:
TEXT[](array) orJSONB - MongoDB:
[String]
Example value: ['customer', 'partner']
radio
Radio button group (single selection).
contact_method:
type: radio
label: Preferred Contact Method
options:
- { value: email, label: Email }
- { value: phone, label: Phone }
- { value: sms, label: SMS }Difference from select:
- All options visible (no dropdown)
- Better UX for 2-5 options
2. Relationship Types
lookup
Foreign key reference to another object.
account_id:
type: lookup
label: Account
reference: account
required: true
referenceFilters:
- "is_active = true"
deleteBehavior: set_null # or restrict, cascadeStorage: Stores id of referenced record
Query behavior:
// Automatic JOIN
const opportunities = await ObjectQL.query({
object: 'opportunity',
fields: ['name', 'account.company_name'] // Joins account
});On Delete Options:
set_null: Set field to null when referenced record is deletedrestrict: Prevent deletion if references existcascade: Delete this record when referenced record is deleted
Required foreign keys. A
required: truelookup cannot be nulled, so the defaultset_nullautomatically escalates torestricton such a field — deleting the parent is refused with409 DELETE_RESTRICTED(the response carriesdependentObjectanddependentCount) instead of a confusing "<field> is required" validation error. To delete the children along with the parent, setdeleteBehavior: cascadeexplicitly. An explicitset_nullorcascadeis always honored as written.
Multiple lookups:
contacts:
type: lookup
reference: contact
multiple: true # Many-to-manyDatabase mapping:
- PostgreSQL:
UUID+ Foreign Key constraint - MongoDB:
ObjectIdorString
master_detail
Strong parent-child relationship.
project_id:
type: master_detail
label: Project
reference: project
deleteBehavior: cascade # Enforced by type usuallyCharacteristics:
- Ownership: Child cannot exist without parent
- Cascade delete: Deleting parent deletes all children
- Sharing inheritance: Child inherits parent's permissions
- Rollup support: Parent can aggregate child data
Difference from lookup:
| Feature | Lookup | Master-Detail |
|---|---|---|
| Deletion | Configurable | Always cascade |
| Permissions | Independent | Inherited |
| Required | Optional | Always required |
| Use case | Loose reference | Ownership |
Example:
# Order (Master)
name: order
# Order Line Item (Detail)
name: order_line_item
fields:
order_id:
type: master_detail
reference: ordertree
Hierarchical reference for parent-child trees.
parent:
type: tree
label: Parent
reference: categoryStorage: Stores the id of the referenced parent record.
Use cases:
- Category / folder hierarchies
- Org charts
- Any self-referential tree
A single polymorphic field type (one field that can point at several different
object types, e.g. Account or Contact) is not currently a built-in field
type. The FieldType enum exposes lookup, master_detail, and tree; the
reference property accepts a single target object name, not a list. Model
"related to any object" use cases (activity feeds, attachments, comments) with
separate lookups or an application-level type discriminator.
3. Computed Types
formula
Calculated field based on other fields.
total_price:
type: formula
label: Total Price
expression: "record.quantity * record.unit_price"Formula expressions use CEL (Common Expression Language). Fields on the
current record are referenced via the record. scope. CEL syntax differs from
spreadsheet/Salesforce formula languages:
- Arithmetic:
+,-,*,/,% - Comparison:
==,!=,>,<,>=,<= - Logical:
&&,||,! - Conditional: ternary
cond ? a : b(there is noIF()function) - Functions:
today(),daysFromNow(),daysBetween(),len(),size(),upper(),lower(),trim(),contains(),startsWith(),coalesce(),min(),max(),abs(),round(), and more (see the formula reference).
Examples:
# Simple calculation
discount_amount:
type: formula
expression: "record.price * (record.discount_rate / 100)"
# Conditional logic (CEL ternary)
status_label:
type: formula
expression: "record.is_active ? 'Active' : 'Inactive'"
# Cross-object formula (via expanded lookup)
account_revenue_tier:
type: formula
expression: "record.account.annual_revenue > 1000000 ? 'Enterprise' : 'SMB'"
# Date calculation
days_until_due:
type: formula
expression: "daysBetween(today(), record.due_date)"summary (Rollup)
Aggregate child records in master-detail relationship.
# On Account object
total_opportunities:
type: summary
label: Total Opportunities
summaryOperations:
object: opportunity
function: count
total_opportunity_value:
type: summary
label: Pipeline Value
summaryOperations:
object: opportunity
field: amount
function: sumSummary Types:
count: Count child recordssum: Sum a numeric fieldmin: Minimum valuemax: Maximum valueavg: Average value
Requirements:
- Aggregates a child object that references this object (via its
lookup/master_detailfield) - Set
relationshipFieldonly when the child has more than one reference back to this object
Database implementation:
- Materialized view (PostgreSQL)
- Aggregation pipeline (MongoDB)
- Background job recalculation
Performance:
- Real-time: Recalculate on child write (slow)
- Batch: Update every N minutes (stale data)
- Hybrid: Increment/decrement on simple changes
autonumber
Auto-incrementing unique identifier.
case_number:
type: autonumber
label: Case Number
autonumberFormat: "CASE-{0000}"Example values: CASE-0001, CASE-0002, ...
Format tokens:
{0000}: Zero-padded number{YYYY}: Year{MM}: Month{DD}: Day
Complex formats:
invoice_number:
type: autonumber
autonumberFormat: "INV-{YYYY}-{0000}"
# Generates: INV-2024-0001, INV-2024-0002, ...Database implementation:
- PostgreSQL:
SEQUENCE - MongoDB: Atomic counter collection
4. Complex Types
json
Unstructured JSON data.
metadata:
type: json
label: MetadataStorage:
- PostgreSQL:
JSONB - MongoDB: Native object
Query support:
// Query JSON properties
const products = await ObjectQL.query({
object: 'product',
filters: [
['metadata.color', '=', 'red']
]
});Use cases:
- Product attributes (varying by category)
- Integration payloads
- User preferences
- Dynamic configurations
tags
Simple list of free-form string tags.
tags:
type: tags
label: TagsThere is no generic array field type. To store multiple values, use tags
(free-form strings), multiselect (multiple choices from options), or set
multiple: true on a scalar/lookup field to store an array of that type.
Storage:
- PostgreSQL:
TEXT[]orJSONB - MongoDB:
[String]
address
Structured address with geocoding.
billing_address:
type: address
label: Billing Address
allowGeocoding: true # Allow address-to-coordinate conversionStructure:
{
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"postalCode": "94105",
"country": "USA",
"countryCode": "US",
"formatted": "123 Main St, San Francisco, CA 94105"
}Database mapping:
- PostgreSQL:
JSONBor composite type - MongoDB: Embedded document
location
Geographic coordinates.
office_location:
type: location
label: Office LocationStorage:
{
"latitude": 37.7749,
"longitude": -122.4194
}Query:
// Find nearby locations (within 10 miles)
const nearby = await ObjectQL.query({
object: 'store',
filters: [
['location', 'near', { lat: 37.7749, lng: -122.4194, distance: 10, unit: 'miles' }]
]
});Database mapping:
- PostgreSQL:
POINTorGEOGRAPHY - MongoDB: GeoJSON
file
File attachment reference.
avatar:
type: file
label: Profile Picture
fileAttachmentConfig:
allowedMimeTypes: [image/png, image/jpeg]
maxSize: 5242880 # 5MB
storageProvider: s3Storage:
{
"filename": "profile.jpg",
"content_type": "image/jpeg",
"size": 1024000,
"url": "https://cdn.example.com/files/abc123.jpg"
}Storage backends:
local: Server filesystems3: Amazon S3azure: Azure Blob Storagegcs: Google Cloud Storage
Features:
- Automatic upload handling
- Content-type validation
- Virus scanning (optional)
- CDN integration
image
Image file with transformations.
product_image:
type: image
label: Product Image
fileAttachmentConfig:
allowedMimeTypes: [image/png, image/jpeg, image/webp]
imageValidation:
maxWidth: 4096
maxHeight: 4096
generateThumbnails: true
thumbnailSizes:
- { name: thumbnail, width: 150, height: 150, crop: true }
- { name: large, width: 1200, height: 800, crop: false }Features:
- Image dimension validation (
minWidth/maxWidth/minHeight/maxHeight,aspectRatio) - Thumbnail generation (
generateThumbnails,thumbnailSizes) - EXIF handling (
preserveMetadata,autoRotate)
Type Conversion Matrix
How types convert between databases:
| ObjectQL Type | PostgreSQL | MongoDB | Redis |
|---|---|---|---|
text | VARCHAR / TEXT | String | String |
number | NUMERIC | Number | String |
currency | JSONB | Object | String (JSON) |
date | DATE | Date | String (ISO) |
datetime | TIMESTAMP | Date | String (ISO) |
boolean | BOOLEAN | Boolean | 0 / 1 |
select | VARCHAR / ENUM | String | String |
lookup | UUID + FK | ObjectId | String |
formula | GENERATED | Virtual | Computed |
json | JSONB | Object | String (JSON) |
location | POINT | GeoJSON | String (JSON) |
Sensitive Data: Masking & Encryption
There is no user-defined "custom type" registry. For sensitive values, use the
dedicated secret field type, which encrypts on write and masks on read, and
restrict reader access with field-level security
(readable: false) or hidden.
# Reversible secret (API keys, DB passwords)
api_key:
type: secret
label: API KeyThe per-field
maskingRuleandencryptionConfigproperties were pruned from the Field schema in 2026-06 — they were declared surface with no runtime consumer. In 2026-07 the masking shapes were removed from the spec entirely (ADR-0056 D8);EncryptionConfigSchemaremains in the System namespace as[EXPERIMENTAL]roadmap surface. See Security & Access Control for status.
Type Selection Guide
For text data:
- Short, single-line →
text - Multi-line →
textarea - Rich formatting →
html - Email address →
email - URL →
url - Phone →
phone
For numbers:
- General purpose →
number - Money →
currency - Percentage →
percent - Unique ID →
autonumber
For dates:
- Date only →
date - Date + time →
datetime - Time only →
time
For selections:
- Fixed options →
select - Multiple selections →
multiselect - 2-5 visible options →
radio - Yes/No →
booleanortoggle
For relationships:
- Loose reference →
lookup - Parent-child →
master_detail - Self-referential hierarchy →
tree
For calculations:
- Derived value →
formula - Aggregate children →
summary
For complex data:
- Flexible schema →
json - List of tags →
tags(ormultiple: true) - Geographic data →
locationoraddress - File upload →
fileorimage