Skip to content

Bindings and services

Inject Cloudflare env bindings and DurableObjectState through Bindings and DurableState.

AI generated, pending review Updated 10 days ago · Flare 0.3

On Cloudflare, platform bindings and Durable Object storage reach your services through two framework tokens: Bindings for Worker env, and DurableState for a DO instance’s DurableObjectState.

Do not construct these classes yourself. The runtime adapter seeds them per execution context.

import { FlareService } from "@flare-ts/core";
import { Bindings } from "@flare-ts/core/cloudflare";
class KvRoom extends FlareService {
public static override deps = [Bindings] as const;
async get(key: string) {
const kv = this.inject(Bindings).env.MY_KV;
return kv.get(key);
}
}

Register the service with host.scoped(KvRoom) and inject it from routes as usual. env is typed from your Worker’s Cloudflare.Env (for example via wrangler types).

Inside a FlareDurableObject, DurableState exposes the instance context:

import { FlareService } from "@flare-ts/core";
import { DurableState, FlareDurableObject } from "@flare-ts/core/cloudflare";
class Counter extends FlareService {
public static override deps = [DurableState] as const;
async increment() {
const storage = this.inject(DurableState).storage;
const n = (await storage.get<number>("n")) ?? 0;
await storage.put("n", n + 1);
return n + 1;
}
}
class CounterRoom extends FlareDurableObject {
public static override deps = [Counter] as const;
}

Each DO instance gets its own lazy container. host.scoped() services resolve per instance, not per Worker isolate globally.

const room = host.durableObject(CounterRoom);
room.http.get(
"/inc",
{ inject: { counter: Counter } },
async (_ctx, scope) => new FlareResponse(200, { n: await scope.counter.increment() }),
);
ServiceSeeded onProvides
BindingsWorker fetch and DO instanceenv bindings
DurableStateDO instance onlystate, storage, id

A stateless Worker route has Bindings but no DurableState. A mounted DO route has both.