Skip to content

Annotations Reference

Experimental

The DB integrations layer is experimental. APIs and annotations described in this section may change in future releases.

Complete reference for all @db.* annotations available in .as files. Generic annotations are provided by @atscript/db/plugin via dbPlugin() and work with every adapter. Adapter-specific annotations (PostgreSQL, MySQL, MongoDB) require the corresponding adapter plugin.

Tables & Columns

AnnotationApplies ToArgumentsDescription
@db.tableInterfacename? (string)Mark as database table (defaults to interface name)
@db.table.renamedInterfaceoldName (string)Previous table name for schema sync migration
@db.schemaInterfacename (string)Assign to a database schema/namespace
@db.columnFieldname (string)Override the physical column name (perf note)
@db.column.renamedFieldoldName (string)Previous column name for schema sync migration
@db.column.collateFieldcollation (string)Portable collation: 'binary', 'nocase', or 'unicode'
@db.column.precisionFieldprecision (number), scale (number)Decimal precision/scale for DB storage (e.g., DECIMAL(10,2))
@db.column.dimensionFieldMark as dimension field — groupable in aggregate queries
@db.column.measureFieldMark as measure field — aggregatable (sum, avg, count, min, max). Numeric/decimal only
@db.jsonFieldStore as a single JSON column instead of flattening
@db.ignoreFieldExclude field from the database schema entirely
atscript
@db.table 'users'
@db.schema 'auth'
interface User {
  @db.column 'full_name'
  name: string

  @db.json
  preferences: Preferences

  @db.ignore
  computedField: string

  @db.column.collate 'nocase'
  username: string

  @db.column.precision 10, 2
  price: number
}

@db.column performance

Only use @db.column when you have a genuine reason — such as mapping to a legacy schema or meeting an external naming convention you cannot change. When a table has no @db.column, nested objects, or @db.json fields, the read, filter, and patch paths take a zero-allocation fast path that skips key translation entirely. Adding even one @db.column activates per-row key remapping on every read, write, filter, and patch operation for that table. In high-throughput scenarios this overhead is measurable.

If you control the database schema, prefer naming your Atscript fields to match the desired column names directly. See Custom Column Names for more details.

Defaults

AnnotationApplies ToArgumentsDescription
@db.defaultFieldvalue (string)Static default value
@db.default.incrementFieldstart? (number)Auto-incrementing integer (requires number type)
@db.default.uuidFieldRandom UUID string (requires string type)
@db.default.nowFieldCurrent timestamp (requires number or string type)
atscript
@db.table
interface Product {
  @meta.id
  @db.default.uuid
  id: string

  @db.default 'untitled'
  name: string

  @db.default.now
  createdAt: number
}

Indexes

AnnotationApplies ToArgumentsDescription
@db.index.plainFieldname? (string), sort? (string)Standard index, optional sort direction ('asc'/'desc')
@db.index.uniqueFieldname? (string)Unique constraint index
@db.index.fulltextFieldname? (string), weight? (number)Full-text search index with optional weight

Use the same index name on multiple fields to create a composite index.

atscript
@db.table
interface Article {
  @db.index.unique
  slug: string

  @db.index.plain 'date_idx', 'desc'
  publishedAt: number

  // Composite index across two fields
  @db.index.plain 'author_cat'
  authorId: string

  @db.index.plain 'author_cat'
  category: string

  @db.index.fulltext 'search', 3
  title: string

  @db.index.fulltext 'search', 1
  body: string
}
AnnotationApplies ToArgumentsDescription
@db.search.vectorFielddimensions (number), similarity? (string), indexName? (string)Vector search field
@db.search.vector.thresholdFieldvalue (number)Default minimum similarity threshold (0--1)
@db.search.filterFieldindexName (string)Pre-filter field for vector search

Similarity options: 'cosine' (default), 'euclidean', 'dotProduct'. Each adapter maps to its native vector type — see Text Search and Vector Search.

