Domain Types Reference

Reepolee defines a canonical vocabulary of column types — domain types — that every new table and column should draw from. Rather than each table inventing its own width for a name or its own precision for money, you pick the domain type that matches the column's meaning and get a consistent SQL type across your schema.

The types are defined as typed constants in config/domain_types/mysql.ts and config/domain_types/sqlite.ts. A few diverge per dialect (noted below); the rest use the same SQL definition in both files. The generator reads these constants to produce correct column metadata, and the suffix/prefix conventions in config/db_structure.ts (DATE_SUFIXES, DATETIME_SUFIXES, BOOLEAN_PREFIXES, IMAGE_SUFFIXES, FILE_SUFFIXES) tell the generator how to recognise each column's role without manual tagging.

Primary Keys & Identifiers

Domain typeMySQLSQLiteNotes
pk_idINT UNSIGNED AUTO_INCREMENTINTEGER PRIMARY KEYCanonical primary key. Migrate INT (signed) and BIGINT UNSIGNED to this
uuid_v7BINARY(16)BLOBTime-ordered UUID (RFC 9562). Generate with Bun.randomUUIDv7Bytes() for DB storage
foreign_keyINT UNSIGNEDINTEGERFK columns; type matches the referenced pk_id

Basic SQL Types

Generic type aliases (not business domains) used by Studio's column picker and default table scaffolding. Reachable via exact column-name match.

Domain typeMySQLSQLite
integerINTINTEGER
unsigned_integerINT UNSIGNEDINTEGER
bigintBIGINTINTEGER
realDOUBLEREAL
numericDECIMAL(18,6)NUMERIC
decimalDECIMAL(10, 2)DECIMAL(18, 2)
floatFLOATREAL
doubleDOUBLEREAL
varcharVARCHAR(255)VARCHAR(255)
charCHAR(1)CHAR(1)
binaryBINARY(16)BLOB
blobBLOBBLOB
longtextLONGTEXTTEXT
datetimeDATETIMEDATETIME
jsonJSONJSON

Names

Domain typeSQLPurpose
first_nameVARCHAR(100)Person's given name
last_nameVARCHAR(100)Person's surname
full_nameVARCHAR(255)Concatenated person or organization display name
usernameVARCHAR(50)Login handle

Text & Descriptions

Domain typeSQLPurpose
short_descriptionVARCHAR(255)Brief label, tagline, module description
long_descriptionTEXTFuller comment, description, note
short_textVARCHAR(255)Short free-form text value
textTEXTUnbounded long text (JSON blobs, translations, contract clauses, session data)
markdownTEXT COMMENT 'MARKDOWN' (MySQL) / MARKDOWN (SQLite)Rich text authored and stored as Markdown. Generates a <markdown-editor> form field
slugVARCHAR(255)URL-safe identifier derived from a title or name
urlVARCHAR(2048)Full external or website link

Monetary, Percent & Quantities

Domain typeSQLPurpose
amountDECIMAL(18,2)All monetary values. Migrate DECIMAL(10,2) → this
percentageDECIMAL(7,4)Percentage / commission rates. Migrate DECIMAL(4,2), DECIMAL(5,2), DECIMAL(10,3) → this
quantityDECIMAL(12,3)Order/inventory quantity, whole or fractional (e.g. 2 pcs, 0.5 liter). Unit lives in a separate column
currency_codeCHAR(3) (MySQL) / VARCHAR(3) (SQLite)ISO 4217 currency code (e.g. USD, EUR)

Temporal

Domain typeSQL (MySQL)SQL (SQLite)Suffix convention
dateDATETEXT_on, _by (e.g. incorporated_on, payment_due_by)
timestampTIMESTAMPTIMESTAMP_at (e.g. created_at, verified_at). Default CURRENT_TIMESTAMP

SQLite stores date as ISO-8601 TEXT (YYYY-MM-DD) rather than a native DATE affinity.

Config constants: DATE_SUFFIXES = ["_on", "_by"], DATETIME_SUFFIXES = ["_at"].

Duration & Time Units

Domain typeSQLPurpose
daysINTEGERDuration/count measured in days
monthsINTEGERDuration/count measured in months
yearsINTEGERDuration/count measured in years
hoursINTEGERDuration/count measured in hours
minutesINTEGERDuration/count measured in minutes

