### 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 ``` -------------------------------- ### Redis Caching with Ohnana Source: https://context7.com/lemonsalve/ohnana/llms.txt Provides access to Bun's built-in Redis client within the Ohnana request context for caching data. This plugin simplifies setting and getting key-value pairs with optional Time-To-Live (TTL). It requires the 'ohnana' framework and its 'redis' plugin. ```typescript import { ohnana } from 'ohnana' import { redis } from 'ohnana/plugins' const app = ohnana({ plugins: [redis()] }) app.get('/api/cache/:key', async (c) => { const redisClient = c.get('redis') const key = c.req.param('key') const value = await redisClient.get(key) if (value) { return c.json({ key, value, cached: true }) } return c.json({ key, value: null, cached: false }, 404) }) app.post('/api/cache/:key', async (c) => { const redisClient = c.get('redis') const key = c.req.param('key') const { value, ttl } = await c.req.json() if (ttl) { await redisClient.set(key, value, { ex: ttl }) } else { await redisClient.set(key, value) } return c.json({ key, value, stored: true }) }) ``` -------------------------------- ### Adding CORS Headers with Ohnana cors Plugin Source: https://context7.com/lemonsalve/ohnana/llms.txt The cors plugin automatically adds Cross-Origin Resource Sharing (CORS) headers to all responses. It uses permissive defaults, allowing requests from any origin ('*'). This plugin simplifies CORS configuration by requiring only the 'cors' plugin to be included in the Ohnana app setup. ```typescript import { ohnana } from 'ohnana' import { cors } from 'ohnana/plugins' const app = ohnana({ plugins: [cors()] }) app.get('/api/data', (c) => { return c.json({ data: 'accessible from any origin' }) }) // Response headers include: // Access-Control-Allow-Origin: * // Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS ``` -------------------------------- ### Create Custom Ohnana Plugin with Toolkit Source: https://github.com/lemonsalve/ohnana/blob/main/README.md Shows how to define a custom plugin for Ohnana using the `definePlugin` function from the toolkit. It covers plugin initialization, request/response handling, error management, and shutdown procedures, along with type inference for context. ```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 }) }) ``` -------------------------------- ### Custom Authentication Plugin for Ohnana (TypeScript) Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt Provides a detailed example of creating a custom authentication plugin using `definePlugin`. This plugin, named `auth`, depends on the `requestId` plugin, defines its own context types (`userId`, `user`), and implements the `onRequest` hook to verify JWT tokens, throwing an `HTTPException` for unauthorized requests. ```typescript import { definePlugin } from 'ohnana/toolkit' import { HTTPException } from 'hono/http-exception' const auth = definePlugin({ id: 'auth', requires: [requestId], // Dependency context: {} as { userId: string; user: User }, onRequest: async (c, next) => { const token = c.req.header('Authorization')?.replace('Bearer ', '') if (!token) { throw new HTTPException(401, { message: 'Missing token' }) } const user = await verifyToken(token) if (!user) { throw new HTTPException(401, { message: 'Invalid token' }) } c.set('userId', user.id) c.set('user', user) await next() } }) // Usage const app = ohnana({ plugins: [requestId(), auth()] }) app.get('/api/me', (c) => { const user = c.get('user') // ✓ Typed as User return c.json({ user }) }) ``` -------------------------------- ### Create Scoped Route Groups with Plugins Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt Demonstrates using the `app.group()` method to create nested route groups. It shows how to apply scoped plugins to a group, enabling type inference within that group, and also how to create groups without additional plugins. ```typescript // With plugins app.group('/api', [authPlugin()], (api) => { api.get('/me', (c) => { const userId = c.get('userId') // ✓ Typed from authPlugin return c.json({ userId }) }) }) // Without plugins (just grouping) app.group('/admin', (admin) => { admin.get('/stats', (c) => c.json({ stats: [] })) }) ``` -------------------------------- ### definePlugin() - Custom Plugin Creation Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt The `definePlugin` utility allows you to create custom Ohnana plugins with full type inference for context and hooks. This enables modular and maintainable plugin development. ```APIDOC ## Plugin Development with definePlugin() ### Description Create custom plugins with full type inference using `definePlugin`. ### Method N/A (This is a utility for plugin creation) ### Endpoint N/A ### Parameters #### Request Body (for `definePlugin` configuration) - **id** (string) - Unique identifier for the plugin. - **context** (object) - Type definition for the plugin's context. - **requires** (array) - Optional - List of plugin IDs that this plugin depends on. - **onInit** ((app: App) => void | Promise) - Optional - Hook executed when the plugin is initialized. - **onRequest** ((c: Context, next: () => Promise) => void | Promise) - Optional - Hook executed before a request is processed. - **onResponse** ((c: Context, response: Response) => Response | Promise) - Optional - Hook executed after a response is generated. - **onError** ((error: Error, c: Context) => Response | Promise) - Optional - Hook executed when an error occurs. - **onShutdown** (() => void | Promise) - Optional - Hook executed when the application is shutting down. ### Request Example (Plugin Definition) ```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') } }) ``` ### Response #### Success Response (Plugin Instance) - The `definePlugin` function returns a `PluginInstance` which can be passed to the `plugins` array in the `ohnana()` constructor. #### Response Example (Using the plugin) ```typescript const app = ohnana({ plugins: [myPlugin()] }) app.get('/', (c) => { const value = c.get('myValue') // ✓ Typed as string return c.json({ value }) }) ``` ``` -------------------------------- ### Wrapping Hono Middleware as an Ohnana Plugin (TypeScript) Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt Shows how to convert existing Hono middleware into an Ohnana plugin using the `fromMiddleware` function from 'ohnana/toolkit'. This allows seamless integration of Hono middleware into an Ohnana application, optionally providing an ID and context type for the wrapped middleware. ```typescript import { fromMiddleware } from 'ohnana/toolkit' import { someHonoMiddleware } from 'some-package' const wrapped = fromMiddleware(someHonoMiddleware, { id: 'myMiddleware', // optional context: {} as { myVar: string } // optional }) const app = ohnana({ plugins: [wrapped] }) ``` -------------------------------- ### Importing Ohnana Toolkit Types (TypeScript) Source: https://github.com/lemonsalve/ohnana/blob/main/llms.txt Provides a list of essential types available from the 'ohnana/toolkit' module for defining and working with Ohnana plugins. These types include `PluginHooks`, `PluginDefinition`, `PluginInstance`, `PluginFactory`, `ExtractPluginContext`, and `CombineRequiredContexts`. ```typescript import type { PluginHooks, PluginDefinition, PluginInstance, PluginFactory, ExtractPluginContext, CombineRequiredContexts } from 'ohnana/toolkit' ```