npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jadiazinf/hibana

v0.1.4

Published

TypeScript backend framework built on Hono + Bun.js, inspired by Spring Boot, Rails and Laravel

Downloads

607

Readme


import { Hibana, Module, Controller, Get, Param, Injectable, ok } from '@jadiazinf/hibana'

@Injectable()
class GreetingService {
  hello(name: string) { return `Hello, ${name}!` }
}

@Controller('/greet')
class GreetController {
  constructor(private svc: GreetingService) {}

  @Get('/:name')
  greet(@Param('name') name: string) {
    return ok({ message: this.svc.hello(name) })
  }
}

@Module({ services: [GreetingService], controllers: [GreetController] })
class AppModule {}

await Hibana.create(AppModule).listen(3000)
// GET /greet/world → { "message": "Hello, world!" }

Controllers, services, DI, routing. All type-safe, all decorator-driven.


Quick Start

# Interactive project creation (recommended)
bunx @jadiazinf/hibana init my-app

# With flags (non-interactive)
bunx @jadiazinf/hibana init my-app --db=sqlite --features=auth,websocket
bunx @jadiazinf/hibana init my-app --db=postgres --features=auth --docker --ci

# Config strategy
bunx @jadiazinf/hibana init my-app --config=env     # .env only (default)
bunx @jadiazinf/hibana init my-app --config=yaml    # hibana.yml + .env for secrets

# Minimal setup
bunx @jadiazinf/hibana new my-app

Or manually:

mkdir my-app && cd my-app
bun init -y
bun add @jadiazinf/hibana hono reflect-metadata

Create src/main.ts:

import 'reflect-metadata'
import { Hibana, Module, Controller, Get } from '@jadiazinf/hibana'

@Controller('/')
class AppController {
  @Get('/')
  index() { return { message: 'Welcome to Hibana!' } }
}

@Module({ controllers: [AppController] })
class AppModule {}

const app = Hibana.create(AppModule)
// app.setGlobalPrefix('/api/v1')  // Optional: prefix all routes
await app.listen(3000)
bun run src/main.ts
#  🔥 H I B A N A
#  ────────────────────────────────────────
#  ➜  Server:     http://localhost:3000
#  ➜  Routes:     5 endpoints
#  ────────────────────────────────────────
#  "Compiling dreams, deploying realities"

Project Structure

env mode (default — --config=env):

my-app/
  src/
    app.module.ts           # Root module (uses Env.get() directly)
    app.controller.ts       # Default controller
    main.ts                 # Entry point
  .env                      # All configuration here
  tsconfig.json
  package.json

yaml mode (--config=yaml):

my-app/
  config/
    hibana.yml              # Framework configuration
  src/
    app.module.ts           # Root module (loads from YAML)
    app.controller.ts       # Default controller
    main.ts                 # Entry point
  .env                      # Secrets only (JWT_SECRET, DATABASE_URL)
  tsconfig.json
  package.json

Why Hibana?

If you've used NestJS, you already know Hibana. Same decorator patterns, same DI, same module system. But Hibana runs on Bun, uses Hono under the hood, and ships with batteries that NestJS makes you install separately.

If Bun is the engine and Hono is the chassis, Hibana is the fully assembled car.

| | Hibana | NestJS | Elysia | Hono | |---|:---:|:---:|:---:|:---:| | Decorators + DI | Yes | Yes | No | No | | Built-in ORM | Drizzle | No | No | No | | Auto-CRUD generation | Yes | No | No | No | | OpenAPI auto-gen | Yes | Separate pkg | Yes | Separate | | Auth + JWT + Roles | Yes | Separate | No | No | | WebSockets + Rooms | Yes | Separate | Yes | No | | Admin dashboard | Yes | No | No | No | | Session management | Yes | Separate | No | No | | File storage (S3) | Yes | Separate | No | No | | Mailer | Yes | Separate | No | No | | OAuth (Google/GitHub) | Yes | Separate | No | No | | HTMX integration | Yes | No | No | No | | View engine (EJS/Pug/HBS) | Yes | Separate | No | No | | Runtime | Bun | Node | Bun | Any | | Tests | 1,389 | - | - | - |

One bun add for a full-stack backend. No hunting for packages, no glue code, no version conflicts.

Philosophy

