Skip to main content

@eigeninteractive/server

@eigeninteractive/server — everything that deploys: the createEngine API factory, the GameDO base class, the D1 applier, and the protocol types.

The D1 and Durable Object table definitions are deliberately NOT exported. They are engine-owned storage internals that migrate on their own schedule, and readGameRow already returns the whole game row typed. Exporting the drizzle tables would turn a private layout into a compatibility surface.

Classes

AuthError

Defined in: eigen-server/packages/server/src/auth/firebase.ts:12

Verification failure — always the caller's fault; the app maps it to 401.

Extends

  • Error

Constructors

Constructor
new AuthError(message?): AuthError;

Defined in: eigen-web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
Returns

AuthError

Inherited from
Error.constructor
Constructor
new AuthError(message?, options?): AuthError;

Defined in: eigen-web/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/lib/lib.es5.d.ts:1080

Parameters
ParameterType
message?string
options?ErrorOptions
Returns

AuthError

Inherited from
Error.constructor

abstract BaseGameDO

Defined in: eigen-server/packages/server/src/do/game-do.ts:104

Durable Object base class that owns one authoritative game session.

A game Worker subclasses this once to supply its gameModule and D1 binding. Do not override command, socket, alarm, or persistence behavior: the base class owns the serialized game loop and applies engine migrations on activation.

Example

export class GameDO extends BaseGameDO<Env> {
protected readonly gameModule = gameModule;
protected d1(env: Env) {
return env.GAME_DB;
}
}

Extends

  • unknown<TEnv>

Type Parameters

Type Parameter
TEnv

Implements

  • GameStub

Constructors

Constructor
new BaseGameDO<TEnv>(ctx, env): BaseGameDO<TEnv>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:118

Parameters
ParameterType
ctxDurableObjectState
envTEnv
Returns

BaseGameDO<TEnv>

Overrides
DurableObject<TEnv>.constructor

Properties

gameModule
abstract protected readonly gameModule: GameModule;

Defined in: eigen-server/packages/server/src/do/game-do.ts:106

The implementor's game — the versions map the engine dispatches on.

Methods

abort()
abort(gameId): Promise<void>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:262

Unconditional teardown (cron reap): mark the game aborted in D1 and drop the DO's storage — no creator gate, no init requirement. A never-touched lobby's DO has no meta row, so the caller passes the gameId. Idempotent: a re-run re-aborts a game whose storage is already gone. Used by the cron; cancel shares the teardown for its live path.

Parameters
ParameterType
gameIdstring
Returns

Promise<void>

Implementation of
GameStub.abort
alarm()
alarm(): Promise<void>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:708

Returns

Promise<void>

d1()
abstract protected d1(env): D1Database;

Defined in: eigen-server/packages/server/src/do/game-do.ts:109

The EngineConfig seam: the engine never assumes binding names — the subclass picks the D1 database off its own Env.

Parameters
ParameterType
envTEnv
Returns

D1Database

fetch()
fetch(request): Promise<Response>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:732

The worker routes the upgrade here after authenticating; the principal header is worker-set (never client-supplied — the worker strips inbound headers when forwarding). One socket serves the game's whole lifetime: unversioned roster snapshots pre-game, versioned frames from v0. A not-yet-seated user's socket simply receives no frames until the roster contains them.

Parameters
ParameterType
requestRequest
Returns

Promise<Response>

Implementation of
GameStub.fetch
firebaseAdmin()
protected firebaseAdmin(env): FirebaseAdminEffects;

Defined in: eigen-server/packages/server/src/do/game-do.ts:112

Required Firebase Admin effects. Tests override this with the explicit fake exported by @eigeninteractive/server/testing.

Parameters
ParameterType
envTEnv
Returns

FirebaseAdminEffects

frames()
frames(args): Promise<FrameMessage[]>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:832

Project a version range for one seat (null = public viewer, replay only). Live rows serve the stored frame; compacted/ratings rows re-project. Raw state never leaves the DO.

Parameters
ParameterType
args{ from: number; isReplay?: boolean; seat: number | null; to: number; }
args.fromnumber
args.isReplay?boolean
args.seatnumber | null
args.tonumber
Returns

Promise<FrameMessage[]>

Implementation of
GameStub.frames
handle()
handle(cmd): Promise<CommandResult>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:131

