Base class for Cloudflare Durable Objects with built-in routing support using @whi/cf-routing.
BaseDurableObject instead of DurableObjectnpm install @whi/cf-do-base
import { BaseDurableObject } from '@whi/cf-do-base';
import { DurableObjectRouteHandler } from '@whi/cf-routing';
class CounterHandler extends DurableObjectRouteHandler {
async get() {
const count = (await this.ctx.storage.get('count')) || 0;
return { count };
}
async post() {
const count = ((await this.ctx.storage.get('count')) || 0) + 1;
await this.ctx.storage.put('count', count);
return { count };
}
}
export class Counter extends BaseDurableObject {
constructor(ctx, env) {
super(ctx, 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(ctx, env) {
// Name your Durable Object for better logging
super(ctx, 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:
class DataHandler extends DurableObjectRouteHandler {
async get() {
const data = await this.ctx.storage.get('data');
return { data };
}
async post(request) {
const body = await request.json();
await this.ctx.storage.put('data', body.data);
return { success: true };
}
async delete() {
await this.ctx.storage.delete('data');
return { deleted: true };
}
}
export class DataStore extends BaseDurableObject {
constructor(ctx, env) {
super(ctx, env, 'data-store');
this.router.defineRouteHandler('/data', DataHandler);
}
}
Pass custom configuration to the underlying itty-router:
export class ApiDurableObject extends BaseDurableObject {
constructor(ctx, env) {
// Pass router options as the fourth parameter
super(ctx, env, 'api', { base: '/api/v1' });
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(ctx: DurableObjectState, env: MyEnv) {
super(ctx, env, 'my-do');
// env is fully typed
const apiKey = this.env.API_KEY;
}
}
Use the router's middleware capabilities:
import { HttpError } from '@whi/cf-routing';
export class SecureDO extends BaseDurableObject {
constructor(ctx, env) {
super(ctx, env, 'secure');
// Add authentication middleware
this.router.all('/api/*', async (request, params) => {
const token = request.headers.get('Authorization');
if (!token) {
throw new HttpError(401, 'Unauthorized');
}
});
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.