Annotations Reference
Use this page when you need the full annotation syntax, inheritance rules, merge behavior, and the built-in annotation catalog.
Annotations are metadata declarations that provide additional information about types, interfaces, and properties.
Purpose
Annotations serve multiple purposes:
- UI metadata - Labels, placeholders, descriptions for schema-driven UI tools
- Validation constraints - Min/max values, patterns, length restrictions
- Database metadata - Collection names, indexes, field strategies
- Documentation - Descriptions and multi-line documentation
- Custom metadata - Any domain-specific information
Where to Apply
Annotations can be applied anywhere:
@meta.description 'User entity' // Interface annotation
export interface User {
@meta.id // Property annotation
id: string
}
@expect.minLength 3 // Type annotation
export type Username = stringAnnotation Inheritance
Type to Property
When a property uses a type with annotations, annotations merge with property having priority:
@expect.minLength 3
@expect.maxLength 20
export type Username = string
export interface User {
@expect.maxLength 15 // Overrides type's maxLength
username: Username // Inherits minLength: 3, gets maxLength: 15
}Property References
When a property references another property, annotations merge in order:
- Final type annotations
- Referenced property annotations
- Current property annotations (highest priority)
Merge Strategies
When annotations are merged (from type inheritance, property references, or ad-hoc annotations), the merge strategy determines how same-named annotations combine:
Replace (default) — Higher-priority annotations replace lower-priority ones entirely:
@expect.min 3
export type PositiveInt = number
export interface Config {
@expect.min 10 // Replaces type's @expect.min 3
threshold: PositiveInt // Result: @expect.min is 10
}Append — Both values are kept, accumulating into an array:
@expect.pattern '^[a-z]+$', '', 'Must be lowercase'
export type SafeString = string
export interface Form {
@expect.pattern '^\S+$', '', 'No spaces'
code: SafeString
// Result: both patterns are validated
}The strategy is configured per annotation via AnnotationSpec. Most annotations use replace. The built-in @expect.pattern uses append.
Repeatable Annotations
Annotations marked with multiple: true can appear more than once on the same node. Their values are stored as arrays:
export interface User {
@expect.pattern '^[A-Z]', '', 'Must start with uppercase'
@expect.pattern '.{3,}', '', 'Must be at least 3 characters'
name: string
}When merged, how repeated annotations combine depends on the merge strategy:
multiple: true+ replace (default) — The higher-priority set replaces the entire arraymultiple: true+ append — Values from both sides are concatenated into a single array
Annotation Syntax
@meta.label 'User Name' // With argument
@meta.sensitive // Flag (no argument)
@expect.pattern "^[A-Z]", "i" // Multiple arguments
@meta.documentation 'Line 1' // Can be repeated
@meta.documentation 'Line 2'Arguments can be optional. Annotations without arguments are flag annotations.
Core Annotations
Atscript provides common-purpose annotations:
Meta Annotations (@meta.*)
@meta.label 'text'- Human-readable label@meta.id- Marks identifier field (multiple fields form composite PK)@meta.description 'text'- Field description@meta.documentation 'text'- Multi-line docs (repeatable)@meta.sensitive- Marks sensitive data@meta.readonly- Read-only field@meta.default 'value'- Default value (string as-is, other types parsed as JSON)@meta.example 'value'- Example value (string as-is, other types parsed as JSON)
UI Annotations (@ui.*)
@ui.placeholder 'text'- Input placeholder text@ui.component 'name'- UI component hint (e.g.,"select","datepicker")@ui.hidden- Hide field from UI forms and tables@ui.group 'name'- Group fields into form sections@ui.order 1- Display order for form and table tools@ui.width 'half'- Layout width hint (e.g.,"half","full","third")@ui.icon 'name'- Icon hint for the field or entity@ui.hint 'text'- Help text or tooltip@ui.disabled- Mark field as non-interactive@ui.type 'textarea'- Input type (maps to HTML input types:"text","textarea","password", etc.)@ui.attr 'key', 'value'- Pass arbitrary HTML/component attributes (repeatable)@ui.class 'names'- CSS class names (repeatable)@ui.style 'css'- Inline CSS styles (repeatable)
Validation Annotations (@expect.*)
@expect.minLength 5, "Custom error message"- Minimum string/array length (optional message)@expect.maxLength 100, "Custom error message"- Maximum string/array length (optional message)@expect.min 0, "Custom error message"- Minimum number value (optional message)@expect.max 100, "Custom error message"- Maximum number value (optional message)@expect.int "Custom error message"- Must be integer (optional message)@expect.pattern "regex", "flags", "message"- Pattern validation (repeatable, optional message)@expect.array.uniqueItems "Custom error message"- Enforce unique items in an array (by key fields if defined, otherwise by deep equality; optional message)@expect.array.key- Mark a field as a key inside an array of objects (used for uniqueness checks, lookups, and patch operations; does not enforce uniqueness by itself)
@expect.array.key has compile-time constraints: the field must be string or number, cannot be optional, and multiple key fields form a composite key.
All validation annotations accept an optional custom error message as the last argument (except @expect.array.key). When validation fails, the custom message is used instead of the default error message.
Array Annotations Example
@expect.array.uniqueItems and @expect.array.key work together to enforce unique array elements by identity fields:
interface Order {
@meta.id
id: number
@expect.array.uniqueItems "Duplicate line items"
items: OrderItem[]
}
interface OrderItem {
@expect.array.key
productId: number
quantity: number
price: number
}For primitive arrays, @expect.array.uniqueItems checks by deep equality — no @expect.array.key needed:
interface Product {
@expect.array.uniqueItems "Tags must be unique"
tags: string[]
}Form Validation (@meta.required)
@meta.requiredor@meta.required "Custom error message"- For strings: must contain at least one non-whitespace character. For booleans: must betrue(optional message)
Form Validation
Use string.required or @meta.required to ensure required string fields are not empty or whitespace-only. A plain string type accepts '' as valid — @meta.required catches this common form validation gap. For checkboxes, @meta.required on a boolean field ensures the value is true (e.g., "accept terms").
Database Annotations (@db.*)
Atscript ships a comprehensive set of database annotations for defining tables, relations, views, indexes, and more. These are covered in detail in the Database Layer documentation:
@db.table,@db.schema— Table definitions@db.column,@db.json,@db.ignore— Column configuration@db.default,@db.default.increment,@db.default.uuid,@db.default.now— Default values@db.column.collate,@db.column.precision— Column storage hints@db.index.plain,@db.index.unique,@db.index.fulltext— Indexes@db.rel.FK,@db.rel.to,@db.rel.from,@db.rel.via,@db.rel.onDelete,@db.rel.onUpdate,@db.rel.filter— Relations@db.view,@db.view.for,@db.view.joins,@db.view.filter,@db.view.materialized,@db.view.renamed— Views@db.patch.strategy— Patch behavior for nested objects@db.sync.method,@db.table.renamed,@db.column.renamed— Schema sync@emit.jsonSchema— Pre-compute and embed JSON Schema at build time
See the Annotations Reference for the complete list.
Special Annotation Argument Types
Some annotations accept special argument types beyond strings and numbers:
- Ref arguments — Type references using dot-notation chains (e.g.,
User.id). Used by@db.rel.FKand@db.view.forto reference fields on other types. - Query arguments — SQL-like expressions in backticks (e.g.,
`Task.status != 'done'`). Used by@db.view.filter,@db.view.joins, and@db.rel.filterfor conditions.
See Queries & Filters for the full query syntax.