Parameters
ParameterType
cmdCommand
Returns

Promise<CommandResult>

Implementation of
GameStub.handle
repokeFinish()
repokeFinish(): Promise<boolean>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:696

The gated admin re-poke (step 4): re-runs the D1 apply for a finish whose effects never landed. Idempotent end to end — finish_id dedupes the apply, and the outbox row exists iff the ratings transition hasn't been committed. Returns false when there is nothing to do.

Returns

Promise<boolean>

Implementation of
GameStub.repokeFinish
webSocketClose()
webSocketClose(): Promise<void>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:766

Returns

Promise<void>

webSocketError()
webSocketError(_ws, error): Promise<void>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:772

Parameters
ParameterType
_wsWebSocket
errorunknown
Returns

Promise<void>

webSocketMessage()
webSocketMessage(): Promise<void>;

Defined in: eigen-server/packages/server/src/do/game-do.ts:761

Returns

Promise<void>


HttpError

Defined in: eigen-server/packages/server/src/http.ts:38

Extends

  • Error

Constructors

Constructor
new HttpError(
status,
message,
code?,
retryAfterSeconds?): HttpError;

Defined in: eigen-server/packages/server/src/http.ts:46

Parameters
ParameterType
status400 | 401 | 403 | 404 | 409 | 413 | 415 | 422 | 429 | 500 | 502
messagestring
code?ErrorCode
retryAfterSeconds?number
Returns

HttpError

Overrides
Error.constructor

Properties

code
readonly code: ErrorCode | undefined;

Defined in: eigen-server/packages/server/src/http.ts:40

retryAfterSeconds
readonly retryAfterSeconds: number | undefined;

Defined in: eigen-server/packages/server/src/http.ts:44

Seconds the caller should wait before retrying — rendered as the Retry-After header. Set only on a 429 (see ErrorCode.rateLimited); undefined everywhere else.

status
readonly status: 400 | 401 | 403 | 404 | 409 | 413 | 415 | 422 | 429 | 500 | 502;

Defined in: eigen-server/packages/server/src/http.ts:39

Interfaces

AuthClaims

Defined in: eigen-server/packages/server/src/auth/firebase.ts:18

What a verified ID token asserts. isAnonymous (the firebase.sign_in_provider === 'anonymous' claim) drives every guest gate; the profile claims seed user provisioning (Google supplies name/picture, Apple usually only email, guests none).

Properties

email
email: string | null;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:21

isAnonymous
isAnonymous: boolean;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:20

name
name: string | null;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:22

picture
picture: string | null;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:23

uid
uid: string;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:19


CreateGameInput

Defined in: eigen-server/packages/server/src/d1/apply.ts:292

The worker-direct create, engine-owned so implementors never touch the D1 schema: seats already validated by worker policy.

Properties

access
access: GameAccess;

Defined in: eigen-server/packages/server/src/d1/apply.ts:296

budgetSeconds
budgetSeconds: number | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:300

config
config: JsonObject;

Defined in: eigen-server/packages/server/src/d1/apply.ts:298

createdBy
createdBy: string | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:294

gameId
gameId: string;

Defined in: eigen-server/packages/server/src/d1/apply.ts:293

incrementSeconds
incrementSeconds: number | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:301

maxPlayers
maxPlayers: number;

Defined in: eigen-server/packages/server/src/d1/apply.ts:305

minPlayers
minPlayers: number;

Defined in: eigen-server/packages/server/src/d1/apply.ts:304

now
now: number;

Defined in: eigen-server/packages/server/src/d1/apply.ts:308

rated
rated: boolean;

Defined in: eigen-server/packages/server/src/d1/apply.ts:302

ratingPool
ratingPool: string | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:303

schemaVersion
schemaVersion: number;

Defined in: eigen-server/packages/server/src/d1/apply.ts:297

seats
seats: Seat[];

Defined in: eigen-server/packages/server/src/d1/apply.ts:307

shortCode
shortCode: string;

Defined in: eigen-server/packages/server/src/d1/apply.ts:306

status
status: "waiting" | "ready";

Defined in: eigen-server/packages/server/src/d1/apply.ts:295

turnSeconds
turnSeconds: number | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:299


EngineConfig

Defined in: eigen-server/packages/server/src/engine.ts:99

