No description
  • TypeScript 100%
Find a file
2026-05-21 10:05:34 -03:00
src Usuarios podem ser adicionados e removidos de chats 2026-05-21 10:05:34 -03:00
tests Usuarios podem ser adicionados e removidos de chats 2026-05-21 10:05:34 -03:00
.gitignore Codigo inicial do projeto 2026-05-21 01:02:00 -03:00
bun.lock Codigo inicial do projeto 2026-05-21 01:02:00 -03:00
drizzle.config.ts Codigo inicial do projeto 2026-05-21 01:02:00 -03:00
LICENSE Initial commit 2026-05-20 09:49:09 -03:00
package.json Adicionado testes 2026-05-21 01:32:21 -03:00
README.md Usuarios podem ser adicionados e removidos de chats 2026-05-21 10:05:34 -03:00
tsconfig.json Codigo inicial do projeto 2026-05-21 01:02:00 -03:00

Bapo API

A real-time chat application API built with a modern, performant TypeScript-native stack.


Tech Stack

Runtime — Bun

Bun is a fast all-in-one JavaScript runtime with native TypeScript support. There is no compilation step — files run directly. It also ships with a built-in package manager, .env loader, and password hashing utilities (Bun.password) used for bcrypt hashing.

Framework — Hono

Lightweight and ultrafast web framework built for the edge with first-class TypeScript support. Used for:

  • HTTP routing and middleware chaining
  • JWT signing/verification via hono/jwt
  • WebSocket upgrade handling via hono/bun's createBunWebSocket

ORM — Drizzle ORM

Type-safe, schema-first ORM for SQL databases. Drizzle infers full TypeScript types from the schema, so query results are always typed. Ships with drizzle-kit for generating and running migrations.

Database driver — postgres.js

High-performance PostgreSQL client for Node/Bun. Used directly by Drizzle as the underlying connection layer.

Database — PostgreSQL

Relational database. Stores users, chats, messages, and the user↔chat join table. All primary keys are UUIDs generated by PostgreSQL (gen_random_uuid()).


Project Structure

src/
├── db/
│   ├── schema.ts        # Table definitions (users, chats, messages, user_chats)
│   ├── index.ts         # postgres.js client + Drizzle instance
│   └── migrations/      # SQL files generated by drizzle-kit
├── middleware/
│   └── auth.ts          # JWT bearer middleware + verifyToken helper
├── routes/
│   ├── auth.ts          # /api/auth  (register, login, logout)
│   ├── users.ts         # /api/user
│   ├── chats.ts         # /api/chats
│   └── messages.ts      # /api/messages (HTTP + WebSocket)
└── index.ts             # App entry point / Bun.serve config

Setup

Prerequisites

  • Bun >= 1.0
  • A running PostgreSQL instance

Install dependencies

bun install

Configure environment

Fill in the values in .env:

DATABASE_URL=postgresql://user:password@localhost:5432/bapo
JWT_SECRET=change-this-to-a-long-random-secret
PORT=3000

Run migrations

bun db:generate   # generates SQL from schema
bun db:migrate    # applies migrations to the database

Start the server

bun dev     # development with hot reload
bun start   # production

Environment Variables

Variable Description Required
DATABASE_URL PostgreSQL connection string
JWT_SECRET Secret key used to sign JWT tokens
PORT Port to listen on (default: 3000)

API Routes

Auth

Method Path Description Auth
POST /api/auth/register Register a new user, returns JWT
POST /api/auth/login Login with credentials, returns JWT
DELETE /api/auth/logout Logout (stateless — client discards token) Bearer

User

Method Path Description Auth
GET /api/user Get the authenticated user's profile Bearer

Chats

Method Path Description Auth
GET /api/chats List all chats the user belongs to Bearer
GET /api/chats/:id Get a specific chat Bearer
POST /api/chats Create a new chat (creator is auto-joined) Bearer
PATCH /api/chats/:id Update the chat name Bearer
DELETE /api/chats/:id Delete a chat Bearer
POST /api/chats/:id/users Add a user to a chat by username Bearer
DELETE /api/chats/:id/users/:userId Remove a user from a chat. Auto-deletes the chat if no members remain Bearer

Messages

Method Path Description Auth
GET /api/messages?chatId= Get message history for a chat Bearer
WS /api/messages/ws?chatId=&token= Real-time messaging via WebSocket Token param
PATCH /api/messages?id= Update a message's content Bearer
DELETE /api/messages?id= Delete a message Bearer

Note on WebSocket auth: The browser WebSocket API does not support custom headers on the upgrade request. The JWT must be passed as a token query parameter instead of a Bearer header.


Data Models

User

{
  "id": "uuid",
  "username": "string",
  "createdAt": "timestamp",
  "updatedAt": "timestamp"
}

passwordHash is stored but never returned by any endpoint.

Chat

{
  "id": "uuid",
  "name": "string",
  "createdAt": "timestamp",
  "updatedAt": "timestamp"
}

Message

{
  "id": "uuid",
  "content": "string",
  "userId": "uuid",
  "chatId": "uuid",
  "createdAt": "timestamp",
  "updatedAt": "timestamp"
}

user_chats (join table)

Column Type
user_id UUID (FK → users)
chat_id UUID (FK → chats)

Scripts

Command Description
bun dev Start with hot reload
bun start Start in production mode
bun db:generate Generate migration SQL from schema changes
bun db:migrate Apply pending migrations
bun db:studio Open Drizzle Studio (visual DB browser)

Rotas

  • POST /api/auth/register
  • POST /api/auth/login
  • DELETE /api/auth/logout
  • GET /api/user

  • GET /api/chats
  • GET /api/chats/{id}
  • POST /api/chats
  • PATCH /api/chats/{id}
  • DELETE /api/chats/{id}
  • POST /api/chats/{id}/users
  • DELETE /api/chats/{id}/users/{userId}

  • GET /api/messages
  • WS /api/messages/ws
  • PATCH /api/messages
  • DELETE /api/messages