Docs / Models

Models

One file defines the table, the row type, the validator.

A model is one file. It defines the table, the validation, the TypeScript row type, and (optionally) the REST endpoints.

// app/models/post.ts
import { model, text, boolean, belongsTo } from '@hopak/core';

export default model('post', {
  title: text().required().min(3).max(200),
  content: text().required(),
  published: boolean().default(false),
  author: belongsTo('user'),
});

Field types

TypeNotes
text()Free-form string (use .min/.max/.pattern to constrain)
email()String with email-format validation
url()String with URL-format validation
phone()String — no built-in regex; add .pattern(...) for strict formats
number(), money()Numbers with min/max (money stored as real)
boolean()Scalar
date(), timestamp()Coerced from ISO strings; rejects invalid dates
enumOf('a', 'b')TypeScript literal union, DB enum
json<T>()Typed JSON column
belongsTo('user'), hasOne('profile'), hasMany('post')Relations
password(), secret(), token()Auto-excluded from JSON responses
file(), image()Stored as JSON metadata { url, mimeType, size, name? }

Modifiers

Chain on any field:

text().required().min(3).max(200).unique().index()
number().required().min(0).max(100).default(0)
text().pattern(/^[a-z]+$/)
date().default('now')
file().maxSize('5MB')
image().maxSize(2_097_152)   // bytes also accepted

Options

model('post', { /* fields */ }, {
  timestamps: true,   // add createdAt + updatedAt columns (default: true)
});