The EngineConfig seam: the engine never assumes binding names — the implementor picks bindings off their own Env. Annotate the accessors' env parameter and both type arguments infer.

Type Parameters

Type Parameter
TEnv
TDO extends BaseGameDO<TEnv>

Properties

appName
appName: string;

Defined in: eigen-server/packages/server/src/engine.ts:106

The whitelabel app's display name — the single source of truth for the engine's own identity (share metadata and public-page titles today; FCM titles and share copy later). Deliberately top-level, not nested under deepLink, so there is one place to set it regardless of which optional feature blocks are enabled.

avatars?
optional avatars?: AvatarsConfig<TEnv>;

Defined in: eigen-server/packages/server/src/engine.ts:128

Opt-in avatar uploads. Omit → not mounted.

clientOrigins?
optional clientOrigins?: readonly string[] | ((env) => readonly string[]);

Defined in: eigen-server/packages/server/src/engine.ts:124

Browser origins allowed to call the engine from a different origin.

Same-origin requests always work. When omitted, the engine trusts the exact origin from the conventional WEB_APP_ORIGIN var when it is set. Supply this option to replace that default for multiple or otherwise non-standard browser origins. Paths and wildcards are intentionally unsupported. The list also protects browser WebSocket upgrades, whose Origin header is not governed by CORS.

Set an empty list to disable the WEB_APP_ORIGIN default.

optional deepLink?: DeepLinkConfig;

Defined in: eigen-server/packages/server/src/engine.ts:126

Native deep-link verification and store links. Omit for web-only.

gameModule
gameModule: GameModule;

Defined in: eigen-server/packages/server/src/engine.ts:100

lifecycle?
optional lifecycle?: LifecycleOptions;

Defined in: eigen-server/packages/server/src/engine.ts:135

Cron-backstop tuning — guest-purge/reap windows and batch caps. Omit for the defaults (LIFECYCLE_DEFAULTS); set any subset to override just those.

site?
optional site?: SiteConfig;

Defined in: eigen-server/packages/server/src/engine.ts:131

The public web surface — download page, legal documents, crawler files. Omit → not mounted (the worker is API-only).

testing?
optional testing?: {
auth: TokenVerifier;
firebaseAdmin: FirebaseAdminEffects;
};

Defined in: eigen-server/packages/server/src/engine.ts:140

Explicit test-only replacements for Firebase verification and Admin effects. Supplying them together prevents a fake verifier from accidentally turning missing production credentials into a nullable runtime path. Leave unset in production.

auth
auth: TokenVerifier;
firebaseAdmin()
firebaseAdmin(env): FirebaseAdminEffects;
Parameters
ParameterType
envTEnv
Returns

FirebaseAdminEffects

Methods

d1()
d1(env): D1Database;

Defined in: eigen-server/packages/server/src/engine.ts:108

The engine's D1 database (engine-private).

Parameters
ParameterType
envTEnv
Returns

D1Database

firebaseProjectId()?
optional firebaseProjectId(env): string;

Defined in: eigen-server/packages/server/src/engine.ts:113

Firebase project id for token verification; defaults to the FIREBASE_PROJECT_ID var (the only secret verification needs).

Parameters
ParameterType
envTEnv
Returns

string

gameDO()
gameDO(env): DurableObjectNamespace<TDO>;

Defined in: eigen-server/packages/server/src/engine.ts:110

The GameDO namespace binding.

Parameters
ParameterType
envTEnv
Returns

DurableObjectNamespace<TDO>


FinishApplyInput

Defined in: eigen-server/packages/server/src/d1/apply.ts:30

Properties

finishId
finishId: string;

Defined in: eigen-server/packages/server/src/d1/apply.ts:34

The DO-minted idempotency key — the apply is a no-op replay when the games row already carries it.

gameId
gameId: string;

Defined in: eigen-server/packages/server/src/d1/apply.ts:31

now
now: number;

Defined in: eigen-server/packages/server/src/d1/apply.ts:39

outcomes
outcomes: OutcomeEntry[];

Defined in: eigen-server/packages/server/src/d1/apply.ts:35

rated
rated: boolean;

Defined in: eigen-server/packages/server/src/d1/apply.ts:37

ratingPool
ratingPool: string | null;

Defined in: eigen-server/packages/server/src/d1/apply.ts:38

roster
roster: Seat[];