atscript
@db.table
interface Document {
  @db.search.vector 1536, 'cosine', 'doc_vec'
  @db.search.vector.threshold 0.7
  embedding: db.vector

  @db.search.filter 'doc_vec'
  category: string
}

Relations

AnnotationApplies ToArgumentsDescription
@db.rel.FKFieldalias? (string)Foreign key (field must use chain ref)
@db.rel.toFieldalias? (string)Forward navigation (N:1, FK on this table)
@db.rel.fromFieldalias? (string)Reverse navigation (1:N, FK on other table)
@db.rel.viaFieldjunction (ref)Many-to-many navigation through a junction table
@db.rel.onDeleteFieldaction (string)Referential action on parent delete
@db.rel.onUpdateFieldaction (string)Referential action on parent update
@db.rel.filterFieldcondition (expr)Static filter condition on navigation property
atscript
@db.table
interface Task {
  @db.rel.FK
  @db.rel.onDelete 'cascade'
  projectId: Project.id

  @db.rel.to
  project: Project

  @db.rel.from
  comments: Comment[]

  @db.rel.via TaskTag
  tags: Tag[]

  @db.rel.from
  @db.rel.filter `status = 'open'`
  openSubtasks: Task[]
}

Referential Action Values

For @db.rel.onDelete and @db.rel.onUpdate:

ActionDescription
'cascade'Propagate delete/update to related rows
'restrict'Prevent operation if related rows exist
'noAction'Database default behavior (no action)
'setNull'Set FK to null (field must be optional)
'setDefault'Set FK to default value (needs @db.default)

Views

AnnotationApplies ToArgumentsDescription
@db.viewInterfacename? (string)Mark as database view (defaults to interface name)
@db.view.forInterfaceentry (ref)Entry/primary table for a managed view
@db.view.joinsInterfacetarget (ref), condition (expr)Explicit join clause (repeatable)
@db.view.filterInterfacecondition (expr)View WHERE clause
@db.view.havingInterfacecondition (expr)Post-aggregation HAVING clause
@db.view.materializedInterfaceMark the view as materialized
@db.view.renamedInterfaceoldName (string)Previous view name for schema sync migration
atscript
@db.view
@db.view.for Task
@db.view.joins Project, `Project.id = Task.projectId`
@db.view.filter `Task.status = 'active'`
interface ActiveTaskView {
  taskName: Task.name
  projectName: Project.name
  dueDate: Task.dueDate
}

Aggregation

AnnotationApplies ToArgumentsDescription
@db.agg.sumFieldfield (string)SUM of a source column (numeric/decimal only)
@db.agg.avgFieldfield (string)AVG of a source column (numeric/decimal only)
@db.agg.countFieldfield? (string)COUNT — omit argument for COUNT(*), provide field name for non-null count
@db.agg.minFieldfield (string)MIN of a source column
@db.agg.maxFieldfield (string)MAX of a source column

Use aggregation annotations on view fields together with @db.column.dimension on grouping fields.

atscript
@db.view
@db.view.for Order
@db.view.having `totalRevenue > 100`
interface CategoryStats {
  @db.column.dimension
  category: Order.category

  @db.agg.sum 'amount'
  totalRevenue: number

  @db.agg.count
  orderCount: number

  @db.agg.avg 'amount'
  avgOrderValue: number
}

Schema Sync

AnnotationApplies ToArgumentsDescription
@db.sync.methodInterfacemethod (string)Sync strategy: 'drop' or 'recreate'
  • 'drop' — Drop and recreate the table on structural changes (lossy, data is deleted).
  • 'recreate' — Recreate with data preservation on structural changes.

Patch Behavior

AnnotationApplies ToArgumentsDescription
@db.patch.strategyFieldstrategy (string)'replace' (default) or 'merge'

Controls how nested objects are handled during PATCH/update operations. With 'replace', the entire nested object is overwritten. With 'merge', individual sub-fields are deep-merged.

