DEV Community

Cover image for Missing Rails Console? Building a Database REPL for NestJS + Prisma
Christoph Grothaus
Christoph Grothaus

Posted on

Missing Rails Console? Building a Database REPL for NestJS + Prisma

TL;DR: Coming from Rails/Phoenix, I missed having an interactive database console. So I built one for my NestJS + Prisma stack. Here's how and why.

The Problem: No Interactive Database Console ๐Ÿ˜ข

If you've ever worked with Ruby on Rails or Elixir Phoenix, you know the joy of having an interactive console at your fingertips:

# Rails
rails console
> User.where(active: true).count
=> 1337

# Phoenix
iex -S mix
> MyApp.Repo.all(User)
Enter fullscreen mode Exit fullscreen mode

These REPLs are game-changers for development. Need to quickly test a query? Explore your data model? Debug a complex association? Just fire up the console and start experimenting.

But when I switched to NestJS + Prisma... ๐Ÿคทโ€โ™‚๏ธ

Sure, there's prisma studio for a GUI, but sometimes you just want to code your way through the data. You want to:

  • Quickly prototype complex queries
  • Test edge cases without writing full test files
  • Explore data relationships interactively
  • Debug production data issues with real queries

The Solution: DIY Database Console ๐Ÿ› ๏ธ

So I built my own (of course with a lot AI assistance by Claude Sonnet)! Meet the Prisma DB Console - a Rails-like interactive REPL for Prisma:

#!/usr/bin/env ts-node

import { PrismaClient } from '@prisma/client';
import repl from 'repl';
import util from 'util';

// Initialize Prisma with query logging
const prisma = new PrismaClient({
  log: [
    { emit: 'event', level: 'query' },
    { emit: 'stdout', level: 'error' },
    { emit: 'stdout', level: 'info' },
    { emit: 'stdout', level: 'warn' },
  ],
});

// Log SQL queries with params and timing
prisma.$on('query', (e) => {
  console.log('---');
  console.log(e.query);
  console.log(e.params);
  console.log(String(e.duration) + 'ms');
  console.log('---');
});
Enter fullscreen mode Exit fullscreen mode

Key Features That Make It Awesome โœจ

1. Prisma Client Pre-loaded

No more import boilerplate - just start querying:

db-console> await prisma.user.findMany()
db-console> await prisma.organization.count()
Enter fullscreen mode Exit fullscreen mode

2. SQL Query Visibility

See exactly what SQL gets generated, with parameters and execution time:

---
SELECT "User"."id", "User"."email" FROM "User"
[]
12ms
---
Enter fullscreen mode Exit fullscreen mode

3. Helpful Examples on Startup

Because who remembers all the Prisma syntax?

๐Ÿš€ Prisma DB Console
๐Ÿ“Š Prisma Client loaded as "prisma"
๐Ÿ’ก Examples:
   await prisma.user.findMany()
   await prisma.tenant.count()
   await prisma.$queryRaw`SELECT COUNT(*) FROM "user"`
   await prisma.organization.findFirst({ include: { tenants: true } })
Enter fullscreen mode Exit fullscreen mode

4. Clean Exit Handling

Properly disconnects from the database when you exit:

function cleanupAndExit() {
  console.log('\n๐Ÿ‘‹ Disconnecting from database...');
  prisma.$disconnect()
    .finally(() => process.exit(0));
}
Enter fullscreen mode Exit fullscreen mode

Usage: Simple as npm run db:console ๐Ÿš€

Added it as an npm script for easy access:

{
  "scripts": {
    "db:console": "ts-node bin/db-console.ts"
  }
}
Enter fullscreen mode Exit fullscreen mode

Now I can just run:

npm run db:console
# or
pnpm db:console
Enter fullscreen mode Exit fullscreen mode

And I'm off to the races! Perfect for:

  • Data exploration: await prisma.user.findMany({ include: { profile: true } })
  • Quick counts: await prisma.order.count({ where: { status: 'PENDING' } })
  • Complex queries: await prisma.$queryRaw\SELECT * FROM ...``
  • Testing relationships: Verify those Prisma relations work as expected

The Real Impact ๐Ÿ“ˆ

Instead of:

  1. Writing a throwaway script
  2. Adding console.logs
  3. Running the script
  4. Deleting the script
  5. Repeat...

I just:

  1. Open console
  2. Experiment
  3. Done!

Want to Build Your Own? ๐Ÿ”จ

The full implementation is about 70 lines of TypeScript. Key ingredients:

  • Node's built-in repl module
  • Your Prisma client
  • Event-based query logging
  • Proper cleanup handlers
  • Some helpful utilities in the REPL context

The beauty is in its simplicity - no external dependencies beyond what you already have in a NestJS + Prisma project. The full code of my db-console.ts is available on GitHub Gist if you want to copy and adapt it.

Closing Thoughts ๐Ÿ’ญ

Sometimes the best tools are the ones you build yourself. They fit your exact workflow, solve your specific pain points, and give you that Rails-like developer experience you've been missing.

If you're working with NestJS + Prisma and find yourself constantly writing throwaway scripts to test database queries, consider building your own console. Your future self will thank you!


What is your experience in the NestJS + Prisma ecosystem? Did I miss out on an existing solution? Just drop a comment below!


Top comments (0)