8.2 KiB
Worker Package
A Cloudflare Worker that provides both HTTP API endpoints (via Hono) and RPC methods (via WorkerEntrypoint) for service bindings.
Features
- HTTP API: REST endpoints using Hono framework
- RPC Methods: Type-safe RPC calls via WorkerEntrypoint for service bindings
- CORS Support: Pre-configured CORS for API endpoints
- TypeScript: Full type safety across the worker
Project Structure
packages/worker/
├── src/
│ ├── index.ts # Main entry point (exports HTTP handler and RPC class)
│ └── rpc.ts # RPC methods (WorkerEntrypoint class)
├── wrangler.jsonc # Cloudflare Worker configuration
├── tsconfig.json # TypeScript configuration
├── vitest.config.mts # Vitest configuration
└── package.json # Package dependencies and scripts
HTTP API Endpoints
Health Check
GET /health
Returns the health status of the worker.
Response:
{
"status": "ok",
"message": "Worker is running!"
}
Root
GET /
Returns information about available endpoints.
Response:
{
"message": "Welcome to the Cloudflare Worker API",
"endpoints": {
"health": "/health",
"api": "/api/v1"
}
}
Hello Endpoint
GET /api/v1/hello?name=World
Returns a greeting message.
Query Parameters:
name(optional): Name to greet (default: "World")
Response:
{
"message": "Hello, World!"
}
Admin API (write access)
These endpoints write directly to Postgres for pragmatic data ingestion.
Authentication:
- If
ADMIN_API_KEYis set, includeAuthorization: Bearer <ADMIN_API_KEY>. - If
ADMIN_API_KEYis not set, requests are allowed (useful for local dev).
Canvas
POST /api/v1/admin/canvasPATCH /api/v1/admin/canvas/:canvasIdPOST /api/v1/admin/canvas/:canvasId/imagesPATCH /api/v1/admin/canvas/images/:imageIdDELETE /api/v1/admin/canvas/images/:imageId
Chat
POST /api/v1/admin/chat/threadsPATCH /api/v1/admin/chat/threads/:threadIdPOST /api/v1/admin/chat/messages
Context Items
POST /api/v1/admin/context-itemsPATCH /api/v1/admin/context-items/:itemIdPOST /api/v1/admin/context-items/:itemId/linkDELETE /api/v1/admin/context-items/:itemId
Browser Sessions
POST /api/v1/admin/browser-sessionsPATCH /api/v1/admin/browser-sessions/:sessionIdDELETE /api/v1/admin/browser-sessions/:sessionId
External Logs
To forward logs into 1focus Logs for the linsa server, set these secrets/vars in the worker:
FOCUS_LOGS_API_KEY(required)FOCUS_LOGS_SERVER(optional, default:linsa)FOCUS_LOGS_ENDPOINT(optional, default:https://1focus.app/api/logs)
Then send a log:
curl -X POST "http://localhost:8787/api/v1/admin/logs" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-d '{"message":"Hello from linsa","level":"info"}'
Example (create chat thread)
curl -X POST "http://localhost:8787/api/v1/admin/chat/threads" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-d '{"title":"Research notes","userId":"user_123"}'
RPC Methods
The WorkerRpc class provides the following methods for service bindings:
sayHello
async sayHello(name: string): Promise<{ message: string; timestamp: number }>
Returns a greeting message with timestamp.
Example:
const result = await env.WORKER_RPC.sayHello('World');
// { message: "Hello, World!", timestamp: 1234567890 }
calculate
async calculate(
operation: 'add' | 'subtract' | 'multiply' | 'divide',
a: number,
b: number
): Promise<number>
Performs arithmetic operations.
Example:
const sum = await env.WORKER_RPC.calculate('add', 5, 3);
// 8
getData
async getData(key: string): Promise<{ key: string; found: boolean; value?: string }>
Fetches data by key. Can be extended to use KV, D1, or R2 bindings.
Example:
const result = await env.WORKER_RPC.getData('myKey');
// { key: "myKey", found: false, value: undefined }
processBatch
async processBatch(items: string[]): Promise<{ processed: number; items: string[] }>
Processes a batch of items.
Example:
const result = await env.WORKER_RPC.processBatch(['item1', 'item2']);
// { processed: 2, items: ["ITEM1", "ITEM2"] }
Development
Install Dependencies
pnpm install
Start Development Server
pnpm dev
The worker will be available at http://localhost:8787
Database configuration
Set DATABASE_URL locally or configure the HYPERDRIVE binding in wrangler.jsonc.
In production, use wrangler secret put ADMIN_API_KEY to secure the admin endpoints.
Run Tests
pnpm test
Linting
# Check for linting issues
pnpm lint
# Fix linting issues
pnpm lint:fix
Format Code
pnpm format
Deployment
Prerequisites
- Install Wrangler CLI (included in dependencies)
- Login to Cloudflare:
pnpm wrangler login
Update Configuration
Edit wrangler.jsonc and update:
name: Your worker nameaccount_id: Your Cloudflare account ID (if needed)
Deploy to Cloudflare
pnpm deploy
Configuration
wrangler.jsonc
Key configuration options:
{
"name": "fullstack-monorepo-template-worker",
"main": "src/index.ts",
"compatibility_date": "2025-09-06",
}
Adding Bindings
You can add various bindings to your worker:
KV Namespace
"kv_namespaces": [
{
"binding": "MY_KV",
"id": "your-kv-namespace-id"
}
]
D1 Database
"d1_databases": [
{
"binding": "DB",
"database_name": "my-database",
"database_id": "your-database-id"
}
]
R2 Bucket
"r2_buckets": [
{
"binding": "MY_BUCKET",
"bucket_name": "my-bucket"
}
]
Environment Variables
"vars": {
"MY_VARIABLE": "production_value"
}
Using RPC from Other Workers
To call this worker's RPC methods from another worker:
- Add a service binding in the calling worker's
wrangler.jsonc:
{
"services": [
{
"binding": "WORKER_RPC",
"service": "fullstack-monorepo-template-worker",
"entrypoint": "WorkerRpc",
},
],
}
- Call RPC methods with full type safety:
export default {
async fetch(request: Request, env: Env) {
// Call RPC methods
const greeting = await env.WORKER_RPC.sayHello('World');
const sum = await env.WORKER_RPC.calculate('add', 5, 3);
return new Response(JSON.stringify({ greeting, sum }));
},
};
Adding New Endpoints
HTTP Endpoint
Add new routes in src/index.ts:
app.get('/api/v1/users', (c) => {
return c.json({ users: [] });
});
RPC Method
Add new methods in src/rpc.ts:
export class WorkerRpc extends WorkerEntrypoint {
async getUser(userId: string): Promise<User> {
// Your logic here
return { id: userId, name: 'John Doe' };
}
}
Testing
Tests use Vitest with the Cloudflare Workers pool. Create test files alongside your source files:
// src/index.test.ts
import { describe, it, expect } from 'vitest';
describe('Worker', () => {
it('should return health status', async () => {
const response = await fetch('http://localhost:8787/health');
const data = await response.json();
expect(data.status).toBe('ok');
});
});
TypeScript Types
The worker uses @cloudflare/workers-types for Cloudflare-specific types. These are automatically available in your TypeScript files.
Tech Stack
- Runtime: Cloudflare Workers
- Framework: Hono (HTTP API)
- RPC: WorkerEntrypoint (Service Bindings)
- Language: TypeScript
- Testing: Vitest + @cloudflare/vitest-pool-workers
- Package Manager: pnpm