Base class for Cloudflare Durable Objects with built-in routing support using @whi/cf-routing.
BaseDurableObject instead of DurableObjectctx argument with request, params, and data; this provides storage accessnpm install @whi/cf-do-base
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);
}
}
[[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
script_name = "my-worker"
[[migrations]]
tag = "v1"
new_classes = ["Counter"]
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
}
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 instanceThe handler's this provides Durable Object instance access:
this.storage - Durable Object storagethis.id - Durable Object IDthis.state - Raw DurableObjectStatethis.env - Environment bindingsPass 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);
}
}
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;
}
}
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);
}
}
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 mode
For advanced routing features, middleware, error handling, and more details on route handlers, see the @whi/cf-routing documentation.
See CONTRIBUTING.md for development setup, testing, and contribution guidelines.
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 report
npm run build # Build TypeScript to lib/
npm run format # Format code with Prettier
LGPL-3.0
Built on top of @whi/cf-routing - Class-based routing framework for Cloudflare Workers.