realworld-hono-drizzle
Version:
A RealWorld backend built with Hono and Drizzle
113 lines (70 loc) • 5.09 kB
Markdown
# 
This a backend for the [RealWorld](https://github.com/gothinkster/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](https://github.com/gothinkster/realworld) repo.
# How it works
The application is built with [Hono](https://hono.dev), which means that the code is compatible with Web standards like `Request` and `Response`. Data is stored in an SQLite database (using the [libSQL](https://turso.tech/libsql) driver) and the database operations are performed with [Drizzle](https://orm.drizzle.team/). Incoming data is parsed with [Valibot](https://valibot.dev/), and the correctness of the format of outgoing data is also ensured with Valibot.
[According to the RealWorld specification](https://realworld-docs.netlify.app/specifications/backend/endpoints/), authentication is done with JWT, specified in the Authorization header of a request.
The code consists of six modules in [`src/modules`](./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`](./src/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](#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`](https://developer.mozilla.org/en-US/docs/Web/API/Request) object as a first argument and the configuration as a second argument. See [Configuration](#configuration) for more explanation.
```js
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:
```js
import { applyMigrations } from 'realworld-hono-drizzle';
await applyMigrations('file:local.db');
```
You can also seed the database with some initial data:
```js
import { seed } from 'realworld-hono-drizzle';
await seed('file:local.db');
```
## From source
You should have Node.js >= 20 and [pnpm](https://pnpm.io/) 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](https://turso.tech/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`](.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:
```js
import realWorldApp from 'realworld-hono-drizzle';
realWorldApp.fetch(req, { DATABASE_URL: '<value>', JWT_SECRET: '<value>' });
```
# License
ISC, [explained](https://choosealicense.com/licenses/isc/)