Defaults & Indexes
Experimental
The DB integrations layer is experimental. APIs and annotations described in this section may change in future releases.
Atscript lets you set default values and create database indexes directly in your .as schema. Defaults ensure fields are populated automatically on insert, while indexes speed up queries and enforce constraints.
Static Defaults
Use @db.default to assign a fixed value when a field is not provided at insert time. The argument is always a string — non-string values are parsed as JSON:
// String default — used as-is
@db.default 'pending'
status: string
// Boolean default — parsed from JSON
@db.default 'false'
isArchived: boolean
// Number default — parsed from JSON
@db.default '0'
retryCount: numberGenerated Defaults
Some defaults need to be computed at insert time. Use @db.default.fn with one of three portable generator functions:
'increment' — Auto-Incrementing Integer
Generates sequential integers (1, 2, 3, ...). The field must be a number type:
@db.default.fn 'increment'
id: number'uuid' — Random UUID
Generates a random UUID v4 string. The field must be a string type:
@db.default.fn 'uuid'
id: string'now' — Current Timestamp
Captures the current time at insert. Works with number (Unix milliseconds) and string (ISO format) types:
@db.default.fn 'now'
createdAt?: numberSemantic Types Include Defaults
Semantic types like number.timestamp.created already include @db.default.fn 'now' — you don't need to add it manually:
// Concise — semantic type handles the default
createdAt?: number.timestamp.created
// Equivalent verbose form
@db.default.fn 'now'
createdAt?: numberIndexes
Indexes improve query performance and can enforce constraints. Atscript supports three index types through the @db.index.* annotations.
Plain Index
Create a standard index for faster lookups with @db.index.plain. The first argument is the index name, and an optional second argument sets the sort direction ('asc' or 'desc'):
@db.index.plain 'name_idx'
name: string
@db.index.plain 'created_idx', 'desc'
createdAt: numberUnique Index
Enforce that no two records share the same value with @db.index.unique:
@db.index.unique 'email_idx'
email: stringAny attempt to insert a duplicate value will result in a constraint violation error.
Full-Text Search Index
Mark fields for full-text search with @db.index.fulltext. An optional second argument sets the field's weight — higher weight means greater relevance in search results:
@db.index.fulltext 'search_idx', 10
title: string
@db.index.fulltext 'search_idx', 1
body?: stringThe weight defaults to 1 when omitted. Weighted full-text search is supported by databases like MongoDB and PostgreSQL. SQLite requires the FTS5 extension and does not auto-manage full-text indexes.
Composite Indexes
When multiple fields share the same index name, they form a composite index. This is useful for queries that filter or sort on multiple columns together:
@db.index.plain 'name_email_idx'
name: string
@db.index.plain 'name_email_idx'
email: stringThis creates a single index spanning both name and email, which speeds up queries that filter on both fields simultaneously.
Multiple Indexes Per Field
A single field can participate in more than one index. Simply stack multiple @db.index.* annotations:
@db.index.unique 'email_idx'
@db.index.plain 'name_email_idx'
email: stringHere email has its own unique index and also participates in a composite index with another field.
Complete Example
Putting it all together — a User table with defaults, generated values, and several index types:
@db.table 'users'
export interface User {
// Primary key with auto-increment
@meta.id
@db.default.fn 'increment'
id: number
// Unique index ensures no duplicate emails
@db.index.unique 'email_idx'
email: string
// Plain index for fast name lookups, also part of a composite index
@db.index.plain 'name_idx'
@db.index.plain 'name_status_idx'
name: string
// Static default — new users start as 'active'
@db.default 'active'
@db.index.plain 'name_status_idx'
status: string
// Full-text search on bio
@db.index.fulltext 'search_idx'
bio?: string
// Auto-generated timestamps
@db.default.fn 'now'
createdAt?: number
@db.default.fn 'now'
updatedAt?: number
}This gives you auto-incrementing IDs, a unique email constraint, composite and full-text indexes, a static default for status, and auto-generated timestamps -- all declared in one place.
Next Steps
- CRUD Operations — Insert, read, update, and delete records
- Queries & Filters — Filter, sort, and paginate results
- Relations — Connect tables with foreign keys and joins