Defined in: eigen-server/packages/server/src/d1/apply.ts:36


FirebaseAdminEffects

Defined in: eigen-server/packages/server/src/firebase/admin-effects.ts:15

The Firebase Admin effects used by authenticated engine paths.

Methods

deleteAccount()
deleteAccount(userId): Promise<void>;

Defined in: eigen-server/packages/server/src/firebase/admin-effects.ts:19

Permanently delete one Firebase Authentication account.

Parameters
ParameterType
userIdstring
Returns

Promise<void>

notifyUser()
notifyUser(
d1,
userId,
message): Promise<void>;

Defined in: eigen-server/packages/server/src/firebase/admin-effects.ts:17

Send one notification through the engine's registered-device store.

Parameters
ParameterType
d1D1Database
userIdstring
messageNotificationMessage
Returns

Promise<void>


FrameMessage

Defined in: eigen-server/packages/server/src/protocol.ts:91

One seat's versioned frame on the wire — the socket fan-out payload, and (for the acting seat) the command-response ride-along. ratings appears only on the post-finish ratings transition.

Properties

data
data: JsonObject;

Defined in: eigen-server/packages/server/src/protocol.ts:94

deadline
deadline: number | null;

Defined in: eigen-server/packages/server/src/protocol.ts:97

The true client-facing deadline (grace is display-only there).

outcomes?
optional outcomes?: OutcomeEntry[];

Defined in: eigen-server/packages/server/src/protocol.ts:99

pendingPlayers
pendingPlayers: number[];

Defined in: eigen-server/packages/server/src/protocol.ts:95

playerTimes
playerTimes: number[] | null;

Defined in: eigen-server/packages/server/src/protocol.ts:98

ratings?
optional ratings?: RatingDelta[];

Defined in: eigen-server/packages/server/src/protocol.ts:100

type
type: "frame";

Defined in: eigen-server/packages/server/src/protocol.ts:92

version
version: number;

Defined in: eigen-server/packages/server/src/protocol.ts:93


LegalConfig

Defined in: eigen-server/packages/server/src/site/config.ts:29

Legal document overrides. Each is an HTML fragment — body content only, no document wrapper; the engine supplies the shell, styling and footer. Omitted documents fall back to the engine's generic templates.

A fragment is inserted as-is, so it is the implementor's own trusted markup with their own values already written in. There are no placeholders to fill: the engine's defaults take an OperatorConfig as typed props, which is what a template's tokens used to stand in for.

Properties

deleteAccount?
optional deleteAccount?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:32

privacy?
optional privacy?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:31

terms?
optional terms?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:30


OperatorConfig

Defined in: eigen-server/packages/server/src/site/config.ts:9

The legal entity publishing the game. Required whenever site is present: the default legal documents take it as a prop and cannot render without it.

Properties

contactEmail
contactEmail: string;

Defined in: eigen-server/packages/server/src/site/config.ts:15

Support and privacy contact address.

effectiveDate
effectiveDate: string;

Defined in: eigen-server/packages/server/src/site/config.ts:18

Effective date of the legal documents, as displayed. A plain string, not a Date — it is prose, and its format is the operator's choice.

jurisdiction
jurisdiction: string;

Defined in: eigen-server/packages/server/src/site/config.ts:13

Governing jurisdiction, e.g. India.

name
name: string;

Defined in: eigen-server/packages/server/src/site/config.ts:11

Legal entity name. Also the page footers' copyright holder.


Principal

Defined in: eigen-server/packages/server/src/protocol.ts:16

Who a command acts as, resolved at the edge. Exactly one id is set.

Properties

botId
botId: string | null;

Defined in: eigen-server/packages/server/src/protocol.ts:18

userId
userId: string | null;

Defined in: eigen-server/packages/server/src/protocol.ts:17


RatingDelta

Defined in: eigen-server/packages/kernel/dist/index.d.ts:171

One rated identity's before → after, exactly the rating_history row minus store keys. Computed by the D1 applier inside the rating CAS and delivered on the post-finish ratings transition (the kind: "ratings" action).

Properties

displayAfter
displayAfter: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:179

displayBefore
displayBefore: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:176

displayChange
displayChange: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:180

identity
identity: RatingIdentity;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:172

muAfter
muAfter: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:177

muBefore
muBefore: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:174

pool
pool: string;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:173

