1.0.5 • Published 4 months ago

realworld-hono-drizzle v1.0.5

Weekly downloads
-
License
ISC
Repository
github
Last release
4 months ago

RealWorld Example App

This a backend for the RealWorld app, also known as Conduit.

This codebase was created to demonstrate a fully fledged backend application built with Hono including CRUD operations, authentication, routing, pagination, and more.

We've gone to great lengths to adhere to the Hono community styleguides & best practices.

For more information on how to this works with other frontends/backends, head over to the RealWorld repo.

How it works

The application is built with Hono, which means that the code is compatible with Web standards like Request and Response. Data is stored in an SQLite database (using the libSQL driver) and the database operations are performed with Drizzle. Incoming data is parsed with Valibot, and the correctness of the format of outgoing data is also ensured with Valibot.

According to the RealWorld specification, authentication is done with JWT, specified in the Authorization header of a request.

The code consists of six modules in src/modules, each handling a different part of the RealWorld API:

  • articles — handles all /api/articles routes
  • comments (located in src/modules/articles/) — handles all /api/articles/:slug/comments routes
  • profiles — handles all /api/profiles routes
  • users — handles all /api/users routes
  • user (located in src/modules/users/) — handles all /api/user routes
  • tags — handles all /api/tags routes

These modules are mostly isolated, but they do reference each other's schemas.

The modules are then attached to their routes in factory.ts and the factory produces Hono application objects that can be run on many different runtimes.

Run the backend

As a standalone application

The simplest way to run the application is through npm. You need to have Node.js installed on your machine.

npx realworld-hono-drizzle

This will start the server on http://localhost:3000 and create a local.db SQLite file in the folder that you're running the command from. Refer to Configuration for available options.

As a Hono module

The realworld-hono-drizzle package default-exports a Hono application that has a simple interface that conforms to Web standards. This lets you easily integrate it into your frontend server. Simply call .fetch on the exported application and pass a Request object as a first argument and the configuration as a second argument. See Configuration for more explanation.

import { randomBytes } from 'node:crypto'; // or the equivalent in your other runtime
import realWorldApp from 'realworld-hono-drizzle';

const JWT_SECRET = randomBytes(64).toString('base64url');

/** 
 * @param {Request} req 
 * @returns {Promise<Response>}
 */
function handleApiRequest(req) {
  return realWorldApp.fetch(req, { 
    DATABASE_URL: 'file:local.db', 
    JWT_SECRET,
  });
}

The app expects the database file to be pre-populated with the necessary tables. You can call the applyMigrations function to do this:

import { applyMigrations } from 'realworld-hono-drizzle';

await applyMigrations('file:local.db');

You can also seed the database with some initial data:

import { seed } from 'realworld-hono-drizzle';

await seed('file:local.db');

From source

You should have Node.js >= 20 and pnpm installed on your machine.

Clone this repository, cd into it, then run pnpm install to install the dependencies.

To start the server with an empty database, run pnpm dev directly. If you want to add some data, run pnpm seed first and then start the server with pnpm dev.

Configuration

The application has three parameters:

  • DATABASE_URL: Either a local file with the file: protocol or a libSQL-compatible URL to the SQLite database.
  • JWT_SECRET: A secret key used to sign and verify JWT tokens.
  • (if running standalone or with pnpm dev) PORT: The port for the server to listen on.

If you're running standalone with npx realworld-hono-drizzle or running from source, then you can specify all three parameters as environment variables:

  • Directly in the command: env PORT=4000 npx realworld-hono-drizzle
  • In a .env file (see .env.example)

If you're running the application as a Hono module, then you should pass the configuration as the second argument to the .fetch method. The PORT parameter does not apply in this case:

import realWorldApp from 'realworld-hono-drizzle';

realWorldApp.fetch(req, { DATABASE_URL: '<value>', JWT_SECRET: '<value>' });

License

ISC, explained