Skip to content

Models

Models define your data entities. Each JSON file in config/models/ is one model.

Basic example

json
{
  "name": "User",
  "fields": {
    "email": "string",
    "name": "string",
    "createdAt": "date_now"
  }
}

id is always implicit — it's generated as a UUID.

Field types

The TypeScript type is always the same regardless of ORM or database. The generated ORM column type depends on the chosen ORM and database.

TypeTypeScriptDrizzle — SQLiteDrizzle — PostgreSQLDrizzle — MySQLPrisma (all databases)Notes
stringstringtexttextvarchar(255)String
numbernumberintegerintegerintInt
booleanbooleaninteger (0/1)booleanbooleanBoolean
dateDateinteger (epoch ms)timestamptimestampDateTime
date_nowDateinteger + .now()timestamp + .now()timestamp + .now()DateTime @default(now())Auto-set on create
uuidstringtext + randomUUID()uuid + .defaultRandom()varchar(36) + randomUUID()String @default(uuid())Auto-generated UUID
ModelNameModelNameFK text / integer columnFK uuid columnFK varchar(36) columnFK relationReferences another model

Full field definition

You can use a shorthand string or a full field object:

json
{
  "name": "Article",
  "fields": {
    "title": "string",
    "body": {
      "type": "string",
      "required": false
    },
    "published": {
      "type": "boolean",
      "default": false
    },
    "authorId": {
      "type": "string",
      "unique": false
    }
  }
}

Relations

json
{
  "name": "Article",
  "fields": {
    "author": {
      "type": "User",
      "relation": {
        "model": "User",
        "type": "one-to-many"
      }
    }
  }
}

Relation generation

When you declare a relation, Codabra automatically generates both sides of the relation. For example:

json
{
  "name": "Article",
  "fields": {
    "title": "string",
    "author": {
      "type": "User",
      "relation": { "model": "User", "type": "one-to-many" }
    }
  }
}

Drizzle + SQLite

ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

export const articles = sqliteTable('articles', {
  id: text('id')
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID()),
  title: text('title').notNull(),
  authorId: text('authorId'), // FK to users
});

export const users = sqliteTable('users', {
  id: text('id')
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID()),
  email: text('email').notNull(),
  name: text('name').notNull(),
  createdAt: integer('createdAt')
    .$defaultFn(() => Date.now())
    .notNull(),
});

Drizzle + PostgreSQL

ts
import { pgTable, text, integer, uuid, timestamp } from 'drizzle-orm/pg-core';

export const articles = pgTable('articles', {
  id: uuid('id').primaryKey().defaultRandom(),
  title: text('title').notNull(),
  authorId: uuid('authorId'), // FK to users
});

export const users = pgTable('users', {
  id: uuid('id').primaryKey().defaultRandom(),
  email: text('email').notNull(),
  name: text('name').notNull(),
  createdAt: timestamp('createdAt').defaultNow().notNull(),
});

Drizzle + MySQL

ts
import {
  mysqlTable,
  varchar,
  int,
  boolean,
  timestamp,
} from 'drizzle-orm/mysql-core';

export const articles = mysqlTable('articles', {
  id: varchar('id', { length: 36 })
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID()),
  title: varchar('title', { length: 255 }).notNull(),
  authorId: varchar('authorId', { length: 36 }), // FK to users
});

export const users = mysqlTable('users', {
  id: varchar('id', { length: 36 })
    .primaryKey()
    .$defaultFn(() => crypto.randomUUID()),
  email: varchar('email', { length: 255 }).notNull(),
  name: varchar('name', { length: 255 }).notNull(),
  createdAt: timestamp('createdAt')
    .$defaultFn(() => new Date())
    .notNull(),
});

Prisma (all databases)

prisma
model Article {
  id      String   @id @default(uuid())
  title   String
  author  User[]
}

model User {
  id        String   @id @default(uuid())
  email     String
  name      String
  createdAt DateTime @default(now())
  article   Article  @relation("Article_author", fields: [articleId], references: [id])
  articleId String
}

Supported relation types: one-to-one, one-to-many, many-to-many.

Generated output

For each model Codabra generates:

  • apps/nextjs/src/types/<ModelName>.ts — TypeScript interface (with relation imports)
  • ORM schema file (aggregated, all models):
    • Drizzle: apps/nextjs/drizzle/schema.ts
    • Prisma: apps/nextjs/prisma/schema.prisma
  • ORM client singleton:
    • Drizzle: apps/nextjs/src/lib/db.ts
    • Prisma: apps/nextjs/src/lib/prisma.ts

Released under the Elastic License 2.0.