Entities
- An entity is a nominal type whose values can become durable records.
- Decorators describe storage behavior; validators reject invalid field values.
- Construction creates an in-memory entity value, while save makes it durable.
Entity Definition Syntax
1entity Room {2 name: string @unique3 active: bool4}An entity file defines one PascalCase entity. Field names are lowercase identifiers followed by a type. The file may also contain shared value types, enums, defaults, and functions, but it cannot contain top-level runnable steps or a second entity.
The Room Expense Model
1entity Room {2 name: string @unique3 active: bool4}The application owns Room, Expense, ExpenseStatus, and Settlement. A draft is still being edited; an open expense is ready for normal room accounting; submitted, approved, and rejected represent review; settled means no further balance remains. The model references the existing platform User type for people and never declares that type itself.
Field Decorators
| Decorator | Purpose | Example |
|---|---|---|
@unique | Require a unique stored value and enable exact named-field lookup. | name: string @unique |
@index | Index a value used by filters, joins, or relationship lookups. | room_id: string @index |
@default(...) | Provide a storage-level field default. | reviewed_at: time @default(now) |
@access | Attach entity-level access behavior. | Placed before entity. |
1@access2entity PrivateReceipt {3 expense_id: string @unique4 receipt_file: file5}Field Transforms
1type ExpenseInput {2 title: string | trim3 category: string | trim | lowercase4 reference: string | uppercase5}| Transform | Allowed field | Effect |
|---|---|---|
| trim | string or string? | Remove surrounding whitespace. |
| lowercase | string or string? | Normalize letters to lowercase. |
| uppercase | string or string? | Normalize letters to uppercase. |
Transforms follow a field type in structural type definitions and metadata-backed contracts, using one pipe per rule. Entity fields accept decorators and validators, not transform pipes. A transform on a number, boolean, time, collection, media value, or unsupported named type is rejected.
Field Validators
1type ExpenseInput {2 title: string | trim ! not_empty ! max_length(120)3 reference: string | lowercase ! slug4 contact_email: string? | trim | lowercase ! email5 amount: number ! positive ! max(1000000)6}| Family | Validators | Allowed field |
|---|---|---|
| String format | email, phone, url, uuid, slug, no_whitespace, alphanumeric, lowercase, uppercase | string or string? |
| String content | min_length(n), max_length(n), length(n), regex("pattern"), has("text") | string or string? |
| Presence | not_empty | Strings, arrays, maps, named values, and structural shapes, including optional wrappers. |
| Number range | min(n), max(n), positive, negative | number or number? |
Each validator begins with !; several validators may follow one field. Length arguments are positive integers, numeric bounds must be finite safe numbers, and regex and has take string literals. Unknown rules and rules used on an incompatible field type are compile-time errors.
Managed Fields
| Invalid field declaration | Reason |
|---|---|
id: string | Identity is platform-managed. |
createdAt: time | Creation time is platform-managed. |
updatedAt: time | Update time is platform-managed. |
| Declaring the platform User type | User is platform-owned, not an application entity. |
Constructing Is Not Saving
1Expense expense = Expense {2 room_id: room.id3 payer4 title: request.title5 amount: request.amount6 note: ?7 receipt: ?8 status: ExpenseStatus.Draft9}1011expense.title = expense.title.trim()12save(expense)Expense { ... } constructs an in-memory value. Assignment changes fields on that value. save(expense) is the explicit durable write. Expense(request.id) is not construction; inside need, it is a fetch form.
Common Mistakes
| Wrong | Correct |
|---|---|
| Two entities in one file | One entity definition per entity file. |
| Top-level save beside an entity definition | Put executable steps in a runnable file. |
new Expense { ... } | Expense { ... } |
| Assume construction persists | Call save in the owning backend workflow. |
Declare User | Reference the platform-provided User type. |