Hibana is built on six foundational ideas:

  1. Convention Over Configuration — Sensible defaults so you only configure what is truly different
  2. Decorator-Driven Development — Decorators describe what something is, not how to implement it
  3. Batteries Included — 33 modules in a single @jadiazinf/hibana package, no transpilation needed
  4. Type Safety First — Built entirely in TypeScript, errors caught at compile time
  5. Bun-Native Performance — Purpose-built for Bun: native TS execution, no transpilation, web-standard APIs
  6. Proven Patterns, Modern Execution — Battle-tested architecture (modules, DI, conventions) in a modern runtime

Features

Core

  • Dependency Injection -- Constructor injection with @Injectable, @Inject, circular dependency detection, request-scoped providers
  • Module System -- @Module with imports, exports, services, controllers, gateways. Dynamic modules via forRoot()
  • Lifecycle Hooks -- onModuleInit() and onModuleDestroy() on any service
  • Plugin System -- app.plugin() with register/onInit/onDestroy lifecycle

HTTP

  • Decorators -- @Controller, @Get/@Post/@Put/@Delete/@Patch/@Options, @Body/@Param/@Query/@Header/@Ctx/@Req/@UploadedFile
  • Guards -- @UseGuard for auth, roles, or custom access control. Extend HibanaGuard for type-safe guards
  • Pipes -- @Validate with Valibot, ParseIntPipe, ParseBoolPipe, ParseUUIDPipe, ParseFilePipe, DefaultValuePipe
  • Interceptors -- @UseInterceptor to transform responses, add timing, logging, caching
  • Exception Filters -- @UseFilter for custom error handling. Extend HibanaExceptionFilter for type safety
  • Middleware -- Class-based @UseMiddleware or global app.use(). Extend HibanaMiddleware for type-safe middleware
  • Exceptions -- HttpException, BadRequestException, UnauthorizedException, ForbiddenException, NotFoundException, ConflictException, UnprocessableEntityException, TooManyRequestsException, InternalServerErrorException
  • Utilities -- @HttpCode(201) to set response status, @Public() to skip auth guards
  • SSE/Streaming -- SseResponse for server-sent events
  • Versioning -- @Version('2') for API versioning
  • Global Prefix -- app.setGlobalPrefix('/api/v1') to prefix all routes
  • Serialization -- @Exclude/@Expose decorators for response shaping

Database

  • Drizzle ORM -- DrizzleRepository with type-safe queries, pagination, sorting, filtering
  • SQLite + PostgreSQL -- Switch drivers with one config change. Auto-detected migration templates
  • Migrations -- hibana migrate run/rollback/status, batch tracking, up/down. Async PostgreSQL support
  • Seeds -- hibana db:seed, per-file seeding
  • Row-Level Security -- @TenantScope, @OwnerScope, @GlobalScope, @UsePolicy for automatic WHERE injection

Auth & Security

  • JWT Auth -- AuthService with access/refresh tokens, JwtAuthGuard, @CurrentUser
  • Roles -- @Roles('admin') + RolesGuard
  • Token Blacklist -- Async revoke()/isRevoked() with pluggable store
  • Helmet -- Security headers
  • CORS -- Configurable origin, credentials, methods
  • Rate Limiting -- Per-IP sliding window, Redis-backed for distributed apps
  • CSRF -- Double-submit cookie pattern

Real-time

  • WebSockets -- @WebSocketGateway, @OnMessage/@OnOpen/@OnClose, rooms, guards on upgrade
  • Notifications -- send(userId, ...), broadcast, rooms, @OnNotification handlers, EventBus auto-forwarding
  • Events -- EventBusService, @OnEvent, wildcards

Infrastructure

  • Cache -- CacheService with in-memory (LRU) or Redis store
  • Queue -- QueueService, @Process, concurrency, retries with capped exponential backoff
  • Scheduler -- @Cron('*/5 * * * *') or @Cron('every:30s'), dashboard UI
  • Config -- Two modes: env-only (.env + Env.get()) or YAML (profiles + .env for secrets), typed env validation
  • Logger -- Structured logging, correlation IDs, JSON or pretty format, automatic request logging
  • Health Checks -- HealthModule.forRoot(), Redis indicator, custom indicators
  • Sessions -- Cookie-based with @Session() decorator, flash data, rolling, store-agnostic
  • i18n -- Interpolation, pluralization, locale middleware