sigmaAfter
sigmaAfter: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:178

sigmaBefore
sigmaBefore: number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:175


RetryOptions

Defined in: eigen-server/packages/server/src/d1/retry.ts:59

Properties

attempts?
optional attempts?: number;

Defined in: eigen-server/packages/server/src/d1/retry.ts:61

Total attempts including the first. Default 4.

baseDelayMs?
optional baseDelayMs?: number;

Defined in: eigen-server/packages/server/src/d1/retry.ts:63

First backoff, doubling each retry. Default 50ms.

maxDelayMs?
optional maxDelayMs?: number;

Defined in: eigen-server/packages/server/src/d1/retry.ts:65

Backoff ceiling. Default 2000ms.

onRetry?
optional onRetry?: (error, attempt) => void;

Defined in: eigen-server/packages/server/src/d1/retry.ts:69

Observe each retry (logging); never throws into the loop.

Parameters
ParameterType
errorunknown
attemptnumber
Returns

void

shouldRetry?
optional shouldRetry?: (error) => boolean;

Defined in: eigen-server/packages/server/src/d1/retry.ts:67

Which failures are worth retrying. Default isTransientD1Error.

Parameters
ParameterType
errorunknown
Returns

boolean

sleep?
optional sleep?: (ms) => Promise<void>;

Defined in: eigen-server/packages/server/src/d1/retry.ts:71

Delay primitive, injectable so tests run without real timers.

Parameters
ParameterType
msnumber
Returns

Promise<void>


RosterSnapshot

Defined in: eigen-server/packages/server/src/protocol.ts:82

The unversioned pre-game snapshot: pushed to every socket on any roster change, idempotent — a reconnect just gets the current one. Also the response body of an accepted waiting-room command.

Properties

players
players: Seat[];

Defined in: eigen-server/packages/server/src/protocol.ts:85

status
status: GameStatus;

Defined in: eigen-server/packages/server/src/protocol.ts:84

type
type: "roster";

Defined in: eigen-server/packages/server/src/protocol.ts:83


SiteConfig

Defined in: eigen-server/packages/server/src/site/config.ts:41

The public web surface a deployed game serves on its own host: download page, legal documents, and the crawler files. Absent → none of it is mounted and the worker stays API-only.

The scaffold reserves these paths for the Worker with Static Assets' run_worker_first; customize legal prose through this typed config.

Properties

description?
optional description?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:47

Longer download-page prose. Defaults to tagline.

optional legal?: LegalConfig;

Defined in: eigen-server/packages/server/src/site/config.ts:59

name?
optional name?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:43

Public game name in titles and OG tags. Defaults to appName.

ogImage?
optional ogImage?: string;

Defined in: eigen-server/packages/server/src/site/config.ts:57

Path under public/ to the 1200x630 OG image. Defaults to /og-image.png, the name the branding guide prescribes for the Flutter app's own share card — one image, both surfaces. The engine never generates images.

operator
operator: OperatorConfig;

Defined in: eigen-server/packages/server/src/site/config.ts:58

primaryColor
primaryColor: string;

Defined in: eigen-server/packages/server/src/site/config.ts:49

Hex accent colour, e.g. #1a237e. Also the theme-color.

screenshots?
optional screenshots?: string[];

Defined in: eigen-server/packages/server/src/site/config.ts:51

Filenames under public/screenshots/, shown as a scrolling strip.

tagline
tagline: string;

Defined in: eigen-server/packages/server/src/site/config.ts:45

One-sentence hook. The meta description and OG description.


TokenVerifier

Defined in: eigen-server/packages/server/src/auth/firebase.ts:29

The seam createEngine consumes. Production is createFirebaseVerifier with the default remote JWKS; tests inject a local JWKS and mint their own RS256 tokens.

Methods

verify()
verify(token): Promise<AuthClaims>;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:31

Resolve a bearer token to claims, or throw AuthError.

Parameters
ParameterType
tokenstring
Returns

Promise<AuthClaims>

Type Aliases

Command

