Skip to content

Declaring state

Create flareState tokens and declare them on routes, middleware, and controllers with provides and state options.

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

Create state tokens with flareState() and wire them through registration options and static class members.

import { flareState } from "@flare-ts/core";
const AuthUser = flareState<{ id: string; role: "admin" | "user" }>("AuthUser");
const RequestId = flareState<string>("RequestId");

The optional name appears in error messages. Two calls to flareState("AuthUser") produce two independent slots. Identity is the object reference, not the name string.

HelperPurpose
.withDefault(value)require / get return a frozen default when nothing was set
.from((ctx) => value)Lazy derivation on first read from other tokens
.withLogging(mapper)Merge fields into the request logger’s async-local store on set (and when a derivation or default is materialized)

Each helper is callable at most once per token.

import { ControllerBase, flareState } from "@flare-ts/core";
import { Get } from "@flare-ts/core/decorators";
const AuthUser = flareState<{ id: string }>("AuthUser");
class MeController extends ControllerBase {
public static override deps = [];
public static override state = [AuthUser];
@Get("")
me() {
return this.ok(this.ctx.state.require(AuthUser));
}
}

Controllers must declare public static override state = [] (or real tokens) at registration time, even when empty.

host.http.get(
"/me",
{ state: [AuthUser] },
(ctx) => new FlareResponse(200, ctx.state.require(AuthUser)),
);

Middleware that writes a token lists it in provides. Middleware that reads upstream tokens lists them in static state (class) or { state: [...] } (builder).

import { FlareHost, MiddlewareBase, flareState } from "@flare-ts/core";
import { node } from "@flare-ts/core/node";
const AuthUser = flareState<{ id: string; role: "admin" | "user" }>("AuthUser");
const host = new FlareHost(node);
class AuthMiddleware extends MiddlewareBase {
public static override deps = [];
public static override state = [];
public static override provides = [AuthUser];
before() {
this.ctx.state.set(AuthUser, { id: "u1", role: "admin" });
}
}
// builder equivalent
host.http.before({ provides: [AuthUser] }, (ctx) => {
ctx.state.set(AuthUser, { id: "u1", role: "admin" });
});

Only before() hooks satisfy route state via provides.

inject / static deps resolve services. state / provides are per-request slots on ctx.state. Don’t confuse the two.