Ecosystem

  • OpenAPI -- Auto-generated spec + optional @ApiOperation, @ApiResponse, @ApiTags, @ApiExcludeEndpoint. Scalar UI at /docs
  • GraphQL -- @Resolver, @Query (exported as GqlQuery), @Mutation (exported as GqlMutation), @Arg
  • Microservices -- @MessagePattern, @EventPattern, transport abstraction
  • OAuth -- Google + GitHub providers, state validation, JWT pair on callback
  • View Engine -- EJS, Handlebars, Pug with @Render decorator
  • HTMX -- HtmxMiddleware, @HxRequest, @HxTrigger, HtmxResponse builder
  • Admin Panel -- Auto-generated CRUD dashboard from Drizzle schemas
  • Scheduler Dashboard -- Task monitoring UI with manual trigger
  • Mailer -- Resend + Console transports, template interpolation
  • File Storage -- Local disk + S3 (Bun native), multi-disk manager

Developer Tools

  • CLI -- hibana generate controller/service/module/crud/guard/pipe/filter/middleware/migration/seeder
  • Interactive Init -- hibana init with database, feature selection, Docker/CI generation
  • Dev Server -- hibana dev with file watching and auto-reload
  • Testing -- Testing.createTestingModule() with overrideProvider()
  • Docker/CI -- Dockerfile, docker-compose, GitHub Actions generators

Module Map

@jadiazinf/hibana
├── Core .............. DI container, modules, lifecycle, plugins
├── HTTP .............. Controllers, guards, pipes, filters, interceptors, SSE
├── ORM ............... Drizzle repository, migrations, seeds
├── Auth .............. JWT, roles, token blacklist
├── Security .......... Helmet, CORS, rate limit, CSRF
├── Cache ............. In-memory (LRU) / Redis
├── Config ............ YAML, profiles, .env, env validation
├── Logger ............ Structured logging, correlation IDs
├── Events ............ EventBus, @OnEvent, wildcards
├── Queue ............. Job processing, retries, concurrency
├── Scheduler ......... Cron jobs, interval tasks, dashboard
├── Session ........... Cookie sessions, flash data
├── i18n .............. Translations, interpolation, pluralization
├── WebSocket ......... Gateways, rooms, guards
├── Notification ...... User targeting, broadcast, rooms
├── Redis ............. Client, cache/rate-limit/blacklist stores
├── OpenAPI ........... Auto spec generation, Scalar UI
├── GraphQL ........... Resolvers, queries, mutations
├── Microservice ...... Message/event patterns, transports
├── OAuth ............. Google, GitHub, extensible providers
├── View .............. EJS, Handlebars, Pug engines
├── HTMX .............. Middleware, guards, response builder
├── Admin ............. Auto-generated CRUD dashboard
├── Mail .............. Resend, console transports
├── Storage ........... Local disk, S3
├── Scope (RLS) ....... Tenant/owner scopes, policies
├── Health ............ Health checks, indicators
├── Testing ........... Test module builder, provider overrides
├── Plugin ............ Plugin lifecycle management
├── Dev ............... Dev server with hot reload
└── CLI ............... Generators, init, migrations, seeds

Architecture

Every HTTP request flows through a layered pipeline:

Request
  │
  ├── Request Logger (auto-registered by LoggerModule)
  │     --> GET /users 200 12.5ms
  │
  ├── Middleware (global → controller → route)
  │     Session, CORS, Helmet, Rate Limit, CSRF, HTMX
  │
  ├── Guards (global → controller → route)
  │     JwtAuthGuard, RolesGuard, HtmxOnlyGuard, custom
  │
  ├── Pipes (parameter transformation + validation)
  │     ValidationPipe, ParseIntPipe, ParseFilePipe
  │
  ├── Interceptors (wrap handler execution)
  │     SerializationInterceptor, timing, caching
  │
  ├── Handler (your controller method)
  │
  ├── Exception Filters (catch and transform errors)
  │
  └── Response

DI is constructor-based with reflect-metadata. Three scopes: @Singleton (default), @Transient, @RequestScoped. Circular dependency detection at resolution time.

Store abstraction (ISP): Cache, rate limiting, and token blacklist share a clean interface pattern — ICacheStore, IRateLimitStore, ITokenBlacklistStore. Each has in-memory and Redis implementations. Swap storage backends without changing application code.

Base classes: Extend HibanaGuard, HibanaMiddleware, HibanaPipe, or HibanaExceptionFilter for type-safe implementations with IDE autocompletion. HibanaService and HibanaController provide auto-CRUD with pagination, sorting, and filtering.

Examples

REST API with Auth and Validation

