@whi/cf-do-base
v0.3.0
Published
Base class for Cloudflare Durable Objects with built-in routing support
Downloads
15
Maintainers
Readme
Cloudflare Durable Object Base Class
Base class for Cloudflare Durable Objects with built-in routing support using @whi/cf-routing.
Features
- Simple Inheritance - Extend
BaseDurableObjectinstead ofDurableObject - Automatic Router Setup - Router is initialized and ready to use
- Class-based Route Handlers - Organize routes using ES6 classes
- Context Object -
ctxargument with request, params, and data;thisprovides storage access - Built-in Error Handling - Automatic JSON error responses with proper status codes
- Type Safety - Full TypeScript support with generic types
- Zero Boilerplate - Focus on your business logic, not routing setup
Installation
npm install @whi/cf-do-baseQuick Start
Basic Durable Object with Routing
import { BaseDurableObject } from '@whi/cf-do-base';
import { DurableObjectRouteHandler, DurableObjectContext } from '@whi/cf-routing';
class CounterHandler extends DurableObjectRouteHandler {
async get(ctx: DurableObjectContext) {
const count = (await this.storage.get('count')) || 0;
return { count };
}
async post(ctx: DurableObjectContext) {
const count = ((await this.storage.get('count')) || 0) + 1;
await this.storage.put('count', count);
return { count };
}
}
export class Counter extends BaseDurableObject {
constructor(state, env) {
super(state, env, 'counter');
this.router.defineRouteHandler('/count', CounterHandler);
}
}Wrangler Configuration
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]Key Features
Extending BaseDurableObject
The base class handles all the router initialization for you:
import { BaseDurableObject } from '@whi/cf-do-base';
export class MyDurableObject extends BaseDurableObject {
constructor(state, env) {
// Name your Durable Object for better logging
super(state, env, 'my-durable-object');
// Router is ready to use
this.router.defineRouteHandler('/users', UserHandler);
this.router.defineRouteHandler('/posts/:id', PostHandler);
}
// fetch() is already implemented - it delegates to the router
}Route Handlers with Multiple HTTP Methods
Create route handlers by implementing multiple HTTP methods in a single class:
import { DurableObjectRouteHandler, DurableObjectContext } from '@whi/cf-routing';
class DataHandler extends DurableObjectRouteHandler {
async get(ctx: DurableObjectContext) {
const data = await this.storage.get('data');
return { data };
}
async post(ctx: DurableObjectContext) {
const body = await ctx.request.json();
await this.storage.put('data', body.data);
return { success: true };
}
async delete(ctx: DurableObjectContext) {
await this.storage.delete('data');
return { deleted: true };
}
}
export class DataStore extends BaseDurableObject {
constructor(state, env) {
super(state, env, 'data-store');
this.router.defineRouteHandler('/data', DataHandler);
}
}The ctx object contains per-request data:
ctx.request- The incoming Requestctx.params- Route parameters (e.g.,{ id: '123' })ctx.data- Shared data for middleware communicationctx.response- Response customization (status, headers)ctx.log- Logger instance
The handler's this provides Durable Object instance access:
this.storage- Durable Object storagethis.id- Durable Object IDthis.state- Raw DurableObjectStatethis.env- Environment bindings
CORS Configuration
Pass CORS configuration to the router:
export class ApiDurableObject extends BaseDurableObject {
constructor(state, env) {
// Pass router options as the fourth parameter
super(state, env, 'api', { cors: { origins: '*' } });
this.router.defineRouteHandler('/users', UserHandler);
}
}Environment Type Safety
Use TypeScript generics for type-safe environment access:
import { BaseDurableObject, Env } from '@whi/cf-do-base';
interface MyEnv extends Env {
DB: D1Database;
MY_KV: KVNamespace;
API_KEY: string;
}
export class MyDO extends BaseDurableObject<MyEnv> {
constructor(state: DurableObjectState, env: MyEnv) {
super(state, env, 'my-do');
// env is fully typed
const apiKey = this.env.API_KEY;
}
}Middleware Support
Use the router's middleware capabilities with the next() pattern:
import { HttpError, DurableObjectMiddleware } from '@whi/cf-routing';
export class SecureDO extends BaseDurableObject {
constructor(state, env) {
super(state, env, 'secure');
// Add authentication middleware
// Middleware receives (ctx, state, next) - state is the DurableObjectState
const authMiddleware: DurableObjectMiddleware = async (ctx, state, next) => {
const token = ctx.request.headers.get('Authorization');
if (!token) {
throw new HttpError(401, 'Unauthorized');
}
ctx.data.authenticated = true;
return next();
};
this.router.use('/api/*', authMiddleware);
this.router.defineRouteHandler('/api/data', DataHandler);
}
}Documentation
https://webheroesinc.github.io/js-cf-durable-object-base/
API documentation is automatically generated from source code using TypeDoc and deployed on every push to master.
To generate locally:
npm run docs # Generate documentation in docs/
npm run docs:watch # Generate docs in watch modeAdvanced Routing
For advanced routing features, middleware, error handling, and more details on route handlers, see the @whi/cf-routing documentation.
Development
See CONTRIBUTING.md for development setup, testing, and contribution guidelines.
Running Tests
npm test # Run all tests
npm run test:unit # Unit tests only
npm run test:integration # Integration tests only
npm run test:coverage # With coverage reportBuilding
npm run build # Build TypeScript to lib/
npm run format # Format code with PrettierLicense
LGPL-3.0
Credits
Built on top of @whi/cf-routing - Class-based routing framework for Cloudflare Workers.