Boolean

Domain typeSQL (MySQL)SQL (SQLite)Detection
booleanTINYINT(1)INTEGERPrefix is_, has_, can_ OR any TINYINT(1) column

Config constant: BOOLEAN_PREFIXES = ["is_", "has_", "can_"].

Contact

Domain typeSQLPurpose
emailVARCHAR(255)Email address
phone_numberVARCHAR(30)E.164 international standard
localeVARCHAR(10)BCP-47 language/region tag (en-US)

Codes & Identifiers

Domain typeSQLExamples
code_shortVARCHAR(5)ISO country codes, currency codes
codeVARCHAR(20)Lookup codes (equipment, articles, languages)
code_longVARCHAR(64)Machine-generated tokens (scope keys, invitation codes)
status_enumVARCHAR(30)State-machine status names
skuVARCHAR(64)Product/inventory stock-keeping unit
gtinVARCHAR(14)Global Trade Item Number — EAN-8/13, UPC-A, GTIN-14 barcode
tax_idVARCHAR(30)VAT/company tax identifier (format varies by country)

Address

Domain typeSQLNotes
street_line_1VARCHAR(150)Primary street address
street_line_2VARCHAR(100)Apartment, suite, floor
cityVARCHAR(100)City or municipality
state_provinceVARCHAR(100)Regional subdivision
postal_codeVARCHAR(20)Postal/ZIP code
country_codeCHAR(3) (MySQL) / VARCHAR(3) (SQLite)ISO 3166-1 alpha-2 / alpha-3
country_nameVARCHAR(100)Full display country name

Security & System

Domain typeSQLPurpose
password_hashVARCHAR(255)Argon2id / PHC formatted password hash
ip_addressVARCHAR(45)IPv4/IPv6 address stored as text
json_dataJSON (MySQL) / TEXT (SQLite)Serialized structured application data

Media

Domain typeSQLSuffix convention
image_pathVARCHAR(512)_image (e.g. portrait_image, logo_image)
file_pathVARCHAR(512)_file (e.g. contract_file, invoice_file)

image_path stores a browsable path (e.g. /images/teams/members/xyz.webp), not the binary. Rendered as <image-upload> in forms and image_thumbnail() in grids. file_path stores a browsable document path; rendered as <file-upload> in forms and file_link() in grids.

Config constants: IMAGE_SUFFIXES = ["_image"], FILE_SUFFIXES = ["_file"].

How Domain Types Are Used

Column-name matching

When you name a column first_name, the generator matches it against the domain type registry and picks up the correct SQL type, form widget, and display formatting. You don't need to annotate columns — the name alone drives the match.

Suffix and prefix conventions

Columns ending in _at are recognised as timestamps, _on and _by as dates, is_ / has_ / can_ as booleans, _image as image paths, and _file as file paths. These conventions live in config/db_structure.ts and the generator uses them to produce the right form control and grid cell for each column.

Comment-driven overrides

For columns that need a specific form widget regardless of their domain type, add a MySQL column comment. Two formats are supported:

  • Plain word — e.g. COMMENT 'autocomplete', COMMENT 'textarea', COMMENT 'markdown'
  • JSON — e.g. COMMENT '{type: "autocomplete", rows: 6}'. JSON takes precedence over plain-word when both are present.

SQLite uses column type naming for the same purpose (MARKDOWN type → markdown editor).

Auditing

Run the Check domain compliance tool from reeman to audit your schema against this taxonomy:

bun reeman
# → Tools & Maintenance → Check domain compliance

It reports columns whose types deviate from the canonical domain types so you can plan migrations. The check reads config/domain_types/ at runtime — the same constants the generator uses — so there's no second source of truth to maintain.

Extending

The domain type registry is your project's own source file. To add a project-specific type, edit config/domain_types/mysql.ts and config/domain_types/sqlite.ts together:

// config/domain_types/mysql.ts
export const DOMAIN_TYPES = {
    // ... existing types ...
    npi_number: "VARCHAR(10)",  // US National Provider Identifier
} as const;

New types are immediately available to generators, Studio, and the compliance checker. Keep the two dialect files in sync — the TypeScript compiler will catch a missing key, but not a different SQL value for the same key.