MasterRecord

Defining Models

Describe your schema as plain classes — no migrations file to hand-edit, no decorators.

A MasterRecord entity is an ES class whose fields are methods. Each method receives the schema builder db and chains a type plus modifiers. MasterRecord reads these definitions to create tables, generate migrations, and track changes.

A basic entity#

User.js
// app/models/User.js
export default class User {
  id(db)         { db.integer().primary().auto(); }
  name(db)       { db.string().notNullable(); }
  email(db)      { db.string().notNullable().unique(); }
  age(db)        { db.integer(); }            // nullable by default
  is_active(db)  { db.boolean().default(true); }
  created_at(db) { db.datetime(); }
}
Fields are methods, not object literals
Define columns as name(db) { db.string(); }. A constructor assignment like this.name = { type: 'string' } is ignored— the builder reads the class prototype’s methods, so object-literal properties never reach the schema.

Field types#

Every type below maps to a real column on all three engines. Call it as a builder method, e.g. db.datetime(). Temporal types (date/time/datetime/timestamp) are stored as TEXT on every engine for cross-engine portability — write ISO-8601 or epoch-millis strings.

BuilderPostgreSQLMySQLSQLite
db.integer()INTEGERINTINTEGER
db.bigint()BIGINTBIGINTINTEGER
db.string()VARCHAR(255)VARCHAR(255)TEXT
db.text()TEXTTEXTTEXT
db.mediumtext() / longtext()TEXTMEDIUMTEXT / LONGTEXTTEXT
db.float()REALFLOATREAL
db.decimal()DECIMALDECIMALREAL
db.boolean()BOOLEANTINYINTINTEGER
db.date()TEXTTEXTTEXT
db.time()TEXTTEXTTEXT
db.datetime() / timestamp()TEXTTEXTTEXT
db.json()JSONJSONTEXT
db.uuid()UUIDVARCHAR(36)TEXT
db.binary()BYTEABLOBBLOB
Tip
The convenience methods for datetime, date, timestamp, float, decimal, bigint, json, uuid and binary arrived in MasterRecord 1.3.0.

Modifiers#

Chain modifiers after the type to shape the column:

ModifierEffect
.primary()Marks the primary key (implies not-null + unique).
.auto()Auto-increment; the DB assigns the value on insert.
.notNullable()NOT NULL. (Columns are nullable by default.)
.nullable()Explicitly allow NULL.
.unique()Adds a UNIQUE constraint.
.default(value)Sets a default value.
.index(name?)Adds an index on the column.
.set(fn) / .get(fn)Transform values in / out of the database. See Transformers.
.defaultSql('expr')Database-side default expression (EF HasDefaultValueSql), e.g. CURRENT_TIMESTAMP.
.computed('expr', { stored })Generated column (EF HasComputedColumnSql); never written by the ORM, read back after insert.
.check('predicate', name?)CHECK constraint (EF HasCheckConstraint).
.rowVersion()ORM-managed integer concurrency token, bumped on every UPDATE (EF IsRowVersion).
.concurrencyToken()App-managed token: original value added to the UPDATE/DELETE WHERE (EF IsConcurrencyToken).
.owned(Class?)Owned / complex value stored as JSON, hydrated into the class on read (EF OwnsOne(...).ToJson()).
.transform({ toDatabase, fromDatabase })Value converter (EF HasConversion).
.virtual()Keep the property on the entity but emit no column.

Inheritance (TPH), composite keys, owned types, computed columns, check constraints, indexes and concurrency tokens are covered on Advanced Modeling.

Registering models in a context#

Models become queryable by registering them in a context with this.dbset(Model). Name the file after the class (AppContext.js) so the migration CLI can resolve it.

AppContext.js
// app/models/AppContext.js
import context from 'masterrecord/context';
import User from './User.js';
import Post from './Post.js';

class AppContext extends context {
  constructor() {
    super();
    this.env('config/environments');  // env.<NODE_ENV>.json
    this.dbset(User);
    this.dbset(Post);
  }
}

export default AppContext;
Note
The Master CLI keeps this in sync for you: master generate model Comment body:text creates the entity and registers the dbset.

Relationships & transformers#

Navigation properties like Posts(db) { db.hasMany('Post'); } and User(db) { db.belongsTo('User'); } declare associations — covered in Relationships. To (de)serialize complex values, use .set() / .get().