import {
  Hibana, Module, Controller, Get, Post, Body, Param,
  UseGuard, JwtAuthGuard, RolesGuard, Roles, CurrentUser,
  Validate, AuthModule, ParseUUIDPipe,
} from '@jadiazinf/hibana'
import * as v from 'valibot'

const CreateUserDto = v.object({
  email: v.pipe(v.string(), v.email()),
  password: v.pipe(v.string(), v.minLength(8)),
  name: v.string(),
})

@Controller('/users')
@UseGuard(JwtAuthGuard)
class UserController {
  @Post('/')
  @Roles('admin')
  @UseGuard(RolesGuard)
  @Validate(CreateUserDto)
  create(@Body() data: v.InferOutput<typeof CreateUserDto>) {
    return { created: data.email }
  }

  @Get('/me')
  me(@CurrentUser() user: any) {
    return user
  }

  @Get('/:id')
  findOne(@Param('id', ParseUUIDPipe) id: string) {
    return { id }
  }
}

Auto-CRUD Controller

import { HibanaController, HibanaService } from '@jadiazinf/hibana'

// Generates GET /, GET /:id, POST /, PUT /:id, DELETE /:id
// with pagination, sorting, search, and field filtering
class UserController extends HibanaController<User> {
  constructor(service: UserService) {
    super(service, '/users')
  }
}

WebSocket Chat

import {
  WebSocketGateway, OnMessage, OnOpen, OnClose,
  ConnectedSocket, WsPayload, WsServer,
} from '@jadiazinf/hibana'

@WebSocketGateway({ path: '/ws/chat' })
class ChatGateway {
  @OnOpen()
  onConnect(@ConnectedSocket() ws: any, @WsServer() server: any) {
    server.joinRoom(ws, 'general')
  }

  @OnMessage('chat')
  onChat(@WsPayload() data: { text: string }, @WsServer() server: any) {
    server.publishToRoom('general', 'chat', data)
  }

  @OnClose()
  onDisconnect(@ConnectedSocket() ws: any) {
    // cleanup
  }
}

Admin Panel from Drizzle Schema

import { Module, DatabaseModule, AdminModule } from '@jadiazinf/hibana'
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'

const products = sqliteTable('products', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  price: integer('price').notNull(),
  category: text('category'),
})

@Module({
  imports: [
    DatabaseModule.forRoot({ driver: 'sqlite', filename: './data.db' }),
    AdminModule.forRoot({
      entities: [{ name: 'Products', table: products }],
      title: 'Store Admin',
    }),
  ],
})
class AppModule {}

// 7 routes auto-generated:
// GET  /admin               → Dashboard with stats
// GET  /admin/products      → Searchable, paginated table
// GET  /admin/products/create → Create form
// POST /admin/products      → Handle create
// GET  /admin/products/:id  → Edit form
// PUT  /admin/products/:id  → Handle update
// DELETE /admin/products/:id → Handle delete

Cron Jobs with Dashboard

import { Injectable, Cron, SchedulerDashboardModule } from '@jadiazinf/hibana'

@Injectable()
class CleanupService {
  @Cron('0 3 * * *')
  async cleanExpiredSessions() {
    // Runs every day at 3 AM
  }

  @Cron('every:30s')
  async checkMetrics() {
    // Runs every 30 seconds
  }
}

// SchedulerDashboardModule.forRoot({ basePath: '/admin/scheduler' })
// → Task table with run counts, last errors, "Run Now" buttons

OpenAPI (Zero Config)

import {
  OpenApiModule, ApiOperation, ApiResponse, ApiTags, ApiExcludeEndpoint,
} from '@jadiazinf/hibana'

@Module({
  imports: [
    OpenApiModule.forRoot({
      info: { title: 'My API', version: '1.0.0' },
    }),
  ],
})
class AppModule {}

// Zero-config: routes, params, Valibot schemas auto-detected
// GET /openapi.json → Full spec
// GET /docs         → Scalar UI

// Optional decorators for fine-tuning:
@Controller('/orders')
@ApiTags('Orders')
class OrderController {
  @Get('/')
  @ApiOperation({ summary: 'List all orders' })
  @ApiResponse({ status: 200, description: 'Order list' })
  list() { /* ... */ }

  @Get('/internal')
  @ApiExcludeEndpoint()
  internal() { /* hidden from docs */ }
}

OAuth Login

import { OAuthModule, GoogleProvider, GithubProvider } from '@jadiazinf/hibana'

