npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@whi/cf-do-base

v0.3.0

Published

Base class for Cloudflare Durable Objects with built-in routing support

Downloads

15

Readme

Cloudflare Durable Object Base Class

License: LGPL-3.0 npm version

Base class for Cloudflare Durable Objects with built-in routing support using @whi/cf-routing.

Features

  • Simple Inheritance - Extend BaseDurableObject instead of DurableObject
  • Automatic Router Setup - Router is initialized and ready to use
  • Class-based Route Handlers - Organize routes using ES6 classes
  • Context Object - ctx argument with request, params, and data; this provides 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-base

Quick 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 Request
  • ctx.params - Route parameters (e.g., { id: '123' })
  • ctx.data - Shared data for middleware communication
  • ctx.response - Response customization (status, headers)
  • ctx.log - Logger instance

The handler's this provides Durable Object instance access:

  • this.storage - Durable Object storage
  • this.id - Durable Object ID
  • this.state - Raw DurableObjectState
  • this.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 mode

Advanced 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 report

Building

npm run build            # Build TypeScript to lib/
npm run format           # Format code with Prettier

License

LGPL-3.0

Credits

Built on top of @whi/cf-routing - Class-based routing framework for Cloudflare Workers.