CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl-labs/drizzle-best-practices

Drizzle ORM patterns -- schema definition, indexes, relations, migrations, transactions, upserts, prepared statements, and connection setup

96

1.60x
Quality

96%

Does it follow best practices?

Impact

98%

1.60x

Average score across 5 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

criteria.jsonevals/scenario-2/

{
  "context": "Tests whether the agent proactively applies Drizzle schema best practices: explicit indexes on FK columns (Drizzle does NOT auto-index), indexes on filtered columns, references with onDelete, money as integer cents, text with enum option for status fields, createdAt/updatedAt on ALL tables, relations() for query API, foreign_keys pragma for SQLite, passing schema to drizzle(), and proper schema file location. The task describes only business requirements.",
  "type": "weighted_checklist",
  "checklist": [
    {
      "name": "Indexes on FK columns",
      "description": "Every foreign key column (e.g., eventId on ticket_types, eventId and ticketTypeId on purchases) has an explicit index() defined in the table's third-argument callback using index('name').on(table.column)",
      "max_score": 12
    },
    {
      "name": "Indexes on filtered columns",
      "description": "Columns used for filtering (event status, event date, purchase status) have indexes defined",
      "max_score": 8
    },
    {
      "name": "References with onDelete",
      "description": "All foreign key .references() calls include an explicit onDelete action (cascade, restrict, or set null) -- not bare references() without onDelete",
      "max_score": 10
    },
    {
      "name": "Money as integer cents",
      "description": "Ticket prices and any monetary values are stored as integer representing cents (e.g., priceCents), not real/float/text",
      "max_score": 10
    },
    {
      "name": "Enum via text with enum option",
      "description": "Event status and purchase status fields use text('col', { enum: ['value1', 'value2'] }) pattern, not plain text()",
      "max_score": 8
    },
    {
      "name": "createdAt on all tables",
      "description": "Every table has a createdAt column with a SQL default expression (sql`(datetime('now'))` for SQLite)",
      "max_score": 7
    },
    {
      "name": "updatedAt on all mutable tables",
      "description": "All tables that can be updated (events, purchases, and ticket_types at minimum) include an updatedAt column -- not just the main entity table",
      "max_score": 8
    },
    {
      "name": "Relations defined",
      "description": "relations() objects are defined for tables with foreign keys, using one() and many() to enable the query API with nested eager loading",
      "max_score": 10
    },
    {
      "name": "Schema passed to drizzle",
      "description": "The drizzle() call in db.ts passes { schema } (or equivalent) as the second argument to enable the query API",
      "max_score": 7
    },
    {
      "name": "SQLite foreign_keys pragma",
      "description": "The SQLite connection setup enables the foreign_keys pragma (sqlite.pragma('foreign_keys = ON') or equivalent) since SQLite has FK enforcement OFF by default",
      "max_score": 8
    },
    {
      "name": "SQLite WAL mode",
      "description": "The SQLite connection enables WAL journal mode for concurrent read access",
      "max_score": 5
    },
    {
      "name": "notNull on required columns",
      "description": "Required columns (name, date, price, status, quantity) are marked with .notNull()",
      "max_score": 7
    }
  ]
}

evals

tile.json