Defining models

Read this page in the documentation

Defining models A model is the mapping between a JavaScript object and a database table. It names the table, declares the columns and their types, and carries the options that decide how Prorm writes SQL for that table — timestamps, soft deletes, schema, indexes, hooks and scopes. There are two ways to declare one. prorm.define() takes a plain object of attributes and is the direct, runtime-only route. Decorators (@Table, @Column) declare the same thing on a TypeScript class and are registered with prorm.addModel(). Both produce the same model object with the same static methods; pick whichever fits the codebase. prorm.define() The sync() call emits, on SQLite: Each dialect renders the same attribute map differently — ENUM becomes a real ENUM(...) on MySQL and a CHECK constraint on SQLite, JSON becomes JSONB on PostgreSQL and TEXT on SQLite. See Data types for the full cross-dialect table. define() is synchronous but schedules the CREATE TABLE in the background. prorm.sync() awaits those pending creates before it runs, which is why the normal startup shape is define every model, then await prorm.sync() once. Attribute options Every value in the attributes map is an AttributeOptions object (or a bare data type, which is shorthand for { type }). Option | Effect | --- | --- | type | The column's data type. Required. | allowNull | false emits NOT NULL. Defaults to nullable. | defaultValue | Column default. A function is evaluated per-insert in JS; DataTypes.NOW maps to the dialect's current-timestamp default. | primaryKey | Marks the column part of the primary key. | autoIncrement | AUTOINCREMENT / SERIAL / IDENTITY depending on dialect. | unique | true, a constraint name, or { name, msg } for a custom UniqueConstraintError message. | uniqueKey | Groups several columns into one composite unique constraint by sharing a name. | references | { model, key } — emits a REFERENCES clause. See Indexes & constraints. | field | The physical column name when it differs from the attribute name. | comment | Column comment, where the dialect supports one. | validate | Per-field validation rules — see Validation. | get / set | Attribute-level accessors, used by virtual fields. | hidden | Excluded from toJSON() by default. | Model options The third argument controls table-level behaviour. Option | Effect | --- | --- | tableName | Explicit table name. Without it the model name is lower-cased and pluralised (User → users). | freezeTableName | Use the model name verbatim instead of pluralising. | schema / schemaDelimiter | Qualify the table (schema.table). PostgreSQL schema, MySQL database. | timestamps | Adds createdAt / updatedAt and maintains them on write. On by default; set false to opt out. | createdAt / updatedAt / deletedAt | Rename those columns, or set to false to drop one. | paranoid | Soft deletes — see below. | underscored | Generate snakecase column names from camelCase attributes. | primaryKey | A string, or an array for a composite key. | indexes / constraints / uniqueKeys | Declarative index and constraint definitions created during sync(). | hooks | Lifecycle handlers — see Hooks. | scopes / defaultScope | Reusable query fragments — see Scopes. | validate | Model-level (multi-field) validators. | classMethods / instanceMethods | Extra statics and instance methods merged onto the model. | hidden | Map of attribute names to hide from toJSON(). | engine, charset, collate, rowFormat, initialAutoIncrement, comment | MySQL/MariaDB CREATE TABLE options. | tablespace, inherit, partitionBy | PostgreSQL CREATE TABLE options. | validateOnInsert / validateOnUpdate / skipValidations | When validation runs. | Global defaults can be set once on the connection and are merged under per-model options: Timestamps Timestamps are on unless you turn them off (timestamps: false). Prorm adds two DATE columns and fills them itself — createdAt on insert, updatedAt on every insert and update. They are ordinary columns: you can query, index and order by them. Rename or disable them individually: Soft deletes (paranoid) A paranoid model never issues DELETE. destroy() writes a timestamp into deletedAt, and every read silently adds deletedAt IS NULL. The deletedAt column is added to the attribute map automatically when paranoid is set, so it exists in the CREATE TABLE without you declaring it. Aggregates honour it too — count() on a paranoid model carries the deletedAt IS NULL predicate. Decorator models The same model as a class. Decorators record metadata; prorm.addModel() reads that metadata and builds the identical model object. addModel() returns the model static, and the class itself is also usable — the returned object is what carries findAll, create and the rest. The full decorator set (constraints, dialect-specific column types, associations, audit, encryption) is documented in Decorators. Custom methods classMethods and instanceMethods attach behaviour without subclassing: Introspecting a model Call | Returns | --- | --- | Model.getTableName() | The resolved table name (schema-qualified if set). | Model.getAttributes() | The raw attribute map. | Model.rawAttributes | Same map, as a property. | Model.describe() | The table as the database reports it, via DESCRIBE/informationschema. | Model.associations | Registered associations keyed by alias. | prorm.getModels() | Map of every model on the connection. | prorm.model(name) / prorm.hasModel(name) | Look one up by name. | Synchronising the schema prorm.sync() creates the tables for every defined model, in dependency order so that referenced tables exist before the tables that reference them. Call | Behaviour | --- | --- | sync() | CREATE TABLE IF NOT EXISTS for each model. | sync({ force: true }) | DROP TABLE then CREATE TABLE — destroys data. | sync({ alter: true }) | Diffs the live table against the model and issues ALTER TABLE for added/changed columns. | sync({ alter: { drop: true } }) | Also drops columns that no longer exist on the model. | Model.sync() | Just that one model. | Model.drop() / Model.truncate() | DROP TABLE / TRUNCATE. | sync() is a development convenience. For versioned, reviewable schema change use Migrations, and for generating those migrations from a model diff see Schema diffing. Next: Data types — which type to reach for, and how each one maps per engine. Related reading Data types — every DataTypes. and its per-dialect SQL Querying — the finder methods on a model Associations — hasOne / hasMany / belongsTo / belongsToMany Indexes & constraints Validation, Hooks, Scopes