npm package: @razvan11/paladin
Description: A Bun-based backend framework with decorators, dependency injection, and controller registration
Author: Razvan
Latest version: 1.1.5

# @razvan11/paladin

A modern, decorator-based backend framework for Bun with dependency injection, controller registration, and WebSocket support.

## Features

- **Decorator-based routing** - Clean, expressive route definitions
- **Dependency Injection** - Powered by Inversify
- **Built for Bun** - Leverages Bun's performance
- **WebSocket support** - First-class WebSocket handling
- **React SSR** - Server-side rendering utilities
- **Middleware support** - Per-route middleware functions
- **Static file serving** - Built-in asset handling

## Installation

```bash
bun add @razvan11/paladin
```

## Quick Start

```typescript
import { App, controller, get, post, service, inject } from '@razvan11/paladin';

@service()
class UserService {
  getUsers() {
    return [{ id: 1, name: 'John' }];
  }
}

@controller('/users')
class UserController {
  constructor(@inject(UserService) private userService: UserService) {}

  @get('/')
  async list(c: Context) {
    return c.json(this.userService.getUsers());
  }

  @post('/')
  async create(c: Context) {
    const body = await c.req.json();
    return c.json({ created: body });
  }
}

const app = new App({ name: 'MyApp' });
app.registerController(UserController);
app.run();
```

## Decorators

### Controller Decorators

| Decorator | Description |
|-----------|-------------|
| `@controller(prefix)` | Marks a class as a controller with a route prefix |
| `@get(path, ...middlewares)` | Handles GET requests |
| `@post(path, ...middlewares)` | Handles POST requests |
| `@put(path, ...middlewares)` | Handles PUT requests |
| `@patch(path, ...middlewares)` | Handles PATCH requests |
| `@del(path, ...middlewares)` | Handles DELETE requests |
| `@options(path, ...middlewares)` | Handles OPTIONS requests |
| `@all(path, ...middlewares)` | Handles all HTTP methods |

### Service Decorators

| Decorator | Description |
|-----------|-------------|
| `@service()` | Marks a class as a service (singleton) |
| `@repository()` | Marks a class as a repository (singleton) |
| `@database(options)` | Marks a class as a database connection |

### WebSocket Decorators

| Decorator | Description |
|-----------|-------------|
| `@websocket(path)` | Marks a class as a WebSocket handler |
| `@onMessage()` | Handles incoming messages |
| `@onOpen()` | Handles connection open |
| `@onClose()` | Handles connection close |
| `@onDrain()` | Handles backpressure drain |

## Dependency Injection

Use the `@inject()` decorator to inject dependencies into your controllers and services:

```typescript
@controller('/api')
class ApiController {
  constructor(
    @inject(UserService) private userService: UserService,
    @inject(AuthService) private authService: AuthService,
  ) {}
}
```

## Middleware

Add middleware to individual routes:

```typescript
const authMiddleware = async (c: Context, next: Next) => {
  const token = c.req.header('Authorization');
  if (!token) return c.json({ error: 'Unauthorized' }, 401);
  await next();
};

@controller('/protected')
class ProtectedController {
  @get('/', authMiddleware)
  async secure(c: Context) {
    return c.json({ message: 'Secret data' });
  }
}
```

## WebSockets

```typescript
import { websocket, onMessage, onOpen, onClose } from '@razvan11/paladin';

@websocket('/chat')
class ChatHandler {
  @onOpen()
  handleOpen(ws: ServerWebSocket) {
    console.log('Client connected');
  }

  @onMessage()
  handleMessage(ws: ServerWebSocket, message: string | Buffer) {
    ws.send(`Echo: ${message}`);
  }

  @onClose()
  handleClose(ws: ServerWebSocket) {
    console.log('Client disconnected');
  }
}

const app = new App({ name: 'ChatApp' });
app.registerWebSocket(ChatHandler);
app.run();
```

## Static Files

```typescript
const app = new App({ name: 'MyApp' });

app.serveStatic({
  path: '/static',
  root: './public'
});
```

Use the `asset()` helper to generate URLs:

```typescript
import { asset } from '@razvan11/paladin';

asset('dist', 'app.js'); // Returns '/static/dist/app.js'
```

## React SSR

Render React components on the server:

```typescript
import { render, LayoutView } from '@razvan11/paladin';

@controller('/')
class IndexController {
  @get('/')
  index(c: Context) {
    return render(c, LayoutView, {
      title: 'My App',
      scripts: [asset('dist', 'app.js')],
      styles: [asset('dist', 'app.css')],
      children: <div id="root" />,
    });
  }
}
```

## Configuration

```typescript
const app = new App({
  name: 'MyApp',
  cors: ['https://example.com'], // CORS origins (default: ['*'])
  validators: myValidators, // Optional validators
});
```

Environment variables:
- `PORT` - Server port (default: 3000)
- `APP_ENV` - Environment mode (`local`, `development`, `staging`, `production`)

## API Reference

### App

| Method | Description |
|--------|-------------|
| `registerController(Controller)` | Register a controller class |
| `registerControllers(...Controllers)` | Register multiple controllers |
| `registerWebSocket(WSHandler)` | Register a WebSocket handler |
| `registerWebSockets(...WSHandlers)` | Register multiple WebSocket handlers |
| `serveStatic(options)` | Serve static files |
| `getAppInstance()` | Get the underlying Hono instance |
| `run()` | Start the server |

## License

MIT © Razvan