Core

Descriptor

Nominal descriptor constructors for schema authoring.

Descriptors are the stable typed identities behind every public ECS surface: schema entries, query slots, system specs, runtime provisioning, long-lived handle intents, and relationships.

If Schema answers "what world can exist?", descriptors answer "what is each named thing in that world?" They are the vocabulary the rest of the ECS system reuses everywhere else.

The normal authoring flow is:

  1. declare descriptors with Descriptor.*
  2. register them in Schema.fragment(...)
  3. bind one Game with Schema.bind(...)

Reach for this module first whenever you introduce a new component, resource, event, or service to the game. Discrete modes whose transitions matter are state machines (Game.StateMachine(...)), not descriptors.

Examples

// Components describe per-entity state that queries can match.
const Position = Descriptor.Component<{ x: number; y: number }>()("Position")

// Resources describe singleton world data shared across systems.
const DeltaTime = Descriptor.Resource<number>()("DeltaTime")

// Events describe messages between systems, read once per reader.
const DamageTaken = Descriptor.Event<{ amount: number }>()("DamageTaken")

// Services describe host capabilities that live outside ECS storage.
const Logger = Descriptor.Service<{ log: (message: string) => void }>()("Logger")

Functions

Component

Defines a component descriptor.

ConstructedComponent

Defines a component descriptor that also knows how to validate raw values.

TransientComponent

Defines a component descriptor that snapshots skip.

Tag

Defines a marker component: no data, only presence ([Player, {}]).

State

Defines a state component: its value is one of states, validated (so snapshots reject unknown states), and it behaves like any other component (storage, change detection, rollback, traces).

isState

Whether a descriptor was built with State.

Resource

Defines a resource descriptor.

ConstructedResource

Defines a resource descriptor that also knows how to validate raw values.

TransientResource

Defines a resource descriptor that snapshots skip. Restoring keeps its current value.

Event

Defines an event descriptor.

Service

Defines a service descriptor.

isTransient

Checks whether one descriptor is transient (skipped by snapshots).

fromStandardSchema

Adapts a Standard Schema validator into a descriptor constructor, so any compliant validation library can guard constructed components and resources. Validation must be synchronous; a schema that returns a promise fails with an issue instead.

decoderOf

Returns the function that validates untrusted values for a constructed descriptor: its constructor's decode when present, otherwise result. The snapshot types only allow the result fallback when it accepts unknown.

hasConstructor

Checks whether one descriptor carries raw-construction metadata.

constructorOf

Returns the raw constructor carried by one descriptor when present.

Functions

Authoring helpers for declaring components, resources, services, and events.

Component

Source

Defines a component descriptor.

Use this when declaring per-entity data that should participate in queries and typed entity proofs.

Components are the only descriptor kind that can be queried directly with Game.Query.read(...), write(...), or optional(...).

const Position = Descriptor.Component<{ x: number; y: number }>()("Position")

ConstructedComponent

Source

Defines a component descriptor that also knows how to validate raw values.

Use this when the component should never exist in the world in an unvalidated shape, for example vectors, sizes, collider bounds, or other branded domain values.

// Route raw component input through a constructor once at the boundary.
const Position = Descriptor.ConstructedComponent(Vector2)("Position")

TransientComponent

Source

Defines a component descriptor that snapshots skip.

Restored entities come back without it, so systems that need it rebuild it, for example from an added(...) query.

const SpriteRef = Descriptor.TransientComponent<{ frame: number }>()("SpriteRef")

Tag

Source

Defines a marker component: no data, only presence ([Player, {}]).

Tags validate on load like any constructed component, so they never block snapshots.

const Player = Descriptor.Tag("Player")
const Enemy = Descriptor.Tag("Enemy")

State

Source

Defines a state component: its value is one of states, validated (so snapshots reject unknown states), and it behaves like any other component (storage, change detection, rollback, traces).

With transitions, its write cell gains transition(from, to): the pair is checked against the graph at compile time, and at runtime the move happens only if the current state is still from, otherwise it returns a StateMismatch failure. Transitions are ordinary component writes: immediate, visible to later systems, rolled back with a failed system.

const Phase = Descriptor.State("Phase", ["ready", "windup", "active"] as const, {
  transitions: { ready: ["windup"], windup: ["active", "ready"], active: ["ready"] }
})
// in a system with a write slot `phase`:
const moved = data.phase.transition("windup", "active")   // "ready" -> "active" does not compile

isState

Source

Whether a descriptor was built with State.

Resource

Source

Defines a resource descriptor.

Resources represent unique world-level values accessed through explicit system specs.

Use resources for singleton world data such as counters, configuration, global timers, camera summaries, or transient per-frame aggregates that should not be duplicated across entities.

// Store shared world state once and request it explicitly from systems.
const Score = Descriptor.Resource<number>()("Score")

ConstructedResource

Source

Defines a resource descriptor that also knows how to validate raw values.

TransientResource

Source

Defines a resource descriptor that snapshots skip. Restoring keeps its current value.

const DeltaTime = Descriptor.TransientResource<number>()("DeltaTime")

Event

Source

Defines an event descriptor.

Use event descriptors to model append-only messages flowing between systems without exposing untyped channels.

Events are per-reader streams, like change detection: each reading system sees the events published since its own previous run, once, in emission order. A system's events are published when it completes successfully, so later systems in the same schedule see them, and a failed system publishes nothing. Events are kept until every system that reads them has run (see Game.System.readEvent).

const Hit = Descriptor.Event<{ target: number; amount: number }>()("Hit")

Service

Source

Defines a service descriptor.

Services are the dependency-injection side of the system model, similar to Effect environment entries.

Use them for capabilities owned by the host instead of the ECS world: clocks, random sources, render/audio bridges, storage, or network clients. Systems request them explicitly with Game.System.service(...), and the runtime provides them through Game.Runtime.services(...).

// Describe one host capability the runtime must provide.
const Logger = Descriptor.Service<{ log: (message: string) => void }>()("Logger")

isTransient

Source

Checks whether one descriptor is transient (skipped by snapshots).

fromStandardSchema

Source

Adapts a Standard Schema validator into a descriptor constructor, so any compliant validation library can guard constructed components and resources. Validation must be synchronous; a schema that returns a promise fails with an issue instead.

const Position = Descriptor.ConstructedComponent(
  Descriptor.fromStandardSchema(type({ x: "number", y: "number" }))
)("Position")

decoderOf

Source

Returns the function that validates untrusted values for a constructed descriptor: its constructor's decode when present, otherwise result. The snapshot types only allow the result fallback when it accepts unknown.

hasConstructor

Source

Checks whether one descriptor carries raw-construction metadata.

constructorOf

Source

Returns the raw constructor carried by one descriptor when present.

Plain descriptors return undefined.

Variables

Stable runtime markers used to brand descriptor kinds and constructor-aware variants.

Hierarchy

Source

Defines the canonical parent/children relationship pair.

The returned relation is the source-of-truth edge component, while related is the reverse collection maintained by the runtime.

Use hierarchy when the relationship must support ordered children, ancestor/descendant traversal, and linked recursive despawn.

Relation

Source

Defines a general relationship pair with direct edges and reverse lookups.

Use a general relation when you need direct source -> target edges plus reverse lookup, but not hierarchy-only behavior such as tree traversal or child reordering.