@Module({
  imports: [
    OAuthModule.forRoot({
      basePath: '/auth',
      providers: [
        new GoogleProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
        new GithubProvider({ clientId: '...', clientSecret: '...', redirectUri: '...' }),
      ],
      onLogin: async (profile, ctx) => {
        // Create/find user, return JWT payload
        return { sub: profile.id, email: profile.email }
      },
    }),
  ],
})
class AppModule {}

// GET /auth/google          → Redirect to Google
// GET /auth/google/callback → Handle callback, return JWT pair
// GET /auth/github          → Redirect to GitHub
// GET /auth/github/callback → Handle callback, return JWT pair

Row-Level Security

import { ScopedDrizzleRepository, TenantScope, OwnerScope, UsePolicy } from '@jadiazinf/hibana'

@TenantScope('organizationId')
@OwnerScope('createdBy')
class InvoiceRepository extends ScopedDrizzleRepository<typeof invoices> {
  constructor(db: any) {
    super(db, invoices)
  }
}

// Every query auto-injects: WHERE organizationId = :tenantId AND createdBy = :userId
// Admin bypass: repo.withoutScopes().findMany()

Security Stack

@Module({
  imports: [
    SecurityModule.forRoot({
      helmet: { contentSecurityPolicy: true },
      cors: { origin: 'https://myapp.com', credentials: true },
      rateLimit: { max: 100, windowMs: 60_000 },
      csrf: { enabled: true },
    }),
  ],
})
class AppModule {}

File Storage

import { StorageModule, StorageService } from '@jadiazinf/hibana'

@Module({
  imports: [
    StorageModule.forRoot({
      default: 'local',
      disks: {
        local: { driver: 'local', root: './uploads', baseUrl: '/files' },
        s3: { driver: 's3', bucket: 'my-bucket', region: 'us-east-1' },
      },
    }),
  ],
})
class AppModule {}

// In controllers:
@Post('/upload')
async upload(@UploadedFile(ParseFilePipe) file: File) {
  const info = await this.storage.put(`uploads/${file.name}`, file)
  return { url: info.url }
}

Redis Adapters

import { RedisModule } from '@jadiazinf/hibana'

@Module({
  imports: [
    RedisModule.forRoot({ url: 'redis://localhost:6379' }),
    // Redis automatically provides:
    // - RedisCacheStore for CacheModule
    // - RedisRateLimitStore for SecurityModule
    // - RedisBlacklistStore for AuthModule
  ],
})
class AppModule {}

Exception Handling

import {
  NotFoundException, ForbiddenException, HibanaExceptionFilter,
  UseFilter, HttpCode, Public,
} from '@jadiazinf/hibana'

// Throw built-in exceptions (auto-serialized to JSON)
@Get('/:id')
findOne(@Param('id') id: string) {
  const item = db.find(id)
  if (!item) throw new NotFoundException(`Item ${id} not found`)
  return item
}

// Custom exception filter
class BusinessErrorFilter extends HibanaExceptionFilter {
  catch(error: Error, ctx: any) {
    return ctx.json({ error: error.message, code: 'BUSINESS_ERROR' }, 422)
  }
}

@Post('/')
@HttpCode(201)        // Set response status
@Public()             // Skip auth guards
@UseFilter(BusinessErrorFilter)
create(@Body() data: any) { /* ... */ }

Sessions

import { SessionModule, SessionDecorator, Session } from '@jadiazinf/hibana'

@Module({
  imports: [
    SessionModule.forRoot({ ttlMs: 3600_000, rolling: true }),
  ],
})
class AppModule {}

@Controller('/cart')
class CartController {
  @Post('/add')
  addToCart(@SessionDecorator() session: Session, @Body() item: any) {
    const cart = session.get<any[]>('cart') ?? []
    cart.push(item)
    session.set('cart', cart)
    session.flash('message', 'Item added!')  // survives 1 request
    return { cart }
  }
}

Logger (Auto Request Logging)

import { Module, LoggerModule } from '@jadiazinf/hibana'

@Module({
  imports: [
    LoggerModule.forRoot({
      level: 'info',
      format: 'pretty',  // 'json' for production
      // requestLogging: true (default) — auto-logs all HTTP requests
    }),
  ],
})
class AppModule {}

// Output:
// [INFO] --> GET /users
// [INFO] <-- GET /users 200 12.5ms

