Build

Model columns and types

Use column builders and modifiers to define stable types and defaults without ad-hoc SQL.

Start with the smallest schema that expresses the database rules. Add indexes and relations only after the columns are clear.

import { model, columns } from "@damatjs/orm-model";

export const UserModel = model("users", {
  id: columns.id({ prefix: "usr" }).primaryKey(),
  email: columns.text().unique(),
  name: columns.text().nullable(),
  isAdmin: columns.boolean().default(false),
  createdAt: columns.timestamp({ withTimezone: true }).defaultNow(),
});

Common builder families:

  • identity: id(), uuid()
  • strings: text(), varchar(), char()
  • numbers: integer(), numeric(), real(), doublePrecision()
  • time: timestamp(), date(), time(), interval()
  • structured values: json(), jsonb(), bytea(), vector(n), halfVector(n)

PostgreSQL NUMERIC keeps exact decimal values. Existing columns.numeric() declarations continue to generate number types. Opt into lossless row/input types and finite decimal-string Zod validation per column:

amount: columns.numeric(30, 8).representation("string");

The representation is codegen metadata only; changing it does not generate SQL.

Native pgvector columns

Use columns.vector(dimensions) for PostgreSQL VECTOR(dimensions) or columns.halfVector(dimensions) for HALFVEC(dimensions). Both are scalar PostgreSQL extension types with a dedicated dimensions field in the schema; their TypeScript row and input representation is number[].

const Asset = model("asset", {
  id: columns.id({ prefix: "ast" }).primaryKey(),
  embedding: columns.halfVector(2048),
  // A normal PostgreSQL array remains a different type:
  scores: columns.real().array(),
});

Dimensions must be positive integers. Generated schemas and runtime write/query boundaries require exactly that many finite numbers, rejecting NaN, positive infinity, and negative infinity before SQL runs. .nullable() and optional input fields preserve their surrounding null/undefined behavior. Native vector builders are not PostgreSQL arrays: array = false, and calling .array() on one throws. Use real().array() or doublePrecision().array() when a regular REAL[] or DOUBLE PRECISION[] is intended.

The PostgreSQL adapter registers the official pgvector types for every pool connection, serializes modeled vector parameters with pgvector.toSql(), and deserializes VECTOR/HALFVEC results to number[]. Application services do not need to add casts or hand-written serializers.

Modifiers such as .primaryKey(), .unique(), .nullable(), .default(), and .defaultNow() describe database behavior. Changing a model does not alter the database until you generate, review, and run a migration.

See package docs for exact options: orm-model column reference