type Command =
| {
actor: Principal;
commandId: string;
gameId: string;
kind: "join" | "leave";
}
| {
actor: Principal;
commandId: string;
gameId: string;
kind: "cancel";
}
| {
actor: Principal;
commandId: string;
gameId: string;
kind: "start";
}
| {
actor: Principal;
botId: string;
commandId: string;
gameId: string;
kind: "add-bot";
}
| {
actor: Principal;
commandId: string;
data: unknown;
expectedVersion: number;
gameId: string;
kind: "action";
seat: number;
}
| {
actor: Principal | null;
commandId: string;
gameId: string;
kind: "lifecycle";
seat?: number;
type: LifecycleType;
};

Defined in: eigen-server/packages/server/src/protocol.ts:23

Everything that crosses the worker → DO boundary after creation ( create itself is a worker-direct D1 write; the DO does not exist yet).

Union Members

Type Literal
{
actor: Principal;
commandId: string;
gameId: string;
kind: "join" | "leave";
}

Type Literal
{
actor: Principal;
commandId: string;
gameId: string;
kind: "cancel";
}

Type Literal
{
actor: Principal;
commandId: string;
gameId: string;
kind: "start";
}

Type Literal
{
actor: Principal;
botId: string;
commandId: string;
gameId: string;
kind: "add-bot";
}

Type Literal
{
actor: Principal;
commandId: string;
data: unknown;
expectedVersion: number;
gameId: string;
kind: "action";
seat: number;
}
actor
actor: Principal;
commandId
commandId: string;
data
data: unknown;
expectedVersion
expectedVersion: number;

The version the client computed the move against — a lower value is arbitrated by the same-view rule.

gameId
gameId: string;
kind
kind: "action";
seat
seat: number;

The acting seat — carried uniformly by humans and bots. The DO verifies it belongs to the actor (user id from the token, bot id from the HMAC claim) against its own roster and rejects otherwise, so a client can never act on a seat it does not hold. Required because one bot id may hold several seats, and uniform for one code path.


Type Literal
{
actor: Principal | null;
commandId: string;
gameId: string;
kind: "lifecycle";
seat?: number;
type: LifecycleType;
}
actor
actor: Principal | null;

Null for identity-less system lifecycles (timeout, autoForfeit).

commandId
commandId: string;
gameId
gameId: string;
kind
kind: "lifecycle";
seat?
optional seat?: number;

The affected seat: forfeit carries the resigning seat (verified against the actor, like an action); autoForfeit the purged seat; timeout carries none (it resolves all pending).

type
type: LifecycleType;

CommandResult

type CommandResult =
| {
frame: FrameMessage | null;
ok: true;
version: number;
}
| {
ok: true;
roster: RosterSnapshot;
}
| {
code: | RejectCode
| LobbyRejectCode;
message: string;
ok: false;
};

Defined in: eigen-server/packages/server/src/protocol.ts:124