No wiring needed — LoggerModule auto-registers request logging middleware.

Global Prefix

const app = Hibana.create(AppModule)
app.setGlobalPrefix('/api/v1')
await app.listen(3000)

// All routes now prefixed:
// GET /api/v1/users
// POST /api/v1/orders

Testing

import { Testing } from '@jadiazinf/hibana'

const module = await Testing.createTestingModule({
  imports: [AppModule],
})
  .overrideProvider(DatabaseService).useValue(mockDb)
  .compile()

const app = module.createApplication()
const res = await app.fetch(new Request('http://localhost/users'))
expect(res.status).toBe(200)

CLI

# Project scaffolding
hibana init my-app                    # Interactive setup (db, features, Docker, CI)
hibana init my-app --config=env       # .env only (default)
hibana init my-app --config=yaml      # YAML config + .env for secrets
hibana new my-app                     # Quick project creation

# Code generation
hibana generate controller user       # src/user/user.controller.ts
hibana generate service user          # src/user/user.service.ts
hibana generate module user           # src/user/user.module.ts
hibana generate crud product          # Controller + service + module
hibana generate guard auth            # src/auth/auth.guard.ts
hibana generate pipe trim             # src/trim/trim.pipe.ts
hibana generate filter http-error     # src/http-error/http-error.filter.ts
hibana generate middleware logger     # src/logger/logger.middleware.ts

# Database
hibana migrate generate create-users  # New migration file
hibana migrate run                    # Run pending migrations
hibana migrate rollback               # Rollback last batch
hibana migrate status                 # Show migration status
hibana db:seed                        # Run all seeders
hibana db:seed --file=users           # Run specific seeder

# Development
hibana dev                            # Dev server with auto-reload
hibana dev --port 8080                # Custom port

Configuration

Hibana supports two configuration strategies, selected at project creation with --config=env|yaml:

Env mode (default)

All configuration lives in .env. Access values with Env.get():

# .env
PORT=3000
DATABASE_URL=postgres://localhost:5432/myapp
JWT_SECRET=my-secret
import { Env } from '@jadiazinf/hibana'

DatabaseModule.forRoot({
  driver: EDatabaseDriver.POSTGRES,
  url: Env.get('DATABASE_URL'),
})

YAML mode

Structured configuration in config/hibana.yml, with .env for secrets:

# config/hibana.yml
app:
  name: my-app
  port: 3000

database:
  driver: sqlite
  filename: ./data.db

auth:
  secret: ${JWT_SECRET}
  accessTokenExpiry: 15m
  refreshTokenExpiry: 7d
# config/hibana.production.yml (overrides base)
database:
  driver: postgres
  host: ${DB_HOST}
  port: 5432
  database: ${DB_NAME}
HIBANA_PROFILE=production bun run src/main.ts

Env validation

ConfigModule.forRoot({
  path: './config',
  envSchema: {
    JWT_SECRET: { type: 'string' },
    DB_PORT: { type: 'number', default: 5432 },
    DEBUG: { type: 'boolean', default: false },
    ALLOWED_ORIGINS: { type: 'string[]' },
  },
})

Scripts

bun run src/main.ts # Run the application (Bun runs TypeScript directly)
bun run dev         # Dev server with auto-reload
bun test            # Run all tests
bun run lint        # Check code with Biome
bun run format      # Format code with Biome
bun run check       # Lint + format (auto-fix)

Note: Bun executes TypeScript natively — no build/transpilation step needed.

Code Quality

Hibana uses Biome for linting and formatting. The configuration lives in biome.json at the project root:

  • Style: 2-space indent, single quotes, semicolons, trailing commas
  • Lint rules: recommended set + noExplicitAny, noUnusedVariables, useConst
  • Import sorting: automatic via organizeImports

New projects created with hibana init or hibana new include Biome pre-configured with VS Code format-on-save support.

Requirements

  • Bun >= 1.0
  • TypeScript >= 5.0
  • "experimentalDecorators": true in tsconfig.json
  • "emitDecoratorMetadata": true in tsconfig.json

Optional peer dependencies:

bun add ioredis     # Redis adapters
bun add ejs         # EJS view engine
bun add handlebars  # Handlebars view engine
bun add pug         # Pug view engine

Contributing

Contributions welcome. Please open an issue first to discuss what you'd like to change.

git clone https://github.com/jadiazinf/hibana.git
cd hibana
bun install
bun test   # 1,389 tests

License

MIT