Hono
Overview
Section titled “Overview”The Hono adapter integrates Uploadista with Hono framework, enabling edge deployments on Cloudflare Workers, Cloudflare Pages, and other edge runtimes. Perfect for global, low-latency file uploads.
Installation
Section titled “Installation”npm install @uploadista/server @uploadista/adapters-hono honopnpm add @uploadista/server @uploadista/adapters-hono honoyarn add @uploadista/server @uploadista/adapters-hono honoQuick Start
Section titled “Quick Start”First, define your flows:
import { createFlow, createInputNode, createOutputNode, createOptimizeNode,} from "@uploadista/flow";
export const optimizeFlow = createFlow({ flowId: "optimize-image", name: "Optimize Image", nodes: { input: createInputNode("input"), optimize: createOptimizeNode("optimize", { format: "webp", quality: 80 }), output: createOutputNode("output"), }, edges: [ { source: "input", target: "optimize" }, { source: "optimize", target: "output" }, ],});
export const flows = { "optimize-image": optimizeFlow,};Then set up the server:
import { Hono } from "hono";import { createUploadistaServer } from "@uploadista/server";import { honoAdapter } from "@uploadista/adapters-hono";import { s3Store } from "@uploadista/data-store-s3";import { redisKvStore } from "@uploadista/kv-store-redis";import { flows } from "./flows";
const app = new Hono();
const uploadistaServer = await createUploadistaServer({ dataStore: s3Store({ /* S3 config */ }), kvStore: redisKvStore({ /* Redis config */ }), flows, adapter: honoAdapter(),});
app.all("/uploadista/api/*", (c) => uploadistaServer.handler(c));
export default app;Cloudflare Workers Setup
Section titled “Cloudflare Workers Setup”import { Hono } from "hono";import { cors } from "hono/cors";import { createUploadistaServer } from "@uploadista/server";import { honoAdapter } from "@uploadista/adapters-hono";import { s3Store } from "@uploadista/data-store-s3";import { cloudflareKvStore } from "@uploadista/kv-store-cloudflare-kv";import { flows } from "./flows";
const app = new Hono();
app.use(cors({ origin: (origin) => origin, // Configure for your domains allowMethods: ["GET", "POST", "PATCH", "DELETE", "OPTIONS"],}));
export default { async fetch(request: Request, env: Env): Promise<Response> { const uploadistaServer = await createUploadistaServer({ dataStore: s3Store({ deliveryUrl: env.R2_DELIVERY_URL, s3ClientConfig: { bucket: env.R2_BUCKET, region: "auto", credentials: { accessKeyId: env.R2_ACCESS_KEY_ID, secretAccessKey: env.R2_SECRET_ACCESS_KEY, }, endpoint: env.R2_ENDPOINT, }, }), kvStore: cloudflareKvStore({ kv: env.KV_METADATA }), flows, adapter: honoAdapter({ authMiddleware: async (c) => { const token = c.req.header("Authorization")?.split(" ")[1]; if (!token) return null;
try { const payload = await verify(token, env.JWT_SECRET); return { clientId: payload.sub as string, permissions: payload.permissions as string[] || [], }; } catch { return null; } }, }), });
app.all("/uploadista/api/*", (c) => uploadistaServer.handler(c));
return app.fetch(request, env); },};wrangler.toml Configuration
Section titled “wrangler.toml Configuration”name = "uploadista-server"main = "src/index.ts"compatibility_date = "2024-01-01"
[[r2_buckets]]binding = "R2_UPLOADS"bucket_name = "uploads-prod"
[[kv_namespaces]]binding = "KV_METADATA"id = "your-kv-namespace-id"
[vars]ALLOWED_ORIGINS = "https://example.com"
[[routes]]pattern = "api.example.com/uploadista/*"zone_name = "example.com"WebSocket Support
Section titled “WebSocket Support”Hono supports WebSockets across multiple runtimes. WebSocket connections enable real-time progress updates for uploads and flow processing.
Node.js with @hono/node-server
Section titled “Node.js with @hono/node-server”import { serve } from "@hono/node-server";import { createNodeWebSocket } from "@hono/node-ws";import { Hono } from "hono";import { flows } from "./flows";
const app = new Hono();const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app });
const uploadistaServer = await createUploadistaServer({ dataStore: s3Store({ /* config */ }), kvStore: redisKvStore({ /* config */ }), flows, adapter: honoAdapter(),});
// HTTP routesapp.all("/uploadista/api/*", (c) => uploadistaServer.handler(c));
// WebSocket routes for real-time progressapp.get( "/uploadista/ws/upload/:uploadId", upgradeWebSocket(uploadistaServer.websocketHandler));app.get( "/uploadista/ws/flow/:jobId", upgradeWebSocket(uploadistaServer.websocketHandler));
const server = serve({ port: 3000, fetch: app.fetch });injectWebSocket(server);Bun has native WebSocket support built-in:
import { Hono } from "hono";import { createBunWebSocket } from "hono/bun";import { flows } from "./flows";
const app = new Hono();const { upgradeWebSocket, websocket } = createBunWebSocket();
const uploadistaServer = await createUploadistaServer({ dataStore: s3Store({ /* config */ }), kvStore: redisKvStore({ /* config */ }), flows, adapter: honoAdapter(),});
// HTTP routesapp.all("/uploadista/api/*", (c) => uploadistaServer.handler(c));
// WebSocket routes for real-time progressapp.get( "/uploadista/ws/upload/:uploadId", upgradeWebSocket(uploadistaServer.websocketHandler));app.get( "/uploadista/ws/flow/:jobId", upgradeWebSocket(uploadistaServer.websocketHandler));
export default { port: 3000, fetch: app.fetch, websocket,};import { Hono } from "hono";import { upgradeWebSocket } from "hono/deno";import { flows } from "./flows.ts";
const app = new Hono();
const uploadistaServer = await createUploadistaServer({ dataStore: s3Store({ /* config */ }), kvStore: redisKvStore({ /* config */ }), flows, adapter: honoAdapter(),});
// HTTP routesapp.all("/uploadista/api/*", (c) => uploadistaServer.handler(c));
// WebSocket routesapp.get( "/uploadista/ws/upload/:uploadId", upgradeWebSocket(uploadistaServer.websocketHandler));app.get( "/uploadista/ws/flow/:jobId", upgradeWebSocket(uploadistaServer.websocketHandler));
Deno.serve(app.fetch);Edge Features
Section titled “Edge Features”- Zero cold starts
- Global edge distribution
- Cloudflare R2 storage
- Cloudflare KV metadata
- WebSocket progress updates
Configuration Options
Section titled “Configuration Options”import { imagePlugin } from "@uploadista/flow-images-sharp";import { redisEventBroadcaster } from "@uploadista/event-broadcaster-redis";
const uploadistaServer = await createUploadistaServer({ // Required dataStore: s3Store({ /* config */ }), // File storage backend kvStore: redisKvStore({ /* config */ }), // Metadata storage flows, // Flow definitions object adapter: honoAdapter(), // Framework adapter
// Optional plugins: [imagePlugin()], // Processing plugins eventBroadcaster: redisEventBroadcaster({ /* config */ }), // Multi-instance sync withTracing: true, // OpenTelemetry tracing baseUrl: "uploadista", // API base path (default)});Deployment
Section titled “Deployment”# Deploy to Cloudflare Workersnpx wrangler deploy
# View logsnpx wrangler tail
# Check deploymentcurl https://api.example.com/uploadista/api/healthRelated Concepts
Section titled “Related Concepts”- Authentication - Authentication and permissions
- Uploadista Server
- Data Stores
- KV Stores