What GameDO.handle() returns; accepted results are stored for commandId dedupe and replayed verbatim to a retry. Rejections are computed fresh each time — re-evaluating one is always sound. State-transitioning commands answer with a version (+ the acting seat's frame); waiting-room commands answer with the post-commit roster snapshot.


LobbyRejectCode

type LobbyRejectCode =
| "unknownGame"
| "notJoinable"
| "gameFull"
| "alreadyJoined"
| "notParticipant"
| "notCreator"
| "creatorCannotLeave";

Defined in: eigen-server/packages/server/src/protocol.ts:62

Why the DO refused a waiting-room command — the integrity column. These are expected refusals (accepted lobby staleness: the lobby may show a game that just filled), returned as values exactly like kernel rejections; the worker maps them to HTTP. Genuine protocol violations (acting on a seat you don't own) still throw.


UserRow

type UserRow = typeof users.$inferSelect;

Defined in: eigen-server/packages/server/src/auth/provision.ts:19

Variables

DEADLINE_GRACE_MS

const DEADLINE_GRACE_MS: 750 = 750;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:443

Grace window (ms) added to every deadline comparison so a player who submits on time is not rejected because network latency carried the request past the deadline. Keep it small relative to per-action turnSeconds windows. The client's display-only kServerDeadlineGrace mirrors this.

Functions

applyFinish()

function applyFinish(d1, input): Promise<RatingDelta[] | null>;

Defined in: eigen-server/packages/server/src/d1/apply.ts:48

Apply one finished game to D1. Returns the rated deltas (null for an unrated game) for the DO to deliver as the ratings transition. Throws on failure — the caller logs and keeps the outbox row (single attempt at the call site; the internal loop only absorbs CAS conflicts).

Parameters

ParameterType
d1D1Database
inputFinishApplyInput

Returns

Promise<RatingDelta[] | null>


createEngine()

function createEngine<TEnv, TDO>(cfg): ExportedHandler<TEnv>;

Defined in: eigen-server/packages/server/src/engine.ts:414

Creates the complete Cloudflare Worker for one game deployment.

Call this once from the default export of src/index.ts. The returned handler mounts the authenticated game API, WebSocket upgrades, scheduled lifecycle work, and any configured public/deep-link routes. Game implementors provide only EngineConfig.gameModule and binding accessors; routes, persistence, migrations, authentication, and session dispatch stay engine-owned.

Type Parameters

Type Parameter
TEnv extends object
TDO extends BaseGameDO<TEnv>

Parameters

ParameterType
cfgEngineConfig<TEnv, TDO>

Returns

ExportedHandler<TEnv>

Example

export default createEngine({
gameModule,
appName: "My Game",
d1: (env: Env) => env.GAME_DB,
gameDO: (env: Env) => env.GAME_DO,
});

createFirebaseVerifier()

function createFirebaseVerifier(projectId, getKey?): TokenVerifier;

Defined in: eigen-server/packages/server/src/auth/firebase.ts:46

Parameters

ParameterType
projectIdstring
getKey?JWTVerifyGetKey

Returns

TokenVerifier


createGame()

function createGame(d1, input): Promise<void>;

Defined in: eigen-server/packages/server/src/d1/apply.ts:314

Write the games row + one participants row per seat, atomically. The DO lazy-inits from exactly these rows on first contact. Callers own the shortCode retry: a duplicate trips the UNIQUE index and throws.

Parameters

ParameterType
d1D1Database
inputCreateGameInput

Returns

Promise<void>


deriveBotKey()

function deriveBotKey(masterSecret, botId): Promise<string>;

Defined in: eigen-server/packages/server/src/bot/bot-auth.ts:60

The per-bot signing key as base64 — the operator utility. This is the one value an external bot's owner is given, and the only one they need: it is what they HMAC their request bodies with. The master BOT_SIGNING_SECRET never leaves the operator, and because every bot's key is derived from it, registering a bot needs no new secret and no redeploy.

Base64 to match the signature transport encoding. Equivalent to:

echo -n "<botId>" | openssl dgst -sha256 -hmac "<BOT_SIGNING_SECRET>" -binary | base64

Treat the result as a credential: it authenticates that bot to the engine for as long as it is registered. Rotating one bot's key means rotating the master secret, which rotates every bot's key — so issue per-bot keys only to owners you would re-issue all of them for.

Parameters

ParameterType
masterSecretstring
botIdstring

Returns

Promise<string>


displayRating()

function displayRating(mu, sigma): number;

Defined in: eigen-server/packages/kernel/dist/index.d.ts:184

max(0, round((mu − 3σ) · 40)) — the one server-side home of the display formula (the client mirrors it for optimistic display only).

Parameters

ParameterType
munumber
sigmanumber

Returns

number


ensureUser()

function ensureUser(
d1,
claims,
now): Promise<{
avatarUrl: string | null;
createdAt: number;
displayName: string;
email: string | null;
id: string;
isAnonymous: boolean;
updatedAt: number;
username: string;
}>;

Defined in: eigen-server/packages/server/src/auth/provision.ts:51

Load the caller's row, creating or backfilling it as the token demands. One read on the hot path; writes only on first sight and on guest → permanent conversion.

Parameters

ParameterType
d1D1Database
claimsAuthClaims
nownumber

Returns

Promise<{ avatarUrl: string | null; createdAt: number; displayName: string; email: string | null; id: string; isAnonymous: boolean; updatedAt: number; username: string; }>


isTransientD1Error()

function isTransientD1Error(error): boolean;

Defined in: eigen-server/packages/server/src/d1/retry.ts:55

True for the D1 failures worth retrying — a network blip, a storage or Durable-Object reset, a code-update restart, or a transient routing failure.

Deliberately narrow. Overload and resource-limit errors are excluded (the remedy is to shed load, not retry), as are deterministic failures such as a constraint or type error, where retrying only delays the report. The whole cause chain is examined, because drizzle rewraps failures in its own message that does not carry the underlying text.

This is the default predicate for withRetry; pass shouldRetry to override it.

Parameters

ParameterType
errorunknown

Returns

boolean


mirrorRoster()

function mirrorRoster(d1, args): Promise<void>;

Defined in: eigen-server/packages/server/src/d1/apply.ts:280

The roster mirror after a committed waiting-room command — the DO's roster is the integrity copy; this rewrites the D1 display copy wholesale (delete + reinsert), which is idempotent and immune to per-row drift. Fire-and-forget post-commit (the DO leaves it unawaited; no waitUntil), single attempt.

Parameters

ParameterType
d1D1Database
args{ gameId: string; now: number; seats: Seat[]; status: GameStatus; }
args.gameIdstring
args.nownumber
args.seatsSeat[]
args.statusGameStatus

Returns

Promise<void>


openApiDocument()

function openApiDocument(version): OpenAPIObject;

Defined in: eigen-server/packages/server/src/engine.ts:490

Build the API document from an inert app — route handlers never run, so the context can refuse everything. appName is an unused placeholder here: with deepLink: null the landing route (its only reader) is never mounted.

version is an argument rather than a constant in here because it has exactly one correct value — @eigeninteractive/server's own — and changesets owns that value. Baked in as a literal it silently disagrees with the package on the first release: nothing reads it back, and the CI drift check only compares this file against itself, so the lie survives every check. The Dart client's pubspec is stamped from the same source for the same reason.

Parameters

ParameterType
versionstring

Returns

OpenAPIObject


readGameRow()

function readGameRow(d1, gameId): Promise<
| {
access: GameAccess;
archivedAt: number | null;
budgetSeconds: number | null;
config: JsonObject;
createdAt: number;
createdBy: string | null;
finishedAt: number | null;
finishId: string | null;
id: string;
incrementSeconds: number | null;
maxPlayers: number;
minPlayers: number;
outcomes: OutcomeEntry[] | null;
participants: Seat[];
pendingPlayers: number[] | null;
rated: boolean;
ratingPool: string | null;
schemaVersion: number;
shortCode: string;
status: GameStatus;
turnDeadline: number | null;
turnSeconds: number | null;
updatedAt: number;
}
| undefined>;

Defined in: eigen-server/packages/server/src/d1/apply.ts:341

Lazy-init read: the D1 game + participants rows the DO copies into its meta/roster on first contact — one batched round trip.

Parameters

ParameterType
d1D1Database
gameIdstring

Returns

Promise< | { access: GameAccess; archivedAt: number | null; budgetSeconds: number | null; config: JsonObject; createdAt: number; createdBy: string | null; finishedAt: number | null; finishId: string | null; id: string; incrementSeconds: number | null; maxPlayers: number; minPlayers: number; outcomes: OutcomeEntry[] | null; participants: Seat[]; pendingPlayers: number[] | null; rated: boolean; ratingPool: string | null; schemaVersion: number; shortCode: string; status: GameStatus; turnDeadline: number | null; turnSeconds: number | null; updatedAt: number; } | undefined>


updateSummary()

function updateSummary(d1, args): Promise<void>;

Defined in: eigen-server/packages/server/src/d1/apply.ts:262

The display upsert after a non-finishing transition — fire-and-forget post-commit (the DO leaves it unawaited; no waitUntil), single attempt, re-derivable from the DO at any time.

Parameters

ParameterType
d1D1Database
args{ gameId: string; now: number; pendingPlayers: number[]; status?: "active"; turnDeadline: number | null; }
args.gameIdstring
args.nownumber
args.pendingPlayersnumber[]
args.status?"active"
args.turnDeadlinenumber | null

Returns

Promise<void>


withRetry()

function withRetry<T>(op, options?): Promise<T>;

Defined in: eigen-server/packages/server/src/d1/retry.ts:88

Run op, retrying a retryable failure with jittered exponential backoff up to attempts. A non-retryable failure — or the last attempt — throws.

Safe to leave unawaited inside a Durable Object: the DO stays alive while the returned promise (and its backoff timers) is pending, so the whole sequence runs to completion without waitUntil, exactly like the single-attempt writes it wraps.

op MUST be idempotent — a retry can fire after a write that actually landed but whose acknowledgement was lost.

Type Parameters

Type Parameter
T

Parameters

ParameterType
op() => Promise<T>
optionsRetryOptions

Returns

Promise<T>