HOPAK.JS · v0.5

Бекенд-фреймворк для Bun.

Файлова маршрутизація. Типізовані моделі. Згенерований CRUD.

$ bun add -g @hopak/cli
Швидкий старт

Чому Hopak?

МОДЕЛІ

Один файл описує весь ресурс.

З оголошення моделі генеруються таблиця, TypeScript-тип запису, валідатор і скелети маршрутів. Поле змінюється один раз — оновлюється все, що з ним пов’язане.

РАНТАЙМ

Не виконується нічого, чого немає у Вашому коді.

Без сканера декораторів, DI-контейнера, маршрутів, що з’являються невідомо звідки. Сервер виконує саме те, що лежить у app/. Відкрийте будь-який файл і перепишіть під себе.

БАЗА ДАНИХ

Три діалекти, один API.

SQLite вбудовано у Bun. Перехід на Postgres або MySQL — однією командою hopak use <dialect>. Код моделей лишається без змін.

ШВИДКІСТЬ

Від порожньої теки до живого API — за хвилини.

Дві команди — і Ви маєте проєкт із шістьма REST-ендпоінтами. Валідація, JSON, пагінація, приховування чутливих полів — усе вже всередині, нічого збирати докупи не доведеться.

У КОМПЛЕКТІ

Auth, міграції, dev TLS — нічого ставити окремо.

JWT, OAuth, RBAC у @hopak/auth. Типізовані up / down міграції. Dev-сертифікати через hopak generate cert. Не доведеться добирати й сполучати чотири окремі пакети.

BUN-NATIVE

Без Node-баласту на гарячому шляху.

bun:sqlite, Bun.password, Bun.serve, Bun.write — фреймворк використовує те, що Bun уже надає, без Node-обгорток.

Як це працює

Модель

Поля, обмеження, звʼязки.

app/models/post.ts
import { model, text, boolean, belongsTo } from '@hopak/core';

export default model('post', {
  title: text().required().min(3).max(200),
  content: text().required(),
  published: boolean().default(false),
  author: belongsTo('user'),
});

Декларація створює колонки таблиці, TypeScript-тип рядка і валідатор.

Маршрути

Два файли. Шість ендпоінтів.

$ hopak generate crud post
Created app/routes/api/posts.ts
Created app/routes/api/posts/[id].ts
app/routes/api/posts.ts
import { crud } from '@hopak/core';
import post from '../../models/post';

export const GET = crud.list(post);
export const POST = crud.create(post);

Згенеровані файли — звичайний TypeScript. Ендпоінт можна змінити або видалити у будь-який момент.

Відповідь

Запит до запущеного сервера.

$ curl localhost:3000/api/posts
HTTP/1.1 200 OK
{
  "items": [
    { "id": 1, "title": "Hello", "published": true, "author_id": 4 }
  ],
  "total": 1,
  "limit": 20,
  "offset": 0
}

Сервер валідує вхідні дані, приховує чутливі поля і пагінує списки.