DEV Community

Cover image for Getting Started with Hono JS and Drizzle ORM
Aaron K Saunders
Aaron K Saunders

Posted on

Getting Started with Hono JS and Drizzle ORM

This short summary is best used as companion documentation to support the video tutorial on Getting Started with Hono JS and Drizzle ORM.

We create a set of API routes to support manipulating a user object is a sqlite database, we interface with the database using drizzle ORM

  • Hono - Fast, lightweight, built on Web Standards. Support for any JavaScript runtime.
  • Drizzle ORM - you can define and manage database schemas in TypeScript, access your data in a SQL-like or relational way, and take advantage of opt-in tools to push your developer experience through the roof.

Installation and Setup

run command to get started with the basic Hono application, we will focus on nodejs build.

npm create hono@latest
Enter fullscreen mode Exit fullscreen mode

Your terminal output should be similar to information below.

aaronksaunders@Aarons-iMac LIVE % npm create hono@latest
Need to install the following packages:
create-hono@0.14.3
Ok to proceed? (y) y

> npx
> create-hono

create-hono version 0.14.3
? Target directory my-hono-1
? Which template do you want to use? nodejs
? Do you want to install project dependencies? yes
? Which package manager do you want to use? npm
βœ” Cloning the template
βœ” Installing project dependencies
πŸŽ‰ Copied project files
Get started with: cd my-hono-1
Enter fullscreen mode Exit fullscreen mode

The minimal code for the hono server is in index.ts

import { serve } from "@hono/node-server";
import { Hono } from "hono";

const app = new Hono();

app.get("/", (c) => {
  return c.text("Hello Hono!");
});

// set port
const port = 3000;
console.log(`Server is running on http://localhost:${port}`);

// serve app
serve({
  fetch: app.fetch,
  port,
});
Enter fullscreen mode Exit fullscreen mode

now to test build, switch to directory and run command below.

npm run dev
Enter fullscreen mode Exit fullscreen mode

the server should be running on localhost:3000, if you access it in your web browser you should get a response from the server.

Hello Hono!
Enter fullscreen mode Exit fullscreen mode

Add Drizzle and SQLite

Helpful Links

run following commands in your terminal

npm i drizzle-orm better-sqlite3 dotenv
npm i -D drizzle-kit tsx
Enter fullscreen mode Exit fullscreen mode
  • better-sqlite-3 is the version of sqlite we are using in the application -dotenv is used to read the environment file
  • drizzle-kit is a set of utilities to support drizzle orm integration

Create .env file

DATABASE_URL=./db.sqlite
Enter fullscreen mode Exit fullscreen mode

Create a drizzle directory, this is where the migration files will be after they are generated.

Create /src/db/schema.ts and add the information below

import { sql } from "drizzle-orm";
import { int, sqliteTable, text, uniqueIndex } from "drizzle-orm/sqlite-core";

export const usersTable = sqliteTable(
  "users_table",
  {
    id: int().primaryKey({ autoIncrement: true }),
    name: text().notNull(),
    age: int().notNull(),
    email: text().notNull().unique(),
    createdAt: text()
      .notNull()
      .default(sql`CURRENT_TIMESTAMP`),
    updatedAt: text()
      .notNull()
      .default(sql`CURRENT_TIMESTAMP`),
  },
  (table) => [uniqueIndex("email_idx").on(table.email)]
);

export type User = typeof usersTable.$inferSelect;
export type InsertUser = typeof usersTable.$inferInsert;
Enter fullscreen mode Exit fullscreen mode

we are creating a table and exporting some types that can be used when interacting with output from queries or when constructing objects need to make queries.

Create /src/db/index.ts which is used for managing database instance created by drizzle orm.

// src/db/index.ts
import { drizzle } from "drizzle-orm/better-sqlite3";
import Database from "better-sqlite3";
import * as schema from "./schema.js";
import "dotenv/config";

const sqlite = new Database(process.env.DATABASE_URL ?? "sqlite.db");

export const db = drizzle(sqlite, { schema });
Enter fullscreen mode Exit fullscreen mode


Create drizzle.config.ts in the project root directory

import "dotenv/config";
import { defineConfig } from "drizzle-kit";

export default defineConfig({
  out: "./drizzle",
  schema: "./src/db/schema.ts",
  dialect: "sqlite",
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
});
Enter fullscreen mode Exit fullscreen mode

Add scripts to package.json to generate migrations and apply them to the database

 "db:generate": "drizzle-kit generate",
 "db:migrate": "drizzle-kit migrate"
Enter fullscreen mode Exit fullscreen mode

Run Scripts to create database and push migrations, the terminal output should look similar to the output below.

aaronksaunders@Aarons-iMac my-hono-1 % npm run db:generate                    

> db:generate
> drizzle-kit generate

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/aaronksaunders/dev/LIVE/my-hono-1/drizzle.config.ts'
1 tables
users_table 6 columns 2 indexes 0 fks

[βœ“] Your SQL migration file ➜ drizzle/0000_wakeful_greymalkin.sql πŸš€
aaronksaunders@Aarons-iMac my-hono-1 % npm run db:migrate 

> db:migrate
> drizzle-kit migrate

No config path provided, using default 'drizzle.config.ts'
Reading config file '/Users/aaronksaunders/dev/LIVE/my-hono-1/drizzle.config.ts'
[βœ“] migrations applied successfully!%                                                         
aaronksaunders@Aarons-iMac my-hono-1 % 
Enter fullscreen mode Exit fullscreen mode

Use drizzle kit studio to add some users to database.





npx drizzle-kit studio 
Enter fullscreen mode Exit fullscreen mode

Add a route for querying the users in the database

import { db } from "./db/index.js";
import { Hono } from "hono";
import { usersTable } from "./db/schema.js";
import { eq } from "drizzle-orm";
const usersRoute = new Hono();

// Get all users
usersRoute.get("/", async (c) => {
  const allUsers = await db.query.usersTable.findMany();
  return c.json(allUsers);
});

// Get a user by id, be sure to note the conversion of
// the id from string back to a number
usersRoute.get("/:id", async (c) => {
  const { id } = c.req.param();
  const userResp = await db.query.usersTable.findFirst({
    where: eq(usersTable.id, Number(id)),
  });
  return c.json(userResp);
});

// Create a user
usersRoute.post("/", async (c) => {
  const { name, email, age } = await c.req.json();
  const newUserResp = await db.insert(usersTable).values({ name, email, age });
  return c.json(newUserResp);
});

export default usersRoute;
Enter fullscreen mode Exit fullscreen mode

Modify index.ts to include the new set of routes





import { serve } from "@hono/node-server";
import { Hono } from "hono";
import usersRoute from "./users-route.js";

const app = new Hono();

app.get("/", (c) => {
  return c.text("Hello Hono!");
});

// Use the users routes
app.route("/users", usersRoute);

const port = 3000;
console.log(`Server is running on http://localhost:${port}`);

serve({
  fetch: app.fetch,
  port,
});
Enter fullscreen mode Exit fullscreen mode

Use a tool like postman or thunderbolt VSCode Extension to test API

Source Code

Video

Top comments (0)