PostgreSQL-Specific

These annotations require the @atscript/db-postgres plugin. See PostgreSQL adapter.

AnnotationApplies ToArgumentsDescription
@db.pg.typeFieldtype (string)Override native PG column type (e.g., CITEXT, INET, MACADDR)
@db.pg.schemaInterfaceschema (string)PostgreSQL schema (default: public)
@db.pg.collateInterface / Fieldcollation (string)Native PG collation (overrides portable @db.column.collate)
atscript
use '@atscript/db-postgres'

@db.table 'users'
@db.pg.schema 'auth'
interface User {
  @meta.id
  @db.default.uuid
  id: string

  @db.pg.type 'CITEXT'
  email: string

  @db.pg.collate 'tr-x-icu'
  name: string
}

MySQL-Specific

These annotations require the @atscript/db-mysql plugin. See MySQL adapter.

AnnotationApplies ToArgumentsDescription
@db.mysql.engineInterfaceengine (string)Storage engine (default: InnoDB)
@db.mysql.charsetInterface / Fieldcharset (string)Character set (default: utf8mb4)
@db.mysql.collateInterface / Fieldcollation (string)Native MySQL collation (overrides portable @db.column.collate)
@db.mysql.unsignedFieldUNSIGNED modifier for integer columns
@db.mysql.typeFieldtype (string)Override native MySQL column type (e.g., MEDIUMTEXT, TINYTEXT)
@db.mysql.onUpdateFieldexpression (string)ON UPDATE expression (e.g., CURRENT_TIMESTAMP)
atscript
use '@atscript/db-mysql'

@db.table 'events'
@db.mysql.engine 'InnoDB'
@db.mysql.charset 'utf8mb4'
interface Event {
  @meta.id
  @db.default.increment
  id: number

  @db.mysql.type 'MEDIUMTEXT'
  description: string

  @db.mysql.unsigned
  viewCount: number

  @db.default.now
  @db.mysql.onUpdate 'CURRENT_TIMESTAMP'
  updatedAt: number
}

MongoDB-Specific

These annotations require the @atscript/db-mongo plugin. See MongoDB adapter.

AnnotationApplies ToArgumentsDescription
@db.mongo.collectionInterfaceMark as MongoDB collection (auto-injects _id)
@db.mongo.cappedInterfacesize (number), max? (number)Capped collection with max byte size and optional doc limit
@db.mongo.search.dynamicInterfaceanalyzer? (string), fuzzy? (number)Dynamic Atlas Search index
@db.mongo.search.staticInterfaceanalyzer? (string), fuzzy? (number), indexName? (string)Named static Atlas Search index
@db.mongo.search.textFieldanalyzer? (string), indexName? (string)Include field in a search index
atscript
use '@atscript/db-mongo'

@db.table 'products'
@db.mongo.collection
@db.mongo.search.static 'lucene.english', 1, 'main_search'
interface Product {
  @meta.id
  _id: mongo.objectId

  @db.mongo.search.text 'lucene.english', 'main_search'
  name: string

  @db.search.vector 1536, 'cosine', 'vec_idx'
  embedding: number[]

  @db.search.filter 'vec_idx'
  category: string
}

Generic search annotations

@db.search.vector and @db.search.filter are generic annotations (not MongoDB-specific) and work across all adapters that support vector search. See the Search section above.

These are not @db.* annotations but are commonly used alongside the database layer.

AnnotationApplies ToArgumentsDescription
@meta.idFieldMark as primary key field (multiple fields form a composite key)
@expect.array.keyFieldArray element key field for patch matching
@expect.array.uniqueItemsFieldEnforce unique items in an array
atscript
@db.table
interface OrderLine {
  // Composite primary key
  @meta.id
  orderId: Order.id

  @meta.id
  productId: Product.id

  quantity: number
}

Released under the MIT License.