Field Types

Nanoka's t object provides a small set of field builders that map directly to SQLite column types and produce Zod validators. All modifiers are chainable and type-safe.

Field Types

t.string()

Maps to a SQLite text column. Accepts optional min, max, and email validators.

import { t } from '@nanokajs/core'

const fields = {
  name:  t.string().min(1).max(255),
  email: t.string().email(),
  bio:   t.string().optional(),
}

t.uuid()

Maps to a SQLite text column. When combined with .primary().readOnly(), Nanoka automatically sets $defaultFn(() => crypto.randomUUID()) on the Drizzle column — you never need to generate the ID manually.

const fields = {
  id: t.uuid().primary().readOnly(),
}

Because readOnly() excludes the field from create and update inputs, callers cannot supply an id. The UUID is generated server-side on every create() call.

t.integer()

Maps to a SQLite integer column. The Zod validator enforces integer values (z.number().int()).

const fields = {
  age:  t.integer().min(0).max(150),
  rank: t.integer().optional(),
}

t.number()

Maps to a SQLite real column. Accepts floating-point values.

const fields = {
  price:  t.number().min(0),
  rating: t.number().min(0).max(5),
}

t.boolean()

Maps to a SQLite integer({ mode: 'boolean' }) column. Drizzle handles the 0/1 ↔ true/false conversion automatically.

const fields = {
  isActive: t.boolean().default(true),
  isAdmin:  t.boolean().default(false),
}

t.timestamp()

Maps to a SQLite integer({ mode: 'timestamp_ms' }) column. Values are stored as milliseconds since epoch and returned as Date objects.

const fields = {
  createdAt: t.timestamp().readOnly().default(() => new Date()),
  updatedAt: t.timestamp().optional(),
}

t.json()

Maps to a SQLite text({ mode: 'json' }) column. Two forms are available:

Type annotation only — no runtime validation beyond JSON parsing:

const fields = {
  metadata: t.json<{ tags: string[] }>(),
}

With Zod schema — runtime validation on every parse:

import { z } from 'zod'

const TagsSchema = z.object({ tags: z.array(z.string()) })

const fields = {
  metadata: t.json(TagsSchema),
}

Note: nanoka generate always emits $type<unknown>() in the generated Drizzle schema regardless of which form you use. If you need a typed Drizzle column, edit the generated file manually or add a cast after generation.

Modifiers

All field builders support the following chainable modifiers:

Modifier Effect
.primary() Marks the column as the primary key
.unique() Adds a unique constraint
.optional() Allows undefined / null; removes the NOT NULL constraint
.default(val) Sets a static default value
.default(fn) Sets a dynamic default via $defaultFn
.min(n) Minimum string length (string/uuid) or minimum value (number/integer)
.max(n) Maximum string length (string/uuid) or maximum value (number/integer)
.email() Adds email format validation (string only)
.serverOnly() Column exists in DB but is excluded from all API inputs and outputs
.writeOnly() Accepted as input but never included in responses
.readOnly() Included in responses but excluded from create/update inputs