### Install Ohnana and Hono
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Installs the ohnana meta-framework and the Hono web framework using the bun package manager.
```bash
bun add ohnana hono
```
--------------------------------
### Basic Ohnana API Setup
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Demonstrates setting up a basic Ohnana application with common plugins (requestId, logger, errorHandler). It includes a simple GET route for '/users/:id' that retrieves the ID from the path and returns it along with the requestId.
```typescript
import { ohnana } from 'ohnana'
import { requestId, logger, errorHandler } from 'ohnana/plugins'
const app = ohnana({
plugins: [requestId(), logger(), errorHandler()]
})
app.get('/users/:id', (c) => {
const id = c.req.param('id')
return c.json({ id, requestId: c.get('requestId') })
})
export default { port: 3000, fetch: app.fetch }
```
--------------------------------
### Quick Start Ohnana App with Plugins
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Demonstrates a basic Ohnana application setup using several built-in plugins like requestId, logger, errorHandler, and cors. It shows how to access inferred types from plugins within route handlers.
```typescript
import { ohnana } from 'ohnana'
import { requestId, logger, errorHandler, cors } from 'ohnana/plugins'
const app = ohnana({
plugins: [
requestId(),
logger(),
errorHandler(),
cors()
]
})
app.get('/', (c) => {
const id = c.get('requestId') // ✅ Fully typed!
return c.json({ message: 'Hello!', requestId: id })
})
export default {
port: 3000,
fetch: app.fetch,
}
```
--------------------------------
### Start Ohnana Server with Graceful Shutdown
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Shows how to start the Ohnana server using the `app.serve()` method, specifying the port. This method includes built-in handling for SIGTERM and SIGINT signals, ensuring graceful shutdown and triggering plugin `onShutdown` hooks in reverse order.
```typescript
app.serve({ port: 3000 })
// Handles SIGTERM/SIGINT, calls plugin onShutdown hooks in reverse order
```
--------------------------------
### Create New Ohnana Project with CLI
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Scaffolds a new Ohnana project using the Ohnana CLI, navigates into the project directory, and starts the development server.
```bash
bunx ohnana create my-app
cd my-app
bun run dev
```
--------------------------------
### Running Bun Server
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Command to run a Bun application with hot module replacement enabled. This is the standard way to start a Bun server for development.
```sh
bun --hot ./index.ts
```
--------------------------------
### app.serve()
Source: https://context7.com/lemonsalve/ohnana/llms.txt
Starts the Ohnana HTTP server and handles graceful shutdown. It automatically manages WebSocket upgrades if the websocket plugin is registered and logs server startup information.
```APIDOC
## GET /api/status
### Description
Retrieves the current status of the Ohnana application, including a timestamp.
### Method
GET
### Endpoint
/api/status
### Parameters
None
### Request Example
```json
{}
```
### Response
#### Success Response (200)
- **status** (string) - The status of the application (e.g., "ok").
- **timestamp** (string) - The current server time in ISO format.
#### Response Example
```json
{
"status": "ok",
"timestamp": "2023-10-27T10:00:00.000Z"
}
```
```
--------------------------------
### Frontend Integration with Bun
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Guide on integrating frontend assets like HTML, CSS, and JavaScript/TypeScript with Bun.js servers, including support for React and Tailwind CSS.
```APIDOC
## Frontend Integration with Bun
### Description
Bun facilitates seamless frontend development by allowing direct imports of HTML, CSS, and JavaScript/TypeScript files within your server code. It includes automatic transpilation and bundling, supporting modern frameworks like React and utility CSS frameworks like Tailwind.
### Key Features
- **HTML Imports**: Import HTML files directly into your server code (`import index from "./index.html"`).
- **Automatic Transpilation & Bundling**: Bun's bundler handles `.tsx`, `.jsx`, and `.js` files imported from HTML.
- **CSS Bundling**: `` tags pointing to stylesheets are automatically bundled.
- **Framework Support**: Fully supports React, and other frameworks/libraries.
- **No Build Tools Required**: Avoids the need for tools like Vite.
### Example Structure
#### `index.ts` (Server)
```typescript
import index from "./index.html"
Bun.serve({
routes: {
"/": index,
},
development: {
hmr: true,
console: true,
}
})
```
#### `index.html`
```html
Hello, world!
```
#### `frontend.tsx` (React Component)
```tsx
import React from "react";
import { createRoot } from "react-dom/client";
// import .css files directly and it works
import './index.css';
const root = createRoot(document.body);
export default function Frontend() {
return
Hello, world!
;
}
root.render();
```
#### `index.css` (Example CSS)
```css
body {
background-color: lightblue;
}
```
### Running the Server
```sh
bun --hot ./index.ts
```
### Error Handling
- Ensure all frontend files are correctly linked and imported.
- Verify that the `script` tag in HTML uses `type="module"` for modern JavaScript imports.
```
--------------------------------
### Create Test Client for Ohnana Applications (TypeScript)
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Demonstrates how to create and use a test client for making requests to an Ohnana application without starting a server. It includes examples of testing GET and POST requests with assertions on status, response body, and headers. This utility is essential for unit and integration testing of API endpoints.
```typescript
import { createTestClient } from 'ohnana/testing'
import type { TestClient, TestResponse } from 'ohnana/testing'
import { test, expect } from 'bun:test'
const app = ohnana({
plugins: [requestId(), errorHandler()]
})
app.get('/users/:id', (c) => {
const id = c.req.param('id')
return c.json({ id, requestId: c.get('requestId') })
})
const client = createTestClient(app)
test('GET /users/:id returns user', async () => {
const res = await client.get('/users/123')
expect(res.status).toBe(200)
const data = await res.json()
expect(data.id).toBe('123')
expect(data.requestId).toBeDefined()
})
test('POST with body', async () => {
const res = await client.post('/users', {
name: 'John',
email: 'john@example.com'
})
expect(res.status).toBe(201)
const data = await res.json()
expect(data.name).toBe('John')
})
```
--------------------------------
### Full Stack Ohnana Application Example (TypeScript)
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
A comprehensive example of a full-stack Ohnana application demonstrating the integration of multiple plugins including `requestId`, `logger`, `cors`, `errorHandler`, `health`, and `rateLimiter`. It showcases a basic root route that returns a JSON response including the request ID.
```typescript
import { ohnana } from 'ohnana'
import { requestId, logger, cors, errorHandler, health, rateLimiter } from 'ohnana/plugins'
const app = ohnana({
plugins: [
requestId(),
logger(),
cors(),
errorHandler(),
health({ checks: { db: () => db.ping() } }),
rateLimiter({ max: 100 })
]
})
app.get('/', (c) => {
return c.json({
message: 'Hello!',
requestId: c.get('requestId')
})
})
export default { port: 3000, fetch: app.fetch }
```
--------------------------------
### Ohnana Logger Plugin Example
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Demonstrates how to integrate the logger plugin into an Ohnana application for basic request and response logging with timing information.
```typescript
import { logger } from 'ohnana/plugins'
ohnana({ plugins: [logger()] })
```
--------------------------------
### Bun Server with WebSockets and Routing
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
An example of a Bun server using `Bun.serve()` to handle HTTP requests, routing, and WebSocket connections. This replaces frameworks like Express.
```typescript
import index from "./index.html"
Bun.serve({
routes: {
"/": index,
"/api/users/:id": {
GET: (req) => {
return new Response(JSON.stringify({ id: req.params.id }));
},
},
},
// optional websocket support
websocket: {
open: (ws) => {
ws.send("Hello, world!");
},
message: (ws, message) => {
ws.send(message);
},
close: (ws) => {
// handle close
}
},
development: {
hmr: true,
console: true,
}
})
```
--------------------------------
### Bun Test Example
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Demonstrates how to write and run tests using Bun's built-in test runner. It replaces traditional testing frameworks like Jest or Vitest.
```typescript
import { test, expect } from "bun:test";
test("hello world", () => {
expect(1).toBe(1);
});
```
--------------------------------
### Ohnana Error Codes
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Provides examples of importing and using predefined error codes from the 'ohnana' package for consistent error handling.
```typescript
import { ErrorCodes } from 'ohnana'
ErrorCodes.NOT_FOUND // 'NOT_FOUND'
ErrorCodes.BAD_REQUEST // 'BAD_REQUEST'
ErrorCodes.UNAUTHORIZED // 'UNAUTHORIZED'
ErrorCodes.FORBIDDEN // 'FORBIDDEN'
ErrorCodes.INTERNAL_ERROR // 'INTERNAL_ERROR'
ErrorCodes.VALIDATION_ERROR // 'VALIDATION_ERROR'
```
--------------------------------
### Ohnana requestId Plugin Example
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Illustrates the usage of the requestId plugin in Ohnana, which generates a unique UUID for each request and adds an 'X-Request-ID' header. The example shows how to initialize Ohnana with this plugin.
```typescript
import { requestId } from 'ohnana/plugins'
ohnana({ plugins: [requestId()] })
```
--------------------------------
### Ohnana ErrorHandler Plugin Example
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Provides an example of using the errorHandler plugin in Ohnana, which formats error responses with a consistent structure including message, code, and requestId. It also includes a 404 handler.
```typescript
import { errorHandler } from 'ohnana/plugins'
ohnana({ plugins: [errorHandler()] })
```
--------------------------------
### Ohnana Error Handling Example
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Illustrates how to handle errors in Ohnana using HTTPException. This example shows throwing an HTTPException with a 400 status code and a custom message, which will be formatted according to the defined error structure.
```typescript
import { HTTPException } from 'hono/http-exception'
app.get('/error', () => {
throw new HTTPException(400, { message: 'Bad Request' })
})
// Returns: { message: 'Bad Request', code: 'BAD_REQUEST', requestId: '...' }
```
--------------------------------
### Creating Custom Ohnana Plugins with definePlugin (TypeScript)
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Demonstrates how to create custom Ohnana plugins using the `definePlugin` function from 'ohnana/toolkit'. This example shows how to define plugin lifecycle hooks (onInit, onRequest, onResponse, onError, onShutdown), manage context, and integrate the custom plugin into an Ohnana application.
```typescript
import { definePlugin } from 'ohnana/toolkit'
const myPlugin = definePlugin({
id: 'myPlugin',
context: {} as { myValue: string },
onInit: (app) => {
console.log('Plugin initialized')
},
onRequest: async (c, next) => {
c.set('myValue', 'hello')
await next()
},
onResponse: (c, response) => {
console.log('Response generated')
return response
},
onError: (error, c) => {
console.error('Error:', error)
return c.json({ error: error.message }, 500)
},
onShutdown: async () => {
console.log('Shutting down')
}
})
const app = ohnana({
plugins: [myPlugin()]
})
app.get('/', (c) => {
const value = c.get('myValue') // ✓ Typed as string
return c.json({ value })
})
```
--------------------------------
### Ohnana WebSocket Plugin with Pub/Sub
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Demonstrates the integration of the websocket plugin in Ohnana, enabling real-time communication with a Pub/Sub rooms pattern. It includes examples for client connection, message handling, broadcasting, and context extension.
```typescript
import { websocket } from 'ohnana/plugins'
const app = ohnana({
plugins: [
websocket({
path: '/ws', // WebSocket endpoint (default: '/ws')
onOpen: (client) => console.log('Connected:', client.id),
onClose: (client) => console.log('Disconnected:', client.id),
onMessage: (client, msg) => {
// Handle custom messages beyond built-in actions
console.log('Message:', msg)
}
})
]
})
// Broadcast from HTTP routes
app.post('/notify', async (c) => {
const { room, message } = await c.req.json()
c.get('ws').broadcast(room, { alert: message })
return c.json({ sent: true })
})
```
```javascript
const ws = new WebSocket('ws://localhost:3000/ws')
// Join a room
ws.send(JSON.stringify({ action: 'join', room: 'updates' }))
// Receive messages
ws.onmessage = (e) => console.log(JSON.parse(e.data))
// Broadcast to room
ws.send(JSON.stringify({
action: 'broadcast',
room: 'updates',
data: { msg: 'Hello!' }
}))
```
--------------------------------
### Bun React Frontend Component
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
A React component example demonstrating how to import and use React within a Bun project, including direct CSS imports. This is part of Bun's integrated frontend build process.
```tsx
import React from "react";
import { createRoot } from "react-dom/client";
// import .css files directly and it works
import './index.css';
const root = createRoot(document.body);
export default function Frontend() {
return
Hello, world!
;
}
root.render();
```
--------------------------------
### Ohnana CORS Plugin Example
Source: https://github.com/lemonsalve/ohnana/blob/main/README.md
Shows the implementation of the CORS plugin in Ohnana, which adds Cross-Origin Resource Sharing headers with permissive default settings.
```typescript
import { cors } from 'ohnana/plugins'
ohnana({ plugins: [cors()] })
```
--------------------------------
### Define Custom Plugins with Ohnana
Source: https://context7.com/lemonsalve/ohnana/llms.txt
Demonstrates how to create custom plugins for Ohnana using the `definePlugin` factory function. It shows examples of extending context, handling configuration, managing dependencies, and utilizing lifecycle hooks like `onRequest` and `onShutdown`. This allows for modular and reusable functionality within an Ohnana application.
```typescript
import { ohnana } from 'ohnana'
import { definePlugin } from 'ohnana/toolkit'
import { requestId } from 'ohnana/plugins'
// Simple plugin with context extension
const timing = definePlugin({
id: 'timing',
context: {} as { startTime: number },
onRequest: async (c, next) => {
c.set('startTime', Date.now())
await next()
const duration = Date.now() - c.get('startTime')
c.header('X-Response-Time', `${duration}ms`)
}
})
// Plugin with configuration options
interface AuthConfig {
secretKey: string
headerName?: string
}
const auth = definePlugin({
id: 'auth',
context: {} as { userId: string; roles: string[] },
onRequest: async (c, next) => {
const token = c.req.header('Authorization')?.replace('Bearer ', '')
if (!token) {
return c.json({ error: 'Unauthorized' }, 401)
}
// Verify token (simplified)
const payload = { userId: 'user-123', roles: ['user', 'admin'] }
c.set('userId', payload.userId)
c.set('roles', payload.roles)
await next()
}
})
// Plugin with dependencies
const audit = definePlugin({
id: 'audit',
requires: [requestId], // Depends on requestId plugin
context: {} as { audit: (action: string) => void },
onRequest: async (c, next) => {
const reqId = c.get('requestId') // Available from dependency
c.set('audit', (action: string) => {
console.log(`[Audit] ${reqId}: ${action}`)
})
await next()
},
onShutdown: async () => {
console.log('[Audit] Flushing audit logs...')
}
})
const app = ohnana({
plugins: [requestId(), timing(), auth(), audit()]
})
app.get('/api/profile', (c) => {
const userId = c.get('userId') // Type: string
const roles = c.get('roles') // Type: string[]
const startTime = c.get('startTime') // Type: number
const auditFn = c.get('audit') // Type: (action: string) => void
auditFn('profile_viewed')
return c.json({ userId, roles, processingStarted: startTime })
})
```
--------------------------------
### Implement CORS Plugin
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Demonstrates the integration of the `cors` plugin from `ohnana/plugins`. This plugin adds necessary CORS headers to responses with permissive default settings. The example also shows how to import the CORS configuration type.
```typescript
import { cors } from 'ohnana/plugins'
import type { CorsConfig } from 'ohnana/plugins'
const app = ohnana({
plugins: [cors()]
})
```
--------------------------------
### Implement Logger Plugin
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Shows the usage of the `logger` plugin from `ohnana/plugins`. This plugin provides request and response logging with colored output and timing information. The example includes importing the logger configuration type and demonstrates the available logger methods.
```typescript
import { logger } from 'ohnana/plugins'
import type { LoggerConfig } from 'ohnana/plugins'
const app = ohnana({
plugins: [logger()]
})
// Context extension: { logger: Logger }
// Logger interface:
// - debug(message: string, meta?: Record): void
// - info(message: string, meta?: Record): void
// - warn(message: string, meta?: Record): void
// - error(message: string, meta?: Record): void
```
--------------------------------
### Implement Request ID Plugin
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Demonstrates how to use the `requestId` plugin from `ohnana/plugins`. This plugin generates a UUID for each request and adds it as the `X-Request-ID` header. The example also shows how to import the configuration type for the plugin.
```typescript
import { requestId } from 'ohnana/plugins'
import type { RequestIdConfig } from 'ohnana/plugins'
const app = ohnana({
plugins: [requestId()]
})
// Context extension: { requestId: string }
```
--------------------------------
### Organize Routes with Scoped Plugins using app.group() (TypeScript)
Source: https://context7.com/lemonsalve/ohnana/llms.txt
Demonstrates using `app.group()` to organize routes and apply middleware to specific path prefixes. This example shows how to create a custom authentication plugin using `definePlugin` and scope it to a `/api` group. It also illustrates simple route grouping without additional plugins.
```typescript
import { ohnana } from 'ohnana'
import { requestId, logger } from 'ohnana/plugins'
import { definePlugin } from 'ohnana/toolkit'
import { HTTPException } from 'hono/http-exception'
// Create an auth plugin for protected routes
const auth = definePlugin({
id: 'auth',
context: {} as { userId: string },
onRequest: async (c, next) => {
const token = c.req.header('Authorization')
if (!token) {
throw new HTTPException(401, { message: 'Unauthorized' })
}
c.set('userId', 'user-123')
await next()
}
})
const app = ohnana({
plugins: [requestId(), logger()]
})
// Public routes
app.get('/', (c) => c.json({ message: 'Public endpoint' }))
// Protected routes with auth plugin scoped to /api group
app.group('/api', [auth()], (api) => {
api.get('/me', (c) => {
const userId = c.get('userId') // Type-safe from auth plugin
return c.json({ userId, profile: { name: 'John' } })
})
api.get('/settings', (c) => {
return c.json({ theme: 'dark', notifications: true })
})
})
// Simple grouping without additional plugins
app.group('/admin', (admin) => {
admin.get('/stats', (c) => c.json({ users: 100, requests: 5000 }))
})
export default { port: 3000, fetch: app.fetch }
```
--------------------------------
### Test Ohnana Apps with createTestClient
Source: https://context7.com/lemonsalve/ohnana/llms.txt
Utilizes the `createTestClient` utility from `ohnana/testing` to create a client for making direct requests to an Ohnana application without starting a server. This facilitates integration testing by allowing assertions on request/response status, headers, and body content.
```typescript
import { ohnana } from 'ohnana'
import { requestId, errorHandler } from 'ohnana/plugins'
import { createTestClient } from 'ohnana/testing'
import { test, expect, describe } from 'bun:test'
const app = ohnana({
plugins: [requestId(), errorHandler()]
})
app.get('/api/users', (c) => {
return c.json({ users: [{ id: 1, name: 'Alice' }] })
})
app.get('/api/users/:id', (c) => {
const id = c.req.param('id')
if (id === '999') {
return c.json({ error: 'Not found' }, 404)
}
return c.json({ id: parseInt(id), name: 'Alice' })
})
app.post('/api/users', async (c) => {
const body = await c.req.json()
return c.json({ id: 2, ...body }, 201)
})
const client = createTestClient(app)
describe('Users API', () => {
test('GET /api/users returns user list', async () => {
const res = await client.get('/api/users')
expect(res.status).toBe(200)
expect(res.headers.get('X-Request-ID')).toBeTruthy()
const data = await res.json<{ users: { id: number; name: string }[] }>()
expect(data.users).toHaveLength(1)
expect(data.users[0].name).toBe('Alice')
})
test('GET /api/users/:id returns single user', async () => {
const res = await client.get('/api/users/1')
expect(res.status).toBe(200)
const user = await res.json<{ id: number; name: string }>()
expect(user.id).toBe(1)
})
test('GET /api/users/999 returns 404', async () => {
const res = await client.get('/api/users/999')
expect(res.status).toBe(404)
})
test('POST /api/users creates new user', async () => {
const res = await client.post('/api/users', { name: 'Bob', email: 'bob@example.com' })
expect(res.status).toBe(201)
const user = await res.json<{ id: number; name: string }>()
expect(user.id).toBe(2)
expect(user.name).toBe('Bob')
})
test('custom request with headers', async () => {
const res = await client.request('/api/users', {
method: 'GET',
headers: { 'X-Custom-Header': 'test-value' }
})
expect(res.status).toBe(200)
})
})
```
--------------------------------
### Bun Testing
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Instructions on how to set up and run tests using Bun's built-in testing framework.
```APIDOC
## Bun Testing
### Description
Bun includes a built-in test runner that simplifies the process of writing and executing tests for your project. It provides an API similar to popular testing frameworks like Jest.
### Running Tests
To run all tests in your project, use the following command:
```sh
bun test
```
### Test File Example (`index.test.ts`)
```typescript
import { test, expect } from "bun:test";
test("hello world", () => {
expect(1).toBe(1);
});
test("async test example", async () => {
const result = await new Promise(resolve => setTimeout(() => resolve(42), 10));
expect(result).toBe(42);
});
```
### API Overview
- **`test(name, fn)`**: Defines a test case.
- **`expect(value)`**: Creates an assertion.
- **`.toBe(expected)`**: Checks for strict equality.
- **`.toEqual(expected)`**: Checks for deep equality.
- **`.toBeTruthy()`**: Checks if the value is truthy.
- **`.toBeDefined()`**: Checks if the value is defined.
- (and many more assertion methods)
### Error Handling
- Ensure test files are correctly named (e.g., ending with `.test.ts` or `.spec.ts`) or placed in a designated test directory.
- Handle asynchronous operations within tests using `async/await`.
```
--------------------------------
### Bun Server API
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Documentation for using `Bun.serve()` for creating web servers with support for routing, WebSockets, and HTTPS.
```APIDOC
## Bun.serve() - Web Server
### Description
`Bun.serve()` is a versatile function for creating web servers that supports routing, WebSockets, and HTTPS. It is recommended over frameworks like Express.
### Method
`Bun.serve(options)`
### Endpoint
N/A (This is a server creation function)
### Parameters
#### `options` Object
- **`routes`** (object) - Required - Defines the routes for the server.
- **`path`** (string | object) - The route path. Can be a string or an object for specific HTTP methods.
- **`GET`** (function) - Handler for GET requests.
- **`POST`** (function) - Handler for POST requests.
- etc.
- **`websocket`** (object) - Optional - Configuration for WebSocket support.
- **`open`** (function) - Callback when a WebSocket connection is opened.
- **`message`** (function) - Callback when a message is received via WebSocket.
- **`close`** (function) - Callback when a WebSocket connection is closed.
- **`development`** (object) - Optional - Development-specific configurations.
- **`hmr`** (boolean) - Enable Hot Module Replacement.
- **`console`** (boolean) - Enable enhanced console logging.
### Request Example (Server Setup)
```typescript
import index from "./index.html"
Bun.serve({
routes: {
"/": index,
"/api/users/:id": {
GET: (req) => {
return new Response(JSON.stringify({ id: req.params.id }));
},
},
},
// optional websocket support
websocket: {
open: (ws) => {
ws.send("Hello, world!");
},
message: (ws, message) => {
ws.send(message);
},
close: (ws) => {
// handle close
}
},
development: {
hmr: true,
console: true,
}
})
```
### Response Example (API Route)
```json
{
"id": "some-user-id"
}
```
### Error Handling
- If `routes` is not provided, the server might not handle requests as expected.
- WebSocket errors should be handled within the `open`, `message`, and `close` callbacks.
```
--------------------------------
### Bun Database Adapters
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
Information on using Bun's built-in database adapters for SQLite and Redis, and its SQL client for PostgreSQL.
```APIDOC
## Bun Database Adapters
### Description
Bun provides built-in modules for interacting with databases like SQLite, Redis, and PostgreSQL, offering alternatives to popular third-party libraries.
### Modules
- **`bun:sqlite`**: For SQLite database operations. Recommended over `better-sqlite3`.
- **`Bun.redis`**: For Redis client functionality. Recommended over `ioredis`.
- **`Bun.sql`**: For PostgreSQL database interactions. Recommended over `pg` or `postgres.js`.
### Usage Examples
#### SQLite (`bun:sqlite`)
```typescript
import { Database } from 'bun:sqlite'
const db = new Database('mydb.sqlite')
// Example query
const row = db.query("SELECT * FROM users WHERE id = ?").get(1)
console.log(row)
db.close()
```
#### Redis (`Bun.redis`)
```typescript
// Assuming Bun.redis is available globally or imported
const redis = new Redis({
host: 'localhost',
port: 6379
});
await redis.set('mykey', 'myvalue');
const value = await redis.get('mykey');
console.log(value);
redis.quit();
```
#### PostgreSQL (`Bun.sql`)
```typescript
import postgres from 'postgres';
const db = postgres('postgresql://user:password@host:port/database')
// Example query
const users = await db`SELECT * FROM users WHERE active = true`;
console.log(users);
// Close the connection pool when done
// db.end()
```
### Error Handling
- Ensure the database drivers are correctly installed or available in your Bun environment.
- Handle potential connection errors and query exceptions appropriately.
```
--------------------------------
### Create Ohnana App with Plugins and Type Inference
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Demonstrates creating an Ohnana application using the `ohnana()` factory function. It shows how to integrate plugins like `requestId` and `logger`, and how the context is automatically typed based on the provided plugins.
```typescript
import { ohnana } from 'ohnana'
import { requestId, logger } from 'ohnana/plugins'
const app = ohnana({
plugins: [requestId(), logger()]
})
// Context is automatically typed from plugins
app.get('/', (c) => {
const id = c.get('requestId') // ✓ string (from requestId plugin)
return c.json({ requestId: id })
})
```
--------------------------------
### fromMiddleware() - Wrap Hono Middleware
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
The `fromMiddleware` utility allows you to wrap existing Hono middleware as Ohnana plugins, making it easy to integrate them into your Ohnana application.
```APIDOC
## Wrapping Hono Middleware with fromMiddleware()
### Description
Wrap Hono middleware as an Ohnana plugin using `fromMiddleware`.
### Method
N/A (This is a utility for plugin creation)
### Endpoint
N/A
### Parameters
#### Request Body (for `fromMiddleware` arguments)
- **middleware** (Function) - The Hono middleware function to wrap.
- **options** (object) - Optional - Configuration for the wrapped plugin.
- **id** (string) - Optional - Unique identifier for the plugin.
- **context** (object) - Optional - Type definition for the plugin's context.
### Request Example
```typescript
import { fromMiddleware } from 'ohnana/toolkit'
import { someHonoMiddleware } from 'some-package'
const wrapped = fromMiddleware(someHonoMiddleware, {
id: 'myMiddleware', // optional
context: {} as { myVar: string } // optional
})
```
### Response
#### Success Response (Wrapped Plugin Instance)
- The `fromMiddleware` function returns a plugin instance that can be added to the Ohnana application's plugins array.
#### Response Example (Using the wrapped middleware)
```typescript
const app = ohnana({
plugins: [wrapped]
})
```
```
--------------------------------
### Standard Bun Server Export
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Illustrates the standard way to export an Ohnana application as a Bun server, defining the port and the fetch handler.
```typescript
export default {
port: 3000,
fetch: app.fetch
}
```
--------------------------------
### Defining Plugin Dependencies with definePlugin (TypeScript)
Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt
Illustrates how to define dependencies between Ohnana plugins using `definePlugin`. The `requires` property ensures that dependent plugins are initialized before the current one. This example shows an `authPlugin` that requires a `requestId` plugin.
```typescript
const authPlugin = definePlugin({
id: 'auth',
requires: [requestId], // Plugin dependencies
context: {} as { userId: string },
onRequest: async (c, next) => {
// Can access requestId from dependency
const reqId = c.get('requestId')
const token = c.req.header('Authorization')
if (!token) {
throw new HTTPException(401, { message: 'Unauthorized' })
}
c.set('userId', 'user-123')
await next()
}
})
// Ohnana validates that requestId is registered before auth
const app = ohnana({
plugins: [
requestId(), // Must be before auth
authPlugin()
]
})
```
--------------------------------
### Bun CLI Commands
Source: https://github.com/lemonsalve/ohnana/blob/main/CLAUDE.md
This section details the equivalent Bun CLI commands for common Node.js package manager and build tool operations.
```APIDOC
## Bun CLI Equivalents
### Description
This section provides a mapping of common Node.js commands to their Bun equivalents.
### Bun Commands
- **Running files**: `bun ` (replaces `node `, `ts-node `)
- **Running tests**: `bun test` (replaces `jest`, `vitest`)
- **Building assets**: `bun build ` (replaces `webpack`, `esbuild`)
- **Installing dependencies**: `bun install` (replaces `npm install`, `yarn install`, `pnpm install`)
- **Running